diff --git a/vendor/github.com/cznic/b/LICENSE b/vendor/github.com/cznic/b/LICENSE new file mode 100644 index 00000000..54c6e908 --- /dev/null +++ b/vendor/github.com/cznic/b/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2014 The b Authors. 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 names of the authors nor the names of the +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/vendor/github.com/cznic/b/btree.go b/vendor/github.com/cznic/b/btree.go new file mode 100644 index 00000000..0809a825 --- /dev/null +++ b/vendor/github.com/cznic/b/btree.go @@ -0,0 +1,929 @@ +// Copyright 2014 The b 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 b + +import ( + "fmt" + "io" + "sync" +) + +const ( + kx = 32 //TODO benchmark tune this number if using custom key/value type(s). + kd = 32 //TODO benchmark tune this number if using custom key/value type(s). +) + +func init() { + if kd < 1 { + panic(fmt.Errorf("kd %d: out of range", kd)) + } + + if kx < 2 { + panic(fmt.Errorf("kx %d: out of range", kx)) + } +} + +var ( + btDPool = sync.Pool{New: func() interface{} { return &d{} }} + btEPool = btEpool{sync.Pool{New: func() interface{} { return &Enumerator{} }}} + btTPool = btTpool{sync.Pool{New: func() interface{} { return &Tree{} }}} + btXPool = sync.Pool{New: func() interface{} { return &x{} }} +) + +type btTpool struct{ sync.Pool } + +func (p *btTpool) get(cmp Cmp) *Tree { + x := p.Get().(*Tree) + x.cmp = cmp + return x +} + +type btEpool struct{ sync.Pool } + +func (p *btEpool) get(err error, hit bool, i int, k interface{} /*K*/, q *d, t *Tree, ver int64) *Enumerator { + x := p.Get().(*Enumerator) + x.err, x.hit, x.i, x.k, x.q, x.t, x.ver = err, hit, i, k, q, t, ver + return x +} + +type ( + // Cmp compares a and b. Return value is: + // + // < 0 if a < b + // 0 if a == b + // > 0 if a > b + // + Cmp func(a, b interface{} /*K*/) int + + d struct { // data page + c int + d [2*kd + 1]de + n *d + p *d + } + + de struct { // d element + k interface{} /*K*/ + v interface{} /*V*/ + } + + // Enumerator captures the state of enumerating a tree. It is returned + // from the Seek* methods. The enumerator is aware of any mutations + // made to the tree in the process of enumerating it and automatically + // resumes the enumeration at the proper key, if possible. + // + // However, once an Enumerator returns io.EOF to signal "no more + // items", it does no more attempt to "resync" on tree mutation(s). In + // other words, io.EOF from an Enumerator is "sticky" (idempotent). + Enumerator struct { + err error + hit bool + i int + k interface{} /*K*/ + q *d + t *Tree + ver int64 + } + + // Tree is a B+tree. + Tree struct { + c int + cmp Cmp + first *d + last *d + r interface{} + ver int64 + } + + xe struct { // x element + ch interface{} + k interface{} /*K*/ + } + + x struct { // index page + c int + x [2*kx + 2]xe + } +) + +var ( // R/O zero values + zd d + zde de + ze Enumerator + zk interface{} /*K*/ + zt Tree + zx x + zxe xe +) + +func clr(q interface{}) { + switch x := q.(type) { + case *x: + for i := 0; i <= x.c; i++ { // Ch0 Sep0 ... Chn-1 Sepn-1 Chn + clr(x.x[i].ch) + } + *x = zx + btXPool.Put(x) + case *d: + *x = zd + btDPool.Put(x) + } +} + +// -------------------------------------------------------------------------- x + +func newX(ch0 interface{}) *x { + r := btXPool.Get().(*x) + r.x[0].ch = ch0 + return r +} + +func (q *x) extract(i int) { + q.c-- + if i < q.c { + copy(q.x[i:], q.x[i+1:q.c+1]) + q.x[q.c].ch = q.x[q.c+1].ch + q.x[q.c].k = zk // GC + q.x[q.c+1] = zxe // GC + } +} + +func (q *x) insert(i int, k interface{} /*K*/, ch interface{}) *x { + c := q.c + if i < c { + q.x[c+1].ch = q.x[c].ch + copy(q.x[i+2:], q.x[i+1:c]) + q.x[i+1].k = q.x[i].k + } + c++ + q.c = c + q.x[i].k = k + q.x[i+1].ch = ch + return q +} + +func (q *x) siblings(i int) (l, r *d) { + if i >= 0 { + if i > 0 { + l = q.x[i-1].ch.(*d) + } + if i < q.c { + r = q.x[i+1].ch.(*d) + } + } + return +} + +// -------------------------------------------------------------------------- d + +func (l *d) mvL(r *d, c int) { + copy(l.d[l.c:], r.d[:c]) + copy(r.d[:], r.d[c:r.c]) + l.c += c + r.c -= c +} + +func (l *d) mvR(r *d, c int) { + copy(r.d[c:], r.d[:r.c]) + copy(r.d[:c], l.d[l.c-c:]) + r.c += c + l.c -= c +} + +// ----------------------------------------------------------------------- Tree + +// TreeNew returns a newly created, empty Tree. The compare function is used +// for key collation. +func TreeNew(cmp Cmp) *Tree { + return btTPool.get(cmp) +} + +// Clear removes all K/V pairs from the tree. +func (t *Tree) Clear() { + if t.r == nil { + return + } + + clr(t.r) + t.c, t.first, t.last, t.r = 0, nil, nil, nil + t.ver++ +} + +// Close performs Clear and recycles t to a pool for possible later reuse. No +// references to t should exist or such references must not be used afterwards. +func (t *Tree) Close() { + t.Clear() + *t = zt + btTPool.Put(t) +} + +func (t *Tree) cat(p *x, q, r *d, pi int) { + t.ver++ + q.mvL(r, r.c) + if r.n != nil { + r.n.p = q + } else { + t.last = q + } + q.n = r.n + *r = zd + btDPool.Put(r) + if p.c > 1 { + p.extract(pi) + p.x[pi].ch = q + return + } + + switch x := t.r.(type) { + case *x: + *x = zx + btXPool.Put(x) + case *d: + *x = zd + btDPool.Put(x) + } + t.r = q +} + +func (t *Tree) catX(p, q, r *x, pi int) { + t.ver++ + q.x[q.c].k = p.x[pi].k + copy(q.x[q.c+1:], r.x[:r.c]) + q.c += r.c + 1 + q.x[q.c].ch = r.x[r.c].ch + *r = zx + btXPool.Put(r) + if p.c > 1 { + p.c-- + pc := p.c + if pi < pc { + p.x[pi].k = p.x[pi+1].k + copy(p.x[pi+1:], p.x[pi+2:pc+1]) + p.x[pc].ch = p.x[pc+1].ch + p.x[pc].k = zk // GC + p.x[pc+1].ch = nil // GC + } + return + } + + switch x := t.r.(type) { + case *x: + *x = zx + btXPool.Put(x) + case *d: + *x = zd + btDPool.Put(x) + } + t.r = q +} + +// Delete removes the k's KV pair, if it exists, in which case Delete returns +// true. +func (t *Tree) Delete(k interface{} /*K*/) (ok bool) { + pi := -1 + var p *x + q := t.r + if q == nil { + return false + } + + for { + var i int + i, ok = t.find(q, k) + if ok { + switch x := q.(type) { + case *x: + if x.c < kx && q != t.r { + x, i = t.underflowX(p, x, pi, i) + } + pi = i + 1 + p = x + q = x.x[pi].ch + ok = false + continue + case *d: + t.extract(x, i) + if x.c >= kd { + return true + } + + if q != t.r { + t.underflow(p, x, pi) + } else if t.c == 0 { + t.Clear() + } + return true + } + } + + switch x := q.(type) { + case *x: + if x.c < kx && q != t.r { + x, i = t.underflowX(p, x, pi, i) + } + pi = i + p = x + q = x.x[i].ch + case *d: + return false + } + } +} + +func (t *Tree) extract(q *d, i int) { // (r interface{} /*V*/) { + t.ver++ + //r = q.d[i].v // prepared for Extract + q.c-- + if i < q.c { + copy(q.d[i:], q.d[i+1:q.c+1]) + } + q.d[q.c] = zde // GC + t.c-- + return +} + +func (t *Tree) find(q interface{}, k interface{} /*K*/) (i int, ok bool) { + var mk interface{} /*K*/ + l := 0 + switch x := q.(type) { + case *x: + h := x.c - 1 + for l <= h { + m := (l + h) >> 1 + mk = x.x[m].k + switch cmp := t.cmp(k, mk); { + case cmp > 0: + l = m + 1 + case cmp == 0: + return m, true + default: + h = m - 1 + } + } + case *d: + h := x.c - 1 + for l <= h { + m := (l + h) >> 1 + mk = x.d[m].k + switch cmp := t.cmp(k, mk); { + case cmp > 0: + l = m + 1 + case cmp == 0: + return m, true + default: + h = m - 1 + } + } + } + return l, false +} + +// First returns the first item of the tree in the key collating order, or +// (zero-value, zero-value) if the tree is empty. +func (t *Tree) First() (k interface{} /*K*/, v interface{} /*V*/) { + if q := t.first; q != nil { + q := &q.d[0] + k, v = q.k, q.v + } + return +} + +// Get returns the value associated with k and true if it exists. Otherwise Get +// returns (zero-value, false). +func (t *Tree) Get(k interface{} /*K*/) (v interface{} /*V*/, ok bool) { + q := t.r + if q == nil { + return + } + + for { + var i int + if i, ok = t.find(q, k); ok { + switch x := q.(type) { + case *x: + q = x.x[i+1].ch + continue + case *d: + return x.d[i].v, true + } + } + switch x := q.(type) { + case *x: + q = x.x[i].ch + default: + return + } + } +} + +func (t *Tree) insert(q *d, i int, k interface{} /*K*/, v interface{} /*V*/) *d { + t.ver++ + c := q.c + if i < c { + copy(q.d[i+1:], q.d[i:c]) + } + c++ + q.c = c + q.d[i].k, q.d[i].v = k, v + t.c++ + return q +} + +// Last returns the last item of the tree in the key collating order, or +// (zero-value, zero-value) if the tree is empty. +func (t *Tree) Last() (k interface{} /*K*/, v interface{} /*V*/) { + if q := t.last; q != nil { + q := &q.d[q.c-1] + k, v = q.k, q.v + } + return +} + +// Len returns the number of items in the tree. +func (t *Tree) Len() int { + return t.c +} + +func (t *Tree) overflow(p *x, q *d, pi, i int, k interface{} /*K*/, v interface{} /*V*/) { + t.ver++ + l, r := p.siblings(pi) + + if l != nil && l.c < 2*kd && i != 0 { + l.mvL(q, 1) + t.insert(q, i-1, k, v) + p.x[pi-1].k = q.d[0].k + return + } + + if r != nil && r.c < 2*kd { + if i < 2*kd { + q.mvR(r, 1) + t.insert(q, i, k, v) + p.x[pi].k = r.d[0].k + return + } + + t.insert(r, 0, k, v) + p.x[pi].k = k + return + } + + t.split(p, q, pi, i, k, v) +} + +// Seek returns an Enumerator positioned on an item such that k >= item's key. +// ok reports if k == item.key The Enumerator's position is possibly after the +// last item in the tree. +func (t *Tree) Seek(k interface{} /*K*/) (e *Enumerator, ok bool) { + q := t.r + if q == nil { + e = btEPool.get(nil, false, 0, k, nil, t, t.ver) + return + } + + for { + var i int + if i, ok = t.find(q, k); ok { + switch x := q.(type) { + case *x: + q = x.x[i+1].ch + continue + case *d: + return btEPool.get(nil, ok, i, k, x, t, t.ver), true + } + } + + switch x := q.(type) { + case *x: + q = x.x[i].ch + case *d: + return btEPool.get(nil, ok, i, k, x, t, t.ver), false + } + } +} + +// SeekFirst returns an enumerator positioned on the first KV pair in the tree, +// if any. For an empty tree, err == io.EOF is returned and e will be nil. +func (t *Tree) SeekFirst() (e *Enumerator, err error) { + q := t.first + if q == nil { + return nil, io.EOF + } + + return btEPool.get(nil, true, 0, q.d[0].k, q, t, t.ver), nil +} + +// SeekLast returns an enumerator positioned on the last KV pair in the tree, +// if any. For an empty tree, err == io.EOF is returned and e will be nil. +func (t *Tree) SeekLast() (e *Enumerator, err error) { + q := t.last + if q == nil { + return nil, io.EOF + } + + return btEPool.get(nil, true, q.c-1, q.d[q.c-1].k, q, t, t.ver), nil +} + +// Set sets the value associated with k. +func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) { + //dbg("--- PRE Set(%v, %v)\n%s", k, v, t.dump()) + //defer func() { + // dbg("--- POST\n%s\n====\n", t.dump()) + //}() + + pi := -1 + var p *x + q := t.r + if q == nil { + z := t.insert(btDPool.Get().(*d), 0, k, v) + t.r, t.first, t.last = z, z, z + return + } + + for { + i, ok := t.find(q, k) + if ok { + switch x := q.(type) { + case *x: + if x.c > 2*kx { + x, i = t.splitX(p, x, pi, i) + } + pi = i + 1 + p = x + q = x.x[i+1].ch + continue + case *d: + x.d[i].v = v + } + return + } + + switch x := q.(type) { + case *x: + if x.c > 2*kx { + x, i = t.splitX(p, x, pi, i) + } + pi = i + p = x + q = x.x[i].ch + case *d: + switch { + case x.c < 2*kd: + t.insert(x, i, k, v) + default: + t.overflow(p, x, pi, i, k, v) + } + return + } + } +} + +// Put combines Get and Set in a more efficient way where the tree is walked +// only once. The upd(ater) receives (old-value, true) if a KV pair for k +// exists or (zero-value, false) otherwise. It can then return a (new-value, +// true) to create or overwrite the existing value in the KV pair, or +// (whatever, false) if it decides not to create or not to update the value of +// the KV pair. +// +// tree.Set(k, v) call conceptually equals calling +// +// tree.Put(k, func(interface{} /*K*/, bool){ return v, true }) +// +// modulo the differing return values. +func (t *Tree) Put(k interface{} /*K*/, upd func(oldV interface{} /*V*/, exists bool) (newV interface{} /*V*/, write bool)) (oldV interface{} /*V*/, written bool) { + pi := -1 + var p *x + q := t.r + var newV interface{} /*V*/ + if q == nil { + // new KV pair in empty tree + newV, written = upd(newV, false) + if !written { + return + } + + z := t.insert(btDPool.Get().(*d), 0, k, newV) + t.r, t.first, t.last = z, z, z + return + } + + for { + i, ok := t.find(q, k) + if ok { + switch x := q.(type) { + case *x: + if x.c > 2*kx { + x, i = t.splitX(p, x, pi, i) + } + pi = i + 1 + p = x + q = x.x[i+1].ch + continue + case *d: + oldV = x.d[i].v + newV, written = upd(oldV, true) + if !written { + return + } + + x.d[i].v = newV + } + return + } + + switch x := q.(type) { + case *x: + if x.c > 2*kx { + x, i = t.splitX(p, x, pi, i) + } + pi = i + p = x + q = x.x[i].ch + case *d: // new KV pair + newV, written = upd(newV, false) + if !written { + return + } + + switch { + case x.c < 2*kd: + t.insert(x, i, k, newV) + default: + t.overflow(p, x, pi, i, k, newV) + } + return + } + } +} + +func (t *Tree) split(p *x, q *d, pi, i int, k interface{} /*K*/, v interface{} /*V*/) { + t.ver++ + r := btDPool.Get().(*d) + if q.n != nil { + r.n = q.n + r.n.p = r + } else { + t.last = r + } + q.n = r + r.p = q + + copy(r.d[:], q.d[kd:2*kd]) + for i := range q.d[kd:] { + q.d[kd+i] = zde + } + q.c = kd + r.c = kd + var done bool + if i > kd { + done = true + t.insert(r, i-kd, k, v) + } + if pi >= 0 { + p.insert(pi, r.d[0].k, r) + } else { + t.r = newX(q).insert(0, r.d[0].k, r) + } + if done { + return + } + + t.insert(q, i, k, v) +} + +func (t *Tree) splitX(p *x, q *x, pi int, i int) (*x, int) { + t.ver++ + r := btXPool.Get().(*x) + copy(r.x[:], q.x[kx+1:]) + q.c = kx + r.c = kx + if pi >= 0 { + p.insert(pi, q.x[kx].k, r) + q.x[kx].k = zk + for i := range q.x[kx+1:] { + q.x[kx+i+1] = zxe + } + + switch { + case i < kx: + return q, i + case i == kx: + return p, pi + default: // i > kx + return r, i - kx - 1 + } + } + + nr := newX(q).insert(0, q.x[kx].k, r) + t.r = nr + q.x[kx].k = zk + for i := range q.x[kx+1:] { + q.x[kx+i+1] = zxe + } + + switch { + case i < kx: + return q, i + case i == kx: + return nr, 0 + default: // i > kx + return r, i - kx - 1 + } +} + +func (t *Tree) underflow(p *x, q *d, pi int) { + t.ver++ + l, r := p.siblings(pi) + + if l != nil && l.c+q.c >= 2*kd { + l.mvR(q, 1) + p.x[pi-1].k = q.d[0].k + return + } + + if r != nil && q.c+r.c >= 2*kd { + q.mvL(r, 1) + p.x[pi].k = r.d[0].k + r.d[r.c] = zde // GC + return + } + + if l != nil { + t.cat(p, l, q, pi-1) + return + } + + t.cat(p, q, r, pi) +} + +func (t *Tree) underflowX(p *x, q *x, pi int, i int) (*x, int) { + t.ver++ + var l, r *x + + if pi >= 0 { + if pi > 0 { + l = p.x[pi-1].ch.(*x) + } + if pi < p.c { + r = p.x[pi+1].ch.(*x) + } + } + + if l != nil && l.c > kx { + q.x[q.c+1].ch = q.x[q.c].ch + copy(q.x[1:], q.x[:q.c]) + q.x[0].ch = l.x[l.c].ch + q.x[0].k = p.x[pi-1].k + q.c++ + i++ + l.c-- + p.x[pi-1].k = l.x[l.c].k + return q, i + } + + if r != nil && r.c > kx { + q.x[q.c].k = p.x[pi].k + q.c++ + q.x[q.c].ch = r.x[0].ch + p.x[pi].k = r.x[0].k + copy(r.x[:], r.x[1:r.c]) + r.c-- + rc := r.c + r.x[rc].ch = r.x[rc+1].ch + r.x[rc].k = zk + r.x[rc+1].ch = nil + return q, i + } + + if l != nil { + i += l.c + 1 + t.catX(p, l, q, pi-1) + q = l + return q, i + } + + t.catX(p, q, r, pi) + return q, i +} + +// ----------------------------------------------------------------- Enumerator + +// Close recycles e to a pool for possible later reuse. No references to e +// should exist or such references must not be used afterwards. +func (e *Enumerator) Close() { + *e = ze + btEPool.Put(e) +} + +// Next returns the currently enumerated item, if it exists and moves to the +// next item in the key collation order. If there is no item to return, err == +// io.EOF is returned. +func (e *Enumerator) Next() (k interface{} /*K*/, v interface{} /*V*/, err error) { + if err = e.err; err != nil { + return + } + + if e.ver != e.t.ver { + f, hit := e.t.Seek(e.k) + if !e.hit && hit { + if err = f.next(); err != nil { + return + } + } + + *e = *f + f.Close() + } + if e.q == nil { + e.err, err = io.EOF, io.EOF + return + } + + if e.i >= e.q.c { + if err = e.next(); err != nil { + return + } + } + + i := e.q.d[e.i] + k, v = i.k, i.v + e.k, e.hit = k, false + e.next() + return +} + +func (e *Enumerator) next() error { + if e.q == nil { + e.err = io.EOF + return io.EOF + } + + switch { + case e.i < e.q.c-1: + e.i++ + default: + if e.q, e.i = e.q.n, 0; e.q == nil { + e.err = io.EOF + } + } + return e.err +} + +// Prev returns the currently enumerated item, if it exists and moves to the +// previous item in the key collation order. If there is no item to return, err +// == io.EOF is returned. +func (e *Enumerator) Prev() (k interface{} /*K*/, v interface{} /*V*/, err error) { + if err = e.err; err != nil { + return + } + + if e.ver != e.t.ver { + f, hit := e.t.Seek(e.k) + if !e.hit && hit { + if err = f.prev(); err != nil { + return + } + } + + *e = *f + f.Close() + } + if e.q == nil { + e.err, err = io.EOF, io.EOF + return + } + + if e.i >= e.q.c { + if err = e.next(); err != nil { + return + } + } + + i := e.q.d[e.i] + k, v = i.k, i.v + e.k, e.hit = k, false + e.prev() + return +} + +func (e *Enumerator) prev() error { + if e.q == nil { + e.err = io.EOF + return io.EOF + } + + switch { + case e.i > 0: + e.i-- + default: + if e.q = e.q.p; e.q == nil { + e.err = io.EOF + break + } + + e.i = e.q.c - 1 + } + return e.err +} diff --git a/vendor/github.com/cznic/b/doc.go b/vendor/github.com/cznic/b/doc.go new file mode 100644 index 00000000..ddcf7370 --- /dev/null +++ b/vendor/github.com/cznic/b/doc.go @@ -0,0 +1,53 @@ +// Copyright 2014 The b 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 b implements the B+tree flavor of a BTree. +// +// Changelog +// +// 2014-06-26: Lower GC presure by recycling things. +// +// 2014-04-18: Added new method Put. +// +// Generic types +// +// Keys and their associated values are interface{} typed, similar to all of +// the containers in the standard library. +// +// Semiautomatic production of a type specific variant of this package is +// supported via +// +// $ make generic +// +// This command will write to stdout a version of the btree.go file where every +// key type occurrence is replaced by the word 'KEY' and every value type +// occurrence is replaced by the word 'VALUE'. Then you have to replace these +// tokens with your desired type(s), using any technique you're comfortable +// with. +// +// This is how, for example, 'example/int.go' was created: +// +// $ mkdir example +// $ make generic | sed -e 's/KEY/int/g' -e 's/VALUE/int/g' > example/int.go +// +// No other changes to int.go are necessary, it compiles just fine. +// +// Running the benchmarks for 1000 keys on a machine with Intel i5-4670 CPU @ +// 3.4GHz, Go release 1.4.2. +// +// $ go test -bench 1e3 example/all_test.go example/int.go +// PASS +// BenchmarkSetSeq1e3 10000 151620 ns/op +// BenchmarkGetSeq1e3 10000 115354 ns/op +// BenchmarkSetRnd1e3 5000 255865 ns/op +// BenchmarkGetRnd1e3 10000 140466 ns/op +// BenchmarkDelSeq1e3 10000 143860 ns/op +// BenchmarkDelRnd1e3 10000 188228 ns/op +// BenchmarkSeekSeq1e3 10000 156448 ns/op +// BenchmarkSeekRnd1e3 10000 190587 ns/op +// BenchmarkNext1e3 200000 9407 ns/op +// BenchmarkPrev1e3 200000 9306 ns/op +// ok command-line-arguments 26.369s +// $ +package b diff --git a/vendor/github.com/cznic/b/example/int.go b/vendor/github.com/cznic/b/example/int.go new file mode 100644 index 00000000..54f7fdff --- /dev/null +++ b/vendor/github.com/cznic/b/example/int.go @@ -0,0 +1,929 @@ +// Copyright 2014 The b 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 b + +import ( + "fmt" + "io" + "sync" +) + +const ( + kx = 32 //TODO benchmark tune this number if using custom key/value type(s). + kd = 32 //TODO benchmark tune this number if using custom key/value type(s). +) + +func init() { + if kd < 1 { + panic(fmt.Errorf("kd %d: out of range", kd)) + } + + if kx < 2 { + panic(fmt.Errorf("kx %d: out of range", kx)) + } +} + +var ( + btDPool = sync.Pool{New: func() interface{} { return &d{} }} + btEPool = btEpool{sync.Pool{New: func() interface{} { return &Enumerator{} }}} + btTPool = btTpool{sync.Pool{New: func() interface{} { return &Tree{} }}} + btXPool = sync.Pool{New: func() interface{} { return &x{} }} +) + +type btTpool struct{ sync.Pool } + +func (p *btTpool) get(cmp Cmp) *Tree { + x := p.Get().(*Tree) + x.cmp = cmp + return x +} + +type btEpool struct{ sync.Pool } + +func (p *btEpool) get(err error, hit bool, i int, k int, q *d, t *Tree, ver int64) *Enumerator { + x := p.Get().(*Enumerator) + x.err, x.hit, x.i, x.k, x.q, x.t, x.ver = err, hit, i, k, q, t, ver + return x +} + +type ( + // Cmp compares a and b. Return value is: + // + // < 0 if a < b + // 0 if a == b + // > 0 if a > b + // + Cmp func(a, b int) int + + d struct { // data page + c int + d [2*kd + 1]de + n *d + p *d + } + + de struct { // d element + k int + v int + } + + // Enumerator captures the state of enumerating a tree. It is returned + // from the Seek* methods. The enumerator is aware of any mutations + // made to the tree in the process of enumerating it and automatically + // resumes the enumeration at the proper key, if possible. + // + // However, once an Enumerator returns io.EOF to signal "no more + // items", it does no more attempt to "resync" on tree mutation(s). In + // other words, io.EOF from an Enumaretor is "sticky" (idempotent). + Enumerator struct { + err error + hit bool + i int + k int + q *d + t *Tree + ver int64 + } + + // Tree is a B+tree. + Tree struct { + c int + cmp Cmp + first *d + last *d + r interface{} + ver int64 + } + + xe struct { // x element + ch interface{} + k int + } + + x struct { // index page + c int + x [2*kx + 2]xe + } +) + +var ( // R/O zero values + zd d + zde de + ze Enumerator + zk int + zt Tree + zx x + zxe xe +) + +func clr(q interface{}) { + switch x := q.(type) { + case *x: + for i := 0; i <= x.c; i++ { // Ch0 Sep0 ... Chn-1 Sepn-1 Chn + clr(x.x[i].ch) + } + *x = zx + btXPool.Put(x) + case *d: + *x = zd + btDPool.Put(x) + } +} + +// -------------------------------------------------------------------------- x + +func newX(ch0 interface{}) *x { + r := btXPool.Get().(*x) + r.x[0].ch = ch0 + return r +} + +func (q *x) extract(i int) { + q.c-- + if i < q.c { + copy(q.x[i:], q.x[i+1:q.c+1]) + q.x[q.c].ch = q.x[q.c+1].ch + q.x[q.c].k = zk // GC + q.x[q.c+1] = zxe // GC + } +} + +func (q *x) insert(i int, k int, ch interface{}) *x { + c := q.c + if i < c { + q.x[c+1].ch = q.x[c].ch + copy(q.x[i+2:], q.x[i+1:c]) + q.x[i+1].k = q.x[i].k + } + c++ + q.c = c + q.x[i].k = k + q.x[i+1].ch = ch + return q +} + +func (q *x) siblings(i int) (l, r *d) { + if i >= 0 { + if i > 0 { + l = q.x[i-1].ch.(*d) + } + if i < q.c { + r = q.x[i+1].ch.(*d) + } + } + return +} + +// -------------------------------------------------------------------------- d + +func (l *d) mvL(r *d, c int) { + copy(l.d[l.c:], r.d[:c]) + copy(r.d[:], r.d[c:r.c]) + l.c += c + r.c -= c +} + +func (l *d) mvR(r *d, c int) { + copy(r.d[c:], r.d[:r.c]) + copy(r.d[:c], l.d[l.c-c:]) + r.c += c + l.c -= c +} + +// ----------------------------------------------------------------------- Tree + +// TreeNew returns a newly created, empty Tree. The compare function is used +// for key collation. +func TreeNew(cmp Cmp) *Tree { + return btTPool.get(cmp) +} + +// Clear removes all K/V pairs from the tree. +func (t *Tree) Clear() { + if t.r == nil { + return + } + + clr(t.r) + t.c, t.first, t.last, t.r = 0, nil, nil, nil + t.ver++ +} + +// Close performs Clear and recycles t to a pool for possible later reuse. No +// references to t should exist or such references must not be used afterwards. +func (t *Tree) Close() { + t.Clear() + *t = zt + btTPool.Put(t) +} + +func (t *Tree) cat(p *x, q, r *d, pi int) { + t.ver++ + q.mvL(r, r.c) + if r.n != nil { + r.n.p = q + } else { + t.last = q + } + q.n = r.n + *r = zd + btDPool.Put(r) + if p.c > 1 { + p.extract(pi) + p.x[pi].ch = q + return + } + + switch x := t.r.(type) { + case *x: + *x = zx + btXPool.Put(x) + case *d: + *x = zd + btDPool.Put(x) + } + t.r = q +} + +func (t *Tree) catX(p, q, r *x, pi int) { + t.ver++ + q.x[q.c].k = p.x[pi].k + copy(q.x[q.c+1:], r.x[:r.c]) + q.c += r.c + 1 + q.x[q.c].ch = r.x[r.c].ch + *r = zx + btXPool.Put(r) + if p.c > 1 { + p.c-- + pc := p.c + if pi < pc { + p.x[pi].k = p.x[pi+1].k + copy(p.x[pi+1:], p.x[pi+2:pc+1]) + p.x[pc].ch = p.x[pc+1].ch + p.x[pc].k = zk // GC + p.x[pc+1].ch = nil // GC + } + return + } + + switch x := t.r.(type) { + case *x: + *x = zx + btXPool.Put(x) + case *d: + *x = zd + btDPool.Put(x) + } + t.r = q +} + +// Delete removes the k's KV pair, if it exists, in which case Delete returns +// true. +func (t *Tree) Delete(k int) (ok bool) { + pi := -1 + var p *x + q := t.r + if q == nil { + return false + } + + for { + var i int + i, ok = t.find(q, k) + if ok { + switch x := q.(type) { + case *x: + if x.c < kx && q != t.r { + x, i = t.underflowX(p, x, pi, i) + } + pi = i + 1 + p = x + q = x.x[pi].ch + ok = false + continue + case *d: + t.extract(x, i) + if x.c >= kd { + return true + } + + if q != t.r { + t.underflow(p, x, pi) + } else if t.c == 0 { + t.Clear() + } + return true + } + } + + switch x := q.(type) { + case *x: + if x.c < kx && q != t.r { + x, i = t.underflowX(p, x, pi, i) + } + pi = i + p = x + q = x.x[i].ch + case *d: + return false + } + } +} + +func (t *Tree) extract(q *d, i int) { // (r int) { + t.ver++ + //r = q.d[i].v // prepared for Extract + q.c-- + if i < q.c { + copy(q.d[i:], q.d[i+1:q.c+1]) + } + q.d[q.c] = zde // GC + t.c-- + return +} + +func (t *Tree) find(q interface{}, k int) (i int, ok bool) { + var mk int + l := 0 + switch x := q.(type) { + case *x: + h := x.c - 1 + for l <= h { + m := (l + h) >> 1 + mk = x.x[m].k + switch cmp := t.cmp(k, mk); { + case cmp > 0: + l = m + 1 + case cmp == 0: + return m, true + default: + h = m - 1 + } + } + case *d: + h := x.c - 1 + for l <= h { + m := (l + h) >> 1 + mk = x.d[m].k + switch cmp := t.cmp(k, mk); { + case cmp > 0: + l = m + 1 + case cmp == 0: + return m, true + default: + h = m - 1 + } + } + } + return l, false +} + +// First returns the first item of the tree in the key collating order, or +// (zero-value, zero-value) if the tree is empty. +func (t *Tree) First() (k int, v int) { + if q := t.first; q != nil { + q := &q.d[0] + k, v = q.k, q.v + } + return +} + +// Get returns the value associated with k and true if it exists. Otherwise Get +// returns (zero-value, false). +func (t *Tree) Get(k int) (v int, ok bool) { + q := t.r + if q == nil { + return + } + + for { + var i int + if i, ok = t.find(q, k); ok { + switch x := q.(type) { + case *x: + q = x.x[i+1].ch + continue + case *d: + return x.d[i].v, true + } + } + switch x := q.(type) { + case *x: + q = x.x[i].ch + default: + return + } + } +} + +func (t *Tree) insert(q *d, i int, k int, v int) *d { + t.ver++ + c := q.c + if i < c { + copy(q.d[i+1:], q.d[i:c]) + } + c++ + q.c = c + q.d[i].k, q.d[i].v = k, v + t.c++ + return q +} + +// Last returns the last item of the tree in the key collating order, or +// (zero-value, zero-value) if the tree is empty. +func (t *Tree) Last() (k int, v int) { + if q := t.last; q != nil { + q := &q.d[q.c-1] + k, v = q.k, q.v + } + return +} + +// Len returns the number of items in the tree. +func (t *Tree) Len() int { + return t.c +} + +func (t *Tree) overflow(p *x, q *d, pi, i int, k int, v int) { + t.ver++ + l, r := p.siblings(pi) + + if l != nil && l.c < 2*kd { + l.mvL(q, 1) + t.insert(q, i-1, k, v) + p.x[pi-1].k = q.d[0].k + return + } + + if r != nil && r.c < 2*kd { + if i < 2*kd { + q.mvR(r, 1) + t.insert(q, i, k, v) + p.x[pi].k = r.d[0].k + return + } + + t.insert(r, 0, k, v) + p.x[pi].k = k + return + } + + t.split(p, q, pi, i, k, v) +} + +// Seek returns an Enumerator positioned on a an item such that k >= item's +// key. ok reports if k == item.key The Enumerator's position is possibly +// after the last item in the tree. +func (t *Tree) Seek(k int) (e *Enumerator, ok bool) { + q := t.r + if q == nil { + e = btEPool.get(nil, false, 0, k, nil, t, t.ver) + return + } + + for { + var i int + if i, ok = t.find(q, k); ok { + switch x := q.(type) { + case *x: + q = x.x[i+1].ch + continue + case *d: + return btEPool.get(nil, ok, i, k, x, t, t.ver), true + } + } + + switch x := q.(type) { + case *x: + q = x.x[i].ch + case *d: + return btEPool.get(nil, ok, i, k, x, t, t.ver), false + } + } +} + +// SeekFirst returns an enumerator positioned on the first KV pair in the tree, +// if any. For an empty tree, err == io.EOF is returned and e will be nil. +func (t *Tree) SeekFirst() (e *Enumerator, err error) { + q := t.first + if q == nil { + return nil, io.EOF + } + + return btEPool.get(nil, true, 0, q.d[0].k, q, t, t.ver), nil +} + +// SeekLast returns an enumerator positioned on the last KV pair in the tree, +// if any. For an empty tree, err == io.EOF is returned and e will be nil. +func (t *Tree) SeekLast() (e *Enumerator, err error) { + q := t.last + if q == nil { + return nil, io.EOF + } + + return btEPool.get(nil, true, q.c-1, q.d[q.c-1].k, q, t, t.ver), nil +} + +// Set sets the value associated with k. +func (t *Tree) Set(k int, v int) { + //dbg("--- PRE Set(%v, %v)\n%s", k, v, t.dump()) + //defer func() { + // dbg("--- POST\n%s\n====\n", t.dump()) + //}() + + pi := -1 + var p *x + q := t.r + if q == nil { + z := t.insert(btDPool.Get().(*d), 0, k, v) + t.r, t.first, t.last = z, z, z + return + } + + for { + i, ok := t.find(q, k) + if ok { + switch x := q.(type) { + case *x: + if x.c > 2*kx { + x, i = t.splitX(p, x, pi, i) + } + pi = i + 1 + p = x + q = x.x[i+1].ch + continue + case *d: + x.d[i].v = v + } + return + } + + switch x := q.(type) { + case *x: + if x.c > 2*kx { + x, i = t.splitX(p, x, pi, i) + } + pi = i + p = x + q = x.x[i].ch + case *d: + switch { + case x.c < 2*kd: + t.insert(x, i, k, v) + default: + t.overflow(p, x, pi, i, k, v) + } + return + } + } +} + +// Put combines Get and Set in a more efficient way where the tree is walked +// only once. The upd(ater) receives (old-value, true) if a KV pair for k +// exists or (zero-value, false) otherwise. It can then return a (new-value, +// true) to create or overwrite the existing value in the KV pair, or +// (whatever, false) if it decides not to create or not to update the value of +// the KV pair. +// +// tree.Set(k, v) call conceptually equals calling +// +// tree.Put(k, func(int, bool){ return v, true }) +// +// modulo the differing return values. +func (t *Tree) Put(k int, upd func(oldV int, exists bool) (newV int, write bool)) (oldV int, written bool) { + pi := -1 + var p *x + q := t.r + var newV int + if q == nil { + // new KV pair in empty tree + newV, written = upd(newV, false) + if !written { + return + } + + z := t.insert(btDPool.Get().(*d), 0, k, newV) + t.r, t.first, t.last = z, z, z + return + } + + for { + i, ok := t.find(q, k) + if ok { + switch x := q.(type) { + case *x: + if x.c > 2*kx { + x, i = t.splitX(p, x, pi, i) + } + pi = i + 1 + p = x + q = x.x[i+1].ch + continue + case *d: + oldV = x.d[i].v + newV, written = upd(oldV, true) + if !written { + return + } + + x.d[i].v = newV + } + return + } + + switch x := q.(type) { + case *x: + if x.c > 2*kx { + x, i = t.splitX(p, x, pi, i) + } + pi = i + p = x + q = x.x[i].ch + case *d: // new KV pair + newV, written = upd(newV, false) + if !written { + return + } + + switch { + case x.c < 2*kd: + t.insert(x, i, k, newV) + default: + t.overflow(p, x, pi, i, k, newV) + } + return + } + } +} + +func (t *Tree) split(p *x, q *d, pi, i int, k int, v int) { + t.ver++ + r := btDPool.Get().(*d) + if q.n != nil { + r.n = q.n + r.n.p = r + } else { + t.last = r + } + q.n = r + r.p = q + + copy(r.d[:], q.d[kd:2*kd]) + for i := range q.d[kd:] { + q.d[kd+i] = zde + } + q.c = kd + r.c = kd + var done bool + if i > kd { + done = true + t.insert(r, i-kd, k, v) + } + if pi >= 0 { + p.insert(pi, r.d[0].k, r) + } else { + t.r = newX(q).insert(0, r.d[0].k, r) + } + if done { + return + } + + t.insert(q, i, k, v) +} + +func (t *Tree) splitX(p *x, q *x, pi int, i int) (*x, int) { + t.ver++ + r := btXPool.Get().(*x) + copy(r.x[:], q.x[kx+1:]) + q.c = kx + r.c = kx + if pi >= 0 { + p.insert(pi, q.x[kx].k, r) + q.x[kx].k = zk + for i := range q.x[kx+1:] { + q.x[kx+i+1] = zxe + } + + switch { + case i < kx: + return q, i + case i == kx: + return p, pi + default: // i > kx + return r, i - kx - 1 + } + } + + nr := newX(q).insert(0, q.x[kx].k, r) + t.r = nr + q.x[kx].k = zk + for i := range q.x[kx+1:] { + q.x[kx+i+1] = zxe + } + + switch { + case i < kx: + return q, i + case i == kx: + return nr, 0 + default: // i > kx + return r, i - kx - 1 + } +} + +func (t *Tree) underflow(p *x, q *d, pi int) { + t.ver++ + l, r := p.siblings(pi) + + if l != nil && l.c+q.c >= 2*kd { + l.mvR(q, 1) + p.x[pi-1].k = q.d[0].k + return + } + + if r != nil && q.c+r.c >= 2*kd { + q.mvL(r, 1) + p.x[pi].k = r.d[0].k + r.d[r.c] = zde // GC + return + } + + if l != nil { + t.cat(p, l, q, pi-1) + return + } + + t.cat(p, q, r, pi) +} + +func (t *Tree) underflowX(p *x, q *x, pi int, i int) (*x, int) { + t.ver++ + var l, r *x + + if pi >= 0 { + if pi > 0 { + l = p.x[pi-1].ch.(*x) + } + if pi < p.c { + r = p.x[pi+1].ch.(*x) + } + } + + if l != nil && l.c > kx { + q.x[q.c+1].ch = q.x[q.c].ch + copy(q.x[1:], q.x[:q.c]) + q.x[0].ch = l.x[l.c].ch + q.x[0].k = p.x[pi-1].k + q.c++ + i++ + l.c-- + p.x[pi-1].k = l.x[l.c].k + return q, i + } + + if r != nil && r.c > kx { + q.x[q.c].k = p.x[pi].k + q.c++ + q.x[q.c].ch = r.x[0].ch + p.x[pi].k = r.x[0].k + copy(r.x[:], r.x[1:r.c]) + r.c-- + rc := r.c + r.x[rc].ch = r.x[rc+1].ch + r.x[rc].k = zk + r.x[rc+1].ch = nil + return q, i + } + + if l != nil { + i += l.c + 1 + t.catX(p, l, q, pi-1) + q = l + return q, i + } + + t.catX(p, q, r, pi) + return q, i +} + +// ----------------------------------------------------------------- Enumerator + +// Close recycles e to a pool for possible later reuse. No references to e +// should exist or such references must not be used afterwards. +func (e *Enumerator) Close() { + *e = ze + btEPool.Put(e) +} + +// Next returns the currently enumerated item, if it exists and moves to the +// next item in the key collation order. If there is no item to return, err == +// io.EOF is returned. +func (e *Enumerator) Next() (k int, v int, err error) { + if err = e.err; err != nil { + return + } + + if e.ver != e.t.ver { + f, hit := e.t.Seek(e.k) + if !e.hit && hit { + if err = f.next(); err != nil { + return + } + } + + *e = *f + f.Close() + } + if e.q == nil { + e.err, err = io.EOF, io.EOF + return + } + + if e.i >= e.q.c { + if err = e.next(); err != nil { + return + } + } + + i := e.q.d[e.i] + k, v = i.k, i.v + e.k, e.hit = k, false + e.next() + return +} + +func (e *Enumerator) next() error { + if e.q == nil { + e.err = io.EOF + return io.EOF + } + + switch { + case e.i < e.q.c-1: + e.i++ + default: + if e.q, e.i = e.q.n, 0; e.q == nil { + e.err = io.EOF + } + } + return e.err +} + +// Prev returns the currently enumerated item, if it exists and moves to the +// previous item in the key collation order. If there is no item to return, err +// == io.EOF is returned. +func (e *Enumerator) Prev() (k int, v int, err error) { + if err = e.err; err != nil { + return + } + + if e.ver != e.t.ver { + f, hit := e.t.Seek(e.k) + if !e.hit && hit { + if err = f.prev(); err != nil { + return + } + } + + *e = *f + f.Close() + } + if e.q == nil { + e.err, err = io.EOF, io.EOF + return + } + + if e.i >= e.q.c { + if err = e.next(); err != nil { + return + } + } + + i := e.q.d[e.i] + k, v = i.k, i.v + e.k, e.hit = k, false + e.prev() + return +} + +func (e *Enumerator) prev() error { + if e.q == nil { + e.err = io.EOF + return io.EOF + } + + switch { + case e.i > 0: + e.i-- + default: + if e.q = e.q.p; e.q == nil { + e.err = io.EOF + break + } + + e.i = e.q.c - 1 + } + return e.err +} diff --git a/vendor/github.com/cznic/bufs/LICENSE b/vendor/github.com/cznic/bufs/LICENSE new file mode 100644 index 00000000..7d80fe28 --- /dev/null +++ b/vendor/github.com/cznic/bufs/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2014 The bufs Authors. 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 names of the authors nor the names of the +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/vendor/github.com/cznic/bufs/bufs.go b/vendor/github.com/cznic/bufs/bufs.go new file mode 100644 index 00000000..f4e0eee2 --- /dev/null +++ b/vendor/github.com/cznic/bufs/bufs.go @@ -0,0 +1,391 @@ +// Copyright 2014 The bufs 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 bufs implements a simple buffer cache. +// +// The intended use scheme is like: +// +// type Foo struct { +// buffers bufs.Buffers +// ... +// } +// +// // Bar can call Qux, but not the other way around (in this example). +// const maxFooDepth = 2 +// +// func NewFoo() *Foo { +// return &Foo{buffers: bufs.New(maxFooDepth), ...} +// } +// +// func (f *Foo) Bar(n int) { +// buf := f.buffers.Alloc(n) // needed locally for computation and/or I/O +// defer f.buffers.Free() +// ... +// f.Qux(whatever) +// } +// +// func (f *Foo) Qux(n int) { +// buf := f.buffers.Alloc(n) // needed locally for computation and/or I/O +// defer f.buffers.Free() +// ... +// } +// +// The whole idea behind 'bufs' is that when calling e.g. Foo.Bar N times, then +// normally, without using 'bufs', there will be 2*N (in this example) []byte +// buffers allocated. While using 'bufs', only 2 buffers (in this example) +// will ever be created. For large N it can be a substantial difference. +// +// It's not a good idea to use Buffers to cache too big buffers. The cost of +// having a cached buffer is that the buffer is naturally not eligible for +// garbage collection. Of course, that holds only while the Foo instance is +// reachable, in the above example. +// +// The buffer count limit is intentionally "hard" (read panicking), although +// configurable in New(). The rationale is to prevent recursive calls, using +// Alloc, to cause excessive, "static" memory consumption. Tune the limit +// carefully or do not use Buffers from within [mutually] recursive functions +// where the nesting depth is not realistically bounded to some rather small +// number. +// +// Buffers cannot guarantee improvements to you program performance. There may +// be a gain in case where they fit well. Firm grasp on what your code is +// actually doing, when and in what order is essential to proper use of +// Buffers. It's _highly_ recommended to first do profiling and memory +// profiling before even thinking about using 'bufs'. The real world example, +// and cause for this package, was a first correct, yet no optimizations done +// version of a program; producing few MB of useful data while allocating 20+GB +// of memory. Of course the garbage collector properly kicked in, yet the +// memory abuse caused ~80+% of run time to be spent memory management. The +// program _was_ expected to be slow in its still development phase, but the +// bottleneck was guessed to be in I/O. Actually the hard disk was waiting for +// the billions bytes being allocated and zeroed. Garbage collect on low +// memory, rinse and repeat. +// +// In the provided tests, TestFoo and TestFooBufs do the same simulated work, +// except the later uses Buffers while the former does not. Suggested test runs +// which show the differences: +// +// $ go test -bench . -benchmem +// +// or +// +// $ go test -c +// $ ./bufs.test -test.v -test.run Foo -test.memprofile mem.out -test.memprofilerate 1 +// $ go tool pprof bufs.test mem.out --alloc_space --nodefraction 0.0001 --edgefraction 0 -web +// $ # Note: Foo vs FooBufs allocated memory is in hundreds of MBs vs 8 kB. +// +// or +// +// $ make demo # same as all of the above +// +// +// NOTE: Alloc/Free calls must be properly nested in the same way as in for +// example BeginTransaction/EndTransaction pairs. If your code can panic then +// the pairing should be enforced by deferred calls. +// +// NOTE: Buffers objects do not allocate any space until requested by Alloc, +// the mechanism works on demand only. +// +// FAQ: Why the 'bufs' package name? +// +// Package name 'bufs' was intentionally chosen instead of the perhaps more +// conventional 'buf'. There are already too many 'buf' named things in the +// code out there and that'll be a source of a lot of trouble. It's a bit +// similar situation as in the case of package "strings" (not "string"). +package bufs + +import ( + "errors" + "sort" + "sync" +) + +// Buffers type represents a buffer ([]byte) cache. +// +// NOTE: Do not modify Buffers directly, use only its methods. Do not create +// additional values (copies) of Buffers, that'll break its functionality. Use +// a pointer instead to refer to a single instance from different +// places/scopes. +type Buffers [][]byte + +// New returns a newly created instance of Buffers with a maximum capacity of n +// buffers. +// +// NOTE: 'bufs.New(n)' is the same as 'make(bufs.Buffers, n)'. +func New(n int) Buffers { + return make(Buffers, n) +} + +// Alloc will return a buffer such that len(r) == n. It will firstly try to +// find an existing and unused buffer of big enough size. Only when there is no +// such, then one of the buffer slots is reallocated to a bigger size. +// +// It's okay to use append with buffers returned by Alloc. But it can cause +// allocation in that case and will again be producing load for the garbage +// collector. The best use of Alloc is for I/O buffers where the needed size of +// the buffer is figured out at some point of the code path in a 'final size' +// sense. Another real world example are compression/decompression buffers. +// +// NOTE: The buffer returned by Alloc _is not_ zeroed. That's okay for e.g. +// passing a buffer to io.Reader. If you need a zeroed buffer use Calloc. +// +// NOTE: Buffers returned from Alloc _must not_ be exposed/returned to your +// clients. Those buffers are intended to be used strictly internally, within +// the methods of some "object". +// +// NOTE: Alloc will panic if there are no buffers (buffer slots) left. +func (p *Buffers) Alloc(n int) (r []byte) { + b := *p + if len(b) == 0 { + panic(errors.New("Buffers.Alloc: out of buffers")) + } + + biggest, best, biggestI, bestI := -1, -1, -1, -1 + for i, v := range b { + //ln := len(v) + // The above was correct, buts it's just confusing. It worked + // because not the buffers, but slices of them are returned in + // the 'if best >= n' code path. + ln := cap(v) + + if ln >= biggest { + biggest, biggestI = ln, i + } + + if ln >= n && (bestI < 0 || best > ln) { + best, bestI = ln, i + if ln == n { + break + } + } + } + + last := len(b) - 1 + if best >= n { + r = b[bestI] + b[last], b[bestI] = b[bestI], b[last] + *p = b[:last] + return r[:n] + } + + r = make([]byte, n, overCommit(n)) + b[biggestI] = r + b[last], b[biggestI] = b[biggestI], b[last] + *p = b[:last] + return +} + +// Calloc will acquire a buffer using Alloc and then clears it to zeros. The +// zeroing goes up to n, not cap(r). +func (p *Buffers) Calloc(n int) (r []byte) { + r = p.Alloc(n) + for i := range r { + r[i] = 0 + } + return +} + +// Free makes the lastly allocated by Alloc buffer free (available) again for +// Alloc. +// +// NOTE: Improper Free invocations, like in the sequence {New, Alloc, Free, +// Free}, will panic. +func (p *Buffers) Free() { + b := *p + b = b[:len(b)+1] + *p = b +} + +// Stats reports memory consumed by Buffers, without accounting for some +// (smallish) additional overhead. +func (p *Buffers) Stats() (bytes int) { + b := *p + b = b[:cap(b)] + for _, v := range b { + bytes += cap(v) + } + return +} + +// Cache caches buffers ([]byte). A zero value of Cache is ready for use. +// +// NOTE: Do not modify a Cache directly, use only its methods. Do not create +// additional values (copies) of a Cache, that'll break its functionality. Use +// a pointer instead to refer to a single instance from different +// places/scopes. +type Cache [][]byte + +// Get returns a buffer ([]byte) of length n. If no such buffer is cached then +// a biggest cached buffer is resized to have length n and returned. If there +// are no cached items at all, Get returns a newly allocated buffer. +// +// In other words the cache policy is: +// +// - If the cache is empty, the buffer must be newly created and returned. +// Cache remains empty. +// +// - If a buffer of sufficient size is found in the cache, remove it from the +// cache and return it. +// +// - Otherwise the cache is non empty, but no cached buffer is big enough. +// Enlarge the biggest cached buffer, remove it from the cache and return it. +// This provide cached buffers size adjustment based on demand. +// +// In short, if the cache is not empty, Get guarantees to make it always one +// item less. This rules prevent uncontrolled cache grow in some scenarios. +// The older policy was not preventing that. Another advantage is better cached +// buffers sizes "auto tuning", although not in every possible use case. +// +// NOTE: The buffer returned by Get _is not guaranteed_ to be zeroed. That's +// okay for e.g. passing a buffer to io.Reader. If you need a zeroed buffer +// use Cget. +func (c *Cache) Get(n int) []byte { + r, _ := c.get(n) + return r +} + +func (c *Cache) get(n int) (r []byte, isZeroed bool) { + s := *c + lens := len(s) + if lens == 0 { + r, isZeroed = make([]byte, n, overCommit(n)), true + return + } + + i := sort.Search(lens, func(x int) bool { return len(s[x]) >= n }) + if i == lens { + i-- + s[i] = make([]byte, n, overCommit(n)) + } + r = s[i][:n] + copy(s[i:], s[i+1:]) + s[lens-1] = nil + s = s[:lens-1] + *c = s + return r, false +} + +// Cget will acquire a buffer using Get and then clears it to zeros. The +// zeroing goes up to n, not cap(r). +func (c *Cache) Cget(n int) (r []byte) { + r, ok := c.get(n) + if ok { + return + } + + for i := range r { + r[i] = 0 + } + return +} + +// Put caches b for possible later reuse (via Get). No other references to b's +// backing array may exist. Otherwise a big mess is sooner or later inevitable. +func (c *Cache) Put(b []byte) { + b = b[:cap(b)] + lenb := len(b) + if lenb == 0 { + return + } + + s := *c + lens := len(s) + i := sort.Search(lens, func(x int) bool { return len(s[x]) >= lenb }) + s = append(s, nil) + copy(s[i+1:], s[i:]) + s[i] = b + *c = s + return +} + +// Stats reports memory consumed by a Cache, without accounting for some +// (smallish) additional overhead. 'n' is the number of cached buffers, bytes +// is their combined capacity. +func (c Cache) Stats() (n, bytes int) { + n = len(c) + for _, v := range c { + bytes += cap(v) + } + return +} + +// CCache is a Cache which is safe for concurrent use by multiple goroutines. +type CCache struct { + c Cache + mu sync.Mutex +} + +// Get returns a buffer ([]byte) of length n. If no such buffer is cached then +// a biggest cached buffer is resized to have length n and returned. If there +// are no cached items at all, Get returns a newly allocated buffer. +// +// In other words the cache policy is: +// +// - If the cache is empty, the buffer must be newly created and returned. +// Cache remains empty. +// +// - If a buffer of sufficient size is found in the cache, remove it from the +// cache and return it. +// +// - Otherwise the cache is non empty, but no cached buffer is big enough. +// Enlarge the biggest cached buffer, remove it from the cache and return it. +// This provide cached buffers size adjustment based on demand. +// +// In short, if the cache is not empty, Get guarantees to make it always one +// item less. This rules prevent uncontrolled cache grow in some scenarios. +// The older policy was not preventing that. Another advantage is better cached +// buffers sizes "auto tuning", although not in every possible use case. +// +// NOTE: The buffer returned by Get _is not guaranteed_ to be zeroed. That's +// okay for e.g. passing a buffer to io.Reader. If you need a zeroed buffer +// use Cget. +func (c *CCache) Get(n int) []byte { + c.mu.Lock() + r, _ := c.c.get(n) + c.mu.Unlock() + return r +} + +// Cget will acquire a buffer using Get and then clears it to zeros. The +// zeroing goes up to n, not cap(r). +func (c *CCache) Cget(n int) (r []byte) { + c.mu.Lock() + r = c.c.Cget(n) + c.mu.Unlock() + return +} + +// Put caches b for possible later reuse (via Get). No other references to b's +// backing array may exist. Otherwise a big mess is sooner or later inevitable. +func (c *CCache) Put(b []byte) { + c.mu.Lock() + c.c.Put(b) + c.mu.Unlock() +} + +// Stats reports memory consumed by a Cache, without accounting for some +// (smallish) additional overhead. 'n' is the number of cached buffers, bytes +// is their combined capacity. +func (c *CCache) Stats() (n, bytes int) { + c.mu.Lock() + n, bytes = c.c.Stats() + c.mu.Unlock() + return +} + +// GCache is a ready to use global instance of a CCache. +var GCache CCache + +func overCommit(n int) int { + switch { + case n < 8: + return 8 + case n < 1e5: + return 2 * n + case n < 1e6: + return 3 * n / 2 + default: + return n + } +} diff --git a/vendor/github.com/cznic/fileutil/LICENSE b/vendor/github.com/cznic/fileutil/LICENSE new file mode 100644 index 00000000..50bbdd24 --- /dev/null +++ b/vendor/github.com/cznic/fileutil/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2014 The fileutil Authors. 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 names of the authors nor the names of the +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/vendor/github.com/cznic/fileutil/falloc/docs.go b/vendor/github.com/cznic/fileutil/falloc/docs.go new file mode 100644 index 00000000..21772fcd --- /dev/null +++ b/vendor/github.com/cznic/fileutil/falloc/docs.go @@ -0,0 +1,251 @@ +// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// blame: jnml, labs.nic.cz + +/* + +WIP: Package falloc provides allocation/deallocation of space within a +file/store (WIP, unstable API). + +Overall structure: + File == n blocks. + Block == n atoms. + Atom == 16 bytes. + +x6..x0 == least significant 7 bytes of a 64 bit integer, highest (7th) byte is +0 and is not stored in the file. + +Block first byte + +Aka block type tag. + +------------------------------------------------------------------------------ + +0xFF: Free atom (free block of size 1). + +------++---------++---------++------+ + | 0 || 1...7 || 8...14 || 15 | + +------++---------++---------++------+ + | 0xFF || p6...p0 || n6...n0 || 0xFF | + +------++---------++---------++------+ + +Link to the previous free block (atom addressed) is p6...p0, next dtto in +n6...n0. Doubly linked lists of "compatible" free blocks allows for free space +reclaiming and merging. "Compatible" == of size at least some K. Heads of all +such lists are organized per K or intervals of Ks elsewhere. + +------------------------------------------------------------------------------ + +0xFE: Free block, size == s6...s0 atoms. + +------++---------++---------++---------++-- + | +0 || 1...7 || 8...14 || 15...21 || 22...16*size-1 + +------++---------++---------++---------++-- + | 0xFE || p6...p0 || n6...n0 || s6...s0 || ... + +------++---------++---------++---------++-- + +Prev and next links as in the 0xFF first byte case. End of this block - see +"Block last byte": 0xFE bellow. Data between == undefined. + +------------------------------------------------------------------------------ + +0xFD: Relocated block. + +------++---------++-----------++------+ + | 0 || 1...7 || 8...14 || 15 | + +------++---------++-----------++------+ + | 0xFD || r6...r0 || undefined || 0x00 | // == used block + +------++---------++-----------++------+ + +Relocation link is r6..r0 == atom address. Relocations MUST NOT chain and MUST +point to a "content" block, i.e. one with the first byte in 0x00...0xFC. + +Relocated block allows to permanently assign a handle/file pointer ("atom" +address) to some content and resize the content anytime afterwards w/o having +to update all the possible existing references to the original handle. + +------------------------------------------------------------------------------ + +0xFC: Used long block. + +------++---------++--------------------++---------+---+ + | 0 || 1...2 || 3...N+2 || | | + +------++---------++--------------------++---------+---+ + | 0xFC || n1...n0 || N bytes of content || padding | Z | + +------++---------++--------------------++---------+---+ + +This block type is used for content of length in N == 238...61680 bytes. N is +encoded as a 2 byte unsigned integer n1..n0 in network byte order. Values +bellow 238 are reserved, those content lengths are to be carried by the +0x00..0xFB block types. + + 1. n in 0x00EE...0xF0F0 is used for content under the same rules + as in the 0x01..0xED type. + + 2. If the last byte of the content is not the last byte of an atom then + the last byte of the block is 0x00. + + 3. If the last byte of the content IS the last byte of an atom: + + 3.1 If the last byte of content is in 0x00..0xFD then everything is OK. + + 3.2 If the last byte of content is 0xFE or 0xFF then the escape + via n > 0xF0F0 MUST be used AND the block's last byte is 0x00 or 0x01, + meaning value 0xFE and 0xFF respectively. + + 4. n in 0xF0F1...0xFFFF is like the escaped 0xEE..0xFB block. + N == 13 + 16(n - 0xF0F1). + +Discussion of the padding and Z fields - see the 0x01..0xED block type. + +------------------------------------------------------------------------------ + +0xEE...0xFB: Used escaped short block. + +---++----------------------++---+ + | 0 || 1...N-1 || | + +---++----------------------++---+ + | X || N-1 bytes of content || Z | + +---++----------------------++---+ + +N == 15 + 16(X - 0xEE). Z is the content last byte encoded as follows. + +case Z == 0x00: The last byte of content is 0xFE + +case Z == 0x01: The last byte of content is 0xFF + +------------------------------------------------------------------------------ + +0x01...0xED: Used short block. + +---++--------------------++---------+---+ + | 0 || 1...N || | | + +---++--------------------++---------+---+ + | N || N bytes of content || padding | Z | + +---++--------------------++---------+---+ + +This block type is used for content of length in 1...237 bytes. The value of +the "padding" field, if of non zero length, is undefined. + +If the last byte of content is the last byte of an atom (== its file byte +offset & 0xF == 0xF) then such last byte MUST be in 0x00...0xFD. + +If the last byte of content is the last byte of an atom AND the last byte of +content is 0xFE or 0xFF then the short escape block type (0xEE...0xFB) MUST be +used. + +If the last byte of content is not the last byte of an atom, then the last byte +of such block, i.e. the Z field, which is also a last byte of some atom, MUST +be 0x00 (i.e. the used block marker). Other "tail" values are reserved. + +------------------------------------------------------------------------------ + +0x00: Used empty block. + +------++-----------++------+ + | 0 || 1...14 || 15 | + +------++-----------++------+ + | 0x00 || undefined || 0x00 | // == used block, other "tail" values reserved. + +------++-----------++------+ + +All of the rules for 0x01..0xED applies. Depicted only for its different +semantics (e.g. an allocated [existing] string but with length of zero). + +============================================================================== + +Block last byte + +------------------------------------------------------------------------------ + +0xFF: Free atom. Layout - see "Block first byte": FF. + +------------------------------------------------------------------------------ + +0xFE: Free block, size n atoms. Preceding 7 bytes == size (s6...s0) of the free +block in atoms, network byte order + --++---------++------+ + || -8...-2 || -1 | + --++---------++------+ + ... || s6...s0 || 0xFE | <- block's last byte + --++---------++------+ + +Layout at start of this block - see "Block first byte": FE. + +------------------------------------------------------------------------------ + +0x00...0xFD: Used (non free) block. + +============================================================================== + +Free lists table + +The free lists table content is stored in the standard layout of a used block. + +A table item is a 7 byte size field followed by a 7 byte atom address field +(both in network byte order), thus every item is 14 contiguous bytes. The +item's address field is pointing to a free block. The size field determines +the minimal size (in atoms) of free blocks on that list. + +The free list table is n above items, thus the content has 14n bytes. Note that +the largest block content is 61680 bytes and as there are 14 bytes per table +item, so the table is limited to at most 4405 entries. + +Items in the table do not have to be sorted according to their size field values. + +No two items can have the same value of the size field. + +When freeing blocks, the block MUST be linked into an item list with the +highest possible size field, which is less or equal to the number of atoms in +the new free block. + +When freeing a block, the block MUST be first merged with any adjacent free +blocks (thus possibly creating a bigger free block) using information derived +from the adjacent blocks first and last bytes. Such merged free blocks MUST be +removed from their original doubly linked lists. Afterwards the new bigger free +block is put to the free list table in the appropriate item. + +Items with address field == 0 are legal. Such item is a placeholder for a empty +list of free blocks of the item's size. + +Items with size field == 0 are legal. Such item is a placeholder, used e.g. to +avoid further reallocations/redirecting of the free lists table. + +The largest possible allocation request (for content length 61680 bytes) is +0xF10 (3856) atoms. All free blocks of this or bigger size are presumably put +into a single table item with the size 3856. It may be useful to additionally +have a free lists table item which links free blocks of some bigger size (say +1M+) and then use the OS sparse file support (if present) to save the physical +space used by such free blocks. + +Smaller (<3856 atoms) free blocks can be organized exactly (every distinct size +has its table item) or the sizes can run using other schema like e.g. "1, 2, +4, 8, ..." (powers of 2) or "1, 2, 3, 5, 8, 13, ..." (the Fibonacci sequence) +or they may be fine tuned to a specific usage pattern. + +============================================================================== + +Header + +The first block of a file (atom address == file offset == 0) is the file header. +The header block has the standard layout of a used short non escaped block. + +Special conditions apply: The header block and its content MUST be like this: + + +------+---------+---------+------+ + | 0 | 1...7 | 8...14 | 15 | + +------+---------+---------+------+ + | 0x0F | m6...m0 | f6...f0 | FLTT | + +------+---------+---------+------+ + +m6..m0 is a "magic" value 0xF1C1A1FE51B1E. + +f6...f0 is the atom address of the free lists table (discussed elsewhere). +If f6...f0 == 0x00 the there is no free lists table (yet). + +FLTT describes the type of the Free List Table. Currently defined values: + +------------------------------------------------------------------------------ + +FLTT == 0: Free List Table is fixed at atom address 2. It has a fixed size for 3856 entries +for free list of size 1..3855 atoms and the last is for the list of free block >= 3856 atoms. +*/ +package falloc + +const ( + INVALID_HANDLE = Handle(-1) +) diff --git a/vendor/github.com/cznic/fileutil/falloc/error.go b/vendor/github.com/cznic/fileutil/falloc/error.go new file mode 100644 index 00000000..dad3d29e --- /dev/null +++ b/vendor/github.com/cznic/fileutil/falloc/error.go @@ -0,0 +1,130 @@ +// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// blame: jnml, labs.nic.cz + +package falloc + +import "fmt" + +// EBadRequest is an error produced for invalid operation, e.g. for data of more than maximum allowed. +type EBadRequest struct { + Name string + Size int +} + +func (e *EBadRequest) Error() string { + return fmt.Sprintf("%s: size %d", e.Name, e.Size) +} + +// EClose is a file/store close error. +type EClose struct { + Name string + Err error +} + +func (e *EClose) Error() string { + return fmt.Sprintf("%sx: %s", e.Name, e.Err) +} + +// ECorrupted is a file/store format error. +type ECorrupted struct { + Name string + Ofs int64 +} + +func (e *ECorrupted) Error() string { + return fmt.Sprintf("%s: corrupted data @%#x", e.Name, e.Ofs) +} + +// ECreate is a file/store create error. +type ECreate struct { + Name string + Err error +} + +func (e *ECreate) Error() string { + return fmt.Sprintf("%s: %s", e.Name, e.Err) +} + +// EFreeList is a file/store format error. +type EFreeList struct { + Name string + Size int64 + Block int64 +} + +func (e *EFreeList) Error() string { + return fmt.Sprintf("%s: invalid free list item, size %#x, block %#x", e.Name, e.Size, e.Block) +} + +// EHandle is an error type reported for invalid Handles. +type EHandle struct { + Name string + Handle Handle +} + +func (e EHandle) Error() string { + return fmt.Sprintf("%s: invalid handle %#x", e.Name, e.Handle) +} + +// EHeader is a file/store format error. +type EHeader struct { + Name string + Header []byte + Expected []byte +} + +func (e *EHeader) Error() string { + return fmt.Sprintf("%s: invalid header, got [% x], expected [% x]", e.Name, e.Header, e.Expected) +} + +// ENullHandle is a file/store access error via a null handle. +type ENullHandle string + +func (e ENullHandle) Error() string { + return fmt.Sprintf("%s: access via null handle", e) +} + +// EOpen is a file/store open error. +type EOpen struct { + Name string + Err error +} + +func (e *EOpen) Error() string { + return fmt.Sprintf("%s: %s", e.Name, e.Err) +} + +// ERead is a file/store read error. +type ERead struct { + Name string + Ofs int64 + Err error +} + +func (e *ERead) Error() string { + return fmt.Sprintf("%s, %#x: %s", e.Name, e.Ofs, e.Err) +} + +// ESize is a file/store size error. +type ESize struct { + Name string + Size int64 +} + +func (e *ESize) Error() string { + return fmt.Sprintf("%s: invalid size %#x(%d), size %%16 != 0", e.Name, e.Size, e.Size) +} + +// EWrite is a file/store write error. +type EWrite struct { + Name string + Ofs int64 + Err error +} + +func (e *EWrite) Error() string { + return fmt.Sprintf("%s, %#x: %s", e.Name, e.Ofs, e.Err) +} diff --git a/vendor/github.com/cznic/fileutil/falloc/falloc.go b/vendor/github.com/cznic/fileutil/falloc/falloc.go new file mode 100644 index 00000000..066a7047 --- /dev/null +++ b/vendor/github.com/cznic/fileutil/falloc/falloc.go @@ -0,0 +1,676 @@ +// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// blame: jnml, labs.nic.cz + +/* + +This is an mostly (WIP) conforming implementation of the "specs" in docs.go. + +The main incompletness is support for only one kind of FTL, though this table kind is still per "specs". + +*/ + +package falloc + +import ( + "bytes" + "github.com/cznic/fileutil/storage" + "sync" +) + +// Handle is a reference to a block in a file/store. +// Handle is an uint56 wrapped in an in64, i.e. the most significant byte must be always zero. +type Handle int64 + +// Put puts the 7 least significant bytes of h into b. The MSB of h should be zero. +func (h Handle) Put(b []byte) { + for ofs := 6; ofs >= 0; ofs-- { + b[ofs] = byte(h) + h >>= 8 + } +} + +// Get gets the 7 least significant bytes of h from b. The MSB of h is zeroed. +func (h *Handle) Get(b []byte) { + var x Handle + for ofs := 0; ofs <= 6; ofs++ { + x = x<<8 | Handle(b[ofs]) + } + *h = x +} + +// File is a file/store with space allocation/deallocation support. +type File struct { + f storage.Accessor + atoms int64 // current file size in atom units + canfree int64 // only blocks >= canfree can be subject to Free() + freetab [3857]int64 // freetab[0] is unused, freetab[1] is size 1 ptr, freetab[2] is size 2 ptr, ... + rwm sync.RWMutex +} + +func (f *File) read(b []byte, off int64) { + if n, err := f.f.ReadAt(b, off); n != len(b) { + panic(&ERead{f.f.Name(), off, err}) + } +} + +func (f *File) write(b []byte, off int64) { + if n, err := f.f.WriteAt(b, off); n != len(b) { + panic(&EWrite{f.f.Name(), off, err}) + } +} + +var ( // R/O + hdr = []byte{0x0f, 0xf1, 0xc1, 0xa1, 0xfe, 0xa5, 0x1b, 0x1e, 0, 0, 0, 0, 0, 0, 2, 0} // free lists table @2 + empty = make([]byte, 16) + zero = []byte{0} + zero7 = make([]byte, 7) +) + +// New returns a new File backed by store or an error if any. +// Any existing data in store are discarded. +func New(store storage.Accessor) (f *File, err error) { + f = &File{f: store} + return f, storage.Mutate(store, func() (err error) { + if err = f.f.Truncate(0); err != nil { + return &ECreate{f.f.Name(), err} + } + + if _, err = f.Alloc(hdr[1:]); err != nil { //TODO internal panicking versions of the exported fns. + return + } + + if _, err = f.Alloc(nil); err != nil { // (empty) root @1 + return + } + + b := make([]byte, 3856*14) + for i := 1; i <= 3856; i++ { + Handle(i).Put(b[(i-1)*14:]) + } + if _, err = f.Alloc(b); err != nil { + return + } + + f.canfree = f.atoms + return + }) +} + +// Open returns a new File backed by store or an error if any. +// Store already has to be in a valid format. +func Open(store storage.Accessor) (f *File, err error) { + defer func() { + if e := recover(); e != nil { + f = nil + err = e.(error) + } + }() + + fi, err := store.Stat() + if err != nil { + panic(&EOpen{store.Name(), err}) + } + + fs := fi.Size() + if fs&0xf != 0 { + panic(&ESize{store.Name(), fi.Size()}) + } + + f = &File{f: store, atoms: fs >> 4} + b := make([]byte, len(hdr)) + f.read(b, 0) + if !bytes.Equal(b, hdr) { + panic(&EHeader{store.Name(), b, append([]byte{}, hdr...)}) + } + + var atoms int64 + b, atoms = f.readUsed(2) + f.canfree = atoms + 2 + ofs := 0 + var size, p Handle + for ofs < len(b) { + size.Get(b[ofs:]) + ofs += 7 + p.Get(b[ofs:]) + ofs += 7 + if sz, pp := int64(size), int64(p); size == 0 || size > 3856 || (pp != 0 && pp < f.canfree) || pp<<4 > fs-16 { + panic(&EFreeList{store.Name(), sz, pp}) + } + + f.freetab[size] = int64(p) + } + return +} + +// Accessor returns the File's underlying Accessor. +func (f *File) Accessor() storage.Accessor { + return f.f +} + +// Close closes f and returns an error if any. +func (f *File) Close() (err error) { + return storage.Mutate(f.Accessor(), func() (err error) { + if err = f.f.Close(); err != nil { + err = &EClose{f.f.Name(), err} + } + return + }) +} + +// Root returns the handle of the DB root (top level directory, ...). +func (f *File) Root() Handle { + return 1 +} + +func (f *File) readUsed(atom int64) (content []byte, atoms int64) { + b, redirected := make([]byte, 7), false +redir: + ofs := atom << 4 + f.read(b[:1], ofs) + switch pre := b[0]; { + default: + panic(&ECorrupted{f.f.Name(), ofs}) + case pre == 0x00: // Empty block + case pre >= 1 && pre <= 237: // Short + content = make([]byte, pre) + f.read(content, ofs+1) + case pre >= 0xee && pre <= 0xfb: // Short esc + content = make([]byte, 15+16*(pre-0xee)) + f.read(content, ofs+1) + content[len(content)-1] += 0xfe + case pre == 0xfc: // Long + f.read(b[:2], ofs+1) + n := int(b[0])<<8 + int(b[1]) + switch { + default: + panic(&ECorrupted{f.f.Name(), ofs + 1}) + case n >= 238 && n <= 61680: // Long non esc + content = make([]byte, n) + f.read(content, ofs+3) + case n >= 61681: // Long esc + content = make([]byte, 13+16*(n-0xf0f1)) + f.read(content, ofs+3) + content[len(content)-1] += 0xfe + } + case pre == 0xfd: // redir + if redirected { + panic(&ECorrupted{f.f.Name(), ofs}) + } + + f.read(b[:7], ofs+1) + (*Handle)(&atom).Get(b) + redirected = true + goto redir + } + return content, rq2Atoms(len(content)) +} + +func (f *File) writeUsed(b []byte, atom int64) { + n := len(b) + switch ofs, atoms, endmark := atom<<4, rq2Atoms(n), true; { + default: + panic("internal error") + case n == 0: + f.write(empty, ofs) + case n <= 237: + if (n+1)&0xf == 0 { // content end == atom end + if v := b[n-1]; v >= 0xfe { // escape + pre := []byte{byte((16*0xee + n - 15) >> 4)} + f.write(pre, ofs) + f.write(b[:n-1], ofs+1) + f.write([]byte{v - 0xfe}, ofs+atoms<<4-1) + return + } + endmark = false + } + // non esacpe + pre := []byte{byte(n)} + f.write(pre, ofs) + f.write(b, ofs+1) + if endmark { + f.write(zero, ofs+atoms<<4-1) // last block byte <- used block + } + case n > 237 && n <= 61680: + if (n+3)&0xf == 0 { // content end == atom end + if v := b[n-1]; v >= 0xfe { // escape + x := (16*0xf0f1 + n - 13) >> 4 + pre := []byte{0xFC, byte(x >> 8), byte(x)} + f.write(pre, ofs) + f.write(b[:n-1], ofs+3) + f.write([]byte{v - 0xfe}, ofs+atoms<<4-1) + return + } + endmark = false + } + // non esacpe + pre := []byte{0xfc, byte(n >> 8), byte(n)} + f.write(pre, ofs) + f.write(b, ofs+3) + if endmark { + f.write(zero, ofs+atoms<<4-1) // last block byte <- used block + } + } +} + +func rq2Atoms(rqbytes int) (rqatoms int64) { + if rqbytes > 237 { + rqbytes += 2 + } + return int64(rqbytes>>4 + 1) +} + +func (f *File) extend(b []byte) (handle int64) { + handle = f.atoms + f.writeUsed(b, handle) + f.atoms += rq2Atoms(len(b)) + return +} + +// Alloc stores b in a newly allocated space and returns its handle and an error if any. +func (f *File) Alloc(b []byte) (handle Handle, err error) { + err = storage.Mutate(f.Accessor(), func() (err error) { + rqAtoms := rq2Atoms(len(b)) + if rqAtoms > 3856 { + return &EBadRequest{f.f.Name(), len(b)} + } + + for foundsize, foundp := range f.freetab[rqAtoms:] { + if foundp != 0 { + // this works only for the current unique sizes list (except the last item!) + size := int64(foundsize) + rqAtoms + handle = Handle(foundp) + if size == 3856 { + buf := make([]byte, 7) + f.read(buf, int64(handle)<<4+15) + (*Handle)(&size).Get(buf) + } + f.delFree(int64(handle), size) + if rqAtoms < size { + f.addFree(int64(handle)+rqAtoms, size-rqAtoms) + } + f.writeUsed(b, int64(handle)) + return + } + } + + handle = Handle(f.extend(b)) + return + }) + return +} + +// checkLeft returns the atom size of a free bleck left adjacent to block @atom. +// If that block is not free the returned size is 0. +func (f *File) checkLeft(atom int64) (size int64) { + if atom <= f.canfree { + return + } + + b := make([]byte, 7) + fp := atom << 4 + f.read(b[:1], fp-1) + switch last := b[0]; { + case last <= 0xfd: + // used block + case last == 0xfe: + f.read(b, fp-8) + (*Handle)(&size).Get(b) + case last == 0xff: + size = 1 + } + return +} + +// getInfo returns the block @atom type and size. +func (f *File) getInfo(atom int64) (pref byte, size int64) { + b := make([]byte, 7) + fp := atom << 4 + f.read(b[:1], fp) + switch pref = b[0]; { + case pref == 0: // Empty used + size = 1 + case pref >= 1 && pref <= 237: // Short + size = rq2Atoms(int(pref)) + case pref >= 0xee && pref <= 0xfb: // Short esc + size = rq2Atoms(15 + 16*int(pref-0xee)) + case pref == 0xfc: // Long + f.read(b[:2], fp+1) + n := int(b[0])<<8 + int(b[1]) + switch { + default: + panic(&ECorrupted{f.f.Name(), fp + 1}) + case n >= 238 && n <= 61680: // Long non esc + size = rq2Atoms(n) + case n >= 61681: // Long esc + size = rq2Atoms(13 + 16*(n-0xf0f1)) + } + case pref == 0xfd: // reloc + size = 1 + case pref == 0xfe: + f.read(b, fp+15) + (*Handle)(&size).Get(b) + case pref == 0xff: + size = 1 + } + return +} + +// getSize returns the atom size of the block @atom and wheter it is free. +func (f *File) getSize(atom int64) (size int64, isFree bool) { + var typ byte + typ, size = f.getInfo(atom) + isFree = typ >= 0xfe + return +} + +// checkRight returns the atom size of a free bleck right adjacent to block @atom,atoms. +// If that block is not free the returned size is 0. +func (f *File) checkRight(atom, atoms int64) (size int64) { + if atom+atoms >= f.atoms { + return + } + + if sz, free := f.getSize(atom + atoms); free { + size = sz + } + return +} + +// delFree removes the atoms@atom free block from the free block list +func (f *File) delFree(atom, atoms int64) { + b := make([]byte, 15) + size := int(atoms) + if n := len(f.freetab); atoms >= int64(n) { + size = n - 1 + } + fp := atom << 4 + f.read(b[1:], fp+1) + var prev, next Handle + prev.Get(b[1:]) + next.Get(b[8:]) + + switch { + case prev == 0 && next != 0: + next.Put(b) + f.write(b[:7], int64(32+3+7+(size-1)*14)) + f.write(zero7, int64(next)<<4+1) + f.freetab[size] = int64(next) + case prev != 0 && next == 0: + f.write(zero7, int64(prev)<<4+8) + case prev != 0 && next != 0: + prev.Put(b) + f.write(b[:7], int64(next)<<4+1) + next.Put(b) + f.write(b[:7], int64(prev)<<4+8) + default: // prev == 0 && next == 0: + f.write(zero7, int64(32+3+7+(size-1)*14)) + f.freetab[size] = 0 + } +} + +// addFree adds atoms@atom to the free block lists and marks it free. +func (f *File) addFree(atom, atoms int64) { + b := make([]byte, 7) + size := int(atoms) + if n := len(f.freetab); atoms >= int64(n) { + size = n - 1 + } + head := f.freetab[size] + if head == 0 { // empty list + f.makeFree(0, atom, atoms, 0) + Handle(atom).Put(b) + f.write(b, int64(32+3+7+(size-1)*14)) + f.freetab[size] = atom + return + } + + Handle(atom).Put(b) + f.write(b, head<<4+1) // head.prev = atom + f.makeFree(0, atom, atoms, head) // atom.next = head + f.write(b, int64(32+3+7+(size-1)*14)) + f.freetab[size] = atom +} + +// makeFree sets up the content of a free block atoms@atom, fills the prev and next links. +func (f *File) makeFree(prev, atom, atoms, next int64) { + b := make([]byte, 23) + fp := atom << 4 + if atoms == 1 { + b[0] = 0xff + Handle(prev).Put(b[1:]) + Handle(next).Put(b[8:]) + b[15] = 0xff + f.write(b[:16], fp) + return + } + + b[0] = 0xfe + Handle(prev).Put(b[1:]) + Handle(next).Put(b[8:]) + Handle(atoms).Put(b[15:]) + f.write(b[:22], fp) + b[22] = 0xfe + f.write(b[15:], fp+atoms<<4-8) +} + +// Read reads and return the data associated with handle and an error if any. +// Passing an invalid handle to Read may return invalid data without error. +// It's like getting garbage via passing an invalid pointer to C.memcopy(). +func (f *File) Read(handle Handle) (b []byte, err error) { + defer func() { + if e := recover(); e != nil { + b = nil + err = e.(error) + } + }() + + switch handle { + case 0: + panic(ENullHandle(f.f.Name())) + case 2: + panic(&EHandle{f.f.Name(), handle}) + default: + b, _ = f.readUsed(int64(handle)) + } + return +} + +// Free frees space associated with handle and returns an error if any. Passing an invalid +// handle to Free or reusing handle afterwards will probably corrupt the database or provide +// invalid data on Read. It's like corrupting memory via passing an invalid pointer to C.free() +// or reusing that pointer. +func (f *File) Free(handle Handle) (err error) { + return storage.Mutate(f.Accessor(), func() (err error) { + atom := int64(handle) + atoms, isFree := f.getSize(atom) + if isFree || atom < f.canfree { + return &EHandle{f.f.Name(), handle} + } + + leftFree, rightFree := f.checkLeft(atom), f.checkRight(atom, atoms) + switch { + case leftFree != 0 && rightFree != 0: + f.delFree(atom-leftFree, leftFree) + f.delFree(atom+atoms, rightFree) + f.addFree(atom-leftFree, leftFree+atoms+rightFree) + case leftFree != 0 && rightFree == 0: + f.delFree(atom-leftFree, leftFree) + if atom+atoms == f.atoms { // the left free neighbour and this block together are an empy tail + f.atoms = atom - leftFree + f.f.Truncate(f.atoms << 4) + return + } + + f.addFree(atom-leftFree, leftFree+atoms) + case leftFree == 0 && rightFree != 0: + f.delFree(atom+atoms, rightFree) + f.addFree(atom, atoms+rightFree) + default: // leftFree == 0 && rightFree == 0 + if atom+atoms < f.atoms { // isolated inner block + f.addFree(atom, atoms) + return + } + + f.f.Truncate(atom << 4) // isolated tail block, shrink file + f.atoms = atom + } + return + }) +} + +// Realloc reallocates space associted with handle to acomodate b, returns the newhandle +// newly associated with b and an error if any. If keepHandle == true then Realloc guarantees +// newhandle == handle even if the new data are larger then the previous content associated +// with handle. If !keepHandle && newhandle != handle then reusing handle will probably corrupt +// the database. +// The above effects are like corrupting memory/data via passing an invalid pointer to C.realloc(). +func (f *File) Realloc(handle Handle, b []byte, keepHandle bool) (newhandle Handle, err error) { + err = storage.Mutate(f.Accessor(), func() (err error) { + switch handle { + case 0, 2: + return &EHandle{f.f.Name(), handle} + case 1: + keepHandle = true + } + newhandle = handle + atom, newatoms := int64(handle), rq2Atoms(len(b)) + if newatoms > 3856 { + return &EBadRequest{f.f.Name(), len(b)} + } + + typ, oldatoms := f.getInfo(atom) + switch { + default: + return &ECorrupted{f.f.Name(), atom << 4} + case typ <= 0xfc: // non relocated used block + switch { + case newatoms == oldatoms: // in place replace + f.writeUsed(b, atom) + case newatoms < oldatoms: // in place shrink + rightFree := f.checkRight(atom, oldatoms) + if rightFree > 0 { // right join + f.delFree(atom+oldatoms, rightFree) + } + f.addFree(atom+newatoms, oldatoms+rightFree-newatoms) + f.writeUsed(b, atom) + case newatoms > oldatoms: + if rightFree := f.checkRight(atom, oldatoms); rightFree > 0 && newatoms <= oldatoms+rightFree { + f.delFree(atom+oldatoms, rightFree) + if newatoms < oldatoms+rightFree { + f.addFree(atom+newatoms, oldatoms+rightFree-newatoms) + } + f.writeUsed(b, atom) + return + } + + if !keepHandle { + f.Free(Handle(atom)) + newhandle, err = f.Alloc(b) + return + } + + // reloc + newatom, e := f.Alloc(b) + if e != nil { + return e + } + + buf := make([]byte, 16) + buf[0] = 0xfd + Handle(newatom).Put(buf[1:]) + f.Realloc(Handle(atom), buf[1:], true) + f.write(buf[:1], atom<<4) + } + case typ == 0xfd: // reloc + var target Handle + buf := make([]byte, 7) + f.read(buf, atom<<4+1) + target.Get(buf) + switch { + case newatoms == 1: + f.writeUsed(b, atom) + f.Free(target) + default: + if rightFree := f.checkRight(atom, 1); rightFree > 0 && newatoms <= 1+rightFree { + f.delFree(atom+1, rightFree) + if newatoms < 1+rightFree { + f.addFree(atom+newatoms, 1+rightFree-newatoms) + } + f.writeUsed(b, atom) + f.Free(target) + return + } + + newtarget, e := f.Realloc(Handle(target), b, false) + if e != nil { + return e + } + + if newtarget != target { + Handle(newtarget).Put(buf) + f.write(buf, atom<<4+1) + } + } + } + return + }) + return +} + +// Lock locks f for writing. If the lock is already locked for reading or writing, +// Lock blocks until the lock is available. To ensure that the lock eventually becomes available, +// a blocked Lock call excludes new readers from acquiring the lock. +func (f *File) Lock() { + f.rwm.Lock() +} + +// RLock locks f for reading. If the lock is already locked for writing or there is a writer +// already waiting to release the lock, RLock blocks until the writer has released the lock. +func (f *File) RLock() { + f.rwm.RLock() +} + +// Unlock unlocks f for writing. It is a run-time error if f is not locked for writing on entry to Unlock. +// +// As with Mutexes, a locked RWMutex is not associated with a particular goroutine. +// One goroutine may RLock (Lock) f and then arrange for another goroutine to RUnlock (Unlock) it. +func (f *File) Unlock() { + f.rwm.Unlock() +} + +// RUnlock undoes a single RLock call; it does not affect other simultaneous readers. +// It is a run-time error if f is not locked for reading on entry to RUnlock. +func (f *File) RUnlock() { + f.rwm.RUnlock() +} + +// LockedAlloc wraps Alloc in a Lock/Unlock pair. +func (f *File) LockedAlloc(b []byte) (handle Handle, err error) { + f.Lock() + defer f.Unlock() + return f.Alloc(b) +} + +// LockedFree wraps Free in a Lock/Unlock pair. +func (f *File) LockedFree(handle Handle) (err error) { + f.Lock() + defer f.Unlock() + return f.Free(handle) +} + +// LockedRead wraps Read in a RLock/RUnlock pair. +func (f *File) LockedRead(handle Handle) (b []byte, err error) { + f.RLock() + defer f.RUnlock() + return f.Read(handle) +} + +// LockedRealloc wraps Realloc in a Lock/Unlock pair. +func (f *File) LockedRealloc(handle Handle, b []byte, keepHandle bool) (newhandle Handle, err error) { + f.Lock() + defer f.Unlock() + return f.Realloc(handle, b, keepHandle) +} diff --git a/vendor/github.com/cznic/fileutil/falloc/test_deps.go b/vendor/github.com/cznic/fileutil/falloc/test_deps.go new file mode 100644 index 00000000..3bdd39f2 --- /dev/null +++ b/vendor/github.com/cznic/fileutil/falloc/test_deps.go @@ -0,0 +1,15 @@ +// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// blame: jnml, labs.nic.cz + +package falloc + +// Pull test dependencies too. +// Enables easy 'go test X' after 'go get X' +import ( + _ "github.com/cznic/fileutil" + _ "github.com/cznic/fileutil/storage" + _ "github.com/cznic/mathutil" +) diff --git a/vendor/github.com/cznic/fileutil/fileutil.go b/vendor/github.com/cznic/fileutil/fileutil.go new file mode 100644 index 00000000..2f0f7ab1 --- /dev/null +++ b/vendor/github.com/cznic/fileutil/fileutil.go @@ -0,0 +1,223 @@ +// Copyright (c) 2014 The fileutil 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 fileutil collects some file utility functions. +package fileutil + +import ( + "fmt" + "io" + "os" + "path/filepath" + "runtime" + "strconv" + "sync" + "time" +) + +// GoMFile is a concurrent access safe version of MFile. +type GoMFile struct { + mfile *MFile + mutex sync.Mutex +} + +// NewGoMFile return a newly created GoMFile. +func NewGoMFile(fname string, flag int, perm os.FileMode, delta_ns int64) (m *GoMFile, err error) { + m = &GoMFile{} + if m.mfile, err = NewMFile(fname, flag, perm, delta_ns); err != nil { + m = nil + } + return +} + +func (m *GoMFile) File() (file *os.File, err error) { + m.mutex.Lock() + defer m.mutex.Unlock() + return m.mfile.File() +} + +func (m *GoMFile) SetChanged() { + m.mutex.Lock() + defer m.mutex.Unlock() + m.mfile.SetChanged() +} + +func (m *GoMFile) SetHandler(h MFileHandler) { + m.mutex.Lock() + defer m.mutex.Unlock() + m.mfile.SetHandler(h) +} + +// MFileHandler resolves modifications of File. +// Possible File context is expected to be a part of the handler's closure. +type MFileHandler func(*os.File) error + +// MFile represents an os.File with a guard/handler on change/modification. +// Example use case is an app with a configuration file which can be modified at any time +// and have to be reloaded in such event prior to performing something configurable by that +// file. The checks are made only on access to the MFile file by +// File() and a time threshold/hysteresis value can be chosen on creating a new MFile. +type MFile struct { + file *os.File + handler MFileHandler + t0 int64 + delta int64 + ctime int64 +} + +// NewMFile returns a newly created MFile or Error if any. +// The fname, flag and perm parameters have the same meaning as in os.Open. +// For meaning of the delta_ns parameter please see the (m *MFile) File() docs. +func NewMFile(fname string, flag int, perm os.FileMode, delta_ns int64) (m *MFile, err error) { + m = &MFile{} + m.t0 = time.Now().UnixNano() + if m.file, err = os.OpenFile(fname, flag, perm); err != nil { + return + } + + var fi os.FileInfo + if fi, err = m.file.Stat(); err != nil { + return + } + + m.ctime = fi.ModTime().UnixNano() + m.delta = delta_ns + runtime.SetFinalizer(m, func(m *MFile) { + m.file.Close() + }) + return +} + +// SetChanged forces next File() to unconditionally handle modification of the wrapped os.File. +func (m *MFile) SetChanged() { + m.ctime = -1 +} + +// SetHandler sets a function to be invoked when modification of MFile is to be processed. +func (m *MFile) SetHandler(h MFileHandler) { + m.handler = h +} + +// File returns an os.File from MFile. If time elapsed between the last invocation of this function +// and now is at least delta_ns ns (a parameter of NewMFile) then the file is checked for +// change/modification. For delta_ns == 0 the modification is checked w/o getting os.Time(). +// If a change is detected a handler is invoked on the MFile file. +// Any of these steps can produce an Error. If that happens the function returns nil, Error. +func (m *MFile) File() (file *os.File, err error) { + var now int64 + + mustCheck := m.delta == 0 + if !mustCheck { + now = time.Now().UnixNano() + mustCheck = now-m.t0 > m.delta + } + + if mustCheck { // check interval reached + var fi os.FileInfo + if fi, err = m.file.Stat(); err != nil { + return + } + + if fi.ModTime().UnixNano() != m.ctime { // modification detected + if m.handler == nil { + return nil, fmt.Errorf("no handler set for modified file %q", m.file.Name()) + } + if err = m.handler(m.file); err != nil { + return + } + + m.ctime = fi.ModTime().UnixNano() + } + m.t0 = now + } + + return m.file, nil +} + +// Read reads buf from r. It will either fill the full buf or fail. +// It wraps the functionality of an io.Reader which may return less bytes than requested, +// but may block if not all data are ready for the io.Reader. +func Read(r io.Reader, buf []byte) (err error) { + have := 0 + remain := len(buf) + got := 0 + for remain > 0 { + if got, err = r.Read(buf[have:]); err != nil { + return + } + + remain -= got + have += got + } + return +} + +// "os" and/or "syscall" extensions + +// FadviseAdvice is used by Fadvise. +type FadviseAdvice int + +// FAdviseAdvice values. +const ( + // $ grep FADV /usr/include/bits/fcntl.h + POSIX_FADV_NORMAL FadviseAdvice = iota // No further special treatment. + POSIX_FADV_RANDOM // Expect random page references. + POSIX_FADV_SEQUENTIAL // Expect sequential page references. + POSIX_FADV_WILLNEED // Will need these pages. + POSIX_FADV_DONTNEED // Don't need these pages. + POSIX_FADV_NOREUSE // Data will be accessed once. +) + +// TempFile creates a new temporary file in the directory dir with a name +// ending with suffix, basename starting with prefix, opens the file for +// reading and writing, and returns the resulting *os.File. If dir is the +// empty string, TempFile uses the default directory for temporary files (see +// os.TempDir). Multiple programs calling TempFile simultaneously will not +// choose the same file. The caller can use f.Name() to find the pathname of +// the file. It is the caller's responsibility to remove the file when no +// longer needed. +// +// NOTE: This function differs from ioutil.TempFile. +func TempFile(dir, prefix, suffix string) (f *os.File, err error) { + if dir == "" { + dir = os.TempDir() + } + + nconflict := 0 + for i := 0; i < 10000; i++ { + name := filepath.Join(dir, prefix+nextInfix()+suffix) + f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) + if os.IsExist(err) { + if nconflict++; nconflict > 10 { + rand = reseed() + } + continue + } + break + } + return +} + +// Random number state. +// We generate random temporary file names so that there's a good +// chance the file doesn't exist yet - keeps the number of tries in +// TempFile to a minimum. +var rand uint32 +var randmu sync.Mutex + +func reseed() uint32 { + return uint32(time.Now().UnixNano() + int64(os.Getpid())) +} + +func nextInfix() string { + randmu.Lock() + r := rand + if r == 0 { + r = reseed() + } + r = r*1664525 + 1013904223 // constants from Numerical Recipes + rand = r + randmu.Unlock() + return strconv.Itoa(int(1e9 + r%1e9))[1:] +} diff --git a/vendor/github.com/cznic/fileutil/fileutil_arm.go b/vendor/github.com/cznic/fileutil/fileutil_arm.go new file mode 100644 index 00000000..9410d1bb --- /dev/null +++ b/vendor/github.com/cznic/fileutil/fileutil_arm.go @@ -0,0 +1,25 @@ +// Copyright (c) 2014 The fileutil 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 fileutil + +import ( + "io" + "os" +) + +// PunchHole deallocates space inside a file in the byte range starting at +// offset and continuing for len bytes. Not supported on ARM. +func PunchHole(f *os.File, off, len int64) error { + return nil +} + +// Fadvise predeclares an access pattern for file data. See also 'man 2 +// posix_fadvise'. Not supported on ARM. +func Fadvise(f *os.File, off, len int64, advice FadviseAdvice) error { + return nil +} + +// IsEOF reports whether err is an EOF condition. +func IsEOF(err error) bool { return err == io.EOF } diff --git a/vendor/github.com/cznic/fileutil/fileutil_darwin.go b/vendor/github.com/cznic/fileutil/fileutil_darwin.go new file mode 100644 index 00000000..a19723fc --- /dev/null +++ b/vendor/github.com/cznic/fileutil/fileutil_darwin.go @@ -0,0 +1,25 @@ +// Copyright (c) 2014 The fileutil 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 fileutil + +import ( + "io" + "os" +) + +// PunchHole deallocates space inside a file in the byte range starting at +// offset and continuing for len bytes. Not supported on OSX. +func PunchHole(f *os.File, off, len int64) error { + return nil +} + +// Fadvise predeclares an access pattern for file data. See also 'man 2 +// posix_fadvise'. Not supported on OSX. +func Fadvise(f *os.File, off, len int64, advice FadviseAdvice) error { + return nil +} + +// IsEOF reports whether err is an EOF condition. +func IsEOF(err error) bool { return err == io.EOF } diff --git a/vendor/github.com/cznic/fileutil/fileutil_freebsd.go b/vendor/github.com/cznic/fileutil/fileutil_freebsd.go new file mode 100644 index 00000000..cefec0cb --- /dev/null +++ b/vendor/github.com/cznic/fileutil/fileutil_freebsd.go @@ -0,0 +1,27 @@ +// Copyright (c) 2014 The fileutil Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !arm + +package fileutil + +import ( + "io" + "os" +) + +// PunchHole deallocates space inside a file in the byte range starting at +// offset and continuing for len bytes. Unimplemented on FreeBSD. +func PunchHole(f *os.File, off, len int64) error { + return nil +} + +// Fadvise predeclares an access pattern for file data. See also 'man 2 +// posix_fadvise'. Unimplemented on FreeBSD. +func Fadvise(f *os.File, off, len int64, advice FadviseAdvice) error { + return nil +} + +// IsEOF reports whether err is an EOF condition. +func IsEOF(err error) bool { return err == io.EOF } diff --git a/vendor/github.com/cznic/fileutil/fileutil_linux.go b/vendor/github.com/cznic/fileutil/fileutil_linux.go new file mode 100644 index 00000000..8babfc55 --- /dev/null +++ b/vendor/github.com/cznic/fileutil/fileutil_linux.go @@ -0,0 +1,96 @@ +// Copyright (c) 2014 The fileutil Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !arm + +package fileutil + +import ( + "bytes" + "io" + "io/ioutil" + "os" + "strconv" + "syscall" +) + +func n(s []byte) byte { + for i, c := range s { + if c < '0' || c > '9' { + s = s[:i] + break + } + } + v, _ := strconv.Atoi(string(s)) + return byte(v) +} + +func init() { + b, err := ioutil.ReadFile("/proc/sys/kernel/osrelease") + if err != nil { + panic(err) + } + + tokens := bytes.Split(b, []byte(".")) + if len(tokens) > 3 { + tokens = tokens[:3] + } + switch len(tokens) { + case 3: + // Supported since kernel 2.6.38 + if bytes.Compare([]byte{n(tokens[0]), n(tokens[1]), n(tokens[2])}, []byte{2, 6, 38}) < 0 { + puncher = func(*os.File, int64, int64) error { return nil } + } + case 2: + if bytes.Compare([]byte{n(tokens[0]), n(tokens[1])}, []byte{2, 7}) < 0 { + puncher = func(*os.File, int64, int64) error { return nil } + } + default: + puncher = func(*os.File, int64, int64) error { return nil } + } +} + +var puncher = func(f *os.File, off, len int64) error { + const ( + /* + /usr/include/linux$ grep FL_ falloc.h + */ + _FALLOC_FL_KEEP_SIZE = 0x01 // default is extend size + _FALLOC_FL_PUNCH_HOLE = 0x02 // de-allocates range + ) + + _, _, errno := syscall.Syscall6( + syscall.SYS_FALLOCATE, + uintptr(f.Fd()), + uintptr(_FALLOC_FL_KEEP_SIZE|_FALLOC_FL_PUNCH_HOLE), + uintptr(off), + uintptr(len), + 0, 0) + if errno != 0 { + return os.NewSyscallError("SYS_FALLOCATE", errno) + } + return nil +} + +// PunchHole deallocates space inside a file in the byte range starting at +// offset and continuing for len bytes. No-op for kernels < 2.6.38 (or < 2.7). +func PunchHole(f *os.File, off, len int64) error { + return puncher(f, off, len) +} + +// Fadvise predeclares an access pattern for file data. See also 'man 2 +// posix_fadvise'. +func Fadvise(f *os.File, off, len int64, advice FadviseAdvice) error { + _, _, errno := syscall.Syscall6( + syscall.SYS_FADVISE64, + uintptr(f.Fd()), + uintptr(off), + uintptr(len), + uintptr(advice), + 0, 0) + return os.NewSyscallError("SYS_FADVISE64", errno) +} + +// IsEOF reports whether err is an EOF condition. +func IsEOF(err error) bool { return err == io.EOF } diff --git a/vendor/github.com/cznic/fileutil/fileutil_netbsd.go b/vendor/github.com/cznic/fileutil/fileutil_netbsd.go new file mode 100644 index 00000000..ca778d6d --- /dev/null +++ b/vendor/github.com/cznic/fileutil/fileutil_netbsd.go @@ -0,0 +1,27 @@ +// Copyright (c) 2014 The fileutil Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !arm + +package fileutil + +import ( + "io" + "os" +) + +// PunchHole deallocates space inside a file in the byte range starting at +// offset and continuing for len bytes. Similar to FreeBSD, this is +// unimplemented. +func PunchHole(f *os.File, off, len int64) error { + return nil +} + +// Unimplemented on NetBSD. +func Fadvise(f *os.File, off, len int64, advice FadviseAdvice) error { + return nil +} + +// IsEOF reports whether err is an EOF condition. +func IsEOF(err error) bool { return err == io.EOF } diff --git a/vendor/github.com/cznic/fileutil/fileutil_openbsd.go b/vendor/github.com/cznic/fileutil/fileutil_openbsd.go new file mode 100644 index 00000000..428171bd --- /dev/null +++ b/vendor/github.com/cznic/fileutil/fileutil_openbsd.go @@ -0,0 +1,25 @@ +// Copyright (c) 2014 The fileutil 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 fileutil + +import ( + "io" + "os" +) + +// PunchHole deallocates space inside a file in the byte range starting at +// offset and continuing for len bytes. Similar to FreeBSD, this is +// unimplemented. +func PunchHole(f *os.File, off, len int64) error { + return nil +} + +// Unimplemented on OpenBSD. +func Fadvise(f *os.File, off, len int64, advice FadviseAdvice) error { + return nil +} + +// IsEOF reports whether err is an EOF condition. +func IsEOF(err error) bool { return err == io.EOF } diff --git a/vendor/github.com/cznic/fileutil/fileutil_plan9.go b/vendor/github.com/cznic/fileutil/fileutil_plan9.go new file mode 100644 index 00000000..a2db64e2 --- /dev/null +++ b/vendor/github.com/cznic/fileutil/fileutil_plan9.go @@ -0,0 +1,25 @@ +// Copyright (c) 2014 The fileutil 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 fileutil + +import ( + "io" + "os" +) + +// PunchHole deallocates space inside a file in the byte range starting at +// offset and continuing for len bytes. Unimplemented on Plan 9. +func PunchHole(f *os.File, off, len int64) error { + return nil +} + +// Fadvise predeclares an access pattern for file data. See also 'man 2 +// posix_fadvise'. Unimplemented on Plan 9. +func Fadvise(f *os.File, off, len int64, advice FadviseAdvice) error { + return nil +} + +// IsEOF reports whether err is an EOF condition. +func IsEOF(err error) bool { return err == io.EOF } diff --git a/vendor/github.com/cznic/fileutil/fileutil_solaris.go b/vendor/github.com/cznic/fileutil/fileutil_solaris.go new file mode 100644 index 00000000..61dfcde3 --- /dev/null +++ b/vendor/github.com/cznic/fileutil/fileutil_solaris.go @@ -0,0 +1,27 @@ +// Copyright (c) 2013 jnml. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.3 + +package fileutil + +import ( + "io" + "os" +) + +// PunchHole deallocates space inside a file in the byte range starting at +// offset and continuing for len bytes. Not supported on Solaris. +func PunchHole(f *os.File, off, len int64) error { + return nil +} + +// Fadvise predeclares an access pattern for file data. See also 'man 2 +// posix_fadvise'. Not supported on Solaris. +func Fadvise(f *os.File, off, len int64, advice FadviseAdvice) error { + return nil +} + +// IsEOF reports whether err is an EOF condition. +func IsEOF(err error) bool { return err == io.EOF } diff --git a/vendor/github.com/cznic/fileutil/fileutil_windows.go b/vendor/github.com/cznic/fileutil/fileutil_windows.go new file mode 100644 index 00000000..3a81f2fc --- /dev/null +++ b/vendor/github.com/cznic/fileutil/fileutil_windows.go @@ -0,0 +1,183 @@ +// Copyright (c) 2014 The fileutil 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 fileutil + +import ( + "io" + "os" + "sync" + "syscall" + "unsafe" +) + +// PunchHole deallocates space inside a file in the byte range starting at +// offset and continuing for len bytes. Not supported on Windows. +func PunchHole(f *os.File, off, len int64) error { + return puncher(f, off, len) +} + +// Fadvise predeclares an access pattern for file data. See also 'man 2 +// posix_fadvise'. Not supported on Windows. +func Fadvise(f *os.File, off, len int64, advice FadviseAdvice) error { + return nil +} + +// IsEOF reports whether err is an EOF condition. +func IsEOF(err error) bool { + if err == io.EOF { + return true + } + + // http://social.technet.microsoft.com/Forums/windowsserver/en-US/1a16311b-c625-46cf-830b-6a26af488435/how-to-solve-error-38-0x26-errorhandleeof-using-fsctlgetretrievalpointers + x, ok := err.(*os.PathError) + return ok && x.Op == "read" && x.Err.(syscall.Errno) == 0x26 +} + +var ( + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + + procDeviceIOControl = modkernel32.NewProc("DeviceIoControl") + + sparseFilesMu sync.Mutex + sparseFiles map[uintptr]struct{} +) + +func init() { + // sparseFiles is an fd set for already "sparsed" files - according to + // msdn.microsoft.com/en-us/library/windows/desktop/aa364225(v=vs.85).aspx + // the file handles are unique per process. + sparseFiles = make(map[uintptr]struct{}) +} + +// puncHoleWindows punches a hole into the given file starting at offset, +// measuring "size" bytes +// (http://msdn.microsoft.com/en-us/library/windows/desktop/aa364597%28v=vs.85%29.aspx) +func puncher(file *os.File, offset, size int64) error { + if err := ensureFileSparse(file); err != nil { + return err + } + + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa364411%28v=vs.85%29.aspx + // typedef struct _FILE_ZERO_DATA_INFORMATION { + // LARGE_INTEGER FileOffset; + // LARGE_INTEGER BeyondFinalZero; + //} FILE_ZERO_DATA_INFORMATION, *PFILE_ZERO_DATA_INFORMATION; + type fileZeroDataInformation struct { + FileOffset, BeyondFinalZero int64 + } + + lpInBuffer := fileZeroDataInformation{ + FileOffset: offset, + BeyondFinalZero: offset + size} + return deviceIOControl(false, file.Fd(), uintptr(unsafe.Pointer(&lpInBuffer)), 16) +} + +// // http://msdn.microsoft.com/en-us/library/windows/desktop/cc948908%28v=vs.85%29.aspx +// type fileSetSparseBuffer struct { +// SetSparse bool +// } + +func ensureFileSparse(file *os.File) (err error) { + fd := file.Fd() + sparseFilesMu.Lock() + if _, ok := sparseFiles[fd]; ok { + sparseFilesMu.Unlock() + return nil + } + + if err = deviceIOControl(true, fd, 0, 0); err == nil { + sparseFiles[fd] = struct{}{} + } + sparseFilesMu.Unlock() + return err +} + +func deviceIOControl(setSparse bool, fd, inBuf, inBufLen uintptr) (err error) { + const ( + //http://source.winehq.org/source/include/winnt.h#L4605 + file_read_data = 1 + file_write_data = 2 + + // METHOD_BUFFERED 0 + method_buffered = 0 + // FILE_ANY_ACCESS 0 + file_any_access = 0 + // FILE_DEVICE_FILE_SYSTEM 0x00000009 + file_device_file_system = 0x00000009 + // FILE_SPECIAL_ACCESS (FILE_ANY_ACCESS) + file_special_access = file_any_access + file_read_access = file_read_data + file_write_access = file_write_data + + // http://source.winehq.org/source/include/winioctl.h + // #define CTL_CODE ( DeviceType, + // Function, + // Method, + // Access ) + // ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) + + // FSCTL_SET_COMPRESSION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 16, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) + fsctl_set_compression = (file_device_file_system << 16) | ((file_read_access | file_write_access) << 14) | (16 << 2) | method_buffered + // FSCTL_SET_SPARSE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 49, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) + fsctl_set_sparse = (file_device_file_system << 16) | (file_special_access << 14) | (49 << 2) | method_buffered + // FSCTL_SET_ZERO_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 50, METHOD_BUFFERED, FILE_WRITE_DATA) + fsctl_set_zero_data = (file_device_file_system << 16) | (file_write_data << 14) | (50 << 2) | method_buffered + ) + retPtr := uintptr(unsafe.Pointer(&(make([]byte, 8)[0]))) + var r1 uintptr + var e1 syscall.Errno + if setSparse { + // BOOL + // WINAPI + // DeviceIoControl( (HANDLE) hDevice, // handle to a file + // FSCTL_SET_SPARSE, // dwIoControlCode + // (PFILE_SET_SPARSE_BUFFER) lpInBuffer, // input buffer + // (DWORD) nInBufferSize, // size of input buffer + // NULL, // lpOutBuffer + // 0, // nOutBufferSize + // (LPDWORD) lpBytesReturned, // number of bytes returned + // (LPOVERLAPPED) lpOverlapped ); // OVERLAPPED structure + r1, _, e1 = syscall.Syscall9(procDeviceIOControl.Addr(), 8, + fd, + uintptr(fsctl_set_sparse), + // If the lpInBuffer parameter is NULL, the operation will behave the same as if the SetSparse member of the FILE_SET_SPARSE_BUFFER structure were TRUE. In other words, the operation sets the file to a sparse file. + 0, // uintptr(unsafe.Pointer(&lpInBuffer)), + 0, // 1, + 0, + 0, + retPtr, + 0, + 0) + } else { + // BOOL + // WINAPI + // DeviceIoControl( (HANDLE) hDevice, // handle to a file + // FSCTL_SET_ZERO_DATA, // dwIoControlCode + // (LPVOID) lpInBuffer, // input buffer + // (DWORD) nInBufferSize, // size of input buffer + // NULL, // lpOutBuffer + // 0, // nOutBufferSize + // (LPDWORD) lpBytesReturned, // number of bytes returned + // (LPOVERLAPPED) lpOverlapped ); // OVERLAPPED structure + r1, _, e1 = syscall.Syscall9(procDeviceIOControl.Addr(), 8, + fd, + uintptr(fsctl_set_zero_data), + inBuf, + inBufLen, + 0, + 0, + retPtr, + 0, + 0) + } + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return err +} diff --git a/vendor/github.com/cznic/fileutil/hdb/hdb.go b/vendor/github.com/cznic/fileutil/hdb/hdb.go new file mode 100644 index 00000000..7c7113d9 --- /dev/null +++ b/vendor/github.com/cznic/fileutil/hdb/hdb.go @@ -0,0 +1,153 @@ +// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// blame: jnml, labs.nic.cz + +/* +WIP: Package hdb provides a "handle"/value DB like store, but actually it's +closer to the model of a process's virtual memory and its alloc, free and move +methods. + +The hdb package is a thin layer around falloc.File providing stable-only +handles and the basic synchronizing primitives. The central functionality of +hdb are the New, Set, Get and Delete methods of Store. + +Conceptual analogy: + New alloc(sizeof(content)), return new "memory" pointer (a handle). + + Get memmove() from "memory" "pointed to" by handle to the result content. + Note: Handle "knows" the size of its content. + + Set memmove() from content to "memory" pointed to by handle. + In contrast to real memory, the new content may have different + size than the previously stored one w/o additional handling + and the "pointer" handle remains the same. + + Delete free() the "memory" "pointed to" by handle. +*/ +package hdb + +import ( + "github.com/cznic/fileutil/falloc" + "github.com/cznic/fileutil/storage" +) + +type Store struct { + f *falloc.File +} + +// New returns a newly created Store backed by accessor, discarding its conents if any. +// If successful, methods on the returned Store can be used for I/O. +// It returns the Store and an error, if any. +func New(accessor storage.Accessor) (store *Store, err error) { + s := &Store{} + if s.f, err = falloc.New(accessor); err == nil { + store = s + } + return +} + +// Open opens the Store from accessor. +// If successful, methods on the returned Store can be used for data exchange. +// It returns the Store and an error, if any. +func Open(accessor storage.Accessor) (store *Store, err error) { + s := &Store{} + if s.f, err = falloc.Open(accessor); err == nil { + store = s + } + return +} + +// Close closes the store. Further access to the store has undefined behavior and may panic. +// It returns an error, if any. +func (s *Store) Close() (err error) { + defer func() { + s.f = nil + }() + + return s.f.Close() +} + +// Delete deletes the data associated with handle. +// It returns an error if any. +func (s *Store) Delete(handle falloc.Handle) (err error) { + return s.f.Free(handle) +} + +// Get gets the data associated with handle. +// It returns the data and an error, if any. +func (s *Store) Get(handle falloc.Handle) (b []byte, err error) { + return s.f.Read(handle) +} + +// New associates data with a new handle. +// It returns the handle and an error, if any. +func (s *Store) New(b []byte) (handle falloc.Handle, err error) { + return s.f.Alloc(b) +} + +// Set associates data with an existing handle. +// It returns an error, if any. +func (s *Store) Set(handle falloc.Handle, b []byte) (err error) { + _, err = s.f.Realloc(handle, b, true) + return +} + +// Root returns the handle of the DB root (top level directory, ...). +func (s *Store) Root() falloc.Handle { + return s.f.Root() +} + +// File returns the underlying falloc.File of 's'. +func (s *Store) File() *falloc.File { + return s.f +} + +// Lock locks 's' for writing. If the lock is already locked for reading or writing, +// Lock blocks until the lock is available. To ensure that the lock eventually becomes available, +// a blocked Lock call excludes new readers from acquiring the lock. +func (s *Store) Lock() { + s.f.Lock() +} + +// RLock locks 's' for reading. If the lock is already locked for writing or there is a writer +// already waiting to release the lock, RLock blocks until the writer has released the lock. +func (s *Store) RLock() { + s.f.RLock() +} + +// Unlock unlocks 's' for writing. It's a run-time error if 's' is not locked for writing on entry to Unlock. +// +// As with Mutexes, a locked RWMutex is not associated with a particular goroutine. +// One goroutine may RLock (Lock) 's' and then arrange for another goroutine to RUnlock (Unlock) it. +func (s *Store) Unlock() { + s.f.Unlock() +} + +// RUnlock undoes a single RLock call; it does not affect other simultaneous readers. +// It's a run-time error if 's' is not locked for reading on entry to RUnlock. +func (s *Store) RUnlock() { + s.f.RUnlock() +} + +// LockedNew wraps New in a Lock/Unlock pair. +func (s *Store) LockedNew(b []byte) (handle falloc.Handle, err error) { + return s.f.LockedAlloc(b) +} + +// LockedDelete wraps Delete in a Lock/Unlock pair. +func (s *Store) LockedDelete(handle falloc.Handle) (err error) { + return s.f.LockedFree(handle) +} + +// LockedGet wraps Get in a RLock/RUnlock pair. +func (s *Store) LockedGet(handle falloc.Handle) (b []byte, err error) { + return s.f.LockedRead(handle) +} + +// LockedSet wraps Set in a Lock/Unlock pair. +func (s *Store) LockedSet(handle falloc.Handle, b []byte) (err error) { + _, err = s.f.Realloc(handle, b, true) + return +} diff --git a/vendor/github.com/cznic/fileutil/hdb/test_deps.go b/vendor/github.com/cznic/fileutil/hdb/test_deps.go new file mode 100644 index 00000000..3164f63a --- /dev/null +++ b/vendor/github.com/cznic/fileutil/hdb/test_deps.go @@ -0,0 +1,13 @@ +// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// blame: jnml, labs.nic.cz + +package hdb + +// Pull test dependencies too. +// Enables easy 'go test X' after 'go get X' +import ( +// nothing yet +) diff --git a/vendor/github.com/cznic/fileutil/storage/cache.go b/vendor/github.com/cznic/fileutil/storage/cache.go new file mode 100644 index 00000000..3a6115a7 --- /dev/null +++ b/vendor/github.com/cznic/fileutil/storage/cache.go @@ -0,0 +1,322 @@ +// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// blame: jnml, labs.nic.cz + +package storage + +import ( + "container/list" + "io" + "math" + "os" + "sync" + "sync/atomic" +) + +type cachepage struct { + b [512]byte + dirty bool + lru *list.Element + pi int64 + valid int // page content is b[:valid] +} + +func (p *cachepage) wr(b []byte, off int) (wasDirty bool) { + copy(p.b[off:], b) + if n := off + len(b); n > p.valid { + p.valid = n + } + wasDirty = p.dirty + p.dirty = true + return +} + +func (c *Cache) rd(off int64, read bool) (p *cachepage, ok bool) { + c.Rq++ + pi := off >> 9 + if p, ok = c.m[pi]; ok { + c.lru.MoveToBack(p.lru) + return + } + + if !read { + return + } + + fp := off &^ 511 + if fp >= c.size { + return + } + + rq := 512 + if fp+512 > c.size { + rq = int(c.size - fp) + } + p = &cachepage{pi: pi, valid: rq} + p.lru = c.lru.PushBack(p) + if n, err := c.f.ReadAt(p.b[:p.valid], fp); n != rq { + panic(err) + } + + c.Load++ + if c.advise != nil { + c.advise(fp, 512, false) + } + c.m[pi], ok = p, true + return +} + +func (c *Cache) wr(off int64) (p *cachepage) { + var ok bool + if p, ok = c.rd(off, false); ok { + return + } + + pi := off >> 9 + p = &cachepage{pi: pi} + p.lru = c.lru.PushBack(p) + c.m[pi] = p + return +} + +// Cache provides caching support for another store Accessor. +type Cache struct { + advise func(int64, int, bool) + clean chan bool + cleaning int32 + close chan bool + f Accessor + fi *FileInfo + lock sync.Mutex + lru *list.List + m map[int64]*cachepage + maxpages int + size int64 + sync chan bool + wlist *list.List + write chan bool + writing int32 + Rq int64 // Pages requested from cache + Load int64 // Pages loaded (cache miss) + Purge int64 // Pages purged + Top int // "High water" pages +} + +// Implementation of Accessor. +func (c *Cache) BeginUpdate() error { return nil } + +// Implementation of Accessor. +func (c *Cache) EndUpdate() error { return nil } + +// NewCache creates a caching Accessor from store with total of maxcache bytes. +// NewCache returns the new Cache, implementing Accessor or an error if any. +// +// The LRU mechanism is used, so the cache tries to keep often accessed pages cached. +// +func NewCache(store Accessor, maxcache int64, advise func(int64, int, bool)) (c *Cache, err error) { + var fi os.FileInfo + if fi, err = store.Stat(); err != nil { + return + } + + x := maxcache >> 9 + if x > math.MaxInt32/2 { + x = math.MaxInt32 / 2 + } + c = &Cache{ + advise: advise, + clean: make(chan bool, 1), + close: make(chan bool), + f: store, + lru: list.New(), // front == oldest used, back == last recently used + m: make(map[int64]*cachepage), + maxpages: int(x), + size: fi.Size(), + sync: make(chan bool), + wlist: list.New(), + write: make(chan bool, 1), + } + c.fi = NewFileInfo(fi, c) + go c.writer() + go c.cleaner(int((int64(c.maxpages) * 95) / 100)) // hysteresis + return +} + +func (c *Cache) Accessor() Accessor { + return c.f +} + +func (c *Cache) Close() (err error) { + close(c.write) + <-c.close + close(c.clean) + <-c.close + return c.f.Close() +} + +func (c *Cache) Name() (s string) { + return c.f.Name() +} + +func (c *Cache) ReadAt(b []byte, off int64) (n int, err error) { + po := int(off) & 0x1ff + bp := 0 + rem := len(b) + m := 0 + for rem != 0 { + c.lock.Lock() // X1+ + p, ok := c.rd(off, true) + if !ok { + c.lock.Unlock() // X1- + return -1, io.EOF + } + + rq := rem + if po+rq > 512 { + rq = 512 - po + } + if n := copy(b[bp:bp+rq], p.b[po:p.valid]); n != rq { + c.lock.Unlock() // X1- + return -1, io.EOF + } + + m = len(c.m) + c.lock.Unlock() // X1- + po = 0 + bp += rq + off += int64(rq) + rem -= rq + n += rq + } + if m > c.maxpages && atomic.CompareAndSwapInt32(&c.cleaning, 0, 1) { + if m > c.Top { + c.Top = m + } + c.clean <- true + } + return +} + +func (c *Cache) Stat() (fi os.FileInfo, err error) { + c.lock.Lock() + defer c.lock.Unlock() + return c.fi, nil +} + +func (c *Cache) Sync() (err error) { + c.write <- false + <-c.sync + return +} + +func (c *Cache) Truncate(size int64) (err error) { + c.Sync() //TODO improve (discard pages, the writer goroutine should also be aware, ...) + c.lock.Lock() + defer c.lock.Unlock() + c.size = size + return c.f.Truncate(size) +} + +func (c *Cache) WriteAt(b []byte, off int64) (n int, err error) { + po := int(off) & 0x1ff + bp := 0 + rem := len(b) + m := 0 + for rem != 0 { + c.lock.Lock() // X+ + p := c.wr(off) + rq := rem + if po+rq > 512 { + rq = 512 - po + } + if wasDirty := p.wr(b[bp:bp+rq], po); !wasDirty { + c.wlist.PushBack(p) + } + m = len(c.m) + po = 0 + bp += rq + off += int64(rq) + if off > c.size { + c.size = off + } + c.lock.Unlock() // X- + rem -= rq + n += rq + } + if atomic.CompareAndSwapInt32(&c.writing, 0, 1) { + c.write <- true + } + if m > c.maxpages && atomic.CompareAndSwapInt32(&c.cleaning, 0, 1) { + if m > c.Top { + c.Top = m + } + c.clean <- true + } + return +} + +func (c *Cache) writer() { + for ok := true; ok; { + var wr bool + var off int64 + wr, ok = <-c.write + for { + c.lock.Lock() // X1+ + item := c.wlist.Front() + if item == nil { + c.lock.Unlock() // X1- + break + } + + p := item.Value.(*cachepage) + off = p.pi << 9 + if n, err := c.f.WriteAt(p.b[:p.valid], off); n != p.valid { + c.lock.Unlock() // X1- + panic("TODO Cache.writer errchan") //TODO +errchan + panic(err) + } + + p.dirty = false + c.wlist.Remove(item) + if c.advise != nil { + c.advise(off, 512, true) + } + c.lock.Unlock() // X1- + } + switch { + case wr: + atomic.AddInt32(&c.writing, -1) + case ok: + c.sync <- true + } + } + c.close <- true +} + +func (c *Cache) cleaner(limit int) { + for _ = range c.clean { + var item *list.Element + for { + c.lock.Lock() // X1+ + if len(c.m) < limit { + c.lock.Unlock() // X1- + break + } + + if item == nil { + item = c.lru.Front() + } + if p := item.Value.(*cachepage); !p.dirty { + delete(c.m, p.pi) + c.lru.Remove(item) + c.Purge++ + } + item = item.Next() + c.lock.Unlock() // X1- + } + atomic.AddInt32(&c.cleaning, -1) + } + c.close <- true +} diff --git a/vendor/github.com/cznic/fileutil/storage/file.go b/vendor/github.com/cznic/fileutil/storage/file.go new file mode 100644 index 00000000..94feda5e --- /dev/null +++ b/vendor/github.com/cznic/fileutil/storage/file.go @@ -0,0 +1,50 @@ +// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// blame: jnml, labs.nic.cz + +package storage + +import ( + "os" +) + +// FileAccessor is the concrete type returned by NewFile and OpenFile. +type FileAccessor struct { + *os.File +} + +// Implementation of Accessor. +func (f *FileAccessor) BeginUpdate() error { return nil } + +// Implementation of Accessor. +func (f *FileAccessor) EndUpdate() error { return nil } + +// NewFile returns an Accessor backed by an os.File named name, It opens the +// named file with specified flag (os.O_RDWR etc.) and perm, (0666 etc.) if +// applicable. If successful, methods on the returned Accessor can be used for +// I/O. It returns the Accessor and an Error, if any. +// +// NOTE: The returned Accessor implements BeginUpdate and EndUpdate as a no op. +func NewFile(name string, flag int, perm os.FileMode) (store Accessor, err error) { + var f FileAccessor + if f.File, err = os.OpenFile(name, flag, perm); err == nil { + store = &f + } + return +} + +// OpenFile returns an Accessor backed by an existing os.File named name, It +// opens the named file with specified flag (os.O_RDWR etc.) and perm, (0666 +// etc.) if applicable. If successful, methods on the returned Accessor can be +// used for I/O. It returns the Accessor and an Error, if any. +// +// NOTE: The returned Accessor implements BeginUpdate and EndUpdate as a no op. +func OpenFile(name string, flag int, perm os.FileMode) (store Accessor, err error) { + var f FileAccessor + if f.File, err = os.OpenFile(name, flag, perm); err == nil { + store = &f + } + return +} diff --git a/vendor/github.com/cznic/fileutil/storage/mem.go b/vendor/github.com/cznic/fileutil/storage/mem.go new file mode 100644 index 00000000..7cda0b66 --- /dev/null +++ b/vendor/github.com/cznic/fileutil/storage/mem.go @@ -0,0 +1,161 @@ +// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// blame: jnml, labs.nic.cz + +package storage + +import ( + "errors" + "fmt" + "io/ioutil" + "math" + "os" +) + +//TODO -> exported type w/ exported fields +type memaccessor struct { + f *os.File + fi *FileInfo + b []byte +} + +// Implementation of Accessor. +func (m *memaccessor) BeginUpdate() error { return nil } + +// Implementation of Accessor. +func (f *memaccessor) EndUpdate() error { return nil } + +// NewMem returns a new Accessor backed by an os.File. The returned Accessor +// keeps all of the store content in memory. The memory and file images are +// synced only by Sync and Close. Recomended for small amounts of data only +// and content which may be lost on process kill/crash. NewMem return the +// Accessor or an error of any. +// +// NOTE: The returned Accessor implements BeginUpdate and EndUpdate as a no op. +func NewMem(f *os.File) (store Accessor, err error) { + a := &memaccessor{f: f} + if err = f.Truncate(0); err != nil { + return + } + + var fi os.FileInfo + if fi, err = a.f.Stat(); err != nil { + return + } + + a.fi = NewFileInfo(fi, a) + store = a + return +} + +// OpenMem return a new Accessor backed by an os.File. The store content is +// loaded from f. The returned Accessor keeps all of the store content in +// memory. The memory and file images are synced only Sync and Close. +// Recomended for small amounts of data only and content which may be lost on +// process kill/crash. OpenMem return the Accessor or an error of any. +// +// NOTE: The returned Accessor implements BeginUpdate and EndUpdate as a no op. +func OpenMem(f *os.File) (store Accessor, err error) { + a := &memaccessor{f: f} + if a.b, err = ioutil.ReadAll(a.f); err != nil { + a.f.Close() + return + } + + var fi os.FileInfo + if fi, err = a.f.Stat(); err != nil { + a.f.Close() + return + } + + a.fi = NewFileInfo(fi, a) + store = a + return +} + +// Close implements Accessor. Specifically it synchronizes the memory and file images. +func (a *memaccessor) Close() (err error) { + defer func() { + a.b = nil + if a.f != nil { + if e := a.f.Close(); e != nil && err == nil { + err = e + } + } + a.f = nil + }() + + return a.Sync() +} + +func (a *memaccessor) Name() string { + return a.f.Name() +} + +func (a *memaccessor) ReadAt(b []byte, off int64) (n int, err error) { + if off < 0 || off > math.MaxInt32 { + return -1, fmt.Errorf("ReadAt: illegal offset %#x", off) + } + + rq, fp := len(b), int(off) + if fp+rq > len(a.b) { + return -1, fmt.Errorf("ReadAt: illegal rq %#x @ offset %#x, len %#x", rq, fp, len(a.b)) + } + + copy(b, a.b[fp:]) + return +} + +func (a *memaccessor) Stat() (fi os.FileInfo, err error) { + i := a.fi + i.FSize = int64(len(a.b)) + fi = i + return +} + +// Sync implements Accessor. Specifically it synchronizes the memory and file images. +func (a *memaccessor) Sync() (err error) { + var n int + if n, err = a.f.WriteAt(a.b, 0); n != len(a.b) { + return + } + + return a.f.Truncate(int64(len(a.b))) +} + +func (a *memaccessor) Truncate(size int64) (err error) { + defer func() { + if e := recover(); e != nil { + err = e.(error) + } + }() + + if size > math.MaxInt32 { + panic(errors.New("truncate: illegal size")) + } + + a.b = a.b[:int(size)] + return +} + +func (a *memaccessor) WriteAt(b []byte, off int64) (n int, err error) { + if off < 0 || off > math.MaxInt32 { + return -1, errors.New("WriteAt: illegal offset") + } + + rq, fp, size := len(b), int(off), len(a.b) + if need := rq + fp; need > size { + if need <= cap(a.b) { + a.b = a.b[:need] + } else { + nb := make([]byte, need, 2*need) + copy(nb, a.b) + a.b = nb + } + } + + copy(a.b[int(off):], b) + return +} diff --git a/vendor/github.com/cznic/fileutil/storage/probe.go b/vendor/github.com/cznic/fileutil/storage/probe.go new file mode 100644 index 00000000..53b146a6 --- /dev/null +++ b/vendor/github.com/cznic/fileutil/storage/probe.go @@ -0,0 +1,74 @@ +// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// blame: jnml, labs.nic.cz + +package storage + +import "sync/atomic" + +// Probe collects usage statistics of the embeded Accessor. +// Probe itself IS an Accessor. +type Probe struct { + Accessor + Chain *Probe + OpsRd int64 + OpsWr int64 + BytesRd int64 + BytesWr int64 + SectorsRd int64 // Assuming 512 byte sector size + SectorsWr int64 +} + +// NewProbe returns a newly created probe which embedes the src Accessor. +// The retuned *Probe satisfies Accessor. if chain != nil then Reset() +// is cascaded down the chained Probes. +func NewProbe(src Accessor, chain *Probe) *Probe { + return &Probe{Accessor: src, Chain: chain} +} + +func reset(n *int64) { + atomic.AddInt64(n, -atomic.AddInt64(n, 0)) +} + +// Reset zeroes the collected statistics of p. +func (p *Probe) Reset() { + if p.Chain != nil { + p.Chain.Reset() + } + reset(&p.OpsRd) + reset(&p.OpsWr) + reset(&p.BytesRd) + reset(&p.BytesWr) + reset(&p.SectorsRd) + reset(&p.SectorsWr) +} + +func (p *Probe) ReadAt(b []byte, off int64) (n int, err error) { + n, err = p.Accessor.ReadAt(b, off) + atomic.AddInt64(&p.OpsRd, 1) + atomic.AddInt64(&p.BytesRd, int64(n)) + if n <= 0 { + return + } + + sectorFirst := off >> 9 + sectorLast := (off + int64(n) - 1) >> 9 + atomic.AddInt64(&p.SectorsRd, sectorLast-sectorFirst+1) + return +} + +func (p *Probe) WriteAt(b []byte, off int64) (n int, err error) { + n, err = p.Accessor.WriteAt(b, off) + atomic.AddInt64(&p.OpsWr, 1) + atomic.AddInt64(&p.BytesWr, int64(n)) + if n <= 0 { + return + } + + sectorFirst := off >> 9 + sectorLast := (off + int64(n) - 1) >> 9 + atomic.AddInt64(&p.SectorsWr, sectorLast-sectorFirst+1) + return +} diff --git a/vendor/github.com/cznic/fileutil/storage/storage.go b/vendor/github.com/cznic/fileutil/storage/storage.go new file mode 100644 index 00000000..4956053a --- /dev/null +++ b/vendor/github.com/cznic/fileutil/storage/storage.go @@ -0,0 +1,141 @@ +// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// blame: jnml, labs.nic.cz + +// WIP: Package storage defines and implements storage providers and store accessors. +package storage + +import ( + "os" + "sync" + "time" +) + +// FileInfo is a type implementing os.FileInfo which has setable fields, like +// the older os.FileInfo used to have. It is used wehere e.g. the Size is +// needed to be faked (encapsulated/memory only file, file cache, etc.). +type FileInfo struct { + FName string // base name of the file + FSize int64 // length in bytes + FMode os.FileMode // file mode bits + FModTime time.Time // modification time + FIsDir bool // abbreviation for Mode().IsDir() + sys interface{} // underlying data source (can be nil) +} + +// NewFileInfo creates FileInfo from os.FileInfo fi. +func NewFileInfo(fi os.FileInfo, sys interface{}) *FileInfo { + return &FileInfo{fi.Name(), fi.Size(), fi.Mode(), fi.ModTime(), fi.IsDir(), sys} +} + +// Implementation of os.FileInfo +func (fi *FileInfo) Name() string { + return fi.FName +} + +// Implementation of os.FileInfo +func (fi *FileInfo) Size() int64 { + return fi.FSize +} + +// Implementation of os.FileInfo +func (fi *FileInfo) Mode() os.FileMode { + return fi.FMode +} + +// Implementation of os.FileInfo +func (fi *FileInfo) ModTime() time.Time { + return fi.FModTime +} + +// Implementation of os.FileInfo +func (fi *FileInfo) IsDir() bool { + return fi.FIsDir +} + +func (fi *FileInfo) Sys() interface{} { + return fi.sys +} + +// Accessor provides I/O methods to access a store. +type Accessor interface { + + // Close closes the store, rendering it unusable for I/O. It returns an + // error, if any. + Close() error + + // Name returns the name of the file as presented to Open. + Name() string + + // ReadAt reads len(b) bytes from the store starting at byte offset off. + // It returns the number of bytes read and the error, if any. + // EOF is signaled by a zero count with err set to os.EOF. + // ReadAt always returns a non-nil Error when n != len(b). + ReadAt(b []byte, off int64) (n int, err error) + + // Stat returns the FileInfo structure describing the store. It returns + // the os.FileInfo and an error, if any. + Stat() (fi os.FileInfo, err error) + + // Sync commits the current contents of the store to stable storage. + // Typically, this means flushing the file system's in-memory copy of + // recently written data to disk. + Sync() (err error) + + // Truncate changes the size of the store. It does not change the I/O + // offset. + Truncate(size int64) error + + // WriteAt writes len(b) bytes to the store starting at byte offset off. + // It returns the number of bytes written and an error, if any. + // WriteAt returns a non-nil Error when n != len(b). + WriteAt(b []byte, off int64) (n int, err error) + + // Before every [structural] change of a store the BeginUpdate is to be + // called and paired with EndUpdate after the change makes the store's + // state consistent again. Invocations of BeginUpdate may nest. On + // invoking the last non nested EndUpdate an implicit "commit" should + // be performed by the store/provider. The concrete mechanism is + // unspecified. It could be for example a write-ahead log. Stores may + // implement BeginUpdate and EndUpdate as a (documented) no op. + BeginUpdate() error + EndUpdate() error +} + +// Mutate is a helper/wrapper for executing f in between a.BeginUpdate and +// a.EndUpdate. Any parameters and/or return values except an error should be +// captured by a function literal passed as f. The returned err is either nil +// or the first non nil error returned from the sequence of execution: +// BeginUpdate, [f,] EndUpdate. The pair BeginUpdate/EndUpdate *is* invoked +// always regardles of any possible errors produced. Mutate doesn't handle +// panic, it should be used only with a function [literal] which doesn't panic. +// Otherwise the pairing of BeginUpdate/EndUpdate is not guaranteed. +// +// NOTE: If BeginUpdate, which is invoked before f, returns a non-nil error, +// then f is not invoked at all (but EndUpdate still is). +func Mutate(a Accessor, f func() error) (err error) { + defer func() { + if e := a.EndUpdate(); e != nil && err == nil { + err = e + } + }() + + if err = a.BeginUpdate(); err != nil { + return + } + + return f() +} + +// LockedMutate wraps Mutate in yet another layer consisting of a +// l.Lock/l.Unlock pair. All other limitations apply as in Mutate, e.g. no +// panics are allowed to happen - otherwise no guarantees can be made about +// Unlock matching the Lock. +func LockedMutate(a Accessor, l sync.Locker, f func() error) (err error) { + l.Lock() + defer l.Unlock() + + return Mutate(a, f) +} diff --git a/vendor/github.com/cznic/fileutil/storage/test_deps.go b/vendor/github.com/cznic/fileutil/storage/test_deps.go new file mode 100644 index 00000000..92ac44a5 --- /dev/null +++ b/vendor/github.com/cznic/fileutil/storage/test_deps.go @@ -0,0 +1,13 @@ +// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// blame: jnml, labs.nic.cz + +package storage + +// Pull test dependencies too. +// Enables easy 'go test X' after 'go get X' +import ( +// nothing yet +) diff --git a/vendor/github.com/cznic/fileutil/test_deps.go b/vendor/github.com/cznic/fileutil/test_deps.go new file mode 100644 index 00000000..eec608ab --- /dev/null +++ b/vendor/github.com/cznic/fileutil/test_deps.go @@ -0,0 +1,13 @@ +// Copyright (c) 2014 The fileutil Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// blame: jnml, labs.nic.cz + +package fileutil + +// Pull test dependencies too. +// Enables easy 'go test X' after 'go get X' +import ( +// nothing yet +) diff --git a/vendor/github.com/cznic/mathutil/LICENSE b/vendor/github.com/cznic/mathutil/LICENSE new file mode 100644 index 00000000..128a1b64 --- /dev/null +++ b/vendor/github.com/cznic/mathutil/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2014 The mathutil Authors. 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 names of the authors nor the names of the +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/vendor/github.com/cznic/mathutil/bits.go b/vendor/github.com/cznic/mathutil/bits.go new file mode 100644 index 00000000..6eaa4e30 --- /dev/null +++ b/vendor/github.com/cznic/mathutil/bits.go @@ -0,0 +1,207 @@ +// Copyright (c) 2014 The mathutil 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 mathutil + +import ( + "math/big" +) + +// BitLenByte returns the bit width of the non zero part of n. +func BitLenByte(n byte) int { + return log2[n] + 1 +} + +// BitLenUint16 returns the bit width of the non zero part of n. +func BitLenUint16(n uint16) int { + if b := n >> 8; b != 0 { + return log2[b] + 8 + 1 + } + + return log2[n] + 1 +} + +// BitLenUint32 returns the bit width of the non zero part of n. +func BitLenUint32(n uint32) int { + if b := n >> 24; b != 0 { + return log2[b] + 24 + 1 + } + + if b := n >> 16; b != 0 { + return log2[b] + 16 + 1 + } + + if b := n >> 8; b != 0 { + return log2[b] + 8 + 1 + } + + return log2[n] + 1 +} + +// BitLen returns the bit width of the non zero part of n. +func BitLen(n int) int { // Should handle correctly [future] 64 bit Go ints + if IntBits == 64 { + return BitLenUint64(uint64(n)) + } + + if b := byte(n >> 24); b != 0 { + return log2[b] + 24 + 1 + } + + if b := byte(n >> 16); b != 0 { + return log2[b] + 16 + 1 + } + + if b := byte(n >> 8); b != 0 { + return log2[b] + 8 + 1 + } + + return log2[byte(n)] + 1 +} + +// BitLenUint returns the bit width of the non zero part of n. +func BitLenUint(n uint) int { // Should handle correctly [future] 64 bit Go uints + if IntBits == 64 { + return BitLenUint64(uint64(n)) + } + + if b := n >> 24; b != 0 { + return log2[b] + 24 + 1 + } + + if b := n >> 16; b != 0 { + return log2[b] + 16 + 1 + } + + if b := n >> 8; b != 0 { + return log2[b] + 8 + 1 + } + + return log2[n] + 1 +} + +// BitLenUint64 returns the bit width of the non zero part of n. +func BitLenUint64(n uint64) int { + if b := n >> 56; b != 0 { + return log2[b] + 56 + 1 + } + + if b := n >> 48; b != 0 { + return log2[b] + 48 + 1 + } + + if b := n >> 40; b != 0 { + return log2[b] + 40 + 1 + } + + if b := n >> 32; b != 0 { + return log2[b] + 32 + 1 + } + + if b := n >> 24; b != 0 { + return log2[b] + 24 + 1 + } + + if b := n >> 16; b != 0 { + return log2[b] + 16 + 1 + } + + if b := n >> 8; b != 0 { + return log2[b] + 8 + 1 + } + + return log2[n] + 1 +} + +// BitLenUintptr returns the bit width of the non zero part of n. +func BitLenUintptr(n uintptr) int { + if b := n >> 56; b != 0 { + return log2[b] + 56 + 1 + } + + if b := n >> 48; b != 0 { + return log2[b] + 48 + 1 + } + + if b := n >> 40; b != 0 { + return log2[b] + 40 + 1 + } + + if b := n >> 32; b != 0 { + return log2[b] + 32 + 1 + } + + if b := n >> 24; b != 0 { + return log2[b] + 24 + 1 + } + + if b := n >> 16; b != 0 { + return log2[b] + 16 + 1 + } + + if b := n >> 8; b != 0 { + return log2[b] + 8 + 1 + } + + return log2[n] + 1 +} + +// PopCountByte returns population count of n (number of bits set in n). +func PopCountByte(n byte) int { + return int(popcnt[byte(n)]) +} + +// PopCountUint16 returns population count of n (number of bits set in n). +func PopCountUint16(n uint16) int { + return int(popcnt[byte(n>>8)]) + int(popcnt[byte(n)]) +} + +// PopCountUint32 returns population count of n (number of bits set in n). +func PopCountUint32(n uint32) int { + return int(popcnt[byte(n>>24)]) + int(popcnt[byte(n>>16)]) + + int(popcnt[byte(n>>8)]) + int(popcnt[byte(n)]) +} + +// PopCount returns population count of n (number of bits set in n). +func PopCount(n int) int { // Should handle correctly [future] 64 bit Go ints + if IntBits == 64 { + return PopCountUint64(uint64(n)) + } + + return PopCountUint32(uint32(n)) +} + +// PopCountUint returns population count of n (number of bits set in n). +func PopCountUint(n uint) int { // Should handle correctly [future] 64 bit Go uints + if IntBits == 64 { + return PopCountUint64(uint64(n)) + } + + return PopCountUint32(uint32(n)) +} + +// PopCountUintptr returns population count of n (number of bits set in n). +func PopCountUintptr(n uintptr) int { + if UintPtrBits == 64 { + return PopCountUint64(uint64(n)) + } + + return PopCountUint32(uint32(n)) +} + +// PopCountUint64 returns population count of n (number of bits set in n). +func PopCountUint64(n uint64) int { + return int(popcnt[byte(n>>56)]) + int(popcnt[byte(n>>48)]) + + int(popcnt[byte(n>>40)]) + int(popcnt[byte(n>>32)]) + + int(popcnt[byte(n>>24)]) + int(popcnt[byte(n>>16)]) + + int(popcnt[byte(n>>8)]) + int(popcnt[byte(n)]) +} + +// PopCountBigInt returns population count of |n| (number of bits set in |n|). +func PopCountBigInt(n *big.Int) (r int) { + for _, v := range n.Bits() { + r += PopCountUintptr(uintptr(v)) + } + return +} diff --git a/vendor/github.com/cznic/mathutil/envelope.go b/vendor/github.com/cznic/mathutil/envelope.go new file mode 100644 index 00000000..ff8e6012 --- /dev/null +++ b/vendor/github.com/cznic/mathutil/envelope.go @@ -0,0 +1,46 @@ +// Copyright (c) 2014 The mathutil 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 mathutil + +import ( + "math" +) + +// Approximation type determines approximation methods used by e.g. Envelope. +type Approximation int + +// Specific approximation method tags +const ( + _ Approximation = iota + Linear // As named + Sinusoidal // Smooth for all derivations +) + +// Envelope is an utility for defining simple curves using a small (usually) +// set of data points. Envelope returns a value defined by x, points and +// approximation. The value of x must be in [0,1) otherwise the result is +// undefined or the function may panic. Points are interpreted as dividing the +// [0,1) interval in len(points)-1 sections, so len(points) must be > 1 or the +// function may panic. According to the left and right points closing/adjacent +// to the section the resulting value is interpolated using the chosen +// approximation method. Unsupported values of approximation are silently +// interpreted as 'Linear'. +func Envelope(x float64, points []float64, approximation Approximation) float64 { + step := 1 / float64(len(points)-1) + fslot := math.Floor(x / step) + mod := x - fslot*step + slot := int(fslot) + l, r := points[slot], points[slot+1] + rmod := mod / step + switch approximation { + case Sinusoidal: + k := (math.Sin(math.Pi*(rmod-0.5)) + 1) / 2 + return l + (r-l)*k + case Linear: + fallthrough + default: + return l + (r-l)*rmod + } +} diff --git a/vendor/github.com/cznic/mathutil/example/example.go b/vendor/github.com/cznic/mathutil/example/example.go new file mode 100644 index 00000000..30a2d115 --- /dev/null +++ b/vendor/github.com/cznic/mathutil/example/example.go @@ -0,0 +1,48 @@ +// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// blame: jnml, labs.nic.cz + +// +build ignore + +package main + +import ( + "bufio" + "flag" + "github.com/cznic/mathutil" + "log" + "math" + "os" +) + +/* + +$ # Usage e.g.: +$ go run example.go -max 1024 > mathutil.dat # generate 1kB of "random" data + +*/ +func main() { + r, err := mathutil.NewFC32(math.MinInt32, math.MaxInt32, true) + if err != nil { + log.Fatal(err) + } + + var mflag uint64 + flag.Uint64Var(&mflag, "max", 0, "limit output to max bytes") + flag.Parse() + stdout := bufio.NewWriter(os.Stdout) + if mflag != 0 { + for i := uint64(0); i < mflag; i++ { + if err := stdout.WriteByte(byte(r.Next())); err != nil { + log.Fatal(err) + } + } + stdout.Flush() + return + } + + for stdout.WriteByte(byte(r.Next())) == nil { + } +} diff --git a/vendor/github.com/cznic/mathutil/example2/example2.go b/vendor/github.com/cznic/mathutil/example2/example2.go new file mode 100644 index 00000000..409aeef3 --- /dev/null +++ b/vendor/github.com/cznic/mathutil/example2/example2.go @@ -0,0 +1,66 @@ +// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// blame: jnml, labs.nic.cz + +// +build ignore + +package main + +import ( + "bytes" + "github.com/cznic/mathutil" + "image" + "image/png" + "io/ioutil" + "log" + "math" + "math/rand" +) + +// $ go run example2.go # view rand.png and rnd.png by your favorite pic viewer +// +// see http://www.boallen.com/random-numbers.html +func main() { + sqr := image.Rect(0, 0, 511, 511) + r, err := mathutil.NewFC32(math.MinInt32, math.MaxInt32, true) + if err != nil { + log.Fatal("NewFC32", err) + } + + img := image.NewGray(sqr) + for y := 0; y < 512; y++ { + for x := 0; x < 512; x++ { + if r.Next()&1 != 0 { + img.Set(x, y, image.White) + } + } + } + buf := bytes.NewBuffer(nil) + if err := png.Encode(buf, img); err != nil { + log.Fatal("Encode rnd.png ", err) + } + + if err := ioutil.WriteFile("rnd.png", buf.Bytes(), 0666); err != nil { + log.Fatal("ioutil.WriteFile/rnd.png ", err) + } + + r2 := rand.New(rand.NewSource(0)) + img = image.NewGray(sqr) + for y := 0; y < 512; y++ { + for x := 0; x < 512; x++ { + if r2.Int()&1 != 0 { + img.Set(x, y, image.White) + } + } + } + buf = bytes.NewBuffer(nil) + if err := png.Encode(buf, img); err != nil { + log.Fatal("Encode rand.png ", err) + } + + if err := ioutil.WriteFile("rand.png", buf.Bytes(), 0666); err != nil { + log.Fatal("ioutil.WriteFile/rand.png ", err) + } +} diff --git a/vendor/github.com/cznic/mathutil/example3/example3.go b/vendor/github.com/cznic/mathutil/example3/example3.go new file mode 100644 index 00000000..572d108b --- /dev/null +++ b/vendor/github.com/cznic/mathutil/example3/example3.go @@ -0,0 +1,43 @@ +// Copyright (c) 2011 CZ.NIC z.s.p.o. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// blame: jnml, labs.nic.cz + +// +build ignore + +package main + +import ( + "bufio" + "flag" + "log" + "math/rand" + "os" +) + +/* + +$ # Usage e.g.: +$ go run example3.go -max 1024 > rand.dat # generate 1kB of "random" data + +*/ +func main() { + r := rand.New(rand.NewSource(1)) + var mflag uint64 + flag.Uint64Var(&mflag, "max", 0, "limit output to max bytes") + flag.Parse() + stdout := bufio.NewWriter(os.Stdout) + if mflag != 0 { + for i := uint64(0); i < mflag; i++ { + if err := stdout.WriteByte(byte(r.Int())); err != nil { + log.Fatal(err) + } + } + stdout.Flush() + return + } + + for stdout.WriteByte(byte(r.Int())) == nil { + } +} diff --git a/vendor/github.com/cznic/mathutil/example4/main.go b/vendor/github.com/cznic/mathutil/example4/main.go new file mode 100644 index 00000000..52b35655 --- /dev/null +++ b/vendor/github.com/cznic/mathutil/example4/main.go @@ -0,0 +1,90 @@ +// Copyright (c) 2011 jnml. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// Let QRN be the number of quadratic residues of N. Let Q be QRN/N. From a +// sorted list of primorial products < 2^32 find "record breakers". "Record +// breaker" is N with new lowest Q. +// +// There are only 49 "record breakers" < 2^32. +// +// To run the example $ go run main.go +package main + +import ( + "fmt" + "math" + "sort" + "time" + + "github.com/cznic/mathutil" + "github.com/cznic/sortutil" +) + +func main() { + pp := mathutil.PrimorialProductsUint32(0, math.MaxUint32, 32) + sort.Sort(sortutil.Uint32Slice(pp)) + var bestN, bestD uint32 = 1, 1 + order, checks := 0, 0 + var ixDirty uint32 + m := make([]byte, math.MaxUint32>>3) + for _, n := range pp { + for i := range m[:ixDirty+1] { + m[i] = 0 + } + ixDirty = 0 + checks++ + limit0 := mathutil.QScaleUint32(n, bestN, bestD) + if limit0 > math.MaxUint32 { + panic(0) + } + limit := uint32(limit0) + n64 := uint64(n) + hi := n64 >> 1 + hits := uint32(0) + check := true + fmt.Printf("\r%10d %d/%d", n, checks, len(pp)) + t0 := time.Now() + for i := uint64(0); i < hi; i++ { + sq := uint32(i * i % n64) + ix := sq >> 3 + msk := byte(1 << (sq & 7)) + if m[ix]&msk == 0 { + hits++ + if hits >= limit { + check = false + break + } + } + m[ix] |= msk + if ix > ixDirty { + ixDirty = ix + } + } + + adjPrime := ".." // Composite before + if mathutil.IsPrime(n - 1) { + adjPrime = "P." // Prime before + } + switch mathutil.IsPrime(n + 1) { + case true: + adjPrime += "P" // Prime after + case false: + adjPrime += "." // Composite after + } + + if check && mathutil.QCmpUint32(hits, n, bestN, bestD) < 0 { + order++ + d := time.Since(t0) + bestN, bestD = hits, n + q := float64(hits) / float64(n) + fmt.Printf( + "\r%2s #%03d %d %d %.2f %.2E %s %s %v\n", + adjPrime, order, n, hits, + 1/q, q, d, time.Now().Format("15:04:05"), mathutil.FactorInt(n), + ) + } + } +} diff --git a/vendor/github.com/cznic/mathutil/ff/main.go b/vendor/github.com/cznic/mathutil/ff/main.go new file mode 100644 index 00000000..6cec57af --- /dev/null +++ b/vendor/github.com/cznic/mathutil/ff/main.go @@ -0,0 +1,83 @@ +// Copyright (c) jnml. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// Factor Finder - searches for Mersenne number factors of one specific special +// form. +package main + +import ( + "flag" + "fmt" + "math/big" + "runtime" + "time" + + "github.com/cznic/mathutil" +) + +const ( + pp = 1 + pp2 = 10 +) + +var ( + _1 = big.NewInt(1) + _2 = big.NewInt(2) +) + +func main() { + runtime.GOMAXPROCS(2) + oClass := flag.Uint64("c", 2, `factor "class" number`) + oDuration := flag.Duration("d", time.Second, "duration to spend on one class") + flag.Parse() + class := *oClass + for class&1 != 0 { + class >>= 1 + } + class = mathutil.MaxUint64(class, 2) + + for { + c := time.After(*oDuration) + factor := big.NewInt(0) + factor.SetUint64(class) + exp := big.NewInt(0) + oneClass: + for { + select { + case <-c: + break oneClass + default: + } + + exp.Set(factor) + factor.Lsh(factor, 1) + factor.Add(factor, _1) + if !factor.ProbablyPrime(pp) { + continue + } + + if !exp.ProbablyPrime(pp) { + continue + } + + if mathutil.ModPowBigInt(_2, exp, factor).Cmp(_1) != 0 { + continue + } + + if !factor.ProbablyPrime(pp2) { + continue + } + + if !exp.ProbablyPrime(pp2) { + continue + } + + fmt.Printf("%d: %s | M%s (%d bits)\n", class, factor, exp, factor.BitLen()) + } + + class += 2 + } +} diff --git a/vendor/github.com/cznic/mathutil/mathutil.go b/vendor/github.com/cznic/mathutil/mathutil.go new file mode 100644 index 00000000..e8f3f562 --- /dev/null +++ b/vendor/github.com/cznic/mathutil/mathutil.go @@ -0,0 +1,829 @@ +// Copyright (c) 2014 The mathutil 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 mathutil provides utilities supplementing the standard 'math' and +// 'math/rand' packages. +// +// Compatibility issues +// +// 2013-12-13: The following functions have been REMOVED +// +// func Uint64ToBigInt(n uint64) *big.Int +// func Uint64FromBigInt(n *big.Int) (uint64, bool) +// +// 2013-05-13: The following functions are now DEPRECATED +// +// func Uint64ToBigInt(n uint64) *big.Int +// func Uint64FromBigInt(n *big.Int) (uint64, bool) +// +// These functions will be REMOVED with Go release 1.1+1. +// +// 2013-01-21: The following functions have been REMOVED +// +// func MaxInt() int +// func MinInt() int +// func MaxUint() uint +// func UintPtrBits() int +// +// They are now replaced by untyped constants +// +// MaxInt +// MinInt +// MaxUint +// UintPtrBits +// +// Additionally one more untyped constant was added +// +// IntBits +// +// This change breaks any existing code depending on the above removed +// functions. They should have not been published in the first place, that was +// unfortunate. Instead, defining such architecture and/or implementation +// specific integer limits and bit widths as untyped constants improves +// performance and allows for static dead code elimination if it depends on +// these values. Thanks to minux for pointing it out in the mail list +// (https://groups.google.com/d/msg/golang-nuts/tlPpLW6aJw8/NT3mpToH-a4J). +// +// 2012-12-12: The following functions will be DEPRECATED with Go release +// 1.0.3+1 and REMOVED with Go release 1.0.3+2, b/c of +// http://code.google.com/p/go/source/detail?r=954a79ee3ea8 +// +// func Uint64ToBigInt(n uint64) *big.Int +// func Uint64FromBigInt(n *big.Int) (uint64, bool) +package mathutil + +import ( + "math" + "math/big" +) + +// Architecture and/or implementation specific integer limits and bit widths. +const ( + MaxInt = 1<<(IntBits-1) - 1 + MinInt = -MaxInt - 1 + MaxUint = 1<>32&1 + ^uint(0)>>16&1 + ^uint(0)>>8&1 + 3) + UintPtrBits = 1 << (^uintptr(0)>>32&1 + ^uintptr(0)>>16&1 + ^uintptr(0)>>8&1 + 3) +) + +var ( + _1 = big.NewInt(1) + _2 = big.NewInt(2) +) + +// GCDByte returns the greatest common divisor of a and b. Based on: +// http://en.wikipedia.org/wiki/Euclidean_algorithm#Implementations +func GCDByte(a, b byte) byte { + for b != 0 { + a, b = b, a%b + } + return a +} + +// GCDUint16 returns the greatest common divisor of a and b. +func GCDUint16(a, b uint16) uint16 { + for b != 0 { + a, b = b, a%b + } + return a +} + +// GCD returns the greatest common divisor of a and b. +func GCDUint32(a, b uint32) uint32 { + for b != 0 { + a, b = b, a%b + } + return a +} + +// GCD64 returns the greatest common divisor of a and b. +func GCDUint64(a, b uint64) uint64 { + for b != 0 { + a, b = b, a%b + } + return a +} + +// ISqrt returns floor(sqrt(n)). Typical run time is few hundreds of ns. +func ISqrt(n uint32) (x uint32) { + if n == 0 { + return + } + + if n >= math.MaxUint16*math.MaxUint16 { + return math.MaxUint16 + } + + var px, nx uint32 + for x = n; ; px, x = x, nx { + nx = (x + n/x) / 2 + if nx == x || nx == px { + break + } + } + return +} + +// SqrtUint64 returns floor(sqrt(n)). Typical run time is about 0.5 µs. +func SqrtUint64(n uint64) (x uint64) { + if n == 0 { + return + } + + if n >= math.MaxUint32*math.MaxUint32 { + return math.MaxUint32 + } + + var px, nx uint64 + for x = n; ; px, x = x, nx { + nx = (x + n/x) / 2 + if nx == x || nx == px { + break + } + } + return +} + +// SqrtBig returns floor(sqrt(n)). It panics on n < 0. +func SqrtBig(n *big.Int) (x *big.Int) { + switch n.Sign() { + case -1: + panic(-1) + case 0: + return big.NewInt(0) + } + + var px, nx big.Int + x = big.NewInt(0) + x.SetBit(x, n.BitLen()/2+1, 1) + for { + nx.Rsh(nx.Add(x, nx.Div(n, x)), 1) + if nx.Cmp(x) == 0 || nx.Cmp(&px) == 0 { + break + } + px.Set(x) + x.Set(&nx) + } + return +} + +// Log2Byte returns log base 2 of n. It's the same as index of the highest +// bit set in n. For n == 0 -1 is returned. +func Log2Byte(n byte) int { + return log2[n] +} + +// Log2Uint16 returns log base 2 of n. It's the same as index of the highest +// bit set in n. For n == 0 -1 is returned. +func Log2Uint16(n uint16) int { + if b := n >> 8; b != 0 { + return log2[b] + 8 + } + + return log2[n] +} + +// Log2Uint32 returns log base 2 of n. It's the same as index of the highest +// bit set in n. For n == 0 -1 is returned. +func Log2Uint32(n uint32) int { + if b := n >> 24; b != 0 { + return log2[b] + 24 + } + + if b := n >> 16; b != 0 { + return log2[b] + 16 + } + + if b := n >> 8; b != 0 { + return log2[b] + 8 + } + + return log2[n] +} + +// Log2Uint64 returns log base 2 of n. It's the same as index of the highest +// bit set in n. For n == 0 -1 is returned. +func Log2Uint64(n uint64) int { + if b := n >> 56; b != 0 { + return log2[b] + 56 + } + + if b := n >> 48; b != 0 { + return log2[b] + 48 + } + + if b := n >> 40; b != 0 { + return log2[b] + 40 + } + + if b := n >> 32; b != 0 { + return log2[b] + 32 + } + + if b := n >> 24; b != 0 { + return log2[b] + 24 + } + + if b := n >> 16; b != 0 { + return log2[b] + 16 + } + + if b := n >> 8; b != 0 { + return log2[b] + 8 + } + + return log2[n] +} + +// ModPowByte computes (b^e)%m. It panics for m == 0 || b == e == 0. +// +// See also: http://en.wikipedia.org/wiki/Modular_exponentiation#Right-to-left_binary_method +func ModPowByte(b, e, m byte) byte { + if b == 0 && e == 0 { + panic(0) + } + + if m == 1 { + return 0 + } + + r := uint16(1) + for b, m := uint16(b), uint16(m); e > 0; b, e = b*b%m, e>>1 { + if e&1 == 1 { + r = r * b % m + } + } + return byte(r) +} + +// ModPowByte computes (b^e)%m. It panics for m == 0 || b == e == 0. +func ModPowUint16(b, e, m uint16) uint16 { + if b == 0 && e == 0 { + panic(0) + } + + if m == 1 { + return 0 + } + + r := uint32(1) + for b, m := uint32(b), uint32(m); e > 0; b, e = b*b%m, e>>1 { + if e&1 == 1 { + r = r * b % m + } + } + return uint16(r) +} + +// ModPowUint32 computes (b^e)%m. It panics for m == 0 || b == e == 0. +func ModPowUint32(b, e, m uint32) uint32 { + if b == 0 && e == 0 { + panic(0) + } + + if m == 1 { + return 0 + } + + r := uint64(1) + for b, m := uint64(b), uint64(m); e > 0; b, e = b*b%m, e>>1 { + if e&1 == 1 { + r = r * b % m + } + } + return uint32(r) +} + +// ModPowUint64 computes (b^e)%m. It panics for m == 0 || b == e == 0. +func ModPowUint64(b, e, m uint64) (r uint64) { + if b == 0 && e == 0 { + panic(0) + } + + if m == 1 { + return 0 + } + + return modPowBigInt(big.NewInt(0).SetUint64(b), big.NewInt(0).SetUint64(e), big.NewInt(0).SetUint64(m)).Uint64() +} + +func modPowBigInt(b, e, m *big.Int) (r *big.Int) { + r = big.NewInt(1) + for i, n := 0, e.BitLen(); i < n; i++ { + if e.Bit(i) != 0 { + r.Mod(r.Mul(r, b), m) + } + b.Mod(b.Mul(b, b), m) + } + return +} + +// ModPowBigInt computes (b^e)%m. Returns nil for e < 0. It panics for m == 0 || b == e == 0. +func ModPowBigInt(b, e, m *big.Int) (r *big.Int) { + if b.Sign() == 0 && e.Sign() == 0 { + panic(0) + } + + if m.Cmp(_1) == 0 { + return big.NewInt(0) + } + + if e.Sign() < 0 { + return + } + + return modPowBigInt(big.NewInt(0).Set(b), big.NewInt(0).Set(e), m) +} + +var uint64ToBigIntDelta big.Int + +func init() { + uint64ToBigIntDelta.SetBit(&uint64ToBigIntDelta, 63, 1) +} + +var uintptrBits int + +func init() { + x := uint64(math.MaxUint64) + uintptrBits = BitLenUintptr(uintptr(x)) +} + +// UintptrBits returns the bit width of an uintptr at the executing machine. +func UintptrBits() int { + return uintptrBits +} + +// AddUint128_64 returns the uint128 sum of uint64 a and b. +func AddUint128_64(a, b uint64) (hi uint64, lo uint64) { + lo = a + b + if lo < a { + hi = 1 + } + return +} + +// MulUint128_64 returns the uint128 bit product of uint64 a and b. +func MulUint128_64(a, b uint64) (hi, lo uint64) { + /* + 2^(2 W) ahi bhi + 2^W alo bhi + 2^W ahi blo + alo blo + + FEDCBA98 76543210 FEDCBA98 76543210 + ---- alo*blo ---- + ---- alo*bhi ---- + ---- ahi*blo ---- + ---- ahi*bhi ---- + */ + const w = 32 + const m = 1<>w, b>>w, a&m, b&m + lo = alo * blo + mid1 := alo * bhi + mid2 := ahi * blo + c1, lo := AddUint128_64(lo, mid1<>w+mid2>>w+uint64(c1+c2)) + return +} + +// PowerizeBigInt returns (e, p) such that e is the smallest number for which p +// == b^e is greater or equal n. For n < 0 or b < 2 (0, nil) is returned. +// +// NOTE: Run time for large values of n (above about 2^1e6 ~= 1e300000) can be +// significant and/or unacceptabe. For any smaller values of n the function +// typically performs in sub second time. For "small" values of n (cca bellow +// 2^1e3 ~= 1e300) the same can be easily below 10 µs. +// +// A special (and trivial) case of b == 2 is handled separately and performs +// much faster. +func PowerizeBigInt(b, n *big.Int) (e uint32, p *big.Int) { + switch { + case b.Cmp(_2) < 0 || n.Sign() < 0: + return + case n.Sign() == 0 || n.Cmp(_1) == 0: + return 0, big.NewInt(1) + case b.Cmp(_2) == 0: + p = big.NewInt(0) + e = uint32(n.BitLen() - 1) + p.SetBit(p, int(e), 1) + if p.Cmp(n) < 0 { + p.Mul(p, _2) + e++ + } + return + } + + bw := b.BitLen() + nw := n.BitLen() + p = big.NewInt(1) + var bb, r big.Int + for { + switch p.Cmp(n) { + case -1: + x := uint32((nw - p.BitLen()) / bw) + if x == 0 { + x = 1 + } + e += x + switch x { + case 1: + p.Mul(p, b) + default: + r.Set(_1) + bb.Set(b) + e := x + for { + if e&1 != 0 { + r.Mul(&r, &bb) + } + if e >>= 1; e == 0 { + break + } + + bb.Mul(&bb, &bb) + } + p.Mul(p, &r) + } + case 0, 1: + return + } + } +} + +// PowerizeUint32BigInt returns (e, p) such that e is the smallest number for +// which p == b^e is greater or equal n. For n < 0 or b < 2 (0, nil) is +// returned. +// +// More info: see PowerizeBigInt. +func PowerizeUint32BigInt(b uint32, n *big.Int) (e uint32, p *big.Int) { + switch { + case b < 2 || n.Sign() < 0: + return + case n.Sign() == 0 || n.Cmp(_1) == 0: + return 0, big.NewInt(1) + case b == 2: + p = big.NewInt(0) + e = uint32(n.BitLen() - 1) + p.SetBit(p, int(e), 1) + if p.Cmp(n) < 0 { + p.Mul(p, _2) + e++ + } + return + } + + var bb big.Int + bb.SetInt64(int64(b)) + return PowerizeBigInt(&bb, n) +} + +/* +ProbablyPrimeUint32 returns true if n is prime or n is a pseudoprime to base a. +It implements the Miller-Rabin primality test for one specific value of 'a' and +k == 1. + +Wrt pseudocode shown at +http://en.wikipedia.org/wiki/Miller-Rabin_primality_test#Algorithm_and_running_time + + Input: n > 3, an odd integer to be tested for primality; + Input: k, a parameter that determines the accuracy of the test + Output: composite if n is composite, otherwise probably prime + write n − 1 as 2^s·d with d odd by factoring powers of 2 from n − 1 + LOOP: repeat k times: + pick a random integer a in the range [2, n − 2] + x ← a^d mod n + if x = 1 or x = n − 1 then do next LOOP + for r = 1 .. s − 1 + x ← x^2 mod n + if x = 1 then return composite + if x = n − 1 then do next LOOP + return composite + return probably prime + +... this function behaves like passing 1 for 'k' and additionaly a +fixed/non-random 'a'. Otherwise it's the same algorithm. + +See also: http://mathworld.wolfram.com/Rabin-MillerStrongPseudoprimeTest.html +*/ +func ProbablyPrimeUint32(n, a uint32) bool { + d, s := n-1, 0 + for ; d&1 == 0; d, s = d>>1, s+1 { + } + x := uint64(ModPowUint32(a, d, n)) + if x == 1 || uint32(x) == n-1 { + return true + } + + for ; s > 1; s-- { + if x = x * x % uint64(n); x == 1 { + return false + } + + if uint32(x) == n-1 { + return true + } + } + return false +} + +// ProbablyPrimeUint64_32 returns true if n is prime or n is a pseudoprime to +// base a. It implements the Miller-Rabin primality test for one specific value +// of 'a' and k == 1. See also ProbablyPrimeUint32. +func ProbablyPrimeUint64_32(n uint64, a uint32) bool { + d, s := n-1, 0 + for ; d&1 == 0; d, s = d>>1, s+1 { + } + x := ModPowUint64(uint64(a), d, n) + if x == 1 || x == n-1 { + return true + } + + bx, bn := big.NewInt(0).SetUint64(x), big.NewInt(0).SetUint64(n) + for ; s > 1; s-- { + if x = bx.Mod(bx.Mul(bx, bx), bn).Uint64(); x == 1 { + return false + } + + if x == n-1 { + return true + } + } + return false +} + +// ProbablyPrimeBigInt_32 returns true if n is prime or n is a pseudoprime to +// base a. It implements the Miller-Rabin primality test for one specific value +// of 'a' and k == 1. See also ProbablyPrimeUint32. +func ProbablyPrimeBigInt_32(n *big.Int, a uint32) bool { + var d big.Int + d.Set(n) + d.Sub(&d, _1) // d <- n-1 + s := 0 + for ; d.Bit(s) == 0; s++ { + } + nMinus1 := big.NewInt(0).Set(&d) + d.Rsh(&d, uint(s)) + + x := ModPowBigInt(big.NewInt(int64(a)), &d, n) + if x.Cmp(_1) == 0 || x.Cmp(nMinus1) == 0 { + return true + } + + for ; s > 1; s-- { + if x = x.Mod(x.Mul(x, x), n); x.Cmp(_1) == 0 { + return false + } + + if x.Cmp(nMinus1) == 0 { + return true + } + } + return false +} + +// ProbablyPrimeBigInt returns true if n is prime or n is a pseudoprime to base +// a. It implements the Miller-Rabin primality test for one specific value of +// 'a' and k == 1. See also ProbablyPrimeUint32. +func ProbablyPrimeBigInt(n, a *big.Int) bool { + var d big.Int + d.Set(n) + d.Sub(&d, _1) // d <- n-1 + s := 0 + for ; d.Bit(s) == 0; s++ { + } + nMinus1 := big.NewInt(0).Set(&d) + d.Rsh(&d, uint(s)) + + x := ModPowBigInt(a, &d, n) + if x.Cmp(_1) == 0 || x.Cmp(nMinus1) == 0 { + return true + } + + for ; s > 1; s-- { + if x = x.Mod(x.Mul(x, x), n); x.Cmp(_1) == 0 { + return false + } + + if x.Cmp(nMinus1) == 0 { + return true + } + } + return false +} + +// Max returns the larger of a and b. +func Max(a, b int) int { + if a > b { + return a + } + + return b +} + +// Min returns the smaller of a and b. +func Min(a, b int) int { + if a < b { + return a + } + + return b +} + +// UMax returns the larger of a and b. +func UMax(a, b uint) uint { + if a > b { + return a + } + + return b +} + +// UMin returns the smaller of a and b. +func UMin(a, b uint) uint { + if a < b { + return a + } + + return b +} + +// MaxByte returns the larger of a and b. +func MaxByte(a, b byte) byte { + if a > b { + return a + } + + return b +} + +// MinByte returns the smaller of a and b. +func MinByte(a, b byte) byte { + if a < b { + return a + } + + return b +} + +// MaxInt8 returns the larger of a and b. +func MaxInt8(a, b int8) int8 { + if a > b { + return a + } + + return b +} + +// MinInt8 returns the smaller of a and b. +func MinInt8(a, b int8) int8 { + if a < b { + return a + } + + return b +} + +// MaxUint16 returns the larger of a and b. +func MaxUint16(a, b uint16) uint16 { + if a > b { + return a + } + + return b +} + +// MinUint16 returns the smaller of a and b. +func MinUint16(a, b uint16) uint16 { + if a < b { + return a + } + + return b +} + +// MaxInt16 returns the larger of a and b. +func MaxInt16(a, b int16) int16 { + if a > b { + return a + } + + return b +} + +// MinInt16 returns the smaller of a and b. +func MinInt16(a, b int16) int16 { + if a < b { + return a + } + + return b +} + +// MaxUint32 returns the larger of a and b. +func MaxUint32(a, b uint32) uint32 { + if a > b { + return a + } + + return b +} + +// MinUint32 returns the smaller of a and b. +func MinUint32(a, b uint32) uint32 { + if a < b { + return a + } + + return b +} + +// MaxInt32 returns the larger of a and b. +func MaxInt32(a, b int32) int32 { + if a > b { + return a + } + + return b +} + +// MinInt32 returns the smaller of a and b. +func MinInt32(a, b int32) int32 { + if a < b { + return a + } + + return b +} + +// MaxUint64 returns the larger of a and b. +func MaxUint64(a, b uint64) uint64 { + if a > b { + return a + } + + return b +} + +// MinUint64 returns the smaller of a and b. +func MinUint64(a, b uint64) uint64 { + if a < b { + return a + } + + return b +} + +// MaxInt64 returns the larger of a and b. +func MaxInt64(a, b int64) int64 { + if a > b { + return a + } + + return b +} + +// MinInt64 returns the smaller of a and b. +func MinInt64(a, b int64) int64 { + if a < b { + return a + } + + return b +} + +// ToBase produces n in base b. For example +// +// ToBase(2047, 22) -> [1, 5, 4] +// +// 1 * 22^0 1 +// 5 * 22^1 110 +// 4 * 22^2 1936 +// ---- +// 2047 +// +// ToBase panics for bases < 2. +func ToBase(n *big.Int, b int) []int { + var nn big.Int + nn.Set(n) + if b < 2 { + panic("invalid base") + } + + k := 1 + switch nn.Sign() { + case -1: + nn.Neg(&nn) + k = -1 + case 0: + return []int{0} + } + + bb := big.NewInt(int64(b)) + var r []int + rem := big.NewInt(0) + for nn.Sign() != 0 { + nn.QuoRem(&nn, bb, rem) + r = append(r, k*int(rem.Int64())) + } + return r +} diff --git a/vendor/github.com/cznic/mathutil/mersenne/mersenne.go b/vendor/github.com/cznic/mathutil/mersenne/mersenne.go new file mode 100644 index 00000000..3eb3f5b1 --- /dev/null +++ b/vendor/github.com/cznic/mathutil/mersenne/mersenne.go @@ -0,0 +1,297 @@ +// Copyright (c) 2014 The mersenne 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 mersenne collects utilities related to Mersenne numbers[1] and/or some +of their properties. + +Exponent + +In this documentation the term 'exponent' refers to 'n' of a Mersenne number Mn +equal to 2^n-1. This package supports only uint32 sized exponents. New() +currently supports exponents only up to math.MaxInt32 (31 bits, up to 256 MB +required to represent such Mn in memory as a big.Int). + +Links + +Referenced from above: + [1] http://en.wikipedia.org/wiki/Mersenne_number +*/ +package mersenne + +import ( + "math" + "math/big" + + "github.com/cznic/mathutil" + "github.com/remyoudompheng/bigfft" +) + +var ( + _0 = big.NewInt(0) + _1 = big.NewInt(1) + _2 = big.NewInt(2) +) + +// Knowns list the exponent of currently (March 2012) known Mersenne primes +// exponents in order. See also: http://oeis.org/A000043 for a partial list. +var Knowns = []uint32{ + 2, // #1 + 3, // #2 + 5, // #3 + 7, // #4 + 13, // #5 + 17, // #6 + 19, // #7 + 31, // #8 + 61, // #9 + 89, // #10 + + 107, // #11 + 127, // #12 + 521, // #13 + 607, // #14 + 1279, // #15 + 2203, // #16 + 2281, // #17 + 3217, // #18 + 4253, // #19 + 4423, // #20 + + 9689, // #21 + 9941, // #22 + 11213, // #23 + 19937, // #24 + 21701, // #25 + 23209, // #26 + 44497, // #27 + 86243, // #28 + 110503, // #29 + 132049, // #30 + + 216091, // #31 + 756839, // #32 + 859433, // #33 + 1257787, // #34 + 1398269, // #35 + 2976221, // #36 + 3021377, // #37 + 6972593, // #38 + 13466917, // #39 + 20996011, // #40 + + 24036583, // #41 + 25964951, // #42 + 30402457, // #43 + 32582657, // #44 + 37156667, // #45 + 42643801, // #46 + 43112609, // #47 + 57885161, // #48 + 74207281, // #49 +} + +// Known maps the exponent of known Mersenne primes its ordinal number/rank. +// Ranks > 41 are currently provisional. +var Known map[uint32]int + +func init() { + Known = map[uint32]int{} + for i, v := range Knowns { + Known[v] = i + 1 + } +} + +// New returns Mn == 2^n-1 for n <= math.MaxInt32 or nil otherwise. +func New(n uint32) (m *big.Int) { + if n > math.MaxInt32 { + return + } + + m = big.NewInt(0) + return m.Sub(m.SetBit(m, int(n), 1), _1) +} + +// HasFactorUint32 returns true if d | Mn. Typical run time for a 32 bit factor +// and a 32 bit exponent is < 1 µs. +func HasFactorUint32(d, n uint32) bool { + return d == 1 || d&1 != 0 && mathutil.ModPowUint32(2, n, d) == 1 +} + +// HasFactorUint64 returns true if d | Mn. Typical run time for a 64 bit factor +// and a 32 bit exponent is < 30 µs. +func HasFactorUint64(d uint64, n uint32) bool { + return d == 1 || d&1 != 0 && mathutil.ModPowUint64(2, uint64(n), d) == 1 +} + +// HasFactorBigInt returns true if d | Mn, d > 0. Typical run time for a 128 +// bit factor and a 32 bit exponent is < 75 µs. +func HasFactorBigInt(d *big.Int, n uint32) bool { + return d.Cmp(_1) == 0 || d.Sign() > 0 && d.Bit(0) == 1 && + mathutil.ModPowBigInt(_2, big.NewInt(int64(n)), d).Cmp(_1) == 0 +} + +// HasFactorBigInt2 returns true if d | Mn, d > 0 +func HasFactorBigInt2(d, n *big.Int) bool { + return d.Cmp(_1) == 0 || d.Sign() > 0 && d.Bit(0) == 1 && + mathutil.ModPowBigInt(_2, n, d).Cmp(_1) == 0 +} + +/* +FromFactorBigInt returns n such that d | Mn if n <= max and d is odd. In other +cases zero is returned. + +It is conjectured that every odd d ∊ N divides infinitely many Mersenne numbers. +The returned n should be the exponent of smallest such Mn. + +NOTE: The computation of n from a given d performs roughly in O(n). It is +thus highly recomended to use the 'max' argument to limit the "searched" +exponent upper bound as appropriate. Otherwise the computation can take a long +time as a large factor can be a divisor of a Mn with exponent above the uint32 +limits. + +The FromFactorBigInt function is a modification of the original Will +Edgington's "reverse method", discussed here: +http://tech.groups.yahoo.com/group/primenumbers/message/15061 +*/ +func FromFactorBigInt(d *big.Int, max uint32) (n uint32) { + if d.Bit(0) == 0 { + return + } + + var m big.Int + for n < max { + m.Add(&m, d) + i := 0 + for ; m.Bit(i) == 1; i++ { + if n == math.MaxUint32 { + return 0 + } + + n++ + } + m.Rsh(&m, uint(i)) + if m.Sign() == 0 { + if n > max { + n = 0 + } + return + } + } + return 0 +} + +// Mod sets mod to n % Mexp and returns mod. It panics for exp == 0 || exp >= +// math.MaxInt32 || n < 0. +func Mod(mod, n *big.Int, exp uint32) *big.Int { + if exp == 0 || exp >= math.MaxInt32 || n.Sign() < 0 { + panic(0) + } + + m := New(exp) + mod.Set(n) + var x big.Int + for mod.BitLen() > int(exp) { + x.Set(mod) + x.Rsh(&x, uint(exp)) + mod.And(mod, m) + mod.Add(mod, &x) + } + if mod.BitLen() == int(exp) && mod.Cmp(m) == 0 { + mod.SetInt64(0) + } + return mod +} + +// ModPow2 returns x such that 2^Me % Mm == 2^x. It panics for m < 2. Typical +// run time is < 1 µs. Use instead of ModPow(2, e, m) wherever possible. +func ModPow2(e, m uint32) (x uint32) { + /* + m < 2 -> panic + e == 0 -> x == 0 + e == 1 -> x == 1 + + 2^M1 % M2 == 2^1 % 3 == 2^1 10 // 2^1, 3, 5, 7 ... +2k + 2^M1 % M3 == 2^1 % 7 == 2^1 010 // 2^1, 4, 7, ... +3k + 2^M1 % M4 == 2^1 % 15 == 2^1 0010 // 2^1, 5, 9, 13... +4k + 2^M1 % M5 == 2^1 % 31 == 2^1 00010 // 2^1, 6, 11, 16... +5k + + 2^M2 % M2 == 2^3 % 3 == 2^1 10.. // 2^3, 5, 7, 9, 11, ... +2k + 2^M2 % M3 == 2^3 % 7 == 2^0 001... // 2^3, 6, 9, 12, 15, ... +3k + 2^M2 % M4 == 2^3 % 15 == 2^3 1000 // 2^3, 7, 11, 15, 19, ... +4k + 2^M2 % M5 == 2^3 % 31 == 2^3 01000 // 2^3, 8, 13, 18, 23, ... +5k + + 2^M3 % M2 == 2^7 % 3 == 2^1 10..--.. // 2^3, 5, 7... +2k + 2^M3 % M3 == 2^7 % 7 == 2^1 010...--- // 2^1, 4, 7... +3k + 2^M3 % M4 == 2^7 % 15 == 2^3 1000.... // +4k + 2^M3 % M5 == 2^7 % 31 == 2^2 00100..... // +5k + 2^M3 % M6 == 2^7 % 63 == 2^1 000010...... // +6k + 2^M3 % M7 == 2^7 % 127 == 2^0 0000001....... + 2^M3 % M8 == 2^7 % 255 == 2^7 10000000 + 2^M3 % M9 == 2^7 % 511 == 2^7 010000000 + + 2^M4 % M2 == 2^15 % 3 == 2^1 10..--..--..--.. + 2^M4 % M3 == 2^15 % 7 == 2^0 1...---...---... + 2^M4 % M4 == 2^15 % 15 == 2^3 1000....----.... + 2^M4 % M5 == 2^15 % 31 == 2^0 1.....-----..... + 2^M4 % M6 == 2^15 % 63 == 2^3 1000......------ + 2^M4 % M7 == 2^15 % 127 == 2^1 10.......------- + 2^M4 % M8 == 2^15 % 255 == 2^7 10000000........ + 2^M4 % M9 == 2^15 % 511 == 2^6 1000000......... + */ + switch { + case m < 2: + panic(0) + case e < 2: + return e + } + + if x = mathutil.ModPowUint32(2, e, m); x == 0 { + return m - 1 + } + + return x - 1 +} + +// ModPow returns b^Me % Mm. Run time grows quickly with 'e' and/or 'm' when b +// != 2 (then ModPow2 is used). +func ModPow(b, e, m uint32) (r *big.Int) { + if m == 1 { + return big.NewInt(0) + } + + if b == 2 { + x := ModPow2(e, m) + r = big.NewInt(0) + r.SetBit(r, int(x), 1) + return + } + + bb := big.NewInt(int64(b)) + r = big.NewInt(1) + for ; e != 0; e-- { + r = bigfft.Mul(r, bb) + Mod(r, r, m) + bb = bigfft.Mul(bb, bb) + Mod(bb, bb, m) + } + return +} + +// ProbablyPrime returns true if Mn is prime or is a pseudoprime to base a. +// Note: Every Mp, prime p, is a prime or is a pseudoprime to base 2, actually +// to every base 2^i, i ∊ [1, p). In contrast - it is conjectured (w/o any +// known counterexamples) that no composite Mp, prime p, is a pseudoprime to +// base 3. +func ProbablyPrime(n, a uint32) bool { + //TODO +test, +bench + if a == 2 { + return ModPow2(n-1, n) == 0 + } + + nMinus1 := New(n) + nMinus1.Sub(nMinus1, _1) + x := ModPow(a, n-1, n) + return x.Cmp(_1) == 0 || x.Cmp(nMinus1) == 0 +} diff --git a/vendor/github.com/cznic/mathutil/permute.go b/vendor/github.com/cznic/mathutil/permute.go new file mode 100644 index 00000000..bf828b69 --- /dev/null +++ b/vendor/github.com/cznic/mathutil/permute.go @@ -0,0 +1,39 @@ +// Copyright (c) 2014 The mathutil 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 mathutil + +import ( + "sort" +) + +// Generate the first permutation of data. +func PermutationFirst(data sort.Interface) { + sort.Sort(data) +} + +// Generate the next permutation of data if possible and return true. +// Return false if there is no more permutation left. +// Based on the algorithm described here: +// http://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order +func PermutationNext(data sort.Interface) bool { + var k, l int + for k = data.Len() - 2; ; k-- { // 1. + if k < 0 { + return false + } + + if data.Less(k, k+1) { + break + } + } + for l = data.Len() - 1; !data.Less(k, l); l-- { // 2. + } + data.Swap(k, l) // 3. + for i, j := k+1, data.Len()-1; i < j; i++ { // 4. + data.Swap(i, j) + j-- + } + return true +} diff --git a/vendor/github.com/cznic/mathutil/primes.go b/vendor/github.com/cznic/mathutil/primes.go new file mode 100644 index 00000000..bd10fe6d --- /dev/null +++ b/vendor/github.com/cznic/mathutil/primes.go @@ -0,0 +1,335 @@ +// Copyright (c) 2014 The mathutil 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 mathutil + +import ( + "math" +) + +// IsPrimeUint16 returns true if n is prime. Typical run time is few ns. +func IsPrimeUint16(n uint16) bool { + return n > 0 && primes16[n-1] == 1 +} + +// NextPrimeUint16 returns first prime > n and true if successful or an +// undefined value and false if there is no next prime in the uint16 limits. +// Typical run time is few ns. +func NextPrimeUint16(n uint16) (p uint16, ok bool) { + return n + uint16(primes16[n]), n < 65521 +} + +// IsPrime returns true if n is prime. Typical run time is about 100 ns. +// +//TODO rename to IsPrimeUint32 +func IsPrime(n uint32) bool { + switch { + case n&1 == 0: + return n == 2 + case n%3 == 0: + return n == 3 + case n%5 == 0: + return n == 5 + case n%7 == 0: + return n == 7 + case n%11 == 0: + return n == 11 + case n%13 == 0: + return n == 13 + case n%17 == 0: + return n == 17 + case n%19 == 0: + return n == 19 + case n%23 == 0: + return n == 23 + case n%29 == 0: + return n == 29 + case n%31 == 0: + return n == 31 + case n%37 == 0: + return n == 37 + case n%41 == 0: + return n == 41 + case n%43 == 0: + return n == 43 + case n%47 == 0: + return n == 47 + case n%53 == 0: + return n == 53 // Benchmarked optimum + case n < 65536: + // use table data + return IsPrimeUint16(uint16(n)) + default: + mod := ModPowUint32(2, (n+1)/2, n) + if mod != 2 && mod != n-2 { + return false + } + blk := &lohi[n>>24] + lo, hi := blk.lo, blk.hi + for lo <= hi { + index := (lo + hi) >> 1 + liar := liars[index] + switch { + case n > liar: + lo = index + 1 + case n < liar: + hi = index - 1 + default: + return false + } + } + return true + } +} + +// IsPrimeUint64 returns true if n is prime. Typical run time is few tens of µs. +// +// SPRP bases: http://miller-rabin.appspot.com +func IsPrimeUint64(n uint64) bool { + switch { + case n%2 == 0: + return n == 2 + case n%3 == 0: + return n == 3 + case n%5 == 0: + return n == 5 + case n%7 == 0: + return n == 7 + case n%11 == 0: + return n == 11 + case n%13 == 0: + return n == 13 + case n%17 == 0: + return n == 17 + case n%19 == 0: + return n == 19 + case n%23 == 0: + return n == 23 + case n%29 == 0: + return n == 29 + case n%31 == 0: + return n == 31 + case n%37 == 0: + return n == 37 + case n%41 == 0: + return n == 41 + case n%43 == 0: + return n == 43 + case n%47 == 0: + return n == 47 + case n%53 == 0: + return n == 53 + case n%59 == 0: + return n == 59 + case n%61 == 0: + return n == 61 + case n%67 == 0: + return n == 67 + case n%71 == 0: + return n == 71 + case n%73 == 0: + return n == 73 + case n%79 == 0: + return n == 79 + case n%83 == 0: + return n == 83 + case n%89 == 0: + return n == 89 // Benchmarked optimum + case n <= math.MaxUint16: + return IsPrimeUint16(uint16(n)) + case n <= math.MaxUint32: + return ProbablyPrimeUint32(uint32(n), 11000544) && + ProbablyPrimeUint32(uint32(n), 31481107) + case n < 105936894253: + return ProbablyPrimeUint64_32(n, 2) && + ProbablyPrimeUint64_32(n, 1005905886) && + ProbablyPrimeUint64_32(n, 1340600841) + case n < 31858317218647: + return ProbablyPrimeUint64_32(n, 2) && + ProbablyPrimeUint64_32(n, 642735) && + ProbablyPrimeUint64_32(n, 553174392) && + ProbablyPrimeUint64_32(n, 3046413974) + case n < 3071837692357849: + return ProbablyPrimeUint64_32(n, 2) && + ProbablyPrimeUint64_32(n, 75088) && + ProbablyPrimeUint64_32(n, 642735) && + ProbablyPrimeUint64_32(n, 203659041) && + ProbablyPrimeUint64_32(n, 3613982119) + default: + return ProbablyPrimeUint64_32(n, 2) && + ProbablyPrimeUint64_32(n, 325) && + ProbablyPrimeUint64_32(n, 9375) && + ProbablyPrimeUint64_32(n, 28178) && + ProbablyPrimeUint64_32(n, 450775) && + ProbablyPrimeUint64_32(n, 9780504) && + ProbablyPrimeUint64_32(n, 1795265022) + } +} + +// NextPrime returns first prime > n and true if successful or an undefined value and false if there +// is no next prime in the uint32 limits. Typical run time is about 2 µs. +// +//TODO rename to NextPrimeUint32 +func NextPrime(n uint32) (p uint32, ok bool) { + switch { + case n < 65521: + p16, _ := NextPrimeUint16(uint16(n)) + return uint32(p16), true + case n >= math.MaxUint32-4: + return + } + + n++ + var d0, d uint32 + switch mod := n % 6; mod { + case 0: + d0, d = 1, 4 + case 1: + d = 4 + case 2, 3, 4: + d0, d = 5-mod, 2 + case 5: + d = 2 + } + + p = n + d0 + if p < n { // overflow + return + } + + for { + if IsPrime(p) { + return p, true + } + + p0 := p + p += d + if p < p0 { // overflow + break + } + + d ^= 6 + } + return +} + +// NextPrimeUint64 returns first prime > n and true if successful or an undefined value and false if there +// is no next prime in the uint64 limits. Typical run time is in hundreds of µs. +func NextPrimeUint64(n uint64) (p uint64, ok bool) { + switch { + case n < 65521: + p16, _ := NextPrimeUint16(uint16(n)) + return uint64(p16), true + case n >= 18446744073709551557: // last uint64 prime + return + } + + n++ + var d0, d uint64 + switch mod := n % 6; mod { + case 0: + d0, d = 1, 4 + case 1: + d = 4 + case 2, 3, 4: + d0, d = 5-mod, 2 + case 5: + d = 2 + } + + p = n + d0 + if p < n { // overflow + return + } + + for { + if ok = IsPrimeUint64(p); ok { + break + } + + p0 := p + p += d + if p < p0 { // overflow + break + } + + d ^= 6 + } + return +} + +// FactorTerm is one term of an integer factorization. +type FactorTerm struct { + Prime uint32 // The divisor + Power uint32 // Term == Prime^Power +} + +// FactorTerms represent a factorization of an integer +type FactorTerms []FactorTerm + +// FactorInt returns prime factorization of n > 1 or nil otherwise. +// Resulting factors are ordered by Prime. Typical run time is few µs. +func FactorInt(n uint32) (f FactorTerms) { + switch { + case n < 2: + return + case IsPrime(n): + return []FactorTerm{{n, 1}} + } + + f, w := make([]FactorTerm, 9), 0 + for p := 2; p < len(primes16); p += int(primes16[p]) { + if uint(p*p) > uint(n) { + break + } + + power := uint32(0) + for n%uint32(p) == 0 { + n /= uint32(p) + power++ + } + if power != 0 { + f[w] = FactorTerm{uint32(p), power} + w++ + } + if n == 1 { + break + } + } + if n != 1 { + f[w] = FactorTerm{n, 1} + w++ + } + return f[:w] +} + +// PrimorialProductsUint32 returns a slice of numbers in [lo, hi] which are a +// product of max 'max' primorials. The slice is not sorted. +// +// See also: http://en.wikipedia.org/wiki/Primorial +func PrimorialProductsUint32(lo, hi, max uint32) (r []uint32) { + lo64, hi64 := int64(lo), int64(hi) + if max > 31 { // N/A + max = 31 + } + + var f func(int64, int64, uint32) + f = func(n, p int64, emax uint32) { + e := uint32(1) + for n <= hi64 && e <= emax { + n *= p + if n >= lo64 && n <= hi64 { + r = append(r, uint32(n)) + } + if n < hi64 { + p, _ := NextPrime(uint32(p)) + f(n, int64(p), e) + } + e++ + } + } + + f(1, 2, max) + return +} diff --git a/vendor/github.com/cznic/mathutil/rat.go b/vendor/github.com/cznic/mathutil/rat.go new file mode 100644 index 00000000..91b1c6fb --- /dev/null +++ b/vendor/github.com/cznic/mathutil/rat.go @@ -0,0 +1,27 @@ +// Copyright (c) 2014 The mathutil 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 mathutil + +// QCmpUint32 compares a/b and c/d and returns: +// +// -1 if a/b < c/d +// 0 if a/b == c/d +// +1 if a/b > c/d +// +func QCmpUint32(a, b, c, d uint32) int { + switch x, y := uint64(a)*uint64(d), uint64(b)*uint64(c); { + case x < y: + return -1 + case x == y: + return 0 + default: // x > y + return 1 + } +} + +// QScaleUint32 returns a such that a/b >= c/d. +func QScaleUint32(b, c, d uint32) (a uint64) { + return 1 + (uint64(b)*uint64(c))/uint64(d) +} diff --git a/vendor/github.com/cznic/mathutil/rnd.go b/vendor/github.com/cznic/mathutil/rnd.go new file mode 100644 index 00000000..9132dc0d --- /dev/null +++ b/vendor/github.com/cznic/mathutil/rnd.go @@ -0,0 +1,383 @@ +// Copyright (c) 2014 The mathutil 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 mathutil + +import ( + "fmt" + "math" + "math/big" +) + +// FC32 is a full cycle PRNG covering the 32 bit signed integer range. +// In contrast to full cycle generators shown at e.g. http://en.wikipedia.org/wiki/Full_cycle, +// this code doesn't produce values at constant delta (mod cycle length). +// The 32 bit limit is per this implementation, the algorithm used has no intrinsic limit on the cycle size. +// Properties include: +// - Adjustable limits on creation (hi, lo). +// - Positionable/randomly accessible (Pos, Seek). +// - Repeatable (deterministic). +// - Can run forward or backward (Next, Prev). +// - For a billion numbers cycle the Next/Prev PRN can be produced in cca 100-150ns. +// That's like 5-10 times slower compared to PRNs generated using the (non FC) rand package. +type FC32 struct { + cycle int64 // On average: 3 * delta / 2, (HQ: 2 * delta) + delta int64 // hi - lo + factors [][]int64 // This trades some space for hopefully a bit of speed (multiple adding vs multiplying). + lo int + mods []int // pos % set + pos int64 // Within cycle. + primes []int64 // Ordered. ∏ primes == cycle. + set []int64 // Reordered primes (magnitude order bases) according to seed. +} + +// NewFC32 returns a newly created FC32 adjusted for the closed interval [lo, hi] or an Error if any. +// If hq == true then trade some generation time for improved (pseudo)randomness. +func NewFC32(lo, hi int, hq bool) (r *FC32, err error) { + if lo > hi { + return nil, fmt.Errorf("invalid range %d > %d", lo, hi) + } + + if uint64(hi)-uint64(lo) > math.MaxUint32 { + return nil, fmt.Errorf("range out of int32 limits %d, %d", lo, hi) + } + + delta := int64(hi) - int64(lo) + // Find the primorial covering whole delta + n, set, p := int64(1), []int64{}, uint32(2) + if hq { + p++ + } + for { + set = append(set, int64(p)) + n *= int64(p) + if n > delta { + break + } + p, _ = NextPrime(p) + } + + // Adjust the set so n ∊ [delta, 2 * delta] (HQ: [delta, 3 * delta]) + // while keeping the cardinality of the set (correlates with the statistic "randomness quality") + // at max, i.e. discard atmost one member. + i := -1 // no candidate prime + if n > 2*(delta+1) { + for j, p := range set { + q := n / p + if q < delta+1 { + break + } + + i = j // mark the highest candidate prime set index + } + } + if i >= 0 { // shrink the inner cycle + n = n / set[i] + set = delete(set, i) + } + r = &FC32{ + cycle: n, + delta: delta, + factors: make([][]int64, len(set)), + lo: lo, + mods: make([]int, len(set)), + primes: set, + } + r.Seed(1) // the default seed should be always non zero + return +} + +// Cycle reports the length of the inner FCPRNG cycle. +// Cycle is atmost the double (HQ: triple) of the generator period (hi - lo + 1). +func (r *FC32) Cycle() int64 { + return r.cycle +} + +// Next returns the first PRN after Pos. +func (r *FC32) Next() int { + return r.step(1) +} + +// Pos reports the current position within the inner cycle. +func (r *FC32) Pos() int64 { + return r.pos +} + +// Prev return the first PRN before Pos. +func (r *FC32) Prev() int { + return r.step(-1) +} + +// Seed uses the provided seed value to initialize the generator to a deterministic state. +// A zero seed produces a "canonical" generator with worse randomness than for most non zero seeds. +// Still, the FC property holds for any seed value. +func (r *FC32) Seed(seed int64) { + u := uint64(seed) + r.set = mix(r.primes, &u) + n := int64(1) + for i, p := range r.set { + k := make([]int64, p) + v := int64(0) + for j := range k { + k[j] = v + v += n + } + n *= p + r.factors[i] = mix(k, &u) + } +} + +// Seek sets Pos to |pos| % Cycle. +func (r *FC32) Seek(pos int64) { //vet:ignore + if pos < 0 { + pos = -pos + } + pos %= r.cycle + r.pos = pos + for i, p := range r.set { + r.mods[i] = int(pos % p) + } +} + +func (r *FC32) step(dir int) int { + for { // avg loops per step: 3/2 (HQ: 2) + y := int64(0) + pos := r.pos + pos += int64(dir) + switch { + case pos < 0: + pos = r.cycle - 1 + case pos >= r.cycle: + pos = 0 + } + r.pos = pos + for i, mod := range r.mods { + mod += dir + p := int(r.set[i]) + switch { + case mod < 0: + mod = p - 1 + case mod >= p: + mod = 0 + } + r.mods[i] = mod + y += r.factors[i][mod] + } + if y <= r.delta { + return int(y) + r.lo + } + } +} + +func delete(set []int64, i int) (y []int64) { + for j, v := range set { + if j != i { + y = append(y, v) + } + } + return +} + +func mix(set []int64, seed *uint64) (y []int64) { + for len(set) != 0 { + *seed = rol(*seed) + i := int(*seed % uint64(len(set))) + y = append(y, set[i]) + set = delete(set, i) + } + return +} + +func rol(u uint64) (y uint64) { + y = u << 1 + if int64(u) < 0 { + y |= 1 + } + return +} + +// FCBig is a full cycle PRNG covering ranges outside of the int32 limits. +// For more info see the FC32 docs. +// Next/Prev PRN on a 1e15 cycle can be produced in about 2 µsec. +type FCBig struct { + cycle *big.Int // On average: 3 * delta / 2, (HQ: 2 * delta) + delta *big.Int // hi - lo + factors [][]*big.Int // This trades some space for hopefully a bit of speed (multiple adding vs multiplying). + lo *big.Int + mods []int // pos % set + pos *big.Int // Within cycle. + primes []int64 // Ordered. ∏ primes == cycle. + set []int64 // Reordered primes (magnitude order bases) according to seed. +} + +// NewFCBig returns a newly created FCBig adjusted for the closed interval [lo, hi] or an Error if any. +// If hq == true then trade some generation time for improved (pseudo)randomness. +func NewFCBig(lo, hi *big.Int, hq bool) (r *FCBig, err error) { + if lo.Cmp(hi) > 0 { + return nil, fmt.Errorf("invalid range %d > %d", lo, hi) + } + + delta := big.NewInt(0) + delta.Add(delta, hi).Sub(delta, lo) + + // Find the primorial covering whole delta + n, set, pp, p := big.NewInt(1), []int64{}, big.NewInt(0), uint32(2) + if hq { + p++ + } + for { + set = append(set, int64(p)) + pp.SetInt64(int64(p)) + n.Mul(n, pp) + if n.Cmp(delta) > 0 { + break + } + p, _ = NextPrime(p) + } + + // Adjust the set so n ∊ [delta, 2 * delta] (HQ: [delta, 3 * delta]) + // while keeping the cardinality of the set (correlates with the statistic "randomness quality") + // at max, i.e. discard atmost one member. + dd1 := big.NewInt(1) + dd1.Add(dd1, delta) + dd2 := big.NewInt(0) + dd2.Lsh(dd1, 1) + i := -1 // no candidate prime + if n.Cmp(dd2) > 0 { + q := big.NewInt(0) + for j, p := range set { + pp.SetInt64(p) + q.Set(n) + q.Div(q, pp) + if q.Cmp(dd1) < 0 { + break + } + + i = j // mark the highest candidate prime set index + } + } + if i >= 0 { // shrink the inner cycle + pp.SetInt64(set[i]) + n.Div(n, pp) + set = delete(set, i) + } + r = &FCBig{ + cycle: n, + delta: delta, + factors: make([][]*big.Int, len(set)), + lo: lo, + mods: make([]int, len(set)), + pos: big.NewInt(0), + primes: set, + } + r.Seed(1) // the default seed should be always non zero + return +} + +// Cycle reports the length of the inner FCPRNG cycle. +// Cycle is atmost the double (HQ: triple) of the generator period (hi - lo + 1). +func (r *FCBig) Cycle() *big.Int { + return r.cycle +} + +// Next returns the first PRN after Pos. +func (r *FCBig) Next() *big.Int { + return r.step(1) +} + +// Pos reports the current position within the inner cycle. +func (r *FCBig) Pos() *big.Int { + return r.pos +} + +// Prev return the first PRN before Pos. +func (r *FCBig) Prev() *big.Int { + return r.step(-1) +} + +// Seed uses the provided seed value to initialize the generator to a deterministic state. +// A zero seed produces a "canonical" generator with worse randomness than for most non zero seeds. +// Still, the FC property holds for any seed value. +func (r *FCBig) Seed(seed int64) { + u := uint64(seed) + r.set = mix(r.primes, &u) + n := big.NewInt(1) + v := big.NewInt(0) + pp := big.NewInt(0) + for i, p := range r.set { + k := make([]*big.Int, p) + v.SetInt64(0) + for j := range k { + k[j] = big.NewInt(0) + k[j].Set(v) + v.Add(v, n) + } + pp.SetInt64(p) + n.Mul(n, pp) + r.factors[i] = mixBig(k, &u) + } +} + +// Seek sets Pos to |pos| % Cycle. +func (r *FCBig) Seek(pos *big.Int) { + r.pos.Set(pos) + r.pos.Abs(r.pos) + r.pos.Mod(r.pos, r.cycle) + mod := big.NewInt(0) + pp := big.NewInt(0) + for i, p := range r.set { + pp.SetInt64(p) + r.mods[i] = int(mod.Mod(r.pos, pp).Int64()) + } +} + +func (r *FCBig) step(dir int) (y *big.Int) { + y = big.NewInt(0) + d := big.NewInt(int64(dir)) + for { // avg loops per step: 3/2 (HQ: 2) + r.pos.Add(r.pos, d) + switch { + case r.pos.Sign() < 0: + r.pos.Add(r.pos, r.cycle) + case r.pos.Cmp(r.cycle) >= 0: + r.pos.SetInt64(0) + } + for i, mod := range r.mods { + mod += dir + p := int(r.set[i]) + switch { + case mod < 0: + mod = p - 1 + case mod >= p: + mod = 0 + } + r.mods[i] = mod + y.Add(y, r.factors[i][mod]) + } + if y.Cmp(r.delta) <= 0 { + y.Add(y, r.lo) + return + } + y.SetInt64(0) + } +} + +func deleteBig(set []*big.Int, i int) (y []*big.Int) { + for j, v := range set { + if j != i { + y = append(y, v) + } + } + return +} + +func mixBig(set []*big.Int, seed *uint64) (y []*big.Int) { + for len(set) != 0 { + *seed = rol(*seed) + i := int(*seed % uint64(len(set))) + y = append(y, set[i]) + set = deleteBig(set, i) + } + return +} diff --git a/vendor/github.com/cznic/mathutil/tables.go b/vendor/github.com/cznic/mathutil/tables.go new file mode 100644 index 00000000..f32952c0 --- /dev/null +++ b/vendor/github.com/cznic/mathutil/tables.go @@ -0,0 +1,6995 @@ +// Copyright (c) 2014 The mathutil Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// "Static" data + +package mathutil + +var ( + // Set bits count in a byte + popcnt = [256]byte{ + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, // 0 + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, // 1 + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, // 2 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, // 3 + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, // 4 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, // 5 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, // 6 + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, // 7 + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, // 8 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, // 9 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, // 10 + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, // 11 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, // 12 + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, // 13 + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, // 14 + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, // 15 + } + + // Highest set bit index in a byte + log2 = [256]int{ + -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 0 + + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 1 + + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 2 + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 3 + + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 4 + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 5 + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 6 + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 7 + + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 8 + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 9 + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 10 + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 11 + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 12 + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 13 + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 14 + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 15 + } + + // "Predivisors": 2-53 + liars = [3660]uint32{ + 31621, 42799, 49141, 49981, 65077, 65281, 80581, 83333, 88357, 90751, + 104653, 130561, 164737, 188057, 194221, 196093, 215749, 219781, 220729, 253241, + 256999, 271951, 280601, 282133, 357761, 390937, 458989, 486737, 489997, 514447, + 580337, 587861, 611701, 647089, 653333, 657901, 665281, 665333, 688213, 710533, + 721801, 722261, 738541, 741751, 742813, 745889, 769757, 818201, 838861, 873181, + 877099, 916327, 976873, 983401, 1016801, 1018921, 1053761, 1064053, 1073021, 1082401, + 1109461, 1132657, 1145257, 1168513, 1194649, 1207361, 1251949, 1252697, 1302451, 1325843, + 1357441, 1373653, 1397419, 1441091, 1493857, 1507963, 1509709, 1530787, 1584133, 1678541, + 1690501, 1730977, 1735841, 1811573, 1876393, 1969417, 1987021, 2004403, 2081713, 2163001, + 2181961, 2205967, 2261953, 2264369, 2269093, 2284453, 2304167, 2387797, 2487941, 2510569, + 2670361, 2746477, 2748023, 2757241, 2811271, 2909197, 2944261, 2976487, 3048841, 3090091, + 3116107, 3125281, 3225601, 3363121, 3375041, 3400013, 3413533, 3429037, 3539101, 3542533, + 3567481, 3568661, 3605429, 3656449, 3763801, 3828001, 3898129, 3911197, 3985921, 4072729, + 4181921, 4188889, 4209661, 4360621, 4469471, 4480477, 4513841, 4835209, 4863127, 4869313, + 4877641, 4922413, 5016191, 5044033, 5095177, 5173169, 5173601, 5176153, 5256091, 5271841, + 5284333, 5351537, 5489641, 5590621, 5672041, 5919187, 6027193, 6118141, 6140161, 6159301, + 6189121, 6226193, 6233977, 6236257, 6278533, 6334351, 6368689, 6386993, 6631549, 6658669, + 6779137, 6787327, 6836233, 6952037, 6955541, 6998881, 7017193, 7232321, 7306261, 7306561, + 7429117, 7462001, 7674967, 7725901, 7759937, 7820201, 7883731, 8036033, 8095447, 8239477, + 8384513, 8534233, 8725753, 8727391, 8902741, 9006401, 9056501, 9073513, 9131401, 9345541, + 9371251, 9439201, 9480461, 9533701, 9564169, 9567673, 9588151, 9591661, 9729301, 9774181, + 9863461, 10024561, 10084177, 10323769, 10331141, 10386241, 10425511, 10610063, 10700761, 10712857, + 10763653, 10974881, 11081459, 11115037, 11335501, 11541307, 11585293, 11592397, 11777599, 12032021, + 12096613, 12263131, 12322133, 12327121, 12599233, 12854437, 13057787, 13338371, 13446253, 13500313, + 13635289, 13694761, 13747361, 13773061, 14026897, 14154337, 14179537, 14324473, 14469841, 14671801, + 14676481, 14709241, 14794081, 14796289, 14865121, 15101893, 15139199, 15162941, 15188557, 15220951, + 15247621, 15479777, 15525241, 15603391, 15621409, 15700301, 15802681, 15976747, 15978007, 16070429, + 16132321, 16149169, 16153633, 16324001, 16349477, 16360381, 16705021, 16773121, 16822081, 16843009, + 16853077, 16879501, 16973393, 17098369, 17116837, 17134043, 17208601, 17236801, 17327773, 17375249, + 17405537, 17585969, 17870561, 18067501, 18073817, 18366937, 18443701, 18454921, 18535177, 18653353, + 18740971, 19328653, 19384289, 19404139, 19471033, 19607561, 20261251, 20417311, 20647621, 20968501, + 21042001, 21303343, 21306157, 21359521, 21397381, 21400481, 21623659, 21654533, 22075579, 22087477, + 22369621, 22591301, 22669501, 22711873, 22849481, 22953673, 23247901, 23382529, 23464033, 23577497, + 23634181, 23734901, 23828017, 23872213, 23963869, 24214051, 24356377, 25080101, 25150501, 25276421, + 25326001, 25457833, 25629913, 25696133, 25768261, 25909453, 26280073, 26377921, 26821601, 26840269, + 26877421, 26886817, 27108397, 27118601, 27219697, 27271151, 27279409, 27331921, 27380831, 27392041, + 27409541, 27491237, 27509653, 27664033, 27798461, 27808463, 28325881, 28527049, 28572961, 29111881, + 29214541, 29581501, 30022129, 30090817, 30185569, 30219757, 30295141, 30338593, 30388753, 30418957, + 30576151, 30662497, 30740417, 30881551, 30894307, 31040833, 31166803, 31436123, 31735621, 31759121, + 32091781, 32095057, 32168117, 32285041, 32497921, 32676481, 33146717, 33298337, 33600533, 33627301, + 33704101, 33872593, 34003061, 34043101, 34124641, 34540801, 34856167, 34944001, 35576599, 35703361, + 35820937, 35851037, 36291193, 36307981, 36861901, 36919681, 36974341, 37109467, 37376509, 37439201, + 37964809, 37988497, 38010307, 38046817, 38118763, 38210323, 39465091, 39512773, 39655153, 39684157, + 40165093, 40238797, 40315441, 40361197, 40629601, 40782589, 40827473, 40987201, 41121433, 41568101, + 41604109, 41642681, 41662297, 41840809, 42009217, 42485119, 42623017, 42984589, 43224397, 43363601, + 43661257, 44070841, 44314129, 44465221, 44482901, 45100177, 45175201, 45219329, 45414433, 45819541, + 45879941, 46094401, 46325029, 46386589, 46469809, 46517857, 46679761, 46860001, 47220367, 47903701, + 47918581, 48064021, 48191653, 48269761, 48316969, 48400753, 48448661, 48551161, 48563089, 49075417, + 49303801, 49411801, 49459801, 50155733, 50201089, 50443201, 50523661, 51030601, 51129781, 51302353, + 51500521, 52072021, 52119289, 52204237, 53283169, 53399449, 53656021, 53675623, 53695721, 53711113, + 54029741, 54449431, 55109401, 55176097, 55318957, 55729957, 56052361, 56420033, 56479897, 56810137, + 57762433, 58003213, 58422409, 58449847, 58509977, 58679941, 58755877, 59631211, 59840537, 59913157, + 59953741, 60155201, 60352921, 60547831, 60566431, 60581401, 60696661, 60738257, 60957361, 61201009, + 61219789, 61377109, 61832377, 62756641, 63001801, 63002501, 63065281, 63167743, 63318169, 63328469, + 63346999, 63388033, 64148717, 64605041, 64735897, 65144501, 65254393, 65301013, 65350801, 65359477, + 66096253, 67194401, 67642513, 67928221, 68102641, 68154001, 68165761, 68512867, 68621701, 68839597, + 69030901, 69128641, 69176647, 69228967, 69231061, 69485281, 69612061, 69885649, 70149631, 70463489, + 70593931, 70728121, 71079661, 71734417, 72498253, 72543547, 73562833, 73645001, 74411131, 74927161, + 75140137, 75565873, 76725091, 76745101, 77533123, 77648941, 77812153, 77817979, 78939089, 79398901, + 79411201, 79417801, 79464533, 79786523, 80142761, 80146909, 80375707, 80556337, 80687881, 80891009, + 81433591, 81954133, 82273201, 82506439, 82870517, 82929001, 83083001, 83103329, 83204801, 84164033, + 84350561, 84421081, 84487457, 84998503, 85328717, 85519337, 85823401, 86027329, 86438857, 86530621, + 86999837, 87499651, 87694261, 88256449, 88368853, 88661861, 89308771, 89784581, 90270613, 90278161, + 90341197, 90665789, 90698401, 91433281, 91659283, 92438581, 92625121, 93431521, 93541537, 93571633, + 93643201, 93677761, 93926197, 94316401, 94502701, 95451361, 95452781, 96135601, 96618397, 96791881, + 96888641, 96895441, 96904081, 96925921, 97255801, 97496449, 97796953, 97863529, 97924217, 99036001, + 99115297, 99486889, 99789673, 99898801, 100463443, 100618933, 100943201, 101152133, 101218921, 101270251, + 101276579, 101649241, 102004421, 102678031, 102690677, 102690901, 103301633, 104078857, 104524421, 104988673, + 105305443, 105919633, 106485121, 106622353, 106743073, 107360641, 107543333, 108596953, 109231229, 109437751, + 109541461, 109879837, 110135821, 110139499, 110312773, 110413333, 110717861, 111370141, 111654401, 112032001, + 112402981, 112828801, 113589601, 113605201, 113730481, 113892589, 114305441, 114329881, 114701341, 114842677, + 114910489, 115039081, 115174681, 115497901, 115804501, 115873801, 116090081, 116321617, 116617289, 116682721, + 116696161, 116998669, 117987841, 118466401, 118901521, 119092801, 119204809, 119261113, 119327041, 119558011, + 119743537, 119940853, 120296677, 120517021, 120838609, 121062001, 121374241, 121472359, 121609489, 122166307, + 122396737, 122941981, 123481777, 123671671, 123877081, 123987793, 124145473, 124630273, 124818601, 125284141, + 125686241, 125848577, 126132553, 127050067, 128079409, 128124151, 128396921, 128468957, 128665319, 128987429, + 129205781, 129256273, 129357061, 129461617, 129524669, 130556329, 130693393, 130944133, 131023201, 131567929, + 131938561, 132332201, 132338881, 132440521, 132575071, 133216381, 133302781, 133467517, 133800661, 134696801, + 134767153, 134868029, 135263269, 135296053, 135308881, 135945853, 135969401, 136043641, 136661201, 136722433, + 137415821, 137763037, 138030721, 138403981, 138828821, 139295701, 139487041, 140197051, 142525333, 142922413, + 143106133, 143168581, 145348529, 146156617, 146272901, 146659801, 146843929, 146884393, 147028001, 147287141, + 148109473, 148171769, 148910653, 149389633, 150379693, 150960239, 150988753, 151533377, 151589881, 152716537, + 152922001, 152991841, 153369061, 153589801, 153754873, 153928133, 154287451, 154513633, 154944533, 155203361, + 156114061, 156532799, 157069189, 157368661, 157405249, 157725829, 158068153, 158192317, 158397247, 158496911, + 158544401, 158895281, 160348189, 160378861, 160491329, 160587841, 160672201, 160730389, 161184013, 161216021, + 161289649, 161304001, 161423377, 162026869, 162067441, 162690481, 162771337, 162776041, 163442551, 163954561, + 164111281, 165061909, 165224321, 165938653, 166082309, 166339057, 166406561, 166827943, 167579497, 167582377, + 167692141, 167881121, 168566501, 169655641, 170640961, 170782921, 170856533, 171454321, 172116181, 172436713, + 172947529, 173401621, 174479729, 176030977, 176597821, 176609441, 176977921, 177167233, 177254533, 177693521, + 177927641, 177951973, 178837201, 178956971, 179083601, 179285137, 179820257, 180115489, 180497633, 180703451, + 181285001, 181285537, 181542601, 181647497, 182383111, 183677341, 184411567, 185653333, 186183469, 186393481, + 186983521, 187050529, 187667969, 187761241, 188516329, 188985961, 189714193, 189738361, 189941761, 190212181, + 190382161, 190913297, 191233813, 191648161, 191981609, 192346153, 192857761, 193330237, 193638337, 193949641, + 194556451, 196035001, 196049701, 196231393, 198982759, 199674721, 200143351, 200753281, 201261061, 202130197, + 202156813, 202538857, 203505697, 204280501, 204582457, 204766381, 205057561, 206304961, 206453509, 206504033, + 206529737, 207008569, 207030541, 207132481, 207477001, 207618781, 208051201, 208969223, 209246701, 209404369, + 209990881, 210592873, 210842113, 213035761, 214038533, 214110541, 214852609, 214858717, 215436241, 216821881, + 217123069, 217875571, 218603617, 218642029, 218947121, 219621781, 220531501, 220883521, 221368153, 221415781, + 221884001, 222010721, 222630193, 223449463, 223625851, 223782263, 224074369, 224136013, 224769241, 224957893, + 225853633, 226359547, 226450297, 227132641, 227444101, 227475481, 228652201, 228842209, 228988033, 229589413, + 230357761, 231383461, 231405701, 231927781, 232114433, 232460821, 232771501, 233110081, 234869009, 235426913, + 235928071, 237791143, 238001653, 238833421, 240068041, 240371713, 240694513, 240785047, 241505377, 242067841, + 242650717, 242860069, 243583201, 243955141, 244883981, 245006623, 245950561, 246099317, 246282511, 246434761, + 246658441, 247318957, 247321301, 247416101, 249582481, 250436033, 250958401, 250988173, 251528401, 251663837, + 251855893, 252853921, 253610281, 253893397, 255416897, 256831433, 257590661, 258020473, 258043229, 258234401, + 258944401, 259763093, 259765747, 260156101, 260518801, 260736341, 260963389, 261186001, 261703417, 262979501, + 263428181, 264269449, 264384469, 265020001, 265584133, 265735969, 265836161, 266790481, 266925601, 270525737, + 271272569, 271763467, 271826629, 271950829, 273361789, 273480637, 274701913, 274810241, 274919401, 275283401, + 275619961, 276018913, 276131137, 276542401, 276638321, 277787141, 278943061, 279377281, 280885153, 282253141, + 282471853, 282769771, 283900961, 284166877, 284301751, 284736091, 284834299, 285820501, 286316801, 287160301, + 287449091, 287715121, 288099001, 288117721, 288735277, 290643601, 290706781, 290953921, 291088513, 291461633, + 292153681, 292290181, 292433321, 292902481, 293346637, 293847721, 293938261, 295419097, 295743017, 297624961, + 297798961, 298212601, 299367877, 299736181, 301413001, 302635351, 304080001, 307629401, 307694323, 307972801, + 308483209, 309666361, 310474249, 310978027, 311177213, 311411629, 311655829, 311671361, 312408113, 312614021, + 314184487, 315034513, 315351521, 317137969, 317365933, 317641171, 317796119, 319053281, 319374577, 319440769, + 319726177, 320326003, 321324589, 321850849, 322469701, 322941881, 324477697, 325028089, 325352101, 325546873, + 326266051, 326405713, 326469137, 326628721, 326694301, 326695141, 327073601, 327093409, 327398009, 328302901, + 329153653, 329769721, 330198331, 330759617, 331658081, 331934989, 337135501, 337420679, 337665901, 337783981, + 338125537, 338458807, 338914369, 339195097, 339492169, 339794641, 341958121, 341994131, 343017529, 343052833, + 344201441, 344255551, 344776301, 346080391, 348989101, 349752913, 350031973, 350244577, 351058753, 351177769, + 352802803, 352932337, 353815801, 353932801, 354062809, 356604421, 356836819, 357348601, 357872971, 358416577, + 359394751, 359727073, 360145633, 360375181, 360787771, 361307521, 361312337, 362569201, 363170837, 363430637, + 364550761, 365077373, 365231401, 366487201, 366532321, 366652201, 367559501, 367632301, 368016949, 368476501, + 369667561, 371011801, 371611153, 372167101, 373012777, 373533617, 373669453, 373906513, 374346361, 374988661, + 376957153, 377192353, 377334497, 377458849, 377806687, 377869031, 378792649, 379732501, 380137633, 382304161, + 384100001, 385175113, 385319089, 387072661, 388695301, 390609941, 390612221, 391014937, 392679737, 393611653, + 394723177, 396864469, 399156661, 399302581, 399647221, 400385701, 400557109, 401100881, 403095967, 403293313, + 405739681, 405782623, 407737201, 407889161, 409302001, 409458241, 410613809, 410680357, 411618241, 411851389, + 412836689, 413138881, 413429801, 413778817, 414216461, 414368641, 415200361, 415204501, 415476343, 416964241, + 417767201, 417779909, 418044563, 418226581, 418616161, 418617281, 418667401, 419184481, 420607441, 421942951, + 422429041, 422928101, 423384001, 423465001, 424175761, 424411501, 424431541, 425967301, 426174101, 426219649, + 426770437, 426783811, 427294141, 428180191, 428758201, 429135841, 429509837, 430046857, 430381921, 430646401, + 430733701, 432227449, 434042801, 435016187, 435358657, 435993301, 436465501, 437247841, 437462101, 437597101, + 437866087, 439309261, 441354497, 441650591, 441758461, 442050577, 442181291, 442543553, 444660421, 445429693, + 446414621, 446619617, 449501761, 450807481, 450866021, 450872573, 452990401, 453366029, 453967739, 454745773, + 455198563, 457274161, 457320533, 459785089, 460251733, 460585861, 461151121, 461272267, 461329601, 462587329, + 462639409, 462701513, 464012033, 464955857, 465505633, 466290949, 466758181, 467100937, 468410113, 468950021, + 470120257, 470268137, 470644021, 471535373, 471664513, 472814413, 473581057, 474892741, 474970501, 474983881, + 475723849, 478614067, 479962009, 480668347, 481153501, 481239361, 482488393, 482824669, 482921297, 483006889, + 483029821, 483945601, 484200289, 486063001, 486902929, 487896601, 488104681, 488169289, 488585521, 488656981, + 489994201, 490950461, 491738801, 493108481, 494288677, 495909871, 496109729, 496560349, 497148599, 497285713, + 498662561, 498706651, 498905189, 500747293, 501172241, 501472333, 502686713, 504870241, 505473263, 505532773, + 505798213, 506349421, 507142567, 507323521, 508606771, 509302873, 509551201, 510925609, 511098521, 511215521, + 511611673, 512330281, 514738981, 516045197, 516259657, 516764063, 517662001, 518216201, 518548801, 521501473, + 522390109, 522758233, 523756711, 526067821, 526359289, 526686889, 528013333, 528043753, 528220117, 530630701, + 531095029, 531681281, 532126801, 532758241, 532800133, 533429881, 534782293, 535252867, 535428577, 535517581, + 536003333, 536114197, 536342419, 536870911, 540207097, 540621181, 540654409, 540680141, 542497201, 542536457, + 544861633, 545550433, 545622401, 546102481, 546117301, 546322201, 548080513, 548989561, 549308761, 550132741, + 550230409, 550635373, 550853137, 551313001, 552573793, 553027201, 554487121, 554599051, 554964001, 555321007, + 555465601, 556001377, 556069849, 556095433, 556114609, 557165209, 558235109, 558900821, 558977761, 561448487, + 562367821, 563298061, 563947141, 564298489, 564689381, 565664761, 565707061, 567358513, 567596401, 568902001, + 568967221, 569332177, 569495809, 570941881, 572123521, 572228929, 572430769, 572567353, 572936869, 573817861, + 573862021, 574998841, 575326033, 576724219, 577210181, 577352641, 577613261, 579606301, 579956653, 581618143, + 582389641, 582799951, 585261637, 586706821, 587343541, 588049001, 591242653, 591822001, 592467451, 592468777, + 593682169, 593728489, 595405201, 595590841, 597537361, 597717121, 599135767, 599945293, 600893921, 601606487, + 602379181, 604584221, 605454917, 605961049, 606872449, 607148653, 607750681, 608421637, 608917753, 609361567, + 609813781, 611097401, 611374453, 611770513, 611812321, 611817421, 612006253, 613849601, 614742241, 615361183, + 615760133, 615895897, 616280897, 617087701, 619239457, 619365121, 619480601, 620169409, 620544961, 620755537, + 621769669, 622137601, 623735953, 624303241, 624732421, 625060801, 625482001, 626717471, 627886657, 628868467, + 629134081, 630496621, 630622753, 630811513, 631767943, 631974613, 633289807, 635155291, 635291077, 635319361, + 636287653, 636337073, 636936697, 638502913, 638837761, 639305921, 639807781, 640650931, 640977373, 643036321, + 643316461, 643552909, 644004817, 644453633, 644457551, 644731357, 644900257, 645556481, 648056449, 648328801, + 651011329, 651064681, 651151801, 651514753, 652469641, 653235841, 653260633, 655264369, 657732349, 659526601, + 659846021, 660095641, 660754117, 661122881, 661207177, 662134201, 663760681, 665462081, 668498321, 670976641, + 670987021, 671716921, 672103001, 672108193, 673778827, 675260477, 676359391, 678481693, 680983817, 681019921, + 681124207, 681303241, 682528687, 683316001, 683362681, 684350833, 686059921, 687741401, 689537441, 690035713, + 690562601, 691131349, 692535637, 693456521, 694116893, 696042901, 696321949, 696998251, 697821857, 698192041, + 698819711, 702683101, 705303457, 705351583, 706728377, 707691601, 709409993, 710382401, 710617861, 710721001, + 714490481, 717096641, 717653129, 717831211, 720767521, 722955773, 724160251, 724969087, 725508241, 731276521, + 732805681, 734166217, 736668013, 739444021, 739576801, 740988151, 741182401, 741214237, 742017181, 742550401, + 744500641, 745493761, 745745461, 746331041, 747406801, 748638001, 749172821, 749640161, 750632137, 751226401, + 751705597, 752186593, 753233717, 753574537, 753594001, 754020361, 754874257, 756205633, 756271909, 756980137, + 758581651, 758687581, 758901701, 759252367, 759266621, 759638881, 762699649, 763907741, 764033999, 764240611, + 765378241, 766303693, 766823797, 770201221, 770909107, 770937931, 771043201, 771337891, 772495777, 773131927, + 773807401, 775368901, 775896181, 776443769, 777218989, 781471001, 782823281, 784450393, 784777393, 784783477, + 784966297, 787085857, 787209277, 788046901, 788931361, 789082001, 790453049, 791118043, 792144161, 792145729, + 794201333, 794399041, 794937601, 795064909, 796072003, 796200901, 796560703, 797418997, 797834017, 799162561, + 799630753, 799898833, 799916101, 801093011, 801227269, 801866647, 804978721, 805505957, 805771501, 807115753, + 807218413, 808214161, 809790881, 810023881, 810455101, 811110301, 811478533, 811607777, 811730923, 815430533, + 815796413, 816024161, 816215401, 816549121, 817832329, 818401321, 819466201, 819743233, 822018961, 822531841, + 824389441, 826004467, 829512001, 830664451, 831933901, 832048447, 832127489, 832169857, 833610751, 837766217, + 839268139, 839280691, 839908217, 840749761, 841217653, 841660961, 842785841, 842824981, 842960981, 843161887, + 844545271, 845376533, 846961321, 848090377, 848755969, 849548671, 852432769, 854094781, 854868257, 855734401, + 857100421, 857902861, 858687103, 859096477, 860334301, 862082677, 862678081, 863196181, 863609113, 863984881, + 865242841, 867022747, 867110501, 867638201, 868088341, 868111597, 868691401, 870985223, 871157233, 871195561, + 871908481, 876850801, 877542481, 878492941, 878940833, 879995689, 880870513, 880922657, 883276549, 884304037, + 884952001, 886180429, 887795221, 888868441, 892740853, 893692819, 894264337, 896901461, 897087361, 897283213, + 899019353, 900736411, 901848301, 902566501, 903108821, 903390643, 905040953, 907378669, 907670501, 907711561, + 908005249, 910202509, 910867481, 911484421, 914348737, 914906539, 920375821, 920696653, 921858631, 922845241, + 923437213, 926756881, 927106561, 927877001, 929159941, 930530701, 932148253, 933729421, 935794081, 936421141, + 937675393, 938376181, 939947009, 940123801, 941056273, 941734657, 943271569, 944832533, 946034057, 946787377, + 947878081, 949317217, 949697233, 952893881, 954924013, 957600541, 957631249, 958131157, 958735681, 960269377, + 960946321, 962442001, 962489557, 962523169, 964412837, 965501857, 967266451, 967287751, 967790401, 968283247, + 968413217, 968751241, 969528337, 970586713, 971975071, 974113601, 974471243, 974774401, 975576281, 976396961, + 977483449, 979363153, 980056507, 980725201, 981484561, 983456377, 984133441, 984252001, 985052881, 985075681, + 987842101, 994133479, 995586373, 995650921, 997836841, 998489017, 998590601, 998596741, 998724481, 999828727, + 1002261781, 1003062061, 1005402133, 1005833971, 1006800829, 1008777001, 1008839999, 1009025263, 1009140161, 1011319501, + 1011333061, 1011570457, 1011909271, 1012438391, 1013833153, 1015339441, 1015626151, 1017748057, 1020515761, 1021281301, + 1022336611, 1024041853, 1024123501, 1024605121, 1025035129, 1026738161, 1027744453, 1028494429, 1034252929, 1034958601, + 1040234231, 1049584313, 1050102901, 1050535501, 1054999441, 1055009117, 1056121453, 1057426651, 1063212481, 1065508321, + 1065602281, 1066972301, 1069388497, 1070639389, 1070941987, 1071512749, 1071643249, 1072898711, 1073159281, 1073288581, + 1073484823, 1075100041, 1077133397, 1078467589, 1081798061, 1082472553, 1084241341, 1084444481, 1090858081, 1093150081, + 1093352833, 1093526353, 1094042321, 1097416321, 1098743563, 1100624857, 1101623381, 1101673501, 1102573501, 1102750013, + 1104194521, 1105038871, 1106529761, 1106580817, 1106595493, 1107138961, 1108135381, 1109304913, 1110582947, 1111205873, + 1111939201, 1112671603, 1114277221, 1116379301, 1117202557, 1117785881, 1117828001, 1117890019, 1119412321, 1120076281, + 1120981021, 1121176981, 1123406047, 1123625501, 1123727617, 1124396521, 1125038377, 1127040769, 1130933429, 1134367777, + 1138289041, 1138607233, 1139137057, 1140573601, 1142466151, 1147434289, 1148578201, 1150229761, 1151670001, 1153164097, + 1153440289, 1154343961, 1154691409, 1154987209, 1155939709, 1156761911, 1156993373, 1157839381, 1159421509, 1160844821, + 1163098249, 1163227759, 1164218641, 1165717129, 1166475601, 1166598217, 1168221121, 1168256953, 1168492417, 1173229201, + 1173545533, 1174300093, 1180970407, 1181566219, 1183338241, 1184554801, 1186325981, 1187235193, 1191153937, 1191216133, + 1192314817, 1192412033, 1192903531, 1193229577, 1193557093, 1195524181, 1196852273, 1198650961, 1198880261, 1200456577, + 1200778753, 1202142061, 1204205449, 1205606533, 1205772499, 1209998077, 1210393801, 1210562701, 1210653541, 1213619761, + 1217181061, 1217823517, 1217924159, 1219816261, 1219858921, 1220114377, 1221127013, 1222861271, 1223531677, 1223941657, + 1225128829, 1226230297, 1226855293, 1227220801, 1229491063, 1229751667, 1230446653, 1231362793, 1232445677, 1234125721, + 1234646533, 1235188597, 1235864033, 1236313501, 1236442421, 1238825569, 1242171349, 1242858317, 1249166881, 1249785941, + 1250656621, 1252236421, 1254277909, 1255665613, 1257102001, 1258903981, 1260332137, 1263293281, 1264145401, 1265477791, + 1266003461, 1266273793, 1266425101, 1267345081, 1269295201, 1269835201, 1270193401, 1270489621, 1270667353, 1272558739, + 1272866167, 1282447477, 1282568741, 1285636801, 1286298133, 1286298263, 1296613501, 1297443913, 1299072721, 1299784141, + 1299963601, 1301509249, 1301926081, 1302745481, 1306836001, 1307004641, 1307520469, 1307823661, 1308758533, 1308998741, + 1309723213, 1309983901, 1310329567, 1311255661, 1311616153, 1312332001, 1312573123, 1313396221, 1315858381, 1316169541, + 1318126321, 1318717531, 1319978701, 1319992181, 1320793813, 1321058213, 1323668917, 1325172421, 1325329297, 1328256247, + 1329174601, 1329431689, 1331973329, 1341010577, 1341926401, 1343575381, 1344597577, 1344975721, 1345514101, 1345523401, + 1347387361, 1348964401, 1350685001, 1351126261, 1352453257, 1353051517, 1356241321, 1356328121, 1357459183, 1362463807, + 1362515701, 1362742561, 1365662917, 1366587661, 1366608377, 1368769681, 1371908137, 1372681861, 1375322101, 1376799577, + 1378646179, 1379464633, 1382453333, 1383283129, 1385656829, 1386705433, 1388972353, 1389353941, 1389975149, 1391890033, + 1393851553, 1394640941, 1394746081, 1394942473, 1397357851, 1398883201, 1400859847, 1401840833, 1404008369, 1404253369, + 1406826241, 1406851249, 1409372779, 1413803197, 1414154827, 1414529533, 1415969101, 1417986901, 1421475031, 1424503849, + 1425860101, 1426319563, 1426534201, 1427771089, 1428966001, 1432354901, 1435091377, 1438648993, 1440231941, 1440922891, + 1441139641, 1441678411, 1442945689, 1443388481, 1443742273, 1446298309, 1446434677, 1446818651, 1448921633, 1451635201, + 1454282449, 1454445413, 1456527461, 1457378449, 1461307717, 1463065501, 1463178817, 1463992661, 1464568381, 1465908193, + 1465945417, 1468540477, 1468824787, 1469059481, 1469960377, 1470080501, 1470650851, 1471628401, 1472221921, 1473580001, + 1477289941, 1481626513, 1482274513, 1482876673, 1483873861, 1483918801, 1485061471, 1486564301, 1493114149, 1495190699, + 1497221281, 1497965713, 1499971457, 1499989177, 1500142001, 1501165097, 1502171117, 1502403121, 1503240559, 1503705601, + 1504139521, 1504832033, 1507746241, 1509156013, 1510870241, 1511558533, 1515175087, 1515785041, 1517039371, 1518014689, + 1518290707, 1520190341, 1521221473, 1522302121, 1526732803, 1529648231, 1529819971, 1530495289, 1532419099, 1532569681, + 1532755369, 1533343261, 1534063081, 1535020133, 1536112001, 1536251047, 1536883357, 1537433899, 1537641691, 1538012449, + 1539583921, 1539804001, 1540454761, 1540550413, 1541047813, 1541849761, 1541955409, 1544145121, 1545019813, 1545177581, + 1546106773, 1546340401, 1546508057, 1547140841, 1547543161, 1547712601, 1550924873, 1554270481, 1557118081, 1560312001, + 1560620041, 1561800833, 1565893201, 1566594551, 1567830241, 1568916311, 1574362441, 1574601601, 1577983489, 1578009401, + 1580449201, 1581576641, 1581714481, 1582783777, 1583230241, 1583658649, 1586436193, 1587650401, 1590394313, 1593706201, + 1595647351, 1595887921, 1598197201, 1602517949, 1603765021, 1603810561, 1603994701, 1609916491, 1609935913, 1612121473, + 1614508267, 1617795181, 1617921667, 1619447741, 1620646177, 1627103521, 1627898401, 1628692201, 1630062253, 1630307617, + 1631314609, 1632286673, 1632513601, 1633044241, 1636185601, 1637434657, 1637436457, 1637930893, 1638294661, 1639351981, + 1639846391, 1641971701, 1642814653, 1644637051, 1645413001, 1647225529, 1648076041, 1649430889, 1650265549, 1650682153, + 1654940509, 1655660761, 1656229921, 1656280033, 1656917377, 1659009601, 1661202113, 1668037621, 1668926629, 1669893661, + 1671603667, 1671714241, 1672125131, 1674091141, 1674658133, 1675978193, 1678274581, 1679130641, 1680901381, 1683174533, + 1685433413, 1686001861, 1687248001, 1691745821, 1692605041, 1694128129, 1695158921, 1696893101, 1698707377, 1699279441, + 1700250049, 1709909293, 1710753001, 1712392321, 1714322377, 1716160321, 1716714793, 1716774481, 1718013133, 1718088301, + 1719197621, 1721061497, 1721986313, 1722007169, 1722685777, 1725675451, 1726372441, 1731048937, 1731995497, 1732924001, + 1734059291, 1734285601, 1735071913, 1736481601, 1738687469, 1740214841, 1742288881, 1742815621, 1743166441, 1744605097, + 1746692641, 1746721681, 1749124829, 1750412161, 1754818561, 1757148121, 1760014561, 1766984389, 1767234613, 1769091241, + 1769267761, 1770236893, 1771303801, 1772267281, 1773582977, 1776439261, 1776820033, 1779649381, 1779892577, 1784306273, + 1784638309, 1785843547, 1786005521, 1787934881, 1790023861, 1791426787, 1792442737, 1792588813, 1794814103, 1801558201, + 1801774081, 1802510669, 1803768091, 1804906517, 1805947313, 1809888967, 1816408273, 1817067169, 1819829749, 1820306953, + 1821514633, 1828682101, 1828887061, 1831258601, 1835114401, 1837156049, 1837599769, 1839568981, 1841034961, 1841099261, + 1841479501, 1844028961, 1846171781, 1847811673, 1849964117, 1850233897, 1850598961, 1852496761, 1853926777, 1854084649, + 1854940231, 1856689453, 1857221281, 1858098497, 1858197961, 1860373241, 1861026133, 1861880689, 1862880401, 1866409861, + 1867906721, 1868682241, 1871987041, 1872937057, 1873177693, 1874634721, 1874849929, 1878691753, 1879111697, 1879623157, + 1879775501, 1883509633, 1883785681, 1885915841, 1894909141, 1894955311, 1897700113, 1899081757, 1899525601, 1900687381, + 1903447841, 1904658913, 1905958891, 1908088001, 1909566073, 1910134309, 1911197947, 1912950241, 1914303841, 1915391521, + 1916987593, 1917397637, 1920301951, 1921309633, 1922092567, 1922687293, 1923224689, 1923311317, 1923845801, 1924201501, + 1925042737, 1928903971, 1929862849, 1930403333, 1930447501, 1930534453, 1930915169, 1934350351, 1938264241, 1940048881, + 1943951041, 1944125633, 1945042181, 1950987193, 1952513369, 1952968753, 1957705177, 1959659857, 1960708261, 1963149553, + 1965007601, 1968002149, 1970065681, 1974474049, 1977257441, 1982123893, 1982826961, 1988071801, 1988713189, 1988835713, + 1988965861, 1989192277, 1991063449, 1995784961, 1995830761, 1996231189, 1996339649, 1997844157, 1998780001, 1999053601, + 1999111801, 1999743661, 2004299641, 2007646961, 2013554869, 2013834961, 2016481477, 2017021333, 2017509601, 2019564769, + 2021392369, 2021884343, 2027675701, 2028279793, 2028631361, 2028812399, 2029830409, 2030600833, 2036224321, 2043173273, + 2049293401, 2050617713, 2052149221, 2054711381, 2055634561, 2057267941, 2057835781, 2058072041, 2059739221, 2062612033, + 2068867841, 2070739441, 2072624761, 2076192007, 2081039297, 2081551753, 2082146617, 2083034113, 2083997441, 2085453649, + 2085882661, 2086645009, 2093300401, 2095627153, 2096046457, 2097317377, 2100292841, 2101470541, 2101744837, 2104994449, + 2106147457, 2107148761, 2114643217, 2115769633, 2115986557, 2116483027, 2116541221, 2117031263, 2117555641, 2118621097, + 2120096161, 2123601751, 2124078653, 2124691213, 2127197489, 2128104001, 2129304997, 2130134533, 2131004737, 2131811501, + 2140699681, 2140771609, 2141340833, 2144961253, 2147418113, 2147429509, 2152627801, 2154446641, 2155416251, 2156151313, + 2164282177, 2168431201, 2170282969, 2172155819, 2173499329, 2173540951, 2173579801, 2175126601, 2175406201, 2175646177, + 2177374321, 2177645557, 2178082901, 2178939221, 2180221201, 2182281601, 2182802689, 2185362233, 2187717761, 2193980881, + 2199617701, 2200115713, 2201924341, 2202101761, 2202205897, 2203649197, 2203856497, 2206095589, 2210578759, 2213431729, + 2216960929, 2217879901, 2219072017, 2224252801, 2229468697, 2231332357, 2233031701, 2240507821, 2241880033, 2241982009, + 2244932281, 2245519981, 2246762899, 2248354153, 2251732033, 2254314241, 2254757077, 2256197761, 2256748777, 2256751837, + 2262861901, 2269307587, 2274584089, 2283289681, 2284416181, 2289251669, 2289624793, 2290316377, 2290910257, 2291205461, + 2292068143, 2295209281, 2296995121, 2299190401, 2300628601, 2300795353, 2301745249, 2304120001, 2308966661, 2309241601, + 2309405617, 2311558021, 2311575001, 2315137261, 2320527613, 2323147201, 2324867399, 2329584217, 2330569541, 2331181621, + 2335341601, 2338157597, 2338728001, 2340460487, 2345907961, 2347597981, 2352371251, 2354453561, 2355230749, 2355320101, + 2355622721, 2355649921, 2355735089, 2358534361, 2360261989, 2370771181, 2370928337, 2371350101, 2372976563, 2374232977, + 2375415841, 2377166401, 2378309041, 2381782597, 2382678101, 2383164577, 2385574201, 2389072321, 2389544977, 2393708761, + 2394311233, 2398393661, 2404912501, 2411128441, 2412172153, 2412675721, 2413973071, 2422296241, 2423401681, 2425249601, + 2428648967, 2428870753, 2428986913, 2429407961, 2430697513, 2431136401, 2431144801, 2432761633, 2432860273, 2433791593, + 2434964321, 2434974433, 2435091221, 2436691321, 2437907779, 2438778413, 2442050353, 2442454561, 2443708961, 2444950561, + 2448039497, 2448374689, 2453473049, 2454285751, 2456536681, 2457846161, 2463713281, 2471205361, 2473120961, 2473189441, + 2473823353, 2474308069, 2474676949, 2476283239, 2477814193, 2478643907, 2480147521, 2480343553, 2482435981, 2482682131, + 2484408301, 2486017249, 2488420801, 2488591117, 2492480233, 2494660033, 2494984321, 2495834329, 2499327041, 2501012599, + 2501771329, 2502525637, 2504008609, 2506529257, 2506733189, 2507121037, 2508178843, 2513230891, 2516684801, 2519297089, + 2525070241, 2526566041, 2528291341, 2529410281, 2529827821, 2529854713, 2530351561, 2532630787, 2533465661, 2533797017, + 2535516173, 2537105761, 2539406281, 2539736257, 2540469901, 2541660367, 2542479481, 2544590161, 2545934077, 2548051801, + 2550139253, 2550780277, 2551365769, 2552418761, 2553272929, 2555391481, 2561945401, 2564536201, 2565186137, 2570087521, + 2571180247, 2575060949, 2575737361, 2577345541, 2582092189, 2582246701, 2582952769, 2583322381, 2584460701, 2588054401, + 2588582089, 2590663681, 2593065721, 2595276353, 2597289241, 2597294701, 2598933481, 2600611861, 2602343521, 2602378721, + 2604465013, 2604803701, 2611122229, 2611461529, 2613382201, 2614688801, 2616180821, 2617563031, 2621080741, 2621977627, + 2622993661, 2624549929, 2625903601, 2626783921, 2627284987, 2630643401, 2632605049, 2634284801, 2634804481, 2634820813, + 2638067881, 2639099233, 2642159809, 2642582251, 2646751249, 2646790033, 2648662777, 2649907201, 2650820329, 2651507713, + 2654716321, 2656494271, 2658630913, 2658696301, 2659265701, 2668095181, 2668469431, 2670972949, 2672605657, 2672651521, + 2676053333, 2677147201, 2677821121, 2678785621, 2681041843, 2682823681, 2683742491, 2684284441, 2687655169, 2688124001, + 2689427281, 2690408533, 2690867401, 2693739751, 2695115473, 2700818017, 2700891839, 2701878941, 2704957909, 2706863833, + 2707661501, 2716157989, 2716275007, 2717428033, 2719319513, 2721666817, 2721721939, 2723859001, 2725357249, 2733156029, + 2736316301, 2738184697, 2740336561, 2744329909, 2746021741, 2753333227, 2753538001, 2759392633, 2765323397, 2766006253, + 2767672189, 2769080161, 2769602333, 2774295577, 2777887297, 2778304273, 2779477741, 2781117721, 2781226477, 2786028337, + 2787998641, 2789218909, 2800352011, 2805762961, 2809635901, 2812672981, 2814748201, 2823570433, 2824256377, 2824804693, + 2824854913, 2828205397, 2832384133, 2832743713, 2837697773, 2837917633, 2840634109, 2840871041, 2841190381, 2847894377, + 2848466281, 2848722131, 2855046421, 2855071801, 2855512909, 2862066481, 2865483601, 2866005139, 2866527841, 2870377309, + 2871536561, 2872527733, 2872948321, 2874382853, 2877769501, 2881429741, 2882370481, 2885594497, 2887955533, 2890316801, + 2890414873, 2892426029, 2894667781, 2895004927, 2899294889, 2903776129, 2915953633, 2916247819, 2918295451, 2920691161, + 2923042141, 2924158001, 2929062533, 2929106753, 2930831641, 2931708097, 2932327549, 2936227603, 2936958181, 2941174897, + 2941343633, 2944555681, 2944677961, 2945208001, 2945549881, 2951136343, 2956724317, 2957320351, 2965700233, 2967053953, + 2968206601, 2974506841, 2975377429, 2976930001, 2978766341, 2980689601, 2986025677, 2987414977, 2990152901, 2993462713, + 2993495041, 2994098281, 2994415201, 2998202353, 2998919873, 3000688381, 3001561441, 3002647829, 3004443679, 3009628301, + 3011421841, 3014101261, 3015502181, 3016957381, 3017444761, 3018147217, 3018576689, 3019916461, 3025350343, 3026575553, + 3028586471, 3030393901, 3033332641, 3034402681, 3034817209, 3035375047, 3036079729, 3037295801, 3037781251, 3038880473, + 3039681457, 3041984353, 3042630533, 3048159841, 3050190163, 3056100623, 3056160929, 3057886591, 3058670677, 3059397793, + 3063685633, 3065998717, 3076505209, 3077122133, 3079496551, 3082054697, 3082068013, 3083053387, 3083537689, 3083884651, + 3088408429, 3089013313, 3091019777, 3094763851, 3099670657, 3103800701, 3112974481, 3114125071, 3115667521, 3120445697, + 3122287981, 3129914881, 3133899409, 3135040133, 3143282221, 3145410761, 3150972917, 3156599161, 3156643141, 3157579861, + 3163106953, 3166504273, 3167442721, 3170262409, 3172658653, 3175204531, 3175255717, 3178375201, 3181356263, 3181391641, + 3182606857, 3182655361, 3182891401, 3185472001, 3187035113, 3187421077, 3187939921, 3196397821, 3196431829, 3197565001, + 3197632441, 3197911001, 3197911741, 3199164901, 3205663921, 3207297773, 3208902491, 3212465437, 3215031751, 3217412881, + 3219808411, 3221580281, 3222693421, 3224143441, 3225081473, 3227082823, 3227209057, 3229131137, 3233558021, 3237992101, + 3242533897, 3248236309, 3250348417, 3250700737, 3252148621, 3257334541, 3258647809, 3258892801, 3261114601, 3263097641, + 3263568901, 3263626957, 3264820001, 3265122451, 3267417677, 3268506541, 3268841941, 3270933121, 3271999249, 3272030401, + 3272702497, 3274264033, 3275671969, 3276075709, 3277047649, 3278640289, 3280067129, 3282974857, 3287174129, 3288757249, + 3295362727, 3296403601, 3299246833, 3302322241, 3304307341, 3305829073, 3306686659, 3306957593, 3310858777, 3312489577, + 3312536569, 3313196881, 3315139717, 3320669437, 3323308501, 3323590463, 3323829169, 3328354801, 3332800021, 3334350781, + 3340214413, 3342005633, 3344191241, 3346172189, 3347908801, 3349218881, 3350993969, 3352091557, 3355382857, 3355953001, + 3357417181, 3359737921, 3360511981, 3369139201, 3371024521, 3371452921, 3371693063, 3372667121, 3373086601, 3381052177, + 3381901921, 3385842877, 3386603221, 3387014401, 3387487351, 3389030261, 3395091311, 3399205591, 3399890413, 3402234749, + 3407609221, 3407772817, 3407952169, 3408135121, 3409339393, 3411250081, 3411574801, 3411829693, 3412575097, 3415379701, + 3415832137, 3417522841, 3420143941, 3421845001, 3423222757, 3423580481, 3427050673, 3428133103, 3429457921, 3429982081, + 3430804297, 3432695921, 3432997537, 3433458073, 3434575327, 3435973837, 3440195713, 3443704261, 3449768513, 3450717901, + 3453900913, 3458257741, 3461861761, 3463907761, 3464236901, 3466158361, 3470716657, 3474335437, 3480174001, 3482161261, + 3485747521, 3489958697, 3491763493, 3492178873, 3492883081, 3493262761, 3497607433, 3504132113, 3512030497, 3512291021, + 3512369857, 3513604657, 3516565057, 3519318721, 3524086333, 3525088961, 3529119361, 3529864391, 3532687201, 3533662129, + 3533856913, 3538213381, 3542303047, 3543203333, 3548378341, 3549286001, 3549988261, 3552158521, 3553567057, 3557646401, + 3562963973, 3563340457, 3566428301, 3574891757, 3582711841, 3583249921, 3583604161, 3584800801, 3586833253, 3587553971, + 3589937261, 3590409439, 3593276353, 3594110081, 3596491907, 3596815169, 3598772761, 3602006101, 3605151241, 3611571121, + 3612298321, 3612825221, 3614770573, 3616574081, 3620631169, 3628526287, 3630596257, 3631828481, 3632452741, 3635993089, + 3649116277, 3649965281, 3650158849, 3651572609, 3656355841, 3658730893, 3662387977, 3662503093, 3663084541, 3668926801, + 3669587533, 3672754633, 3677180797, 3679657997, 3682471321, 3685647701, 3685775741, 3692307161, 3695628133, 3697278427, + 3700801861, 3705582073, 3705623281, 3708123301, 3708905341, 3709626961, 3712887289, 3713287801, 3713448769, 3718226401, + 3721486081, 3723410161, 3723699373, 3725016749, 3727828501, 3729097633, 3733761739, 3736293461, 3745192001, 3746101189, + 3749383681, 3751554581, 3751782737, 3754680403, 3756668401, 3759781369, 3760622689, 3760896133, 3762110881, 3767640601, + 3773061337, 3774337201, 3784123501, 3787491457, 3798040471, 3798626833, 3799111681, 3800084401, 3805699501, 3807112123, + 3807308269, 3807749821, 3809018947, 3813919453, 3817561777, 3817706621, 3821233121, 3827035237, 3832807681, 3833208961, + 3842941741, 3846174151, 3846532801, 3847106803, 3850058689, 3852800033, 3863326897, 3865604023, 3867183937, 3874471147, + 3874523017, 3875096893, 3875965417, 3886515361, 3886643801, 3887423437, 3887635753, 3891892421, 3891919417, 3894053311, + 3896079281, 3897241129, 3897869201, 3898906129, 3900327241, 3903711841, 3905533721, 3905876501, 3907577521, 3907752241, + 3912174421, 3914880337, 3914923211, 3915467341, 3915604421, 3915921241, 3918227437, 3922321561, 3926912669, 3929293061, + 3934940833, 3935864017, 3936123601, 3945165841, 3947233201, 3947383201, 3953408801, 3953949421, 3955572001, 3958597301, + 3958930441, 3959578801, 3960728641, 3962037061, 3966350203, 3967343161, 3971095301, 3973556837, 3979485931, 3982017601, + 3987528793, 3987960913, 3991124341, 3992697997, 3997536427, 4005660961, 4007365741, 4011996871, 4015548769, 4017684529, + 4018283501, 4020144133, 4026822577, 4027012021, 4027518961, 4028465873, 4028771849, 4031223841, 4034969401, 4034993269, + 4035498409, 4036395581, 4042538497, 4044601751, 4044884689, 4048493983, 4053267217, 4054039841, 4057195309, 4058433931, + 4059776533, 4060942381, 4061009971, 4064633821, 4067039461, 4067887501, 4068671881, 4071644893, 4075241633, 4075721921, + 4076009857, 4079665633, 4079682361, 4083376067, 4085074909, 4088147617, 4088838913, 4092929149, 4098258707, 4099180801, + 4100934241, 4103745689, 4105691393, 4108970251, 4109461709, 4109711581, 4110320663, 4113013141, 4115891893, 4117058221, + 4117447441, 4121286907, 4127050621, 4129914673, 4133928761, 4135847101, 4136916001, 4137262541, 4138838401, 4139015987, + 4150174393, 4155375349, 4157008813, 4162880401, 4166032873, 4183664101, 4185636781, 4186561633, 4187360341, 4191864013, + 4192060699, 4195843037, 4196323561, 4204344601, 4206006229, 4206295433, 4212105409, 4215885697, 4218900001, 4220122321, + 4232966251, 4234224601, 4237212061, 4243744201, 4244022301, 4244663651, 4247990917, 4250920459, 4251904273, 4255695013, + 4257003353, 4261352869, 4271267333, 4275011401, 4277526901, 4278305651, 4282867213, 4285148981, 4293088801, 4294901761, + } + + primes16 = [65536]byte{ + 2, 1, 1, 2, 1, 2, 1, 4, 3, 2, // 0-9 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 10-19 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 20-29 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 30-39 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 40-49 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 50-59 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 60-69 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 70-79 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 80-89 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 90-99 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 100-109 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 110-119 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 120-129 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 130-139 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 140-149 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 150-159 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 160-169 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 170-179 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 180-189 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 190-199 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 200-209 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 210-219 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 220-229 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 230-239 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 240-249 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 250-259 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 260-269 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 270-279 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 280-289 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 290-299 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 300-309 + 1, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 310-319 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 320-329 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 330-339 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 340-349 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 350-359 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 360-369 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 370-379 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 380-389 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 390-399 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 400-409 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 410-419 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 420-429 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 430-439 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 440-449 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 450-459 + 1, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 460-469 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 470-479 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 480-489 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 490-499 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 500-509 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 510-519 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 520-529 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 530-539 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 540-549 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 550-559 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 560-569 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 570-579 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 580-589 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 590-599 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 600-609 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 610-619 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 620-629 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 630-639 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 640-649 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 650-659 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 660-669 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 670-679 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 680-689 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 690-699 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 700-709 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 710-719 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 720-729 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 730-739 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 740-749 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 750-759 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 760-769 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 770-779 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 780-789 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 790-799 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 800-809 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 810-819 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 10, // 820-829 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 830-839 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 840-849 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 850-859 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 860-869 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 870-879 + 1, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 880-889 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 890-899 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 900-909 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 910-919 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 920-929 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 930-939 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 940-949 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 950-959 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 960-969 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 970-979 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 980-989 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 990-999 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 1000-1009 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 1010-1019 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 1020-1029 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 1030-1039 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 1040-1049 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 1050-1059 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 1060-1069 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 1070-1079 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 1080-1089 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 1090-1099 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 1100-1109 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 1110-1119 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 1120-1129 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 1130-1139 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 1140-1149 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 1150-1159 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 1160-1169 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 1170-1179 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 1180-1189 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 1190-1199 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 1200-1209 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 1210-1219 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 1220-1229 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 1230-1239 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 1240-1249 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 1250-1259 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 1260-1269 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 1270-1279 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 1280-1289 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 1290-1299 + 1, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 1300-1309 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 1310-1319 + 1, 6, 5, 4, 3, 2, 1, 34, 33, 32, // 1320-1329 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 1330-1339 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 1340-1349 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 1350-1359 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 1360-1369 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 1370-1379 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 1380-1389 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 1390-1399 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 1400-1409 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 1410-1419 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 1420-1429 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 1430-1439 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 1440-1449 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 1450-1459 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 1460-1469 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 1470-1479 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 1480-1489 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 1490-1499 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 1500-1509 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 1510-1519 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 1520-1529 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 1530-1539 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 1540-1549 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 1550-1559 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 1560-1569 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 1570-1579 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 1580-1589 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 1590-1599 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 1600-1609 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 1610-1619 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 1620-1629 + 7, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 1630-1639 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 1640-1649 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 1650-1659 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 24, // 1660-1669 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 1670-1679 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 1680-1689 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 10, // 1690-1699 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 1700-1709 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 1710-1719 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 1720-1729 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 1730-1739 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 1740-1749 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 1750-1759 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 1760-1769 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 1770-1779 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 1780-1789 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 1790-1799 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 1800-1809 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 1810-1819 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 1820-1829 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 1830-1839 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 1840-1849 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 1850-1859 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 1860-1869 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 10, // 1870-1879 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 1880-1889 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 1890-1899 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 1900-1909 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 1910-1919 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 1920-1929 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 1930-1939 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 1940-1949 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 1950-1959 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 1960-1969 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 1970-1979 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 1980-1989 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 1990-1999 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 2000-2009 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 2010-2019 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 2020-2029 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 2030-2039 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 2040-2049 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 2050-2059 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 2060-2069 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 2070-2079 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 10, // 2080-2089 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 2090-2099 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 2100-2109 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 2110-2119 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 2120-2129 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 2130-2139 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 2140-2149 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 2150-2159 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 2160-2169 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 2170-2179 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 2180-2189 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 2190-2199 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 2200-2209 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 2210-2219 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 2220-2229 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 2230-2239 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 2240-2249 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 2250-2259 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 2260-2269 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 2270-2279 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 2280-2289 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 2290-2299 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 2300-2309 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 2310-2319 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 2320-2329 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 2330-2339 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 2340-2349 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 2350-2359 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 2360-2369 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 2370-2379 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 2380-2389 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 2390-2399 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 2400-2409 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 2410-2419 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 2420-2429 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 2430-2439 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 2440-2449 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 2450-2459 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 2460-2469 + 3, 2, 1, 4, 3, 2, 1, 26, 25, 24, // 2470-2479 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 2480-2489 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 2490-2499 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 2500-2509 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 2510-2519 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 2520-2529 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 2530-2539 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 2540-2549 + 1, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 2550-2559 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 2560-2569 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 2570-2579 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 2580-2589 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 2590-2599 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 2600-2609 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 2610-2619 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 2620-2629 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 2630-2639 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 2640-2649 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 2650-2659 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 2660-2669 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 2670-2679 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 2680-2689 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 2690-2699 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 2700-2709 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 2710-2719 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 2720-2729 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 2730-2739 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 2740-2749 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 2750-2759 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 2760-2769 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 2770-2779 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 2780-2789 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 2790-2799 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 2800-2809 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 2810-2819 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 2820-2829 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 2830-2839 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 2840-2849 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 2850-2859 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 2860-2869 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 2870-2879 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 2880-2889 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 2890-2899 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 2900-2909 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 2910-2919 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 2920-2929 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 2930-2939 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 2940-2949 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 2950-2959 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 2960-2969 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 2970-2979 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 2980-2989 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 2990-2999 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 3000-3009 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 3010-3019 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 3020-3029 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 3030-3039 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 3040-3049 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 3050-3059 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 3060-3069 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 3070-3079 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 20, // 3080-3089 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 3090-3099 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 3100-3109 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 3110-3119 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 3120-3129 + 7, 6, 5, 4, 3, 2, 1, 26, 25, 24, // 3130-3139 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 3140-3149 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 3150-3159 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 3160-3169 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 3170-3179 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 3180-3189 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 3190-3199 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 3200-3209 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 3210-3219 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 3220-3229 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 3230-3239 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 3240-3249 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 3250-3259 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 3260-3269 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 3270-3279 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 3280-3289 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 3290-3299 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 3300-3309 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 3310-3319 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 3320-3329 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 3330-3339 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 3340-3349 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 3350-3359 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 3360-3369 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 3370-3379 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 3380-3389 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 3390-3399 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 3400-3409 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 3410-3419 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 3420-3429 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 3430-3439 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 3440-3449 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 3450-3459 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 22, // 3460-3469 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 3470-3479 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 3480-3489 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 3490-3499 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 3500-3509 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 3510-3519 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 3520-3529 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 3530-3539 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 3540-3549 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 3550-3559 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 3560-3569 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 3570-3579 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 3580-3589 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 3590-3599 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 3600-3609 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 3610-3619 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 3620-3629 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 3630-3639 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 3640-3649 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 3650-3659 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 3660-3669 + 1, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 3670-3679 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 3680-3689 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 3690-3699 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 3700-3709 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 3710-3719 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 3720-3729 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 3730-3739 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 3740-3749 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 3750-3759 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 3760-3769 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 3770-3779 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 3780-3789 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 3790-3799 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 3800-3809 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 3810-3819 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 3820-3829 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 3830-3839 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 3840-3849 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 3850-3859 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 3860-3869 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 3870-3879 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 3880-3889 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 3890-3899 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 3900-3909 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 3910-3919 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 3920-3929 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 3930-3939 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 3940-3949 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 3950-3959 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 3960-3969 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 3970-3979 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 3980-3989 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 3990-3999 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 4000-4009 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 4010-4019 + 1, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 4020-4029 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 4030-4039 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 4040-4049 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 4050-4059 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 4060-4069 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 4070-4079 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4080-4089 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 4090-4099 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4100-4109 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 4110-4119 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 4120-4129 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 4130-4139 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 4140-4149 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 18, // 4150-4159 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 4160-4169 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 4170-4179 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 4180-4189 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4190-4199 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4200-4209 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 4210-4219 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 4220-4229 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4230-4239 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 4240-4249 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 4250-4259 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4260-4269 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 4270-4279 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 4280-4289 + 7, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 4290-4299 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 4300-4309 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 4310-4319 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 4320-4329 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 4330-4339 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 4340-4349 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 4350-4359 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 4360-4369 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 4370-4379 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4380-4389 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 4390-4399 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 4400-4409 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4410-4419 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 4420-4429 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4430-4439 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 4440-4449 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 4450-4459 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 4460-4469 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4470-4479 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 4480-4489 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 4490-4499 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 4500-4509 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 4510-4519 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 4520-4529 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 4530-4539 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 4540-4549 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4550-4559 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 4560-4569 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 4570-4579 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 4580-4589 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 4590-4599 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 4600-4609 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4610-4619 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 4620-4629 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 4630-4639 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 4640-4649 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 4650-4659 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 4660-4669 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 4670-4679 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4680-4689 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 4690-4699 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 4700-4709 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4710-4719 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 4720-4729 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 4730-4739 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4740-4749 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 4750-4759 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 4760-4769 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 4770-4779 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 4780-4789 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 4790-4799 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 4800-4809 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 4810-4819 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4820-4829 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 4830-4839 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 4840-4849 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4850-4859 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4860-4869 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 4870-4879 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 4880-4889 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 4890-4899 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 4900-4909 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 4910-4919 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 4920-4929 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 4930-4939 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 4940-4949 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 4950-4959 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 4960-4969 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 4970-4979 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 4980-4989 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 4990-4999 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 5000-5009 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 5010-5019 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 5020-5029 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 5030-5039 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 5040-5049 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 5050-5059 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 5060-5069 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 5070-5079 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 5080-5089 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 5090-5099 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 5100-5109 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 28, // 5110-5119 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 5120-5129 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 5130-5139 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 5140-5149 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 5150-5159 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 5160-5169 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 5170-5179 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 5180-5189 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 5190-5199 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 5200-5209 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 5210-5219 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 5220-5229 + 1, 2, 1, 4, 3, 2, 1, 24, 23, 22, // 5230-5239 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 5240-5249 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 5250-5259 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 5260-5269 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 5270-5279 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 5280-5289 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 5290-5299 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 5300-5309 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 5310-5319 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 5320-5329 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 5330-5339 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 5340-5349 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 5350-5359 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 5360-5369 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 5370-5379 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 5380-5389 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 5390-5399 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 5400-5409 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 5410-5419 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 5420-5429 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 5430-5439 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 5440-5449 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 5450-5459 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 5460-5469 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 5470-5479 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 5480-5489 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 5490-5499 + 1, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 5500-5509 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 5510-5519 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 5520-5529 + 1, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 5530-5539 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 5540-5549 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 5550-5559 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 5560-5569 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 5570-5579 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 5580-5589 + 1, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 5590-5599 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 5600-5609 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 5610-5619 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 5620-5629 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 5630-5639 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 5640-5649 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 10, // 5650-5659 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 5660-5669 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 5670-5679 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 5680-5689 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 5690-5699 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 5700-5709 + 1, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 5710-5719 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 5720-5729 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 5730-5739 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 30, // 5740-5749 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 5750-5759 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 5760-5769 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 5770-5779 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 5780-5789 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 5790-5799 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 5800-5809 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 5810-5819 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 5820-5829 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 5830-5839 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 5840-5849 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 5850-5859 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 5860-5869 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 5870-5879 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 5880-5889 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 5890-5899 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 5900-5909 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 5910-5919 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 5920-5929 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 5930-5939 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 5940-5949 + 3, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 5950-5959 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 5960-5969 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 5970-5979 + 1, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 5980-5989 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 5990-5999 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 6000-6009 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 6010-6019 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 6020-6029 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 6030-6039 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 6040-6049 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 6050-6059 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 6060-6069 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 6070-6079 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 6080-6089 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 6090-6099 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 6100-6109 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 6110-6119 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 6120-6129 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 6130-6139 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 6140-6149 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 6150-6159 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 6160-6169 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 6170-6179 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 6180-6189 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 6190-6199 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 6200-6209 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 6210-6219 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 6220-6229 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 6230-6239 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 6240-6249 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 6250-6259 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 6260-6269 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 6270-6279 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 6280-6289 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 6290-6299 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 6300-6309 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 6310-6319 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 6320-6329 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 6330-6339 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 6340-6349 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 6350-6359 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 6360-6369 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 6370-6379 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 6380-6389 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 6390-6399 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 6400-6409 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 6410-6419 + 1, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 6420-6429 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 6430-6439 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 6440-6449 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 6450-6459 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 6460-6469 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 6470-6479 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 6480-6489 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 6490-6499 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 6500-6509 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 6510-6519 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 6520-6529 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 6530-6539 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 6540-6549 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 6550-6559 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 6560-6569 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 6570-6579 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 6580-6589 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 6590-6599 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 6600-6609 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 6610-6619 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 6620-6629 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 6630-6639 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 6640-6649 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 6650-6659 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 6660-6669 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 6670-6679 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 6680-6689 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 6690-6699 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 6700-6709 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 6710-6719 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 6720-6729 + 3, 2, 1, 4, 3, 2, 1, 24, 23, 22, // 6730-6739 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 6740-6749 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 6750-6759 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 6760-6769 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 6770-6779 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 6780-6789 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 6790-6799 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 6800-6809 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 6810-6819 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 6820-6829 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 6830-6839 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 6840-6849 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 6850-6859 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 6860-6869 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 6870-6879 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 6880-6889 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 6890-6899 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 6900-6909 + 1, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 6910-6919 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 6920-6929 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 6930-6939 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 6940-6949 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 6950-6959 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 6960-6969 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 6970-6979 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 6980-6989 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 6990-6999 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 7000-7009 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 7010-7019 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 7020-7029 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 7030-7039 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 7040-7049 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 7050-7059 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 7060-7069 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 7070-7079 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 7080-7089 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 7090-7099 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 7100-7109 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 7110-7119 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 22, // 7120-7129 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 7130-7139 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 7140-7149 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 7150-7159 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 7160-7169 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 7170-7179 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 7180-7189 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 7190-7199 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 7200-7209 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 7210-7219 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 7220-7229 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 7230-7239 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 7240-7249 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 7250-7259 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 7260-7269 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 7270-7279 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 7280-7289 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 7290-7299 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 7300-7309 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 7310-7319 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 7320-7329 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 7330-7339 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 7340-7349 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 7350-7359 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 7360-7369 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 7370-7379 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 7380-7389 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 7390-7399 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 7400-7409 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 7410-7419 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 7420-7429 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 7430-7439 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 7440-7449 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 18, // 7450-7459 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 7460-7469 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 7470-7479 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 7480-7489 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 7490-7499 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 7500-7509 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 7510-7519 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 7520-7529 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 7530-7539 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 7540-7549 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 7550-7559 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 7560-7569 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 7570-7579 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 7580-7589 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 7590-7599 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 7600-7609 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 7610-7619 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 7620-7629 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 7630-7639 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 20, // 7640-7649 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 7650-7659 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 7660-7669 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 7670-7679 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 7680-7689 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 7690-7699 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 7700-7709 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 7710-7719 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 7720-7729 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 7730-7739 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 7740-7749 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 30, // 7750-7759 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 7760-7769 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 7770-7779 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 7780-7789 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 7790-7799 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 7800-7809 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 7810-7819 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 7820-7829 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 7830-7839 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 7840-7849 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 7850-7859 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 7860-7869 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 7870-7879 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 7880-7889 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 7890-7899 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 7900-7909 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 7910-7919 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 7920-7929 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 7930-7939 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 7940-7949 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 7950-7959 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 7960-7969 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 7970-7979 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 7980-7989 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 7990-7999 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 8000-8009 + 1, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 8010-8019 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 8020-8029 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 8030-8039 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 8040-8049 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 8050-8059 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 8060-8069 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 8070-8079 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 8080-8089 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 8090-8099 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 8100-8109 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 8110-8119 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 8120-8129 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 8130-8139 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 8140-8149 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 8150-8159 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 8160-8169 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 8170-8179 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 8180-8189 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 8190-8199 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 8200-8209 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 8210-8219 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 8220-8229 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 8230-8239 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 8240-8249 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 8250-8259 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 8260-8269 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 8270-8279 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 8280-8289 + 1, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 8290-8299 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 8300-8309 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 8310-8319 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 8320-8329 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 8330-8339 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 8340-8349 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 8350-8359 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 8360-8369 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 8370-8379 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 30, // 8380-8389 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 8390-8399 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 8400-8409 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 8410-8419 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 8420-8429 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 8430-8439 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 8440-8449 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 8450-8459 + 1, 6, 5, 4, 3, 2, 1, 34, 33, 32, // 8460-8469 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 8470-8479 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 8480-8489 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 8490-8499 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 8500-8509 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 8510-8519 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 8520-8529 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 8530-8539 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 8540-8549 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 8550-8559 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 8560-8569 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 8570-8579 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 8580-8589 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 8590-8599 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 8600-8609 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 8610-8619 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 8620-8629 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 8630-8639 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 8640-8649 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 8650-8659 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 8660-8669 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 8670-8679 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 8680-8689 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 8690-8699 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 8700-8709 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 8710-8719 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 8720-8729 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 8730-8739 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 8740-8749 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 8750-8759 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 8760-8769 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 8770-8779 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 8780-8789 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 8790-8799 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 8800-8809 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 8810-8819 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 8820-8829 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 8830-8839 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 8840-8849 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 8850-8859 + 1, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 8860-8869 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 8870-8879 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 8880-8889 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 8890-8899 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 8900-8909 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 8910-8919 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 8920-8929 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 8930-8939 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 8940-8949 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 8950-8959 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 8960-8969 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 8970-8979 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 8980-8989 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 8990-8999 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 9000-9009 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 9010-9019 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 9020-9029 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9030-9039 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 9040-9049 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 9050-9059 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 9060-9069 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 9070-9079 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9080-9089 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 9090-9099 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 9100-9109 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 9110-9119 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 9120-9129 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 9130-9139 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9140-9149 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 9150-9159 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 9160-9169 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 9170-9179 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 9180-9189 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 9190-9199 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 9200-9209 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9210-9219 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 9220-9229 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 9230-9239 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 9240-9249 + 7, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 9250-9259 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 9260-9269 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 9270-9279 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 9280-9289 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 9290-9299 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9300-9309 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 9310-9319 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 9320-9329 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 9330-9339 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 9340-9349 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 9350-9359 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9360-9369 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 9370-9379 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9380-9389 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 9390-9399 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 9400-9409 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 9410-9419 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9420-9429 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 22, // 9430-9439 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 9440-9449 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9450-9459 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 9460-9469 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 9470-9479 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9480-9489 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 9490-9499 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9500-9509 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9510-9519 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 9520-9529 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 9530-9539 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 9540-9549 + 1, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 9550-9559 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 9560-9569 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 9570-9579 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 9580-9589 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9590-9599 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 9600-9609 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 9610-9619 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 9620-9629 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 9630-9639 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 9640-9649 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9650-9659 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 9660-9669 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 9670-9679 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 9680-9689 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 9690-9699 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 9700-9709 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 9710-9719 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 9720-9729 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 9730-9739 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 9740-9749 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 9750-9759 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 9760-9769 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9770-9779 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 9780-9789 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 9790-9799 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 9800-9809 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 9810-9819 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 9820-9829 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 9830-9839 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9840-9849 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 9850-9859 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9860-9869 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 9870-9879 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 9880-9889 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9890-9899 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 9900-9909 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 9910-9919 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 9920-9929 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 9930-9939 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 9940-9949 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 9950-9959 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 9960-9969 + 3, 2, 1, 34, 33, 32, 31, 30, 29, 28, // 9970-9979 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 9980-9989 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 9990-9999 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 28, // 10000-10009 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 10010-10019 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 10020-10029 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 22, // 10030-10039 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 10040-10049 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 10050-10059 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 10060-10069 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 10070-10079 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 10080-10089 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 10090-10099 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 10100-10109 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 10110-10119 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 10120-10129 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 10130-10139 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 10140-10149 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 10150-10159 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 10160-10169 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 10170-10179 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 10180-10189 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 10190-10199 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 10200-10209 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 10210-10219 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 10220-10229 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 10230-10239 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 10240-10249 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 10250-10259 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 10260-10269 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 10270-10279 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 10280-10289 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 10290-10299 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 10300-10309 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 10310-10319 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 10320-10329 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 10330-10339 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 10340-10349 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 10350-10359 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 10360-10369 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 10370-10379 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 10380-10389 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 28, // 10390-10399 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 10400-10409 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 10410-10419 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 10420-10429 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 10430-10439 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 10440-10449 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 10450-10459 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 10460-10469 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 10470-10479 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 10480-10489 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 10490-10499 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 10500-10509 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 10510-10519 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 10520-10529 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 10530-10539 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 10540-10549 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 10550-10559 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 10560-10569 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 10570-10579 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 10580-10589 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 10590-10599 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 10600-10609 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 10610-10619 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 10620-10629 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 10630-10639 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 10640-10649 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 10650-10659 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 10660-10669 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 10670-10679 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 10680-10689 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 10690-10699 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 10700-10709 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 10710-10719 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 10720-10729 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 10730-10739 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 10740-10749 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 10750-10759 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 10760-10769 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 10770-10779 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 10780-10789 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 32, // 10790-10799 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 10800-10809 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 10810-10819 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 10820-10829 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 10830-10839 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 10840-10849 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 10850-10859 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 10860-10869 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 10870-10879 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 10880-10889 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 10890-10899 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 28, // 10900-10909 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 10910-10919 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 10920-10929 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 10930-10939 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 10940-10949 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 10950-10959 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 10960-10969 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 10970-10979 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 10980-10989 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 10990-10999 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 11000-11009 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 11010-11019 + 7, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 11020-11029 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 11030-11039 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 11040-11049 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 11050-11059 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 11060-11069 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 11070-11079 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 11080-11089 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 11090-11099 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 11100-11109 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 11110-11119 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 11120-11129 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 11130-11139 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 11140-11149 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 11150-11159 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 11160-11169 + 1, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 11170-11179 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 11180-11189 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 11190-11199 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 11200-11209 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 11210-11219 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 11220-11229 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 11230-11239 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 11240-11249 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 11250-11259 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 11260-11269 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 11270-11279 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 11280-11289 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 11290-11299 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 11300-11309 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 11310-11319 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 11320-11329 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 11330-11339 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 11340-11349 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 11350-11359 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 11360-11369 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 11370-11379 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 11380-11389 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 11390-11399 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 11400-11409 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 11410-11419 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 11420-11429 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 11430-11439 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 11440-11449 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 11450-11459 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 11460-11469 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 11470-11479 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 11480-11489 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 11490-11499 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 11500-11509 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 11510-11519 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 11520-11529 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 11530-11539 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 11540-11549 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 11550-11559 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 11560-11569 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 11570-11579 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 11580-11589 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 11590-11599 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 11600-11609 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 11610-11619 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 11620-11629 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 11630-11639 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 11640-11649 + 7, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 11650-11659 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 11660-11669 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 11670-11679 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 11680-11689 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 11690-11699 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 11700-11709 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 11710-11719 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 11720-11729 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 11730-11739 + 3, 2, 1, 34, 33, 32, 31, 30, 29, 28, // 11740-11749 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 11750-11759 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 11760-11769 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 11770-11779 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 11780-11789 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 11790-11799 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 11800-11809 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 11810-11819 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 11820-11829 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 24, // 11830-11839 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 11840-11849 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 11850-11859 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 11860-11869 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 11870-11879 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 11880-11889 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 11890-11899 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 11900-11909 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 11910-11919 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 11920-11929 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 11930-11939 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 11940-11949 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 11950-11959 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 11960-11969 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 11970-11979 + 1, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 11980-11989 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 11990-11999 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 12000-12009 + 1, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 12010-12019 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 12020-12029 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 12030-12039 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 12040-12049 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 12050-12059 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 12060-12069 + 1, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 12070-12079 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 12080-12089 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 12090-12099 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 12100-12109 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 24, // 12110-12119 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 12120-12129 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 12130-12139 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 12140-12149 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 12150-12159 + 1, 2, 1, 34, 33, 32, 31, 30, 29, 28, // 12160-12169 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 12170-12179 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 12180-12189 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 12190-12199 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 12200-12209 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 12210-12219 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 12220-12229 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 12230-12239 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 12240-12249 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 12250-12259 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 12260-12269 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 12270-12279 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 12280-12289 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 12290-12299 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 12300-12309 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 12310-12319 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 12320-12329 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 12330-12339 + 3, 2, 1, 4, 3, 2, 1, 26, 25, 24, // 12340-12349 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 12350-12359 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 12360-12369 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 12370-12379 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 12380-12389 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 12390-12399 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 12400-12409 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 12410-12419 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 12420-12429 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 12430-12439 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 12440-12449 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 12450-12459 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 12460-12469 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 12470-12479 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 12480-12489 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 12490-12499 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 12500-12509 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 12510-12519 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 12520-12529 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 12530-12539 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 12540-12549 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 12550-12559 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 12560-12569 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 12570-12579 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 12580-12589 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 12590-12599 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 12600-12609 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 12610-12619 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 12620-12629 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 12630-12639 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 12640-12649 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 12650-12659 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 12660-12669 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 12670-12679 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 12680-12689 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 12690-12699 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 12700-12709 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 12710-12719 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 12720-12729 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 12730-12739 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 12740-12749 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 12750-12759 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 12760-12769 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 12770-12779 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 12780-12789 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 12790-12799 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 12800-12809 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 12810-12819 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 12820-12829 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 12830-12839 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 12840-12849 + 3, 2, 1, 36, 35, 34, 33, 32, 31, 30, // 12850-12859 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 12860-12869 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 12870-12879 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 12880-12889 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 12890-12899 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 12900-12909 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 12910-12919 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 12920-12929 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 12930-12939 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 12940-12949 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 12950-12959 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 12960-12969 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 12970-12979 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 12980-12989 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 12990-12999 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 24, // 13000-13009 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 13010-13019 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 13020-13029 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 13030-13039 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 13040-13049 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 13050-13059 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 13060-13069 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 13070-13079 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 13080-13089 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 13090-13099 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 13100-13109 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 13110-13119 + 1, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 13120-13129 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 13130-13139 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 13140-13149 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 13150-13159 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 13160-13169 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 13170-13179 + 3, 2, 1, 4, 3, 2, 1, 30, 29, 28, // 13180-13189 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 13190-13199 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 13200-13209 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 13210-13219 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 13220-13229 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 13230-13239 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 13240-13249 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 13250-13259 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 13260-13269 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 13270-13279 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 13280-13289 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 13290-13299 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 13300-13309 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 13310-13319 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 13320-13329 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 28, // 13330-13339 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 13340-13349 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 13350-13359 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 13360-13369 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 13370-13379 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 13380-13389 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 13390-13399 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 13400-13409 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 13410-13419 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 13420-13429 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 13430-13439 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 13440-13449 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 13450-13459 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 13460-13469 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 13470-13479 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 13480-13489 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 13490-13499 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 13500-13509 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 13510-13519 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 13520-13529 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 13530-13539 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 13540-13549 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 13550-13559 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 13560-13569 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 13570-13579 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 13580-13589 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 13590-13599 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 13600-13609 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 13610-13619 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 13620-13629 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 13630-13639 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 20, // 13640-13649 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 13650-13659 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 13660-13669 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 13670-13679 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 13680-13689 + 1, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 13690-13699 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 13700-13709 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 13710-13719 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 13720-13729 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 13730-13739 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 13740-13749 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 13750-13759 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 13760-13769 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 13770-13779 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 13780-13789 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 13790-13799 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 13800-13809 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 13810-13819 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 13820-13829 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 13830-13839 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 13840-13849 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 13850-13859 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 13860-13869 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 13870-13879 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 13880-13889 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 13890-13899 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 13900-13909 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 13910-13919 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 13920-13929 + 1, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 13930-13939 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 13940-13949 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 13950-13959 + 3, 2, 1, 4, 3, 2, 1, 30, 29, 28, // 13960-13969 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 13970-13979 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 13980-13989 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 13990-13999 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 14000-14009 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 14010-14019 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 14020-14029 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 14030-14039 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 14040-14049 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 14050-14059 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 14060-14069 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 14070-14079 + 1, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 14080-14089 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 14090-14099 + 7, 6, 5, 4, 3, 2, 1, 36, 35, 34, // 14100-14109 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 14110-14119 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 14120-14129 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 14130-14139 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 14140-14149 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 14150-14159 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 14160-14169 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 14170-14179 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 14180-14189 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 14190-14199 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 14200-14209 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 14210-14219 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 14220-14229 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 14230-14239 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 14240-14249 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 14250-14259 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 14260-14269 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 14270-14279 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 14280-14289 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 14290-14299 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 14300-14309 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 14310-14319 + 1, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 14320-14329 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 14330-14339 + 1, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 14340-14349 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 14350-14359 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 14360-14369 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 14370-14379 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 14380-14389 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 14390-14399 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 14400-14409 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 14410-14419 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 14420-14429 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 14430-14439 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 14440-14449 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 14450-14459 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 14460-14469 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 14470-14479 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 14480-14489 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 14490-14499 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 14500-14509 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 14510-14519 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 14520-14529 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 14530-14539 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 14540-14549 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 14550-14559 + 1, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 14560-14569 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 14570-14579 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 14580-14589 + 1, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 14590-14599 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 14600-14609 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 14610-14619 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 14620-14629 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 14630-14639 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 14640-14649 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 14650-14659 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 14660-14669 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 14670-14679 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 14680-14689 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 14690-14699 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 14700-14709 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 14710-14719 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 14720-14729 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 14730-14739 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 14740-14749 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 14750-14759 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 14760-14769 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 14770-14779 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 14780-14789 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 14790-14799 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 14800-14809 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 14810-14819 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 14820-14829 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 14830-14839 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 14840-14849 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 14850-14859 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 14860-14869 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 14870-14879 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 14880-14889 + 1, 6, 5, 4, 3, 2, 1, 26, 25, 24, // 14890-14899 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 14900-14909 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 14910-14919 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 14920-14929 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 14930-14939 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 14940-14949 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 14950-14959 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 14960-14969 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 14970-14979 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 14980-14989 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 14990-14999 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 15000-15009 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 15010-15019 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15020-15029 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 15030-15039 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 15040-15049 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 15050-15059 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 15060-15069 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 15070-15079 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 15080-15089 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15090-15099 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 15100-15109 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15110-15119 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15120-15129 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 15130-15139 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 15140-15149 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15150-15159 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 15160-15169 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 15170-15179 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 15180-15189 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 15190-15199 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 15200-15209 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 15210-15219 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 15220-15229 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 15230-15239 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 15240-15249 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 15250-15259 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 15260-15269 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 15270-15279 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 15280-15289 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 15290-15299 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 15300-15309 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 15310-15319 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 15320-15329 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 15330-15339 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 15340-15349 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 15350-15359 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 15360-15369 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 15370-15379 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 15380-15389 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15390-15399 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 15400-15409 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 15410-15419 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 15420-15429 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 15430-15439 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 15440-15449 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15450-15459 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 15460-15469 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 15470-15479 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 15480-15489 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 15490-15499 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15500-15509 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 15510-15519 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 15520-15529 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15530-15539 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15540-15549 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 15550-15559 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 15560-15569 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15570-15579 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 15580-15589 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15590-15599 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 15600-15609 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 15610-15619 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 15620-15629 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15630-15639 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 15640-15649 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15650-15659 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 15660-15669 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 15670-15679 + 3, 2, 1, 44, 43, 42, 41, 40, 39, 38, // 15680-15689 + 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 15690-15699 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 15700-15709 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 15710-15719 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 15720-15729 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 10, // 15730-15739 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 15740-15749 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15750-15759 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 15760-15769 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 15770-15779 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 15780-15789 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 15790-15799 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 15800-15809 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 15810-15819 + 3, 2, 1, 36, 35, 34, 33, 32, 31, 30, // 15820-15829 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 15830-15839 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 15840-15849 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 15850-15859 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 15860-15869 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 15870-15879 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 15880-15889 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15890-15899 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 15900-15909 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 15910-15919 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 15920-15929 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 15930-15939 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 15940-15949 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 15950-15959 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15960-15969 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 15970-15979 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15980-15989 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 15990-15999 + 1, 6, 5, 4, 3, 2, 1, 26, 25, 24, // 16000-16009 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 16010-16019 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 16020-16029 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 16030-16039 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 16040-16049 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 16050-16059 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 16060-16069 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 16070-16079 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 16080-16089 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 16090-16099 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 16100-16109 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 16110-16119 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 16120-16129 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 16130-16139 + 1, 42, 41, 40, 39, 38, 37, 36, 35, 34, // 16140-16149 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 16150-16159 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 16160-16169 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 16170-16179 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 16180-16189 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 16190-16199 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 16200-16209 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 16210-16219 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 16220-16229 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 16230-16239 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 16240-16249 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 16250-16259 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 16260-16269 + 3, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 16270-16279 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 16280-16289 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 16290-16299 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 16300-16309 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 16310-16319 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 16320-16329 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 16330-16339 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 16340-16349 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 16350-16359 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 16360-16369 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 16370-16379 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 16380-16389 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 16390-16399 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 16400-16409 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 16410-16419 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 16420-16429 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 16430-16439 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 16440-16449 + 1, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 16450-16459 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 16460-16469 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 16470-16479 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 16480-16489 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 16490-16499 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 16500-16509 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 16510-16519 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 16520-16529 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 16530-16539 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 16540-16549 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 16550-16559 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 16560-16569 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 16570-16579 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 16580-16589 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 16590-16599 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 16600-16609 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 16610-16619 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 16620-16629 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 16630-16639 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 16640-16649 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 16650-16659 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 16660-16669 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 16670-16679 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 16680-16689 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 16690-16699 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 16700-16709 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 16710-16719 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 16720-16729 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 16730-16739 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 16740-16749 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 16750-16759 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 16760-16769 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 16770-16779 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 16780-16789 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 16790-16799 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 16800-16809 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 16810-16819 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 16820-16829 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 16830-16839 + 3, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 16840-16849 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 16850-16859 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 16860-16869 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 16870-16879 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 16880-16889 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 16890-16899 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 16900-16909 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 16910-16919 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 16920-16929 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 16930-16939 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 16940-16949 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 16950-16959 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 16960-16969 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 16970-16979 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 16980-16989 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 16990-16999 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 17000-17009 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 17010-17019 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 17020-17029 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 17030-17039 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 17040-17049 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 17050-17059 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 17060-17069 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 17070-17079 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 17080-17089 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 17090-17099 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 17100-17109 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 17110-17119 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 17120-17129 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 17130-17139 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 17140-17149 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 17150-17159 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 17160-17169 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 17170-17179 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 17180-17189 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 17190-17199 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 22, // 17200-17209 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 17210-17219 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 17220-17229 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 17230-17239 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 17240-17249 + 7, 6, 5, 4, 3, 2, 1, 34, 33, 32, // 17250-17259 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 17260-17269 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 17270-17279 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 17280-17289 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 17290-17299 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 17300-17309 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 17310-17319 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 17320-17329 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 17330-17339 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 17340-17349 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 17350-17359 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 17360-17369 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 17370-17379 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 17380-17389 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 17390-17399 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 17400-17409 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 17410-17419 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 17420-17429 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 17430-17439 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 17440-17449 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 17450-17459 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 17460-17469 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 17470-17479 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 17480-17489 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 17490-17499 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 17500-17509 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 20, // 17510-17519 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 17520-17529 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 17530-17539 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 17540-17549 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 17550-17559 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 17560-17569 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 17570-17579 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 17580-17589 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 17590-17599 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 17600-17609 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 17610-17619 + 3, 2, 1, 4, 3, 2, 1, 30, 29, 28, // 17620-17629 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 17630-17639 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 17640-17649 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 17650-17659 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 17660-17669 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 17670-17679 + 1, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 17680-17689 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 17690-17699 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 17700-17709 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 17710-17719 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 17720-17729 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 17730-17739 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 17740-17749 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 17750-17759 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 17760-17769 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 17770-17779 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 17780-17789 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 17790-17799 + 7, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 17800-17809 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 17810-17819 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 17820-17829 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 17830-17839 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 17840-17849 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 17850-17859 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 17860-17869 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 17870-17879 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 17880-17889 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 17890-17899 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 17900-17909 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 17910-17919 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 17920-17929 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 17930-17939 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 17940-17949 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 17950-17959 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 17960-17969 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 17970-17979 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 24, // 17980-17989 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 17990-17999 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 18000-18009 + 3, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 18010-18019 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 18020-18029 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 18030-18039 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 10, // 18040-18049 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 18050-18059 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 18060-18069 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 18070-18079 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 18080-18089 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 18090-18099 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 18100-18109 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 18110-18119 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 18120-18129 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 18130-18139 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 20, // 18140-18149 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 18150-18159 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 18160-18169 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 18170-18179 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 18180-18189 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 18190-18199 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 18200-18209 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 18210-18219 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 18220-18229 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 18230-18239 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 18240-18249 + 1, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 18250-18259 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 18260-18269 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 18270-18279 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 18280-18289 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 18290-18299 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 18300-18309 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 18310-18319 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 18320-18329 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 18330-18339 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 18340-18349 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 18350-18359 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 18360-18369 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 18370-18379 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 18380-18389 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 18390-18399 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 18400-18409 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 18410-18419 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 18420-18429 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 18430-18439 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 18440-18449 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 18450-18459 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 18460-18469 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 18470-18479 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 18480-18489 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 18490-18499 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 18500-18509 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 18510-18519 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 18520-18529 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 18530-18539 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 18540-18549 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 18550-18559 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 18560-18569 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 18570-18579 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 18580-18589 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 18590-18599 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 18600-18609 + 7, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 18610-18619 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 18620-18629 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 18630-18639 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 18640-18649 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 18650-18659 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 18660-18669 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 18670-18679 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 18680-18689 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 18690-18699 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 18700-18709 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 18710-18719 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 18720-18729 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 18730-18739 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 18740-18749 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 18750-18759 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 18760-18769 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 18770-18779 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 18780-18789 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 18790-18799 + 3, 2, 1, 36, 35, 34, 33, 32, 31, 30, // 18800-18809 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 18810-18819 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 18820-18829 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 20, // 18830-18839 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 18840-18849 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 18850-18859 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 30, // 18860-18869 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 18870-18879 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 18880-18889 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 18890-18899 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 18900-18909 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 28, // 18910-18919 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 18920-18929 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 18930-18939 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 18940-18949 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 18950-18959 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 18960-18969 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 18970-18979 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 18980-18989 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 18990-18999 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 19000-19009 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 19010-19019 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 19020-19029 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 19030-19039 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 19040-19049 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 19050-19059 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 19060-19069 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 19070-19079 + 1, 6, 5, 4, 3, 2, 1, 34, 33, 32, // 19080-19089 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 19090-19099 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 19100-19109 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 19110-19119 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 19120-19129 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 19130-19139 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 19140-19149 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 19150-19159 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 19160-19169 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 19170-19179 + 1, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 19180-19189 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 19190-19199 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 19200-19209 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 19210-19219 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 19220-19229 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 19230-19239 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 19240-19249 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 19250-19259 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 19260-19269 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 19270-19279 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 19280-19289 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 19290-19299 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 19300-19309 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 19310-19319 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 19320-19329 + 3, 2, 1, 40, 39, 38, 37, 36, 35, 34, // 19330-19339 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 19340-19349 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 19350-19359 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 19360-19369 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 19370-19379 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 19380-19389 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 19390-19399 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 19400-19409 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 19410-19419 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 19420-19429 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 19430-19439 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 19440-19449 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 19450-19459 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 19460-19469 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 19470-19479 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 19480-19489 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 19490-19499 + 1, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 19500-19509 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 19510-19519 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 19520-19529 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 19530-19539 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 19540-19549 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 19550-19559 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 19560-19569 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 19570-19579 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 19580-19589 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 19590-19599 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 52, // 19600-19609 + 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, // 19610-19619 + 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, // 19620-19629 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 19630-19639 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 19640-19649 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 19650-19659 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 19660-19669 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 19670-19679 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 19680-19689 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 19690-19699 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 19700-19709 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 19710-19719 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 19720-19729 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 19730-19739 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 19740-19749 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 19750-19759 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 19760-19769 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 19770-19779 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 19780-19789 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 19790-19799 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 19800-19809 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 19810-19819 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 19820-19829 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 19830-19839 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 19840-19849 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 19850-19859 + 1, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 19860-19869 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 19870-19879 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 19880-19889 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 19890-19899 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 19900-19909 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 19910-19919 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 19920-19929 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 19930-19939 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 19940-19949 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 19950-19959 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 19960-19969 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 19970-19979 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 19980-19989 + 1, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 19990-19999 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20000-20009 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20010-20019 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 20020-20029 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 20030-20039 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 20040-20049 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 20050-20059 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 20060-20069 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 20070-20079 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 20080-20089 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20090-20099 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 20100-20109 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 20110-20119 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 20120-20129 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 20130-20139 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 20140-20149 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20150-20159 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 20160-20169 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 20170-20179 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 20180-20189 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20190-20199 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 20200-20209 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 20210-20219 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20220-20229 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 20230-20239 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 20240-20249 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20250-20259 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 20260-20269 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 20270-20279 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 20280-20289 + 7, 6, 5, 4, 3, 2, 1, 26, 25, 24, // 20290-20299 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 20300-20309 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 20310-20319 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 20320-20329 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 20330-20339 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 20340-20349 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 10, // 20350-20359 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 20, // 20360-20369 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 20370-20379 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 20380-20389 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 20390-20399 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 20400-20409 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 20410-20419 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20420-20429 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20430-20439 + 1, 2, 1, 34, 33, 32, 31, 30, 29, 28, // 20440-20449 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 20450-20459 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 20460-20469 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 20470-20479 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 20480-20489 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 20490-20499 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 20500-20509 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20510-20519 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 20520-20529 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 20530-20539 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 20540-20549 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 20550-20559 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 20560-20569 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 20570-20579 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 20580-20589 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 20590-20599 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20600-20609 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 20610-20619 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 20620-20629 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 20630-20639 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 20640-20649 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 20650-20659 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 20660-20669 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20670-20679 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 20680-20689 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 20690-20699 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 20700-20709 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 20710-20719 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20720-20729 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 20730-20739 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 20740-20749 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 20750-20759 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20760-20769 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 20770-20779 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 20780-20789 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 20790-20799 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 40, // 20800-20809 + 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, // 20810-20819 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 20820-20829 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 20830-20839 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 20840-20849 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 20850-20859 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 20860-20869 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 20870-20879 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 20880-20889 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 20890-20899 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 20900-20909 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20910-20919 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 20920-20929 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 20930-20939 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 20940-20949 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 20950-20959 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 20960-20969 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20970-20979 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 20980-20989 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 20990-20999 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 21000-21009 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 21010-21019 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 21020-21029 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 21030-21039 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 21040-21049 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 21050-21059 + 1, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 21060-21069 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 21070-21079 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 21080-21089 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 21090-21099 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 21100-21109 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 21110-21119 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 21120-21129 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 21130-21139 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 21140-21149 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 21150-21159 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 21160-21169 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 21170-21179 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 21180-21189 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 21190-21199 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 21200-21209 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 21210-21219 + 1, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 21220-21229 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 21230-21239 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 21240-21249 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 21250-21259 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 21260-21269 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 21270-21279 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 21280-21289 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 21290-21299 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 21300-21309 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 21310-21319 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 21320-21329 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 21330-21339 + 1, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 21340-21349 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 21350-21359 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 21360-21369 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 21370-21379 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 21380-21389 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 21390-21399 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 21400-21409 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 21410-21419 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 21420-21429 + 3, 2, 1, 34, 33, 32, 31, 30, 29, 28, // 21430-21439 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 21440-21449 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 21450-21459 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 21460-21469 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 21470-21479 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 21480-21489 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 21490-21499 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 21500-21509 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 21510-21519 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 28, // 21520-21529 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 21530-21539 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 21540-21549 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 21550-21559 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 21560-21569 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 21570-21579 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 21580-21589 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 21590-21599 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 21600-21609 + 1, 2, 1, 4, 3, 2, 1, 30, 29, 28, // 21610-21619 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 21620-21629 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 21630-21639 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 21640-21649 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 21650-21659 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 21660-21669 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 21670-21679 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 21680-21689 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 21690-21699 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 21700-21709 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 21710-21719 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 21720-21729 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 21730-21739 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 21740-21749 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 21750-21759 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 21760-21769 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 21770-21779 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 21780-21789 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 21790-21799 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 21800-21809 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 21810-21819 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 21820-21829 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 21830-21839 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 21840-21849 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 21850-21859 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 21860-21869 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 21870-21879 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 21880-21889 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 21890-21899 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 21900-21909 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 21910-21919 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 21920-21929 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 21930-21939 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 21940-21949 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 21950-21959 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 21960-21969 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 21970-21979 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 21980-21989 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 21990-21999 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 22000-22009 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 22010-22019 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 22020-22029 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 22030-22039 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22040-22049 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 22050-22059 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 22060-22069 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 22070-22079 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22080-22089 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 22090-22099 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 22100-22109 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 22110-22119 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 22120-22129 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 22130-22139 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 22140-22149 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 22150-22159 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22160-22169 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 22170-22179 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 22180-22189 + 3, 2, 1, 36, 35, 34, 33, 32, 31, 30, // 22190-22199 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 22200-22209 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 22210-22219 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 22220-22229 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 22230-22239 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 22240-22249 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 22250-22259 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22260-22269 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 22270-22279 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 22280-22289 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 22290-22299 + 3, 2, 1, 4, 3, 2, 1, 36, 35, 34, // 22300-22309 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 22310-22319 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 22320-22329 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 22330-22339 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 22340-22349 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 22350-22359 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 22360-22369 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22370-22379 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22380-22389 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 22390-22399 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 22400-22409 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 22410-22419 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 22420-22429 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 22430-22439 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 22440-22449 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 22450-22459 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 22460-22469 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22470-22479 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 22480-22489 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22490-22499 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22500-22509 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 22510-22519 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22520-22529 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22530-22539 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 22540-22549 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 22550-22559 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 22560-22569 + 1, 2, 1, 40, 39, 38, 37, 36, 35, 34, // 22570-22579 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 22580-22589 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 22590-22599 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 22600-22609 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 22610-22619 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 22620-22629 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 22630-22639 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 22640-22649 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 22650-22659 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 22660-22669 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 22670-22679 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22680-22689 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 22690-22699 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 22700-22709 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 22710-22719 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 22720-22729 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 22730-22739 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22740-22749 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 22750-22759 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 22760-22769 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 22770-22779 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 22780-22789 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 22790-22799 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 22800-22809 + 1, 6, 5, 4, 3, 2, 1, 36, 35, 34, // 22810-22819 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 22820-22829 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 22830-22839 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 22840-22849 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 22850-22859 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22860-22869 + 1, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 22870-22879 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 22880-22889 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22890-22899 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 22900-22909 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22910-22919 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 22920-22929 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 22930-22939 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 22940-22949 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 22950-22959 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 22960-22969 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 22970-22979 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 22980-22989 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 22990-22999 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 23000-23009 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 23010-23019 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 23020-23029 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 23030-23039 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 23040-23049 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 23050-23059 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 23060-23069 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 23070-23079 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 23080-23089 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 23090-23099 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 23100-23109 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 23110-23119 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 23120-23129 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 23130-23139 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 23140-23149 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 23150-23159 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 23160-23169 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 23170-23179 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 23180-23189 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 23190-23199 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 23200-23209 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 23210-23219 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 23220-23229 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 23230-23239 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 23240-23249 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 23250-23259 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 23260-23269 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 23270-23279 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 23280-23289 + 1, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 23290-23299 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 23300-23309 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 23310-23319 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 23320-23329 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 23330-23339 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 23340-23349 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 23350-23359 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 23360-23369 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 23370-23379 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 23380-23389 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 23390-23399 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 23400-23409 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 23410-23419 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 23420-23429 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 23430-23439 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 23440-23449 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 23450-23459 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 23460-23469 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 23470-23479 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 23480-23489 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 23490-23499 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 23500-23509 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 23510-23519 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 23520-23529 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 23530-23539 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 23540-23549 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 23550-23559 + 1, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 23560-23569 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 23570-23579 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 23580-23589 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 23590-23599 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 23600-23609 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 23610-23619 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 23620-23629 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 23630-23639 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 23640-23649 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 23650-23659 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 23660-23669 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 23670-23679 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 30, // 23680-23689 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 23690-23699 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 23700-23709 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 23710-23719 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 23720-23729 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 23730-23739 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 23740-23749 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 23750-23759 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 23760-23769 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 23770-23779 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 23780-23789 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 23790-23799 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 23800-23809 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 23810-23819 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 23820-23829 + 1, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 23830-23839 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 23840-23849 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 23850-23859 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 23860-23869 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 23870-23879 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 23880-23889 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 23890-23899 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 23900-23909 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 23910-23919 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 28, // 23920-23929 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 23930-23939 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 23940-23949 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 23950-23959 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 23960-23969 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 23970-23979 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 23980-23989 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 23990-23999 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 24000-24009 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 24010-24019 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 24020-24029 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 24030-24039 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 24040-24049 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 24050-24059 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 24060-24069 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 24070-24079 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 24080-24089 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 24090-24099 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 24100-24109 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 24110-24119 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 24120-24129 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 24130-24139 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 24140-24149 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 24150-24159 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 24160-24169 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 24170-24179 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 24180-24189 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 24190-24199 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 24200-24209 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 24210-24219 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 24220-24229 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 24230-24239 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 24240-24249 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 24250-24259 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 24260-24269 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 24270-24279 + 1, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 24280-24289 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 24290-24299 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 24300-24309 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 24310-24319 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 24320-24329 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 24330-24339 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 24340-24349 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 24350-24359 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 24360-24369 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 24370-24379 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 24380-24389 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 24390-24399 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 24400-24409 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 24410-24419 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 24420-24429 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 24430-24439 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 24440-24449 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 24450-24459 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 24460-24469 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 24470-24479 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 24480-24489 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 24490-24499 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 24500-24509 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 24510-24519 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 24520-24529 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 24530-24539 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 24540-24549 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 24550-24559 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 24560-24569 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 24570-24579 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 24580-24589 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 24590-24599 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 24600-24609 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 24610-24619 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 24620-24629 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 24630-24639 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 24640-24649 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 24650-24659 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 24660-24669 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 24670-24679 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 24680-24689 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 24690-24699 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 24700-24709 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 24710-24719 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 24720-24729 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 24730-24739 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 24740-24749 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 24750-24759 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 24760-24769 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 24770-24779 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 24780-24789 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 24790-24799 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 24800-24809 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 24810-24819 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 24820-24829 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 24830-24839 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 24840-24849 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 24850-24859 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 24860-24869 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 24870-24879 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 24880-24889 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 24890-24899 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 24900-24909 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 24910-24919 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 24920-24929 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 24930-24939 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 24940-24949 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 24950-24959 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 24960-24969 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 24970-24979 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 24980-24989 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 24990-24999 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 25000-25009 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 25010-25019 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 25020-25029 + 1, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 25030-25039 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 25040-25049 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 25050-25059 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 25060-25069 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 25070-25079 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 25080-25089 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 25090-25099 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 25100-25109 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 25110-25119 + 1, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 25120-25129 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 25130-25139 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 25140-25149 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 25150-25159 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 25160-25169 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 25170-25179 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 30, // 25180-25189 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 25190-25199 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 25200-25209 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 25210-25219 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 25220-25229 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 25230-25239 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 25240-25249 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 25250-25259 + 1, 40, 39, 38, 37, 36, 35, 34, 33, 32, // 25260-25269 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 25270-25279 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 25280-25289 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 25290-25299 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 25300-25309 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 25310-25319 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 25320-25329 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 25330-25339 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 25340-25349 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 25350-25359 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 25360-25369 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 25370-25379 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 25380-25389 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 25390-25399 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 25400-25409 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 25410-25419 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 25420-25429 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 25430-25439 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 25440-25449 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 25450-25459 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 25460-25469 + 1, 52, 51, 50, 49, 48, 47, 46, 45, 44, // 25470-25479 + 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, // 25480-25489 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 25490-25499 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 25500-25509 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 25510-25519 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 25520-25529 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 25530-25539 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 25540-25549 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 25550-25559 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 25560-25569 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 25570-25579 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 25580-25589 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 25590-25599 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 25600-25609 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 25610-25619 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 25620-25629 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 25630-25639 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 25640-25649 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 25650-25659 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 25660-25669 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 25670-25679 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 25680-25689 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 25690-25699 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 25700-25709 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 25710-25719 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 25720-25729 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 25730-25739 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 25740-25749 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 25750-25759 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 25760-25769 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 25770-25779 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 25780-25789 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 25790-25799 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 25800-25809 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 25810-25819 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 25820-25829 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 25830-25839 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 18, // 25840-25849 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 25850-25859 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 25860-25869 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 25870-25879 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 25880-25889 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 25890-25899 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 25900-25909 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 25910-25919 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 25920-25929 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 25930-25939 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 25940-25949 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 25950-25959 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 25960-25969 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 25970-25979 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 25980-25989 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 25990-25999 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 26000-26009 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 26010-26019 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 26020-26029 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 26030-26039 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 26040-26049 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 26050-26059 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 26060-26069 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 26070-26079 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 26080-26089 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 26090-26099 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 26100-26109 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 26110-26119 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 26120-26129 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 26130-26139 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 26140-26149 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 26150-26159 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 26160-26169 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 26170-26179 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 26180-26189 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 26190-26199 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 26200-26209 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 26210-26219 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 26220-26229 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 26230-26239 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 26240-26249 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 26250-26259 + 1, 2, 1, 4, 3, 2, 1, 26, 25, 24, // 26260-26269 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 26270-26279 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 26280-26289 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 26290-26299 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 26300-26309 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 26310-26319 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 26320-26329 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 26330-26339 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 26340-26349 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 26350-26359 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 26360-26369 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 26370-26379 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 26380-26389 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 26390-26399 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 26400-26409 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 26410-26419 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 26420-26429 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 26430-26439 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 26440-26449 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 20, // 26450-26459 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 26460-26469 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 26470-26479 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 26480-26489 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 26490-26499 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 26500-26509 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 26510-26519 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 26520-26529 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 26530-26539 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 26540-26549 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 26550-26559 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 26560-26569 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 26570-26579 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 26580-26589 + 1, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 26590-26599 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 26600-26609 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 26610-26619 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 26620-26629 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 26630-26639 + 1, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 26640-26649 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 26650-26659 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 26660-26669 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 26670-26679 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 26680-26689 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 26690-26699 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 26700-26709 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 26710-26719 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 26720-26729 + 1, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 26730-26739 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 26740-26749 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 26750-26759 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 26760-26769 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 26770-26779 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 26780-26789 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 26790-26799 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 26800-26809 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 26810-26819 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 26820-26829 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 26830-26839 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 26840-26849 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 26850-26859 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 26860-26869 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 26870-26879 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 26880-26889 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 26890-26899 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 26900-26909 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 26910-26919 + 1, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 26920-26929 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 26930-26939 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 26940-26949 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 26950-26959 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 26960-26969 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 26970-26979 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 26980-26989 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 26990-26999 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 27000-27009 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 27010-27019 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 27020-27029 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 27030-27039 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 27040-27049 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 27050-27059 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 27060-27069 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 27070-27079 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 27080-27089 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 27090-27099 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 18, // 27100-27109 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 27110-27119 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 27120-27129 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 27130-27139 + 3, 2, 1, 36, 35, 34, 33, 32, 31, 30, // 27140-27149 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 27150-27159 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 27160-27169 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 27170-27179 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 27180-27189 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 27190-27199 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 27200-27209 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 27210-27219 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 27220-27229 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 27230-27239 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 27240-27249 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 27250-27259 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 27260-27269 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 27270-27279 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 27280-27289 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 30, // 27290-27299 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 27300-27309 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 27310-27319 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 27320-27329 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 27330-27339 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 27340-27349 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 27350-27359 + 1, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 27360-27369 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 27370-27379 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 27380-27389 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 27390-27399 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 18, // 27400-27409 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 27410-27419 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 27420-27429 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 27430-27439 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 27440-27449 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 27450-27459 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 27460-27469 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 27470-27479 + 1, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 27480-27489 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 27490-27499 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 27500-27509 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 27510-27519 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 27520-27529 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 27530-27539 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 27540-27549 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 27550-27559 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 27560-27569 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 27570-27579 + 1, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 27580-27589 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 27590-27599 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 27600-27609 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 27610-27619 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 27620-27629 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 27630-27639 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 27640-27649 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 27650-27659 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 27660-27669 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 27670-27679 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 27680-27689 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 27690-27699 + 1, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 27700-27709 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 27710-27719 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 27720-27729 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 27730-27739 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 27740-27749 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 27750-27759 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 27760-27769 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 27770-27779 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 27780-27789 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 27790-27799 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 27800-27809 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 27810-27819 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 27820-27829 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 27830-27839 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 27840-27849 + 1, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 27850-27859 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 27860-27869 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 27870-27879 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 27880-27889 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 27890-27899 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 27900-27909 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 22, // 27910-27919 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 27920-27929 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 27930-27939 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 27940-27949 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 27950-27959 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 27960-27969 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 27970-27979 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 27980-27989 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 27990-27999 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 28000-28009 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 28010-28019 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 28020-28029 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 28030-28039 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 28040-28049 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 28050-28059 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 28060-28069 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 28070-28079 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 28080-28089 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 28090-28099 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 28100-28109 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 28110-28119 + 3, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 28120-28129 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 28130-28139 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 28140-28149 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 28150-28159 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 28160-28169 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 28170-28179 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 28180-28189 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 28190-28199 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 28200-28209 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 28210-28219 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 48, // 28220-28229 + 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, // 28230-28239 + 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 28240-28249 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 28250-28259 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 28260-28269 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 28270-28279 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 28280-28289 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 28290-28299 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 28300-28309 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 30, // 28310-28319 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 28320-28329 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 28330-28339 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 28340-28349 + 1, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 28350-28359 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 28360-28369 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 28370-28379 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 28380-28389 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 28390-28399 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 28400-28409 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 28410-28419 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 28420-28429 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 28430-28439 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 28440-28449 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 28450-28459 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 28460-28469 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 28470-28479 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 28480-28489 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 28490-28499 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 28500-28509 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 28510-28519 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 28520-28529 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 28530-28539 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 28540-28549 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 28550-28559 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 28560-28569 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 28570-28579 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 28580-28589 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 28590-28599 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 28600-28609 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 28610-28619 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 28620-28629 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 28630-28639 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 28640-28649 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 28650-28659 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 28660-28669 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 28670-28679 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 28680-28689 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 28690-28699 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 28700-28709 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 28710-28719 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 28720-28729 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 28730-28739 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 28740-28749 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 28750-28759 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 28760-28769 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 28770-28779 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 28780-28789 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 28790-28799 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 28800-28809 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 28810-28819 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 28820-28829 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 28830-28839 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 28840-28849 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 28850-28859 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 28860-28869 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 28870-28879 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 28880-28889 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 28890-28899 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 28900-28909 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 28910-28919 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 28920-28929 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 28930-28939 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 28940-28949 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 28950-28959 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 28960-28969 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 30, // 28970-28979 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 28980-28989 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 28990-28999 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 29000-29009 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 29010-29019 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 29020-29029 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 29030-29039 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 29040-29049 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 29050-29059 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 29060-29069 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 29070-29079 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 29080-29089 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 29090-29099 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 29100-29109 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 29110-29119 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 29120-29129 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 29130-29139 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 29140-29149 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 29150-29159 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 29160-29169 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 29170-29179 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 29180-29189 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 29190-29199 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 29200-29209 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 29210-29219 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 29220-29229 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 29230-29239 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 29240-29249 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 29250-29259 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 29260-29269 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 29270-29279 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 29280-29289 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 29290-29299 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 29300-29309 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 29310-29319 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 29320-29329 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 29330-29339 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 29340-29349 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 29350-29359 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 29360-29369 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 29370-29379 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 10, // 29380-29389 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 29390-29399 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 29400-29409 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 29410-29419 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 29420-29429 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 29430-29439 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 29440-29449 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 29450-29459 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 29460-29469 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 29470-29479 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 29480-29489 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 29490-29499 + 1, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 29500-29509 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 29510-29519 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 29520-29529 + 1, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 29530-29539 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 29540-29549 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 29550-29559 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 29560-29569 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 29570-29579 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 29580-29589 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 29590-29599 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 29600-29609 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 29610-29619 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 29620-29629 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 29630-29639 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 29640-29649 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 29650-29659 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 29660-29669 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 29670-29679 + 3, 2, 1, 34, 33, 32, 31, 30, 29, 28, // 29680-29689 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 29690-29699 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 29700-29709 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 29710-29719 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 29720-29729 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 29730-29739 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 29740-29749 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 29750-29759 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 29760-29769 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 29770-29779 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 29780-29789 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 29790-29799 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 29800-29809 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 29810-29819 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 29820-29829 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 29830-29839 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 29840-29849 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 29850-29859 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 29860-29869 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 29870-29879 + 1, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 29880-29889 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 29890-29899 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 29900-29909 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 29910-29919 + 1, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 29920-29929 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 29930-29939 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 29940-29949 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 29950-29959 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 29960-29969 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 29970-29979 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 29980-29989 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 29990-29999 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 30000-30009 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 30010-30019 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 30020-30029 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 30030-30039 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 30040-30049 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 30050-30059 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 30060-30069 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 30070-30079 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 30080-30089 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 30090-30099 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 30100-30109 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 30110-30119 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 30120-30129 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 22, // 30130-30139 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 30140-30149 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 30150-30159 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 30160-30169 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 30170-30179 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 30180-30189 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 30190-30199 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 30200-30209 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 30210-30219 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 30220-30229 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 30230-30239 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 30240-30249 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 30250-30259 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 30260-30269 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 30270-30279 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 30280-30289 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 30290-30299 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 30300-30309 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 30310-30319 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 30320-30329 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 30330-30339 + 1, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 30340-30349 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 30350-30359 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 30360-30369 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 30370-30379 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 30380-30389 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 30390-30399 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 30400-30409 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 30410-30419 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 30420-30429 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 30430-30439 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 30440-30449 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 30450-30459 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 22, // 30460-30469 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 30470-30479 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 30480-30489 + 1, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 30490-30499 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 30500-30509 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 30510-30519 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 30520-30529 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 30530-30539 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 30540-30549 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 18, // 30550-30559 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 30560-30569 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 30570-30579 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 30580-30589 + 3, 2, 1, 38, 37, 36, 35, 34, 33, 32, // 30590-30599 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 30600-30609 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 30610-30619 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 30620-30629 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 30630-30639 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 30640-30649 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 30650-30659 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 30660-30669 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 30670-30679 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 30680-30689 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 30690-30699 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 30700-30709 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 30710-30719 + 7, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 30720-30729 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 30730-30739 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 30740-30749 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 30750-30759 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 30760-30769 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 30770-30779 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 30780-30789 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 30790-30799 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 30800-30809 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 30810-30819 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 30820-30829 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 30830-30839 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 30840-30849 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 30850-30859 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 30860-30869 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 30870-30879 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 30880-30889 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 30890-30899 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 30900-30909 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 30910-30919 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 30920-30929 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 30930-30939 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 30940-30949 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 30950-30959 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 30960-30969 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 30970-30979 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 30980-30989 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 30990-30999 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 31000-31009 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 31010-31019 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 31020-31029 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 31030-31039 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 31040-31049 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 31050-31059 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 31060-31069 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 31070-31079 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 31080-31089 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 31090-31099 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 31100-31109 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 31110-31119 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 31120-31129 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 31130-31139 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 31140-31149 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 31150-31159 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 31160-31169 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 31170-31179 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 31180-31189 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 31190-31199 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 31200-31209 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 31210-31219 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 31220-31229 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 31230-31239 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 31240-31249 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 31250-31259 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 31260-31269 + 1, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 31270-31279 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 31280-31289 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 31290-31299 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 31300-31309 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 31310-31319 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 31320-31329 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 31330-31339 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 31340-31349 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 31350-31359 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 31360-31369 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 31370-31379 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 31380-31389 + 1, 2, 1, 4, 3, 2, 1, 72, 71, 70, // 31390-31399 + 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, // 31400-31409 + 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, // 31410-31419 + 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, // 31420-31429 + 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, // 31430-31439 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 31440-31449 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 31450-31459 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 31460-31469 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 31470-31479 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 31480-31489 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 31490-31499 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 31500-31509 + 1, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 31510-31519 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 31520-31529 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 31530-31539 + 1, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 31540-31549 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 31550-31559 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 31560-31569 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 31570-31579 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 31580-31589 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 31590-31599 + 1, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 31600-31609 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 31610-31619 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 31620-31629 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 31630-31639 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 31640-31649 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 31650-31659 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 31660-31669 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 31670-31679 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 31680-31689 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 31690-31699 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 31700-31709 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 31710-31719 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 31720-31729 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 31730-31739 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 31740-31749 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 31750-31759 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 31760-31769 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 31770-31779 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 31780-31789 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 31790-31799 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 31800-31809 + 7, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 31810-31819 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 31820-31829 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 31830-31839 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 31840-31849 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 31850-31859 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 31860-31869 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 31870-31879 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 31880-31889 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 31890-31899 + 7, 6, 5, 4, 3, 2, 1, 50, 49, 48, // 31900-31909 + 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, // 31910-31919 + 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 31920-31929 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 31930-31939 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 31940-31949 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 31950-31959 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 31960-31969 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 31970-31979 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 31980-31989 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 31990-31999 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 32000-32009 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 32010-32019 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 22, // 32020-32029 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 32030-32039 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 32040-32049 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 32050-32059 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 32060-32069 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 32070-32079 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 32080-32089 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 32090-32099 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 32100-32109 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 22, // 32110-32119 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 32120-32129 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 32130-32139 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 32140-32149 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 32150-32159 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 32160-32169 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 32170-32179 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 32180-32189 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 32190-32199 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 32200-32209 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 32210-32219 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 32220-32229 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 32230-32239 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 32240-32249 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 32250-32259 + 1, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 32260-32269 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 32270-32279 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 32280-32289 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 32290-32299 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 32300-32309 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 32310-32319 + 1, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 32320-32329 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 32330-32339 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 32340-32349 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 32350-32359 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 32360-32369 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 32370-32379 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 32380-32389 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 32390-32399 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 32400-32409 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 32410-32419 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 32420-32429 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 32430-32439 + 1, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 32440-32449 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 32450-32459 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 32460-32469 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 32470-32479 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 32480-32489 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 32490-32499 + 3, 2, 1, 4, 3, 2, 1, 24, 23, 22, // 32500-32509 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 32510-32519 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 32520-32529 + 1, 2, 1, 4, 3, 2, 1, 24, 23, 22, // 32530-32539 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 32540-32549 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 32550-32559 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 32560-32569 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 32570-32579 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 32580-32589 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 32590-32599 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 32600-32609 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 32610-32619 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 32620-32629 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 32630-32639 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 32640-32649 + 3, 2, 1, 34, 33, 32, 31, 30, 29, 28, // 32650-32659 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 32660-32669 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 32670-32679 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 32680-32689 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 32690-32699 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 32700-32709 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 30, // 32710-32719 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 32720-32729 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 32730-32739 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 32740-32749 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 32750-32759 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 32760-32769 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 32770-32779 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 32780-32789 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 32790-32799 + 1, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 32800-32809 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 32810-32819 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 32820-32829 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 32830-32839 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 32840-32849 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 32850-32859 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 32860-32869 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 32870-32879 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 32880-32889 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 32890-32899 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 32900-32909 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 32910-32919 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 32920-32929 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 32930-32939 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 32940-32949 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 32950-32959 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 32960-32969 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 32970-32979 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 32980-32989 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 32990-32999 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 33000-33009 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 33010-33019 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 33020-33029 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 33030-33039 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 33040-33049 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 33050-33059 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 33060-33069 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 33070-33079 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 33080-33089 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 33090-33099 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 33100-33109 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 30, // 33110-33119 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 33120-33129 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 33130-33139 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 33140-33149 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 33150-33159 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 33160-33169 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 33170-33179 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 33180-33189 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 33190-33199 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 33200-33209 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 33210-33219 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 33220-33229 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 33230-33239 + 7, 6, 5, 4, 3, 2, 1, 40, 39, 38, // 33240-33249 + 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 33250-33259 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 33260-33269 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 33270-33279 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 33280-33289 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 33290-33299 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 33300-33309 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 33310-33319 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 33320-33329 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 33330-33339 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 33340-33349 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 33350-33359 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 33360-33369 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 33370-33379 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 33380-33389 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 33390-33399 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 33400-33409 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 33410-33419 + 7, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 33420-33429 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 33430-33439 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 33440-33449 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 33450-33459 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 33460-33469 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 33470-33479 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 33480-33489 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 33490-33499 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 33500-33509 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 33510-33519 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 33520-33529 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 33530-33539 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 33540-33549 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 33550-33559 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 33560-33569 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 33570-33579 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 33580-33589 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 33590-33599 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 33600-33609 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 33610-33619 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 33620-33629 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 33630-33639 + 1, 6, 5, 4, 3, 2, 1, 32, 31, 30, // 33640-33649 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 33650-33659 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 33660-33669 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 33670-33679 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 33680-33689 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 33690-33699 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 33700-33709 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 33710-33719 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 33720-33729 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 33730-33739 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 33740-33749 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 33750-33759 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 33760-33769 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 33770-33779 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 33780-33789 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 33790-33799 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 33800-33809 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 33810-33819 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 22, // 33820-33829 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 33830-33839 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 33840-33849 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 33850-33859 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 33860-33869 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 33870-33879 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 33880-33889 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 33890-33899 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 33900-33909 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 33910-33919 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 33920-33929 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 33930-33939 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 33940-33949 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 33950-33959 + 1, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 33960-33969 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 33970-33979 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 33980-33989 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 33990-33999 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 34000-34009 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 34010-34019 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34020-34029 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 34030-34039 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 34040-34049 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 34050-34059 + 1, 62, 61, 60, 59, 58, 57, 56, 55, 54, // 34060-34069 + 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, // 34070-34079 + 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, // 34080-34089 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 34090-34099 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 34100-34109 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 34110-34119 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 34120-34129 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34130-34139 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 34140-34149 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 34150-34159 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34160-34169 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 34170-34179 + 3, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 34180-34189 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 34190-34199 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34200-34209 + 1, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 34210-34219 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34220-34229 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 34230-34239 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 34240-34249 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 34250-34259 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 34260-34269 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 34270-34279 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 34280-34289 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 34290-34299 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 34300-34309 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 34310-34319 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 34320-34329 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 34330-34339 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34340-34349 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34350-34359 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 34360-34369 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34370-34379 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 34380-34389 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 34390-34399 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 34400-34409 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34410-34419 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 34420-34429 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 34430-34439 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 34440-34449 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 34450-34459 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 34460-34469 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 34470-34479 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 34480-34489 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 34490-34499 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34500-34509 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 34510-34519 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 34520-34529 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 34530-34539 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 34, // 34540-34549 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 34550-34559 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 34560-34569 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 34570-34579 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 34580-34589 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 34590-34599 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 34600-34609 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 34610-34619 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34620-34629 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 34630-34639 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 34640-34649 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 34650-34659 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 34660-34669 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 34670-34679 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 34680-34689 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 34690-34699 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 34700-34709 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34710-34719 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 34720-34729 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 34730-34739 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 34740-34749 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 34750-34759 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 34760-34769 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34770-34779 + 1, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 34780-34789 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 34790-34799 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 34800-34809 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 34810-34819 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 34820-34829 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34830-34839 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 22, // 34840-34849 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 34850-34859 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34860-34869 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 34870-34879 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 34880-34889 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 34890-34899 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 34900-34909 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 20, // 34910-34919 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 34920-34929 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 34930-34939 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 34940-34949 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34950-34959 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 34960-34969 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 34970-34979 + 1, 42, 41, 40, 39, 38, 37, 36, 35, 34, // 34980-34989 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 34990-34999 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 35000-35009 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 35010-35019 + 3, 2, 1, 4, 3, 2, 1, 24, 23, 22, // 35020-35029 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 35030-35039 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35040-35049 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 35050-35059 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 35060-35069 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35070-35079 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 35080-35089 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 35090-35099 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 35100-35109 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 35110-35119 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 35120-35129 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35130-35139 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 35140-35149 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 35150-35159 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35160-35169 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 35170-35179 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 35180-35189 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35190-35199 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 35200-35209 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35210-35219 + 1, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 35220-35229 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 35230-35239 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35240-35249 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 35250-35259 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 35260-35269 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 35270-35279 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35280-35289 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 35290-35299 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35300-35309 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 35310-35319 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 35320-35329 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 35330-35339 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 35340-35349 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 35350-35359 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 35360-35369 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35370-35379 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 35380-35389 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 35390-35399 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 35400-35409 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 35410-35419 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 35420-35429 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 35430-35439 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 35440-35449 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35450-35459 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 35460-35469 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 35470-35479 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35480-35489 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 35490-35499 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 35500-35509 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35510-35519 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 35520-35529 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 35530-35539 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 35540-35549 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 35550-35559 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 35560-35569 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 35570-35579 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35580-35589 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 35590-35599 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 35600-35609 + 7, 6, 5, 4, 3, 2, 1, 54, 53, 52, // 35610-35619 + 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, // 35620-35629 + 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, // 35630-35639 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 35640-35649 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 35650-35659 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35660-35669 + 1, 6, 5, 4, 3, 2, 1, 52, 51, 50, // 35670-35679 + 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, // 35680-35689 + 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, // 35690-35699 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 35700-35709 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 35710-35719 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 35720-35729 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 35730-35739 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 35740-35749 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 35750-35759 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35760-35769 + 1, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 35770-35779 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 35780-35789 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 35790-35799 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 35800-35809 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 35810-35819 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35820-35829 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 35830-35839 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35840-35849 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 35850-35859 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 35860-35869 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 35870-35879 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 35880-35889 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 35890-35899 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35900-35909 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 35910-35919 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 35920-35929 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 35930-35939 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 35940-35949 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 35950-35959 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 35960-35969 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 35970-35979 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 35980-35989 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 35990-35999 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 36000-36009 + 1, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 36010-36019 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 36020-36029 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 36030-36039 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 36040-36049 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 36050-36059 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 36060-36069 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 36070-36079 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 36080-36089 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 36090-36099 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 22, // 36100-36109 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 36110-36119 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 36120-36129 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 36130-36139 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 36140-36149 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 36150-36159 + 1, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 36160-36169 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 36170-36179 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 36180-36189 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 36190-36199 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 36200-36209 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 36210-36219 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 36220-36229 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 36230-36239 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 36240-36249 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 36250-36259 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 36260-36269 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 36270-36279 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 36280-36289 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 36290-36299 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 36300-36309 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 36310-36319 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 36320-36329 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 36330-36339 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 36340-36349 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 36350-36359 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 36360-36369 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 36370-36379 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 44, // 36380-36389 + 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, // 36390-36399 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 36400-36409 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 36410-36419 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 36420-36429 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 36430-36439 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 36440-36449 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 36450-36459 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 36460-36469 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 36470-36479 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 36480-36489 + 3, 2, 1, 4, 3, 2, 1, 26, 25, 24, // 36490-36499 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 36500-36509 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 36510-36519 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 36520-36529 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 36530-36539 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 36540-36549 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 36550-36559 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 36560-36569 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 36570-36579 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 36580-36589 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 36590-36599 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 36600-36609 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 36610-36619 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 36620-36629 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 36630-36639 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 36640-36649 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 36650-36659 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 36660-36669 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 36670-36679 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 36680-36689 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 36690-36699 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 36700-36709 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 36710-36719 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 36720-36729 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 36730-36739 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 36740-36749 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 36750-36759 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 36760-36769 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 36770-36779 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 36780-36789 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 36790-36799 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 36800-36809 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 36810-36819 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 36820-36829 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 36830-36839 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 36840-36849 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 36850-36859 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 36860-36869 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 36870-36879 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 36880-36889 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 36890-36899 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 36900-36909 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 36910-36919 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 36920-36929 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 36930-36939 + 3, 2, 1, 4, 3, 2, 1, 26, 25, 24, // 36940-36949 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 36950-36959 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 36960-36969 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 36970-36979 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 36980-36989 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 36990-36999 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 37000-37009 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 37010-37019 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 37020-37029 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 37030-37039 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 37040-37049 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 37050-37059 + 1, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 37060-37069 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 37070-37079 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 37080-37089 + 7, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 37090-37099 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 37100-37109 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 37110-37119 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 37120-37129 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 20, // 37130-37139 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 37140-37149 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 37150-37159 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 37160-37169 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 37170-37179 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 37180-37189 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 37190-37199 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 37200-37209 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 37210-37219 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 37220-37229 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 37230-37239 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 37240-37249 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 37250-37259 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 37260-37269 + 3, 2, 1, 4, 3, 2, 1, 30, 29, 28, // 37270-37279 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 37280-37289 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 37290-37299 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 37300-37309 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 37310-37319 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 37320-37329 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 18, // 37330-37339 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 37340-37349 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 37350-37359 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 37360-37369 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 37370-37379 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 37380-37389 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 37390-37399 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 37400-37409 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 37410-37419 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 37420-37429 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 37430-37439 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 37440-37449 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 37450-37459 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 37460-37469 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 37470-37479 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 37480-37489 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 37490-37499 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 37500-37509 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 37510-37519 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 37520-37529 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 37530-37539 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 37540-37549 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 37550-37559 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 37560-37569 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 37570-37579 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 37580-37589 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 37590-37599 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 37600-37609 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 37610-37619 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 37620-37629 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 37630-37639 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 37640-37649 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 37650-37659 + 3, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 37660-37669 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 37670-37679 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 37680-37689 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 37690-37699 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 37700-37709 + 7, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 37710-37719 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 37720-37729 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 37730-37739 + 7, 6, 5, 4, 3, 2, 1, 34, 33, 32, // 37740-37749 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 37750-37759 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 37760-37769 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 37770-37779 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 37780-37789 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 37790-37799 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 37800-37809 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 37810-37819 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 37820-37829 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 37830-37839 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 37840-37849 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 37850-37859 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 37860-37869 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 37870-37879 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 37880-37889 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 37890-37899 + 7, 6, 5, 4, 3, 2, 1, 44, 43, 42, // 37900-37909 + 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, // 37910-37919 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 37920-37929 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 37930-37939 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 37940-37949 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 37950-37959 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 37960-37969 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 37970-37979 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 37980-37989 + 1, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 37990-37999 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 38000-38009 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 38010-38019 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 38020-38029 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 38030-38039 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 38040-38049 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 38050-38059 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 38060-38069 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 38070-38079 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 38080-38089 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 38090-38099 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 38100-38109 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 30, // 38110-38119 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 38120-38129 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 38130-38139 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 38140-38149 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 38150-38159 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 38160-38169 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 38170-38179 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 38180-38189 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 38190-38199 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 38200-38209 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 38210-38219 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 38220-38229 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 22, // 38230-38239 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 38240-38249 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 38250-38259 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 38260-38269 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 38270-38279 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 38280-38289 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 38290-38299 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 38300-38309 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 38310-38319 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 38320-38329 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 38330-38339 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 38340-38349 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 38350-38359 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 38360-38369 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 38370-38379 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 38380-38389 + 3, 2, 1, 38, 37, 36, 35, 34, 33, 32, // 38390-38399 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 38400-38409 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 38410-38419 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 38420-38429 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 38430-38439 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 38440-38449 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 38450-38459 + 1, 40, 39, 38, 37, 36, 35, 34, 33, 32, // 38460-38469 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 38470-38479 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 38480-38489 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 38490-38499 + 1, 42, 41, 40, 39, 38, 37, 36, 35, 34, // 38500-38509 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 38510-38519 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 38520-38529 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 38530-38539 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 38540-38549 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 38550-38559 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 24, // 38560-38569 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 38570-38579 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 38580-38589 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 38590-38599 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 38600-38609 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 38610-38619 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 38620-38629 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 38630-38639 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 38640-38649 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 38650-38659 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 38660-38669 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 38670-38679 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 38680-38689 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 38690-38699 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 38700-38709 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 38710-38719 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 38720-38729 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 38730-38739 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 18, // 38740-38749 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 38750-38759 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 38760-38769 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 38770-38779 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 38780-38789 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 38790-38799 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 38800-38809 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 38810-38819 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 38820-38829 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 38830-38839 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 38840-38849 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 38850-38859 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 38860-38869 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 38870-38879 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 38880-38889 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 38890-38899 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 38900-38909 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 38910-38919 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 38920-38929 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 38930-38939 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 38940-38949 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 38950-38959 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 38960-38969 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 38970-38979 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 38980-38989 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 38990-38999 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 39000-39009 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 39010-39019 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 39020-39029 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 39030-39039 + 1, 2, 1, 4, 3, 2, 1, 32, 31, 30, // 39040-39049 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 39050-39059 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 39060-39069 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 39070-39079 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 39080-39089 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 39090-39099 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 39100-39109 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 39110-39119 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 39120-39129 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 39130-39139 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 39140-39149 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 39150-39159 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 39160-39169 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 39170-39179 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 39180-39189 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 39190-39199 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 39200-39209 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 39210-39219 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 39220-39229 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 39230-39239 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 39240-39249 + 1, 42, 41, 40, 39, 38, 37, 36, 35, 34, // 39250-39259 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 39260-39269 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 39270-39279 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 39280-39289 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 39290-39299 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 39300-39309 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 39310-39319 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 39320-39329 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 39330-39339 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 39340-39349 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 39350-39359 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 39360-39369 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 39370-39379 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 39380-39389 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 39390-39399 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 39400-39409 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 20, // 39410-39419 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 39420-39429 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 39430-39439 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 39440-39449 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 39450-39459 + 1, 38, 37, 36, 35, 34, 33, 32, 31, 30, // 39460-39469 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 39470-39479 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 39480-39489 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 39490-39499 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 39500-39509 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 39510-39519 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 39520-39529 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 39530-39539 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 39540-39549 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 39550-39559 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 39560-39569 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 39570-39579 + 1, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 39580-39589 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 39590-39599 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 39600-39609 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 39610-39619 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 39620-39629 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 39630-39639 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 39640-39649 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 39650-39659 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 39660-39669 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 39670-39679 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 39680-39689 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 39690-39699 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 39700-39709 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 39710-39719 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 39720-39729 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 39730-39739 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 39740-39749 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 39750-39759 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 39760-39769 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 39770-39779 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 39780-39789 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 39790-39799 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 39800-39809 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 39810-39819 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 39820-39829 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 39830-39839 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 39840-39849 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 39850-39859 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 39860-39869 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 39870-39879 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 39880-39889 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 39890-39899 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 39900-39909 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 39910-39919 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 39920-39929 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 39930-39939 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 39940-39949 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 39950-39959 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 39960-39969 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 39970-39979 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 20, // 39980-39989 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 39990-39999 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 40000-40009 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 40010-40019 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 40020-40029 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 24, // 40030-40039 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 40040-40049 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 40050-40059 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 40060-40069 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 40070-40079 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 40080-40089 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 40090-40099 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 40100-40109 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 40110-40119 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 22, // 40120-40129 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 40130-40139 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 40140-40149 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 40150-40159 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 40160-40169 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 40170-40179 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 40180-40189 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 40190-40199 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 40200-40209 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 40210-40219 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 40220-40229 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 40230-40239 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 40240-40249 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 40250-40259 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 40260-40269 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 40270-40279 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 54, // 40280-40289 + 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, // 40290-40299 + 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, // 40300-40309 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 40310-40319 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 40320-40329 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 40330-40339 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 40340-40349 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 40350-40359 + 1, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 40360-40369 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 40370-40379 + 7, 6, 5, 4, 3, 2, 1, 36, 35, 34, // 40380-40389 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 40390-40399 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 40400-40409 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 40410-40419 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 40420-40429 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 40430-40439 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 40440-40449 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 40450-40459 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 40460-40469 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 40470-40479 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 40480-40489 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 40490-40499 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 40500-40509 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 40510-40519 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 40520-40529 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 40530-40539 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 40540-40549 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 40550-40559 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 40560-40569 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 40570-40579 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 40580-40589 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 40590-40599 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 40600-40609 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 40610-40619 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 40620-40629 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 54, // 40630-40639 + 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, // 40640-40649 + 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, // 40650-40659 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 40660-40669 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 40670-40679 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 40680-40689 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 10, // 40690-40699 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 30, // 40700-40709 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 40710-40719 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 40720-40729 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 40730-40739 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 40740-40749 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 40750-40759 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 40760-40769 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 40770-40779 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 40780-40789 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 40790-40799 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 40800-40809 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 40810-40819 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 40820-40829 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 40830-40839 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 40840-40849 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 40850-40859 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 40860-40869 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 40870-40879 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 40880-40889 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 40890-40899 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 40900-40909 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 40910-40919 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 40920-40929 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 40930-40939 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 40940-40949 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 40950-40959 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 40960-40969 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 40970-40979 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 40980-40989 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 40990-40999 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 41000-41009 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 41010-41019 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 41020-41029 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 41030-41039 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 41040-41049 + 1, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 41050-41059 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 41060-41069 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 41070-41079 + 1, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 41080-41089 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 41090-41099 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 41100-41109 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 41110-41119 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 41120-41129 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 41130-41139 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 41140-41149 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 41150-41159 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 41160-41169 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 41170-41179 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 41180-41189 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 41190-41199 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 41200-41209 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 41210-41219 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 41220-41229 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 41230-41239 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 41240-41249 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 41250-41259 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 41260-41269 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 41270-41279 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 41280-41289 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 34, // 41290-41299 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 41300-41309 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 41310-41319 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 41320-41329 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 41330-41339 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 41340-41349 + 1, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 41350-41359 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 41360-41369 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 41370-41379 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 41380-41389 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 41390-41399 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 41400-41409 + 1, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 41410-41419 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 41420-41429 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 41430-41439 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 41440-41449 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 41450-41459 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 41460-41469 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 41470-41479 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 41480-41489 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 41490-41499 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 41500-41509 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 41510-41519 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 41520-41529 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 41530-41539 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 30, // 41540-41549 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 41550-41559 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 41560-41569 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 41570-41579 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 41580-41589 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 41590-41599 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 41600-41609 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 41610-41619 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 41620-41629 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 41630-41639 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 41640-41649 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 41650-41659 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 41660-41669 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 41670-41679 + 1, 6, 5, 4, 3, 2, 1, 32, 31, 30, // 41680-41689 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 41690-41699 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 41700-41709 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 41710-41719 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 41720-41729 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 41730-41739 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 41740-41749 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 41750-41759 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 41760-41769 + 1, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 41770-41779 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 41780-41789 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 41790-41799 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 41800-41809 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 41810-41819 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 41820-41829 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 41830-41839 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 41840-41849 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 41850-41859 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 41860-41869 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 41870-41879 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 41880-41889 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 41890-41899 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 41900-41909 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 41910-41919 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 41920-41929 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 41930-41939 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 41940-41949 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 10, // 41950-41959 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 41960-41969 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 41970-41979 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 41980-41989 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 41990-41999 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 42000-42009 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 42010-42019 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 42020-42029 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 42030-42039 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 42040-42049 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 42050-42059 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 42060-42069 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 42070-42079 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 42080-42089 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 42090-42099 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 42100-42109 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 42110-42119 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 42120-42129 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 42130-42139 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 42140-42149 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 42150-42159 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 42160-42169 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 42170-42179 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 42180-42189 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 42190-42199 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 42200-42209 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 42210-42219 + 1, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 42220-42229 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 42230-42239 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 42240-42249 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 42250-42259 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 42260-42269 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 42270-42279 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 42280-42289 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 42290-42299 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 42300-42309 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 42310-42319 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 42320-42329 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 42330-42339 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 42340-42349 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 42350-42359 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 42360-42369 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 42370-42379 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 42380-42389 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 42390-42399 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 24, // 42400-42409 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 42410-42419 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 42420-42429 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 42430-42439 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 42440-42449 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 42450-42459 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 42460-42469 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 42470-42479 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 42480-42489 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 42490-42499 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 42500-42509 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 42510-42519 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 42520-42529 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 42530-42539 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 42540-42549 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 42550-42559 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 42560-42569 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 42570-42579 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 42580-42589 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 42590-42599 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 42600-42609 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 42610-42619 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 42620-42629 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 42630-42639 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 42640-42649 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 42650-42659 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 42660-42669 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 42670-42679 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 42680-42689 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 42690-42699 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 42700-42709 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 42710-42719 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 42720-42729 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 42730-42739 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 42740-42749 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 42750-42759 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 42760-42769 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 42770-42779 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 42780-42789 + 3, 2, 1, 4, 3, 2, 1, 24, 23, 22, // 42790-42799 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 42800-42809 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 42810-42819 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 42820-42829 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 42830-42839 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 42840-42849 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 42850-42859 + 3, 2, 1, 36, 35, 34, 33, 32, 31, 30, // 42860-42869 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 42870-42879 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 42880-42889 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 42890-42899 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 42900-42909 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 42910-42919 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 42920-42929 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 42930-42939 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 42940-42949 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 42950-42959 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 42960-42969 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 42970-42979 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 42980-42989 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 42990-42999 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 43000-43009 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 43010-43019 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 43020-43029 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 43030-43039 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 43040-43049 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 43050-43059 + 3, 2, 1, 4, 3, 2, 1, 26, 25, 24, // 43060-43069 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 43070-43079 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 43080-43089 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 43090-43099 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 43100-43109 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 43110-43119 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 43120-43129 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 43130-43139 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 43140-43149 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 43150-43159 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 43160-43169 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 43170-43179 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 43180-43189 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 43190-43199 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 43200-43209 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 43210-43219 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 43220-43229 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 43230-43239 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 43240-43249 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 43250-43259 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 43260-43269 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 43270-43279 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 43280-43289 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 43290-43299 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 43300-43309 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 43310-43319 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 43320-43329 + 1, 60, 59, 58, 57, 56, 55, 54, 53, 52, // 43330-43339 + 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, // 43340-43349 + 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, // 43350-43359 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 43360-43369 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 43370-43379 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 43380-43389 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 43390-43399 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 43400-43409 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 43410-43419 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 43420-43429 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 43430-43439 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 43440-43449 + 1, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 43450-43459 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 43460-43469 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 43470-43479 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 43480-43489 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 43490-43499 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 43500-43509 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 43510-43519 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 43520-43529 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 43530-43539 + 1, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 43540-43549 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 43550-43559 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 43560-43569 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 43570-43579 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 43580-43589 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 43590-43599 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 43600-43609 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 43610-43619 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 43620-43629 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 43630-43639 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 43640-43649 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 43650-43659 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 43660-43669 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 43670-43679 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 43680-43689 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 43690-43699 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 43700-43709 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 43710-43719 + 1, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 43720-43729 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 43730-43739 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 43740-43749 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 43750-43759 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 43760-43769 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 43770-43779 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 43780-43789 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 43790-43799 + 1, 52, 51, 50, 49, 48, 47, 46, 45, 44, // 43800-43809 + 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, // 43810-43819 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 43820-43829 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 43830-43839 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 43840-43849 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 43850-43859 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 43860-43869 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 43870-43879 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 43880-43889 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 43890-43899 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 43900-43909 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 43910-43919 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 43920-43929 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 43930-43939 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 43940-43949 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 43950-43959 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 43960-43969 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 43970-43979 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 43980-43989 + 1, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 43990-43999 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 44000-44009 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 44010-44019 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 44020-44029 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 44030-44039 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 44040-44049 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 44050-44059 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 44060-44069 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 44070-44079 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 44080-44089 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 44090-44099 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 44100-44109 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 44110-44119 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 44120-44129 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 44130-44139 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 44140-44149 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 44150-44159 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 44160-44169 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 44170-44179 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 44180-44189 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 44190-44199 + 1, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 44200-44209 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 44210-44219 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 44220-44229 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 44230-44239 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 44240-44249 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 44250-44259 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 44260-44269 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 44270-44279 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 44280-44289 + 3, 2, 1, 58, 57, 56, 55, 54, 53, 52, // 44290-44299 + 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, // 44300-44309 + 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, // 44310-44319 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 44320-44329 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 44330-44339 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 44340-44349 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 44350-44359 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 44360-44369 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 44370-44379 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 28, // 44380-44389 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 44390-44399 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 44400-44409 + 7, 6, 5, 4, 3, 2, 1, 32, 31, 30, // 44410-44419 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 44420-44429 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 44430-44439 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 44440-44449 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 44450-44459 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 44460-44469 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 44470-44479 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 44480-44489 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 44490-44499 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 44500-44509 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 44510-44519 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 44520-44529 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 44530-44539 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 44540-44549 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 44550-44559 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 44560-44569 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 44570-44579 + 7, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 44580-44589 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 44590-44599 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 44600-44609 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 44610-44619 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 44620-44629 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 44630-44639 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 44640-44649 + 1, 6, 5, 4, 3, 2, 1, 26, 25, 24, // 44650-44659 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 44660-44669 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 44670-44679 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 44680-44689 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 44690-44699 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 44700-44709 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 44710-44719 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 44720-44729 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 44730-44739 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 44740-44749 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 44750-44759 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 44760-44769 + 1, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 44770-44779 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 44780-44789 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 44790-44799 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 44800-44809 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 20, // 44810-44819 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 44820-44829 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 44830-44839 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 44840-44849 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 44850-44859 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 44860-44869 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 44870-44879 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 44880-44889 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 44890-44899 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 44900-44909 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 44910-44919 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 44920-44929 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 44930-44939 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 44940-44949 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 44950-44959 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 44960-44969 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 44970-44979 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 44980-44989 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 44990-44999 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 45000-45009 + 3, 2, 1, 40, 39, 38, 37, 36, 35, 34, // 45010-45019 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 45020-45029 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 45030-45039 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 45040-45049 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 45050-45059 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 45060-45069 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 45070-45079 + 3, 2, 1, 36, 35, 34, 33, 32, 31, 30, // 45080-45089 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 45090-45099 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 45100-45109 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 45110-45119 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 45120-45129 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 22, // 45130-45139 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 45140-45149 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 45150-45159 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 45160-45169 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 45170-45179 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 45180-45189 + 1, 6, 5, 4, 3, 2, 1, 36, 35, 34, // 45190-45199 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 45200-45209 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 45210-45219 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 45220-45229 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 45230-45239 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 45240-45249 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 45250-45259 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 45260-45269 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 45270-45279 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 45280-45289 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 45290-45299 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 45300-45309 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 45310-45319 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 45320-45329 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 45330-45339 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 45340-45349 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 45350-45359 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 45360-45369 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 45370-45379 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 45380-45389 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 45390-45399 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 45400-45409 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 45410-45419 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 45420-45429 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 42, // 45430-45439 + 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, // 45440-45449 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 45450-45459 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 45460-45469 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 45470-45479 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 45480-45489 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 45490-45499 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 45500-45509 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 45510-45519 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 45520-45529 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 45530-45539 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 45540-45549 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 45550-45559 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 45560-45569 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 45570-45579 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 45580-45589 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 45590-45599 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 45600-45609 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 45610-45619 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 45620-45629 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 45630-45639 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 45640-45649 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 45650-45659 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 45660-45669 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 45670-45679 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 45680-45689 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 45690-45699 + 7, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 45700-45709 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 45710-45719 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 45720-45729 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 45730-45739 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 45740-45749 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 45750-45759 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 45760-45769 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 38, // 45770-45779 + 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 45780-45789 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 45790-45799 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 45800-45809 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 45810-45819 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 45820-45829 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 45830-45839 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 45840-45849 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 45850-45859 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 45860-45869 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 45870-45879 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 45880-45889 + 3, 2, 1, 50, 49, 48, 47, 46, 45, 44, // 45890-45899 + 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, // 45900-45909 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 45910-45919 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 45920-45929 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 45930-45939 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 45940-45949 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 45950-45959 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 45960-45969 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 45970-45979 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 32, // 45980-45989 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 45990-45999 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 46000-46009 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 46010-46019 + 1, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 46020-46029 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 46030-46039 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 46040-46049 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 46050-46059 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 46060-46069 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 46070-46079 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 46080-46089 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 46090-46099 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 46100-46109 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 46110-46119 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 46120-46129 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 46130-46139 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 46140-46149 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 46150-46159 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 46160-46169 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 46170-46179 + 1, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 46180-46189 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 20, // 46190-46199 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 46200-46209 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 46210-46219 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 46220-46229 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 46230-46239 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 46240-46249 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 46250-46259 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 46260-46269 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 46270-46279 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 46280-46289 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 46290-46299 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 18, // 46300-46309 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 46310-46319 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 46320-46329 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 46330-46339 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 46340-46349 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 46350-46359 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 46360-46369 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 46370-46379 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 46380-46389 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 46390-46399 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 46400-46409 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 46410-46419 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 46420-46429 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 46430-46439 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 46440-46449 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 46450-46459 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 46460-46469 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 46470-46479 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 46480-46489 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 46490-46499 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 46500-46509 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 46510-46519 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 46520-46529 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 46530-46539 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 46540-46549 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 46550-46559 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 46560-46569 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 46570-46579 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 46580-46589 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 46590-46599 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 46600-46609 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 46610-46619 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 46620-46629 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 46630-46639 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 46640-46649 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 46650-46659 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 46660-46669 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 46670-46679 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 46680-46689 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 46690-46699 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 46700-46709 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 46710-46719 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 46720-46729 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 46730-46739 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 46740-46749 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 46750-46759 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 46760-46769 + 1, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 46770-46779 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 46780-46789 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 46790-46799 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 46800-46809 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 46810-46819 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 46820-46829 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 46830-46839 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 46840-46849 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 46850-46859 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 46860-46869 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 46870-46879 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 46880-46889 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 46890-46899 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 46900-46909 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 46910-46919 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 46920-46929 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 46930-46939 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 46940-46949 + 7, 6, 5, 4, 3, 2, 1, 36, 35, 34, // 46950-46959 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 46960-46969 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 46970-46979 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 46980-46989 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 46990-46999 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 47000-47009 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 47010-47019 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 47020-47029 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47030-47039 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47040-47049 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 28, // 47050-47059 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 47060-47069 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 47070-47079 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 47080-47089 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 47090-47099 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47100-47109 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 47110-47119 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 47120-47129 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 47130-47139 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 47140-47149 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47150-47159 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 47160-47169 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 47170-47179 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 47180-47189 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 47190-47199 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 47200-47209 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47210-47219 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 47220-47229 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 47230-47239 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47240-47249 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 47250-47259 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 47260-47269 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 47270-47279 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 47280-47289 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 47290-47299 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 47300-47309 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 47310-47319 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 47320-47329 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 47330-47339 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47340-47349 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 47350-47359 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 47360-47369 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47370-47379 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 18, // 47380-47389 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 47390-47399 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 47400-47409 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 47410-47419 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47420-47429 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47430-47439 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 47440-47449 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 32, // 47450-47459 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 47460-47469 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 47470-47479 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47480-47489 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 47490-47499 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 47500-47509 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 47510-47519 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 47520-47529 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 47530-47539 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 47540-47549 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 47550-47559 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 47560-47569 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47570-47579 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47580-47589 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 47590-47599 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 47600-47609 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 47610-47619 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 47620-47629 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 47630-47639 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 47640-47649 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 22, // 47650-47659 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 47660-47669 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47670-47679 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 47680-47689 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 47690-47699 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47700-47709 + 1, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 47710-47719 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 47720-47729 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 47730-47739 + 1, 2, 1, 34, 33, 32, 31, 30, 29, 28, // 47740-47749 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 47750-47759 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 47760-47769 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 47770-47779 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47780-47789 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 47790-47799 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 47800-47809 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 47810-47819 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 47820-47829 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 47830-47839 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 47840-47849 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 47850-47859 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 47860-47869 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 47870-47879 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 47880-47889 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 47890-47899 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 47900-47909 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 47910-47919 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 47920-47929 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 47930-47939 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 47940-47949 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 47950-47959 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 47960-47969 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 47970-47979 + 1, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 47980-47989 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 47990-47999 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 48000-48009 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 48010-48019 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 20, // 48020-48029 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 48030-48039 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 48040-48049 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 48050-48059 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 48060-48069 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 48070-48079 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 48080-48089 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 48090-48099 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 48100-48109 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 48110-48119 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 48120-48129 + 1, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 48130-48139 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 48140-48149 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 48150-48159 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 48160-48169 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 48170-48179 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 48180-48189 + 3, 2, 1, 4, 3, 2, 1, 24, 23, 22, // 48190-48199 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 48200-48209 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 48210-48219 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 48220-48229 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 48230-48239 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 48240-48249 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 48250-48259 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 48260-48269 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 48270-48279 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 48280-48289 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 48290-48299 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 48300-48309 + 1, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 48310-48319 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 48320-48329 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 48330-48339 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 48340-48349 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 48350-48359 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 48360-48369 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 48370-48379 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 48380-48389 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 48390-48399 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 48400-48409 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 48410-48419 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 48420-48429 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 48430-48439 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 48440-48449 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 48450-48459 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 48460-48469 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 48470-48479 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 48480-48489 + 1, 6, 5, 4, 3, 2, 1, 26, 25, 24, // 48490-48499 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 48500-48509 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 48510-48519 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 48520-48529 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 48530-48539 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 48540-48549 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 48550-48559 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 48560-48569 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 48570-48579 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 48580-48589 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 48590-48599 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 48600-48609 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 48610-48619 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 48620-48629 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 48630-48639 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 48640-48649 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 48650-48659 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 48660-48669 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 52, // 48670-48679 + 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, // 48680-48689 + 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, // 48690-48699 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 48700-48709 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 48710-48719 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 48720-48729 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 48730-48739 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 48740-48749 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 48750-48759 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 48760-48769 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 48770-48779 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 48780-48789 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 48790-48799 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 48800-48809 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 48810-48819 + 1, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 48820-48829 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 48830-48839 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 48840-48849 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 48850-48859 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 48860-48869 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 48870-48879 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 48880-48889 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 48890-48899 + 7, 6, 5, 4, 3, 2, 1, 40, 39, 38, // 48900-48909 + 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 48910-48919 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 48920-48929 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 48930-48939 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 48940-48949 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 48950-48959 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 48960-48969 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 48970-48979 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 48980-48989 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 48990-48999 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 49000-49009 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 49010-49019 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 49020-49029 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 49030-49039 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 49040-49049 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 49050-49059 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 49060-49069 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 49070-49079 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 49080-49089 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 49090-49099 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 49100-49109 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 49110-49119 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 49120-49129 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 49130-49139 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 49140-49149 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 49150-49159 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 49160-49169 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 49170-49179 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 49180-49189 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 49190-49199 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 49200-49209 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 49210-49219 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 49220-49229 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 49230-49239 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 49240-49249 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 49250-49259 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 49260-49269 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 18, // 49270-49279 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 49280-49289 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 49290-49299 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 49300-49309 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 49310-49319 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 49320-49329 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 24, // 49330-49339 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 49340-49349 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 49350-49359 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 22, // 49360-49369 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 49370-49379 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 49380-49389 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 49390-49399 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 49400-49409 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 49410-49419 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 49420-49429 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 49430-49439 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 49440-49449 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 49450-49459 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 49460-49469 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 49470-49479 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 49480-49489 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 49490-49499 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 49500-49509 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 49510-49519 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 49520-49529 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 49530-49539 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 49540-49549 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 38, // 49550-49559 + 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 49560-49569 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 49570-49579 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 49580-49589 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 49590-49599 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 49600-49609 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 49610-49619 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 49620-49629 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 24, // 49630-49639 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 49640-49649 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 49650-49659 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 49660-49669 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 49670-49679 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 49680-49689 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 49690-49699 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 49700-49709 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 49710-49719 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 49720-49729 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 49730-49739 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 49740-49749 + 7, 6, 5, 4, 3, 2, 1, 26, 25, 24, // 49750-49759 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 49760-49769 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 49770-49779 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 49780-49789 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 49790-49799 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 49800-49809 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 49810-49819 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 49820-49829 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 49830-49839 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 49840-49849 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 49850-49859 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 49860-49869 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 49870-49879 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 49880-49889 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 49890-49899 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 49900-49909 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 49910-49919 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 49920-49929 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 49930-49939 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 49940-49949 + 7, 6, 5, 4, 3, 2, 1, 34, 33, 32, // 49950-49959 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 49960-49969 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 49970-49979 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 49980-49989 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 49990-49999 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 50000-50009 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 50010-50019 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 50020-50029 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 50030-50039 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 50040-50049 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 50050-50059 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 50060-50069 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 50070-50079 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 50080-50089 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 50090-50099 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 50100-50109 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 50110-50119 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 50120-50129 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 50130-50139 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 50140-50149 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 50150-50159 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 50160-50169 + 7, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 50170-50179 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 50180-50189 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 50190-50199 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 50200-50209 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 50210-50219 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 50220-50229 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 50230-50239 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 50240-50249 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 50250-50259 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 50260-50269 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 50270-50279 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 50280-50289 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 50290-50299 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 50300-50309 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 50310-50319 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 50320-50329 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 50330-50339 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 50340-50349 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 50350-50359 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 50360-50369 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 50370-50379 + 3, 2, 1, 4, 3, 2, 1, 24, 23, 22, // 50380-50389 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 50390-50399 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 50400-50409 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 50410-50419 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 50420-50429 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 50430-50439 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 50440-50449 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 50450-50459 + 1, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 50460-50469 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 50470-50479 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 50480-50489 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 50490-50499 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 50500-50509 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 50510-50519 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 50520-50529 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 50530-50539 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 50540-50549 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 50550-50559 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 50560-50569 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 50570-50579 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 50580-50589 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 28, // 50590-50599 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 50600-50609 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 50610-50619 + 7, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 50620-50629 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 50630-50639 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 50640-50649 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 50650-50659 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 50660-50669 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 50670-50679 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 50680-50689 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 50690-50699 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 50700-50709 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 50710-50719 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 50720-50729 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 50730-50739 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 50740-50749 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 50750-50759 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 50760-50769 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 50770-50779 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 32, // 50780-50789 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 50790-50799 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 50800-50809 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 50810-50819 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 50820-50829 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 50830-50839 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 50840-50849 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 50850-50859 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 50860-50869 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 50870-50879 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 50880-50889 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 50890-50899 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 50900-50909 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 50910-50919 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 50920-50929 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 50930-50939 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 50940-50949 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 50950-50959 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 50960-50969 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 50970-50979 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 50980-50989 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 50990-50999 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 51000-51009 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 51010-51019 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 51020-51029 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 51030-51039 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 51040-51049 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 51050-51059 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 51060-51069 + 1, 38, 37, 36, 35, 34, 33, 32, 31, 30, // 51070-51079 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 51080-51089 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 51090-51099 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 51100-51109 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 51110-51119 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 51120-51129 + 1, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 51130-51139 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 51140-51149 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 51150-51159 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 51160-51169 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 51170-51179 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 51180-51189 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 51190-51199 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 51200-51209 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 51210-51219 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 51220-51229 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 51230-51239 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 51240-51249 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 51250-51259 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 51260-51269 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 51270-51279 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 51280-51289 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 51290-51299 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 51300-51309 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 51310-51319 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 51320-51329 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 51330-51339 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 12, // 51340-51349 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 51350-51359 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 51360-51369 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 51370-51379 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 51380-51389 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 51390-51399 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 51400-51409 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 51410-51419 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 51420-51429 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 51430-51439 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 51440-51449 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 51450-51459 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 51460-51469 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 51470-51479 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 51480-51489 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 51490-51499 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 51500-51509 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 51510-51519 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 51520-51529 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 51530-51539 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 51540-51549 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 51550-51559 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 51560-51569 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 51570-51579 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 51580-51589 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 51590-51599 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 51600-51609 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 51610-51619 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 51620-51629 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 51630-51639 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 51640-51649 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 51650-51659 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 51660-51669 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 51670-51679 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 51680-51689 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 51690-51699 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 51700-51709 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 51710-51719 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 51720-51729 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 51730-51739 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 51740-51749 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 51750-51759 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 18, // 51760-51769 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 51770-51779 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 51780-51789 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 51790-51799 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 51800-51809 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 51810-51819 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 51820-51829 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 51830-51839 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 51840-51849 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 51850-51859 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 51860-51869 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 51870-51879 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 51880-51889 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 51890-51899 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 51900-51909 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 51910-51919 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 51920-51929 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 51930-51939 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 51940-51949 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 51950-51959 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 51960-51969 + 1, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 51970-51979 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 51980-51989 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 51990-51999 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 52000-52009 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 52010-52019 + 1, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 52020-52029 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 52030-52039 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 52040-52049 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 52050-52059 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 52060-52069 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 52070-52079 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 52080-52089 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 52090-52099 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 52100-52109 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 52110-52119 + 1, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 52120-52129 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 52130-52139 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 52140-52149 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 52150-52159 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 52160-52169 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 52170-52179 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 52180-52189 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 52190-52199 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 52200-52209 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 52210-52219 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 52220-52229 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 52230-52239 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 52240-52249 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 52250-52259 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 52260-52269 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 52270-52279 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 52280-52289 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 52290-52299 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 52300-52309 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 52310-52319 + 1, 40, 39, 38, 37, 36, 35, 34, 33, 32, // 52320-52329 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 52330-52339 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 52340-52349 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 52350-52359 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 52360-52369 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 52370-52379 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 52380-52389 + 1, 42, 41, 40, 39, 38, 37, 36, 35, 34, // 52390-52399 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 52400-52409 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 52410-52419 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 52420-52429 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 52430-52439 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 52440-52449 + 3, 2, 1, 4, 3, 2, 1, 32, 31, 30, // 52450-52459 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 52460-52469 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 52470-52479 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 52480-52489 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 52490-52499 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 52500-52509 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 52510-52519 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 52520-52529 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 52530-52539 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 52540-52549 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 52550-52559 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 52560-52569 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 52570-52579 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 52580-52589 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 52590-52599 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 52600-52609 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 52610-52619 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 52620-52629 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 28, // 52630-52639 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 52640-52649 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 52650-52659 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 52660-52669 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 52670-52679 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 52680-52689 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 52690-52699 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 52700-52709 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 52710-52719 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 52720-52729 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 52730-52739 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 52740-52749 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 52750-52759 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 52760-52769 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 52770-52779 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 52780-52789 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 52790-52799 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 52800-52809 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 52810-52819 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 52820-52829 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 52830-52839 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 52840-52849 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 52850-52859 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 52860-52869 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 52870-52879 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 52880-52889 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 52890-52899 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 52900-52909 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 52910-52919 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 52920-52929 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 52930-52939 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 52940-52949 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 52950-52959 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 52960-52969 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 52970-52979 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 52980-52989 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 52990-52999 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 53000-53009 + 7, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 53010-53019 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 53020-53029 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 53030-53039 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 53040-53049 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 53050-53059 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 53060-53069 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 53070-53079 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 53080-53089 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 53090-53099 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 53100-53109 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 53110-53119 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 53120-53129 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 53130-53139 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 53140-53149 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 53150-53159 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 53160-53169 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 53170-53179 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 53180-53189 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 53190-53199 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 53200-53209 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 53210-53219 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 53220-53229 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 28, // 53230-53239 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 53240-53249 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 53250-53259 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 53260-53269 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 53270-53279 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 53280-53289 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 53290-53299 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 53300-53309 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 53310-53319 + 3, 2, 1, 4, 3, 2, 1, 26, 25, 24, // 53320-53329 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 53330-53339 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 53340-53349 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 53350-53359 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 53360-53369 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 53370-53379 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 53380-53389 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 53390-53399 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 53400-53409 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 53410-53419 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 53420-53429 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 53430-53439 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 53440-53449 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 53450-53459 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 53460-53469 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 53470-53479 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 53480-53489 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 53490-53499 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 53500-53509 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 53510-53519 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 53520-53529 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 53530-53539 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 53540-53549 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 53550-53559 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 53560-53569 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 53570-53579 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 53580-53589 + 1, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 53590-53599 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 53600-53609 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 53610-53619 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 53620-53629 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 53630-53639 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 53640-53649 + 3, 2, 1, 4, 3, 2, 1, 24, 23, 22, // 53650-53659 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 53660-53669 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 53670-53679 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 53680-53689 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 53690-53699 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 53700-53709 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 53710-53719 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 53720-53729 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 53730-53739 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 53740-53749 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 53750-53759 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 53760-53769 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 53770-53779 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 53780-53789 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 53790-53799 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 53800-53809 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 53810-53819 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 53820-53829 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 53830-53839 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 53840-53849 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 53850-53859 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 53860-53869 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 53870-53879 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 53880-53889 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 18, // 53890-53899 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 53900-53909 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 53910-53919 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 53920-53929 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 53930-53939 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 53940-53949 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 28, // 53950-53959 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 53960-53969 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 53970-53979 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 53980-53989 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 53990-53999 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 54000-54009 + 1, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 54010-54019 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 54020-54029 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 54030-54039 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 54040-54049 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 54050-54059 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 54060-54069 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 54070-54079 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 54080-54089 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 54090-54099 + 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 54100-54109 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 54110-54119 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 54120-54129 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 54130-54139 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 54140-54149 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 54150-54159 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 54160-54169 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 54170-54179 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 54180-54189 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 54190-54199 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 54200-54209 + 7, 6, 5, 4, 3, 2, 1, 34, 33, 32, // 54210-54219 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 54220-54229 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 54230-54239 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 54240-54249 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 54250-54259 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 54260-54269 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 54270-54279 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 54280-54289 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 54290-54299 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 54300-54309 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 54310-54319 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 54320-54329 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 54330-54339 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 54340-54349 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 54350-54359 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 54360-54369 + 1, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 54370-54379 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 54380-54389 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 54390-54399 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 54400-54409 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 54410-54419 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 54420-54429 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 54430-54439 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 20, // 54440-54449 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 54450-54459 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 54460-54469 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 54470-54479 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 54480-54489 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 54490-54499 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 54500-54509 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 54510-54519 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 54520-54529 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 54530-54539 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 54540-54549 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 54550-54559 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 54560-54569 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 54570-54579 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 54580-54589 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 54590-54599 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 54600-54609 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 54610-54619 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 54620-54629 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 54630-54639 + 7, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 54640-54649 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 54650-54659 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 54660-54669 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 30, // 54670-54679 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 54680-54689 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 54690-54699 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 54700-54709 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 54710-54719 + 1, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 54720-54729 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 54730-54739 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 54740-54749 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 54750-54759 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 54760-54769 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 54770-54779 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 54780-54789 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 30, // 54790-54799 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 54800-54809 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 54810-54819 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 54820-54829 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 54830-54839 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 54840-54849 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 54850-54859 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 54860-54869 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 54870-54879 + 1, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 54880-54889 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 54890-54899 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 54900-54909 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 22, // 54910-54919 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 54920-54929 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 54930-54939 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 54940-54949 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 54950-54959 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 54960-54969 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 54970-54979 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 54980-54989 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 54990-54999 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 55000-55009 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 55010-55019 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 55020-55029 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 55030-55039 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 55040-55049 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 55050-55059 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 55060-55069 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 24, // 55070-55079 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 55080-55089 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 55090-55099 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 55100-55109 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 55110-55119 + 7, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 55120-55129 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 55130-55139 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 55140-55149 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 55150-55159 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 55160-55169 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 55170-55179 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 55180-55189 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 55190-55199 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 55200-55209 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 10, // 55210-55219 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 55220-55229 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 55230-55239 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 55240-55249 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 32, // 55250-55259 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 55260-55269 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 55270-55279 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 55280-55289 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 55290-55299 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 55300-55309 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 55310-55319 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 55320-55329 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 55330-55339 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 55340-55349 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 55350-55359 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 55360-55369 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 55370-55379 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 55380-55389 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 55390-55399 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 55400-55409 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 55410-55419 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 55420-55429 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 55430-55439 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 55440-55449 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 55450-55459 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 55460-55469 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 55470-55479 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 55480-55489 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 55490-55499 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 55500-55509 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 55510-55519 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 55520-55529 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 55530-55539 + 1, 6, 5, 4, 3, 2, 1, 32, 31, 30, // 55540-55549 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 55550-55559 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 55560-55569 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 55570-55579 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 55580-55589 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 55590-55599 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 55600-55609 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 55610-55619 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 55620-55629 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 55630-55639 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 55640-55649 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 55650-55659 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 55660-55669 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 55670-55679 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 55680-55689 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 55690-55699 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 55700-55709 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 55710-55719 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 55720-55729 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 55730-55739 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 55740-55749 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 55750-55759 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 55760-55769 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 55770-55779 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 55780-55789 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 55790-55799 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 55800-55809 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 55810-55819 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 55820-55829 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 55830-55839 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 55840-55849 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 55850-55859 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 55860-55869 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 55870-55879 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 55880-55889 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 55890-55899 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 55900-55909 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 55910-55919 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 55920-55929 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 55930-55939 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 55940-55949 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 55950-55959 + 7, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 55960-55969 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 55970-55979 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 55980-55989 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 55990-55999 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 30, // 56000-56009 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 56010-56019 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 56020-56029 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 56030-56039 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 56040-56049 + 3, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 56050-56059 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 56060-56069 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 56070-56079 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 56080-56089 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 56090-56099 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 56100-56109 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 56110-56119 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 56120-56129 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 56130-56139 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 56140-56149 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 56150-56159 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 56160-56169 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 56170-56179 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 56180-56189 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 56190-56199 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 28, // 56200-56209 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 56210-56219 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 56220-56229 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 56230-56239 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 56240-56249 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 56250-56259 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 30, // 56260-56269 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 56270-56279 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 56280-56289 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 56290-56299 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 56300-56309 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 56310-56319 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 56320-56329 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 56330-56339 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 56340-56349 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 56350-56359 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 56360-56369 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 56370-56379 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 56380-56389 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 56390-56399 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 56400-56409 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 56410-56419 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 56420-56429 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 56430-56439 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 56440-56449 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 56450-56459 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 56460-56469 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 10, // 56470-56479 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 56480-56489 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 56490-56499 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 56500-56509 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 56510-56519 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 56520-56529 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 56530-56539 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 56540-56549 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 56550-56559 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 56560-56569 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 56570-56579 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 56580-56589 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 56590-56599 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 56600-56609 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 56610-56619 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 56620-56629 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 56630-56639 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 56640-56649 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 56650-56659 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 56660-56669 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 56670-56679 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 56680-56689 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 56690-56699 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 56700-56709 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 56710-56719 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 56720-56729 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 56730-56739 + 7, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 56740-56749 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 56750-56759 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 56760-56769 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 56770-56779 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 56780-56789 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 56790-56799 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 56800-56809 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 56810-56819 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 56820-56829 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 56830-56839 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 56840-56849 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 56850-56859 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 56860-56869 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 56870-56879 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 56880-56889 + 1, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 56890-56899 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 56900-56909 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 56910-56919 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 56920-56929 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 56930-56939 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 56940-56949 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 56950-56959 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 56960-56969 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 56970-56979 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 56980-56989 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 38, // 56990-56999 + 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 57000-57009 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 57010-57019 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 57020-57029 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 57030-57039 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 57040-57049 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 57050-57059 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 57060-57069 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 57070-57079 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 57080-57089 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 57090-57099 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 57100-57109 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 57110-57119 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 57120-57129 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 57130-57139 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 57140-57149 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 57150-57159 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 57160-57169 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 57170-57179 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 57180-57189 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 57190-57199 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 57200-57209 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 57210-57219 + 1, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 57220-57229 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 57230-57239 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 57240-57249 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 57250-57259 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 57260-57269 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 57270-57279 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 57280-57289 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 57290-57299 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 57300-57309 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 57310-57319 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 57320-57329 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 57330-57339 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 18, // 57340-57349 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 57350-57359 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 57360-57369 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 57370-57379 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 57380-57389 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 57390-57399 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 57400-57409 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 57410-57419 + 7, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 57420-57429 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 57430-57439 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 57440-57449 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 57450-57459 + 7, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 57460-57469 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 57470-57479 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 57480-57489 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 57490-57499 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 57500-57509 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 57510-57519 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 28, // 57520-57529 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 57530-57539 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 57540-57549 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 57550-57559 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 57560-57569 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 57570-57579 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 57580-57589 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 57590-57599 + 1, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 57600-57609 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 57610-57619 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 57620-57629 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 57630-57639 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 57640-57649 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 57650-57659 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 57660-57669 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 57670-57679 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 57680-57689 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 57690-57699 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 57700-57709 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 57710-57719 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 57720-57729 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 57730-57739 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 57740-57749 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 57750-57759 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 57760-57769 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 57770-57779 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 57780-57789 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 57790-57799 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 20, // 57800-57809 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 57810-57819 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 57820-57829 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 57830-57839 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 57840-57849 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 57850-57859 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 57860-57869 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 57870-57879 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 57880-57889 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 57890-57899 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 57900-57909 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 57910-57919 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 57920-57929 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 57930-57939 + 3, 2, 1, 4, 3, 2, 1, 26, 25, 24, // 57940-57949 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 57950-57959 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 57960-57969 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 57970-57979 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 57980-57989 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 57990-57999 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 58000-58009 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 58010-58019 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 58020-58029 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 58030-58039 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 58040-58049 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 58050-58059 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 58060-58069 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 58070-58079 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 58080-58089 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 58090-58099 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 58100-58109 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 58110-58119 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 58120-58129 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 58130-58139 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 58140-58149 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 58150-58159 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 58160-58169 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 58170-58179 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 58180-58189 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 58190-58199 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 58200-58209 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 58210-58219 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 58220-58229 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 58230-58239 + 3, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 58240-58249 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 58250-58259 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 58260-58269 + 1, 38, 37, 36, 35, 34, 33, 32, 31, 30, // 58270-58279 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 58280-58289 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 58290-58299 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 58300-58309 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 58310-58319 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 58320-58329 + 7, 6, 5, 4, 3, 2, 1, 26, 25, 24, // 58330-58339 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 58340-58349 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 58350-58359 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 10, // 58360-58369 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 58370-58379 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 58380-58389 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 58390-58399 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 58400-58409 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 58410-58419 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 58420-58429 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 58430-58439 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 58440-58449 + 1, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 58450-58459 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 58460-58469 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 58470-58479 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 58480-58489 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 58490-58499 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 58500-58509 + 1, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 58510-58519 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 58520-58529 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 58530-58539 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 58540-58549 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 58550-58559 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 58560-58569 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 58570-58579 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 58580-58589 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 58590-58599 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 58600-58609 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 58610-58619 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 58620-58629 + 1, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 58630-58639 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 58640-58649 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 58650-58659 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 58660-58669 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 58670-58679 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 58680-58689 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 58690-58699 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 58700-58709 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 58710-58719 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 58720-58729 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 58730-58739 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 58740-58749 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 58750-58759 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 58760-58769 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 58770-58779 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 42, // 58780-58789 + 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, // 58790-58799 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 58800-58809 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 58810-58819 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 58820-58829 + 1, 58, 57, 56, 55, 54, 53, 52, 51, 50, // 58830-58839 + 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, // 58840-58849 + 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, // 58850-58859 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 58860-58869 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 58870-58879 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 58880-58889 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 58890-58899 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 58900-58909 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 58910-58919 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 58920-58929 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 58930-58939 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 58940-58949 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 58950-58959 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 58960-58969 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 58970-58979 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 58980-58989 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 58990-58999 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 59000-59009 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 59010-59019 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 59020-59029 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 59030-59039 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 59040-59049 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 59050-59059 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 59060-59069 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 59070-59079 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 59080-59089 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 59090-59099 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 59100-59109 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 59110-59119 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 59120-59129 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 59130-59139 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 59140-59149 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 59150-59159 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 59160-59169 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 59170-59179 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 59180-59189 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 59190-59199 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 59200-59209 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 59210-59219 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 59220-59229 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 59230-59239 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 59240-59249 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 59250-59259 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 59260-59269 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 59270-59279 + 1, 52, 51, 50, 49, 48, 47, 46, 45, 44, // 59280-59289 + 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, // 59290-59299 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 59300-59309 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 59310-59319 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 59320-59329 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 59330-59339 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 59340-59349 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 59350-59359 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 59360-59369 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 59370-59379 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 59380-59389 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 59390-59399 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 59400-59409 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 22, // 59410-59419 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 59420-59429 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 59430-59439 + 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 59440-59449 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 59450-59459 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 59460-59469 + 1, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 59470-59479 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 59480-59489 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 59490-59499 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 59500-59509 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 59510-59519 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 59520-59529 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 59530-59539 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 59540-59549 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 59550-59559 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 59560-59569 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 59570-59579 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 59580-59589 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 59590-59599 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 59600-59609 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 59610-59619 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 22, // 59620-59629 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 59630-59639 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 59640-59649 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 59650-59659 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 59660-59669 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 59670-59679 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 59680-59689 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 59690-59699 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 59700-59709 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 59710-59719 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 59720-59729 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 59730-59739 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 59740-59749 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 59750-59759 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 59760-59769 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 59770-59779 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 59780-59789 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 59790-59799 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 59800-59809 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 59810-59819 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 59820-59829 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 59830-59839 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 59840-59849 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 59850-59859 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 59860-59869 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 59870-59879 + 7, 6, 5, 4, 3, 2, 1, 34, 33, 32, // 59880-59889 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 59890-59899 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 59900-59909 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 59910-59919 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 59920-59929 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 59930-59939 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 59940-59949 + 1, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 59950-59959 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 59960-59969 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 59970-59979 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 59980-59989 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 59990-59999 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 60000-60009 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 60010-60019 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 60020-60029 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 60030-60039 + 1, 36, 35, 34, 33, 32, 31, 30, 29, 28, // 60040-60049 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 60050-60059 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 60060-60069 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 60070-60079 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 60080-60089 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 60090-60099 + 1, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 60100-60109 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 60110-60119 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 60120-60129 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 60130-60139 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 60140-60149 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 60150-60159 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 40, // 60160-60169 + 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, // 60170-60179 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 60180-60189 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 60190-60199 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 60200-60209 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 60210-60219 + 3, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 60220-60229 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 60230-60239 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 60240-60249 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 60250-60259 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 60260-60269 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 60270-60279 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 60280-60289 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 60290-60299 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 60300-60309 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 60310-60319 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 60320-60329 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 60330-60339 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 60340-60349 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 60350-60359 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 60360-60369 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 60370-60379 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 60380-60389 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 60390-60399 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 60400-60409 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 60410-60419 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 60420-60429 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 60430-60439 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 60440-60449 + 7, 6, 5, 4, 3, 2, 1, 36, 35, 34, // 60450-60459 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 60460-60469 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 60470-60479 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 60480-60489 + 3, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 60490-60499 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 60500-60509 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 60510-60519 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 60520-60529 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 50, // 60530-60539 + 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, // 60540-60549 + 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, // 60550-60559 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 60560-60569 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 60570-60579 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 60580-60589 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 60590-60599 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 60600-60609 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 60610-60619 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 60620-60629 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 60630-60639 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 60640-60649 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 60650-60659 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 60660-60669 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 60670-60679 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 60680-60689 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 60690-60699 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 60700-60709 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 60710-60719 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 60720-60729 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 60730-60739 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 60740-60749 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 60750-60759 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 60760-60769 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 60770-60779 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 60780-60789 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 60790-60799 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 60800-60809 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 60810-60819 + 1, 38, 37, 36, 35, 34, 33, 32, 31, 30, // 60820-60829 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 60830-60839 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 60840-60849 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 60850-60859 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 60860-60869 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 60870-60879 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 60880-60889 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 60890-60899 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 60900-60909 + 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, // 60910-60919 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 60920-60929 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 60930-60939 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 60940-60949 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 60950-60959 + 1, 40, 39, 38, 37, 36, 35, 34, 33, 32, // 60960-60969 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 60970-60979 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 60980-60989 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 60990-60999 + 1, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 61000-61009 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 61010-61019 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 61020-61029 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 61030-61039 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 61040-61049 + 1, 6, 5, 4, 3, 2, 1, 34, 33, 32, // 61050-61059 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 61060-61069 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 61070-61079 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 61080-61089 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 22, // 61090-61099 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 61100-61109 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 61110-61119 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 61120-61129 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 61130-61139 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 61140-61149 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 61150-61159 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 42, // 61160-61169 + 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, // 61170-61179 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 61180-61189 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 61190-61199 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 61200-61209 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 61210-61219 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 61220-61229 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 61230-61239 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 61240-61249 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 61250-61259 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 61260-61269 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 61270-61279 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 61280-61289 + 1, 6, 5, 4, 3, 2, 1, 34, 33, 32, // 61290-61299 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 61300-61309 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 61310-61319 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 61320-61329 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 61330-61339 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 61340-61349 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 61350-61359 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 61360-61369 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 61370-61379 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 61380-61389 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 61390-61399 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 8, // 61400-61409 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 61410-61419 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 61420-61429 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 61430-61439 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 61440-61449 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 61450-61459 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 61460-61469 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 61470-61479 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 61480-61489 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 61490-61499 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 61500-61509 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 24, // 61510-61519 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 61520-61529 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 61530-61539 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 61540-61549 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 2, // 61550-61559 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 61560-61569 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 61570-61579 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 61580-61589 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 61590-61599 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 61600-61609 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 61610-61619 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 61620-61629 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 61630-61639 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 61640-61649 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 61650-61659 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 61660-61669 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 61670-61679 + 1, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 61680-61689 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 61690-61699 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 61700-61709 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 61710-61719 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 61720-61729 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 61730-61739 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 61740-61749 + 1, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 61750-61759 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 61760-61769 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 61770-61779 + 1, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 61780-61789 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 61790-61799 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 61800-61809 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 61810-61819 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 61820-61829 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 61830-61839 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 61840-61849 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 61850-61859 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 61860-61869 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 30, // 61870-61879 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 61880-61889 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 61890-61899 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 61900-61909 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 61910-61919 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 61920-61929 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 61930-61939 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 61940-61949 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 61950-61959 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 61960-61969 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 61970-61979 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 61980-61989 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 61990-61999 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 62000-62009 + 1, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 62010-62019 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 62020-62029 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 62030-62039 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 62040-62049 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 62050-62059 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 62060-62069 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 62070-62079 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 62080-62089 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 20, // 62090-62099 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 62100-62109 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 62110-62119 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 62120-62129 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 62130-62139 + 1, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 62140-62149 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 62150-62159 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 62160-62169 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 62170-62179 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 62180-62189 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 62190-62199 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 62200-62209 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 62210-62219 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 62220-62229 + 3, 2, 1, 40, 39, 38, 37, 36, 35, 34, // 62230-62239 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 62240-62249 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 62250-62259 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 62260-62269 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 62270-62279 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 62280-62289 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 62290-62299 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 62300-62309 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 62310-62319 + 3, 2, 1, 4, 3, 2, 1, 20, 19, 18, // 62320-62329 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 62330-62339 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 62340-62349 + 1, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 62350-62359 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 62360-62369 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 62370-62379 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 62380-62389 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 62390-62399 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 62400-62409 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 62410-62419 + 3, 2, 1, 36, 35, 34, 33, 32, 31, 30, // 62420-62429 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 62430-62439 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 62440-62449 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 62450-62459 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 62460-62469 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 62470-62479 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 62480-62489 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 62490-62499 + 1, 6, 5, 4, 3, 2, 1, 26, 25, 24, // 62500-62509 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 62510-62519 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 62520-62529 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 62530-62539 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 62540-62549 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 62550-62559 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 62560-62569 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 62570-62579 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 62580-62589 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 62590-62599 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 62600-62609 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 62610-62619 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 62620-62629 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 62630-62639 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 62640-62649 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 24, // 62650-62659 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 62660-62669 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 62670-62679 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 62680-62689 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 62690-62699 + 1, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 62700-62709 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 62710-62719 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 62720-62729 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 62730-62739 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 62740-62749 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 62750-62759 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 62760-62769 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 62770-62779 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 62780-62789 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 62790-62799 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 62800-62809 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 62810-62819 + 7, 6, 5, 4, 3, 2, 1, 24, 23, 22, // 62820-62829 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 62830-62839 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 62840-62849 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 62850-62859 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 62860-62869 + 3, 2, 1, 24, 23, 22, 21, 20, 19, 18, // 62870-62879 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 62880-62889 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 62890-62899 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 62900-62909 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 62910-62919 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 62920-62929 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 30, // 62930-62939 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 62940-62949 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 62950-62959 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 62960-62969 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 62970-62979 + 1, 2, 1, 4, 3, 2, 1, 2, 1, 40, // 62980-62989 + 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, // 62990-62999 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 63000-63009 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 63010-63019 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 63020-63029 + 1, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 63030-63039 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 63040-63049 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 63050-63059 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 63060-63069 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 18, // 63070-63079 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 63080-63089 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 63090-63099 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 63100-63109 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 63110-63119 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 63120-63129 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 63130-63139 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 30, // 63140-63149 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 63150-63159 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 63160-63169 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 63170-63179 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 63180-63189 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 63190-63199 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 63200-63209 + 1, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 63210-63219 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 63220-63229 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 63230-63239 + 1, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 63240-63249 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 63250-63259 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 63260-63269 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 63270-63279 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 63280-63289 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 12, // 63290-63299 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 63300-63309 + 1, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 63310-63319 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 63320-63329 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 63330-63339 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 63340-63349 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 63350-63359 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 63360-63369 + 7, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 63370-63379 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 63380-63389 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 63390-63399 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 63400-63409 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 63410-63419 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 63420-63429 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 63430-63439 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 63440-63449 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 63450-63459 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 63460-63469 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 63470-63479 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 63480-63489 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 22, // 63490-63499 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 63500-63509 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 63510-63519 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 63520-63529 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 63530-63539 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 63540-63549 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 63550-63559 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 63560-63569 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 63570-63579 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 63580-63589 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 63590-63599 + 1, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 63600-63609 + 1, 6, 5, 4, 3, 2, 1, 12, 11, 10, // 63610-63619 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 63620-63629 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 63630-63639 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 10, // 63640-63649 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 63650-63659 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 63660-63669 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 63670-63679 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 63680-63689 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 63690-63699 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 63700-63709 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 63710-63719 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 63720-63729 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 63730-63739 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 63740-63749 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 63750-63759 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 63760-63769 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 63770-63779 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 63780-63789 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 63790-63799 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 63800-63809 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 63810-63819 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 63820-63829 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 63830-63839 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 63840-63849 + 3, 2, 1, 4, 3, 2, 1, 6, 5, 4, // 63850-63859 + 3, 2, 1, 38, 37, 36, 35, 34, 33, 32, // 63860-63869 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 63870-63879 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 63880-63889 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 63890-63899 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 63900-63909 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 63910-63919 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 20, // 63920-63929 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 63930-63939 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 28, // 63940-63949 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 63950-63959 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 63960-63969 + 7, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 63970-63979 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 63980-63989 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 63990-63999 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 64000-64009 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 14, // 64010-64019 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 64020-64029 + 3, 2, 1, 4, 3, 2, 1, 26, 25, 24, // 64030-64039 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 64040-64049 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 64050-64059 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 64060-64069 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 64070-64079 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 64080-64089 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 64090-64099 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 64100-64109 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 64110-64119 + 3, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 64120-64129 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 64130-64139 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 64140-64149 + 1, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 64150-64159 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 64160-64169 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 64170-64179 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 28, // 64180-64189 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 64190-64199 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 64200-64209 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 64210-64219 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 64220-64229 + 1, 6, 5, 4, 3, 2, 1, 34, 33, 32, // 64230-64239 + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, // 64240-64249 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 64250-64259 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 64260-64269 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 64270-64279 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 64280-64289 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 64290-64299 + 1, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 64300-64309 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 64310-64319 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 64320-64329 + 3, 2, 1, 40, 39, 38, 37, 36, 35, 34, // 64330-64339 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 64340-64349 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 64350-64359 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 64360-64369 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 64370-64379 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 64380-64389 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 64390-64399 + 3, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 64400-64409 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 64410-64419 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 64420-64429 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 64430-64439 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 64440-64449 + 1, 2, 1, 30, 29, 28, 27, 26, 25, 24, // 64450-64459 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 64460-64469 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 64470-64479 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 10, // 64480-64489 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 64490-64499 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 64500-64509 + 3, 2, 1, 40, 39, 38, 37, 36, 35, 34, // 64510-64519 + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, // 64520-64529 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 64530-64539 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 64540-64549 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 64550-64559 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 64560-64569 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 64570-64579 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 64580-64589 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 64590-64599 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 64600-64609 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 64610-64619 + 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 64620-64629 + 3, 2, 1, 28, 27, 26, 25, 24, 23, 22, // 64630-64639 + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, // 64640-64649 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 64650-64659 + 1, 2, 1, 4, 3, 2, 1, 12, 11, 10, // 64660-64669 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 64670-64679 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 64680-64689 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 64690-64699 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 8, // 64700-64709 + 7, 6, 5, 4, 3, 2, 1, 30, 29, 28, // 64710-64719 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 64720-64729 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 64730-64739 + 7, 6, 5, 4, 3, 2, 1, 16, 15, 14, // 64740-64749 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 64750-64759 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 64760-64769 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 64770-64779 + 1, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 64780-64789 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 64790-64799 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 64800-64809 + 1, 6, 5, 4, 3, 2, 1, 32, 31, 30, // 64810-64819 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 64820-64829 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 64830-64839 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 64840-64849 + 3, 2, 1, 18, 17, 16, 15, 14, 13, 12, // 64850-64859 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 64860-64869 + 1, 6, 5, 4, 3, 2, 1, 2, 1, 12, // 64870-64879 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 64880-64889 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 64890-64899 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 64900-64909 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 64910-64919 + 1, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 64920-64929 + 7, 6, 5, 4, 3, 2, 1, 14, 13, 12, // 64930-64939 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 64940-64949 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 64950-64959 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 28, // 64960-64969 + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, // 64970-64979 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 64980-64989 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 64990-64999 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 65000-65009 + 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 65010-65019 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 4, // 65020-65029 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 65030-65039 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 65040-65049 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 65050-65059 + 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, // 65060-65069 + 1, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 65070-65079 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, // 65080-65089 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 65090-65099 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 65100-65109 + 1, 8, 7, 6, 5, 4, 3, 2, 1, 4, // 65110-65119 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 12, // 65120-65129 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 65130-65139 + 1, 6, 5, 4, 3, 2, 1, 20, 19, 18, // 65140-65149 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 65150-65159 + 7, 6, 5, 4, 3, 2, 1, 4, 3, 2, // 65160-65169 + 1, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 65170-65179 + 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, // 65180-65189 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 65190-65199 + 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, // 65200-65209 + 3, 2, 1, 26, 25, 24, 23, 22, 21, 20, // 65210-65219 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 65220-65229 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 65230-65239 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 65240-65249 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 65250-65259 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 18, // 65260-65269 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 65270-65279 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 65280-65289 + 3, 2, 1, 16, 15, 14, 13, 12, 11, 10, // 65290-65299 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 14, // 65300-65309 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 65310-65319 + 3, 2, 1, 4, 3, 2, 1, 26, 25, 24, // 65320-65329 + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, // 65330-65339 + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 65340-65349 + 3, 2, 1, 4, 3, 2, 1, 14, 13, 12, // 65350-65359 + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 65360-65369 + 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, // 65370-65379 + 1, 12, 11, 10, 9, 8, 7, 6, 5, 4, // 65380-65389 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 65390-65399 + 7, 6, 5, 4, 3, 2, 1, 6, 5, 4, // 65400-65409 + 3, 2, 1, 6, 5, 4, 3, 2, 1, 4, // 65410-65419 + 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, // 65420-65429 + 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, // 65430-65439 + 7, 6, 5, 4, 3, 2, 1, 2, 1, 30, // 65440-65449 + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, // 65450-65459 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 65460-65469 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 18, // 65470-65479 + 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, // 65480-65489 + 7, 6, 5, 4, 3, 2, 1, 22, 21, 20, // 65490-65499 + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, // 65500-65509 + 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, // 65510-65519 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 65520-65529 + 0, 0, 0, 0, 0, 0, + } + + lohi [256]struct{ lo, hi int } +) + +func init() { + for i, v := range liars { + blk := v >> 24 + x := &lohi[blk] + if x.lo == 0 || i < x.lo { + x.lo = i + } + if i > x.hi { + x.hi = i + } + } +} diff --git a/vendor/github.com/cznic/mathutil/test_deps.go b/vendor/github.com/cznic/mathutil/test_deps.go new file mode 100644 index 00000000..40054dca --- /dev/null +++ b/vendor/github.com/cznic/mathutil/test_deps.go @@ -0,0 +1,11 @@ +// Copyright (c) 2014 The mathutil 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 mathutil + +// Pull test dependencies too. +// Enables easy 'go test X' after 'go get X' +import ( +// nothing yet +) diff --git a/vendor/github.com/cznic/ql/LICENSE b/vendor/github.com/cznic/ql/LICENSE new file mode 100644 index 00000000..0d10c02b --- /dev/null +++ b/vendor/github.com/cznic/ql/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2014 The ql Authors. 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 names of the authors nor the names of the +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/vendor/github.com/cznic/ql/blob.go b/vendor/github.com/cznic/ql/blob.go new file mode 100644 index 00000000..2005b52c --- /dev/null +++ b/vendor/github.com/cznic/ql/blob.go @@ -0,0 +1,155 @@ +// Copyright 2014 The ql 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 ql + +import ( + "bytes" + "encoding/gob" + "math/big" + "sync" + "time" +) + +const shortBlob = 256 // bytes + +var ( + gobInitDuration = time.Duration(278) + gobInitInt = big.NewInt(42) + gobInitRat = big.NewRat(355, 113) + gobInitTime time.Time +) + +func init() { + var err error + if gobInitTime, err = time.ParseInLocation( + "Jan 2, 2006 at 3:04pm (MST)", + "Jul 9, 2012 at 5:02am (CEST)", + time.FixedZone("XYZ", 1234), + ); err != nil { + panic(err) + } + newGobCoder() +} + +type gobCoder struct { + buf bytes.Buffer + dec *gob.Decoder + enc *gob.Encoder + mu sync.Mutex +} + +func newGobCoder() (g *gobCoder) { + g = &gobCoder{} + g.enc = gob.NewEncoder(&g.buf) + if err := g.enc.Encode(gobInitInt); err != nil { + panic(err) + } + + if err := g.enc.Encode(gobInitRat); err != nil { + panic(err) + } + + if err := g.enc.Encode(gobInitTime); err != nil { + panic(err) + } + + if err := g.enc.Encode(gobInitDuration); err != nil { + panic(err) + } + + g.dec = gob.NewDecoder(&g.buf) + i := big.NewInt(0) + if err := g.dec.Decode(i); err != nil { + panic(err) + } + + r := big.NewRat(3, 5) + if err := g.dec.Decode(r); err != nil { + panic(err) + } + + t := time.Now() + if err := g.dec.Decode(&t); err != nil { + panic(err) + } + + var d time.Duration + if err := g.dec.Decode(&d); err != nil { + panic(err) + } + + return +} + +func isBlobType(v interface{}) (bool, Type) { + switch v.(type) { + case []byte: + return true, Blob + case *big.Int: + return true, BigInt + case *big.Rat: + return true, BigRat + case time.Time: + return true, Time + case time.Duration: + return true, Duration + default: + return false, -1 + } +} + +func (g *gobCoder) encode(v interface{}) (b []byte, err error) { + g.mu.Lock() + defer g.mu.Unlock() + + g.buf.Reset() + switch x := v.(type) { + case []byte: + return x, nil + case *big.Int: + err = g.enc.Encode(x) + case *big.Rat: + err = g.enc.Encode(x) + case time.Time: + err = g.enc.Encode(x) + case time.Duration: + err = g.enc.Encode(int64(x)) + default: + panic("internal error 002") + } + b = g.buf.Bytes() + return +} + +func (g *gobCoder) decode(b []byte, typ int) (v interface{}, err error) { + g.mu.Lock() + defer g.mu.Unlock() + + g.buf.Reset() + g.buf.Write(b) + switch typ { + case qBlob: + return b, nil + case qBigInt: + x := big.NewInt(0) + err = g.dec.Decode(&x) + v = x + case qBigRat: + x := big.NewRat(1, 1) + err = g.dec.Decode(&x) + v = x + case qTime: + var x time.Time + err = g.dec.Decode(&x) + v = x + case qDuration: + var x int64 + err = g.dec.Decode(&x) + v = time.Duration(x) + default: + panic("internal error 003") + } + return +} diff --git a/vendor/github.com/cznic/ql/btree.go b/vendor/github.com/cznic/ql/btree.go new file mode 100644 index 00000000..2b588b70 --- /dev/null +++ b/vendor/github.com/cznic/ql/btree.go @@ -0,0 +1,725 @@ +// Copyright 2014 The ql 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 ql + +import ( + "io" +) + +const ( + kx = 128 //DONE benchmark tune this number if using custom key/value type(s). + kd = 64 //DONE benchmark tune this number if using custom key/value type(s). +) + +type ( + // cmp compares a and b. Return value is: + // + // < 0 if a < b + // 0 if a == b + // > 0 if a > b + // + cmp func(a, b []interface{}) int + + d struct { // data page + c int + d [2*kd + 1]de + n *d + p *d + } + + de struct { // d element + k []interface{} + v []interface{} + } + + enumerator struct { + err error + hit bool + i int + k []interface{} + q *d + t *tree + ver int64 + } + + // tree is a B+tree. + tree struct { + c int + cmp cmp + first *d + last *d + r interface{} + ver int64 + } + + xe struct { // x element + ch interface{} + sep *d + } + + x struct { // index page + c int + x [2*kx + 2]xe + } +) + +var ( // R/O zero values + zd d + zde de + zx x + zxe xe +) + +func clr(q interface{}) { + switch z := q.(type) { + case *x: + for i := 0; i <= z.c; i++ { // Ch0 Sep0 ... Chn-1 Sepn-1 Chn + clr(z.x[i].ch) + } + *z = zx // GC + case *d: + *z = zd // GC + } +} + +// -------------------------------------------------------------------------- x + +func newX(ch0 interface{}) *x { + r := &x{} + r.x[0].ch = ch0 + return r +} + +func (q *x) extract(i int) { + q.c-- + if i < q.c { + copy(q.x[i:], q.x[i+1:q.c+1]) + q.x[q.c].ch = q.x[q.c+1].ch + q.x[q.c].sep = nil // GC + q.x[q.c+1] = zxe // GC + } +} + +func (q *x) insert(i int, d *d, ch interface{}) *x { + c := q.c + if i < c { + q.x[c+1].ch = q.x[c].ch + copy(q.x[i+2:], q.x[i+1:c]) + q.x[i+1].sep = q.x[i].sep + } + c++ + q.c = c + q.x[i].sep = d + q.x[i+1].ch = ch + return q +} + +func (q *x) siblings(i int) (l, r *d) { + if i >= 0 { + if i > 0 { + l = q.x[i-1].ch.(*d) + } + if i < q.c { + r = q.x[i+1].ch.(*d) + } + } + return +} + +// -------------------------------------------------------------------------- d + +func (l *d) mvL(r *d, c int) { + copy(l.d[l.c:], r.d[:c]) + copy(r.d[:], r.d[c:r.c]) + l.c += c + r.c -= c +} + +func (l *d) mvR(r *d, c int) { + copy(r.d[c:], r.d[:r.c]) + copy(r.d[:c], l.d[l.c-c:]) + r.c += c + l.c -= c +} + +// ----------------------------------------------------------------------- tree + +// treeNew returns a newly created, empty tree. The compare function is used +// for key collation. +func treeNew(cmp cmp) *tree { + return &tree{cmp: cmp} +} + +// Clear removes all K/V pairs from the tree. +func (t *tree) Clear() { + if t.r == nil { + return + } + + clr(t.r) + t.c, t.first, t.last, t.r = 0, nil, nil, nil + t.ver++ +} + +func (t *tree) cat(p *x, q, r *d, pi int) { + t.ver++ + q.mvL(r, r.c) + if r.n != nil { + r.n.p = q + } else { + t.last = q + } + q.n = r.n + if p.c > 1 { + p.extract(pi) + p.x[pi].ch = q + } else { + t.r = q + } +} + +func (t *tree) catX(p, q, r *x, pi int) { + t.ver++ + q.x[q.c].sep = p.x[pi].sep + copy(q.x[q.c+1:], r.x[:r.c]) + q.c += r.c + 1 + q.x[q.c].ch = r.x[r.c].ch + if p.c > 1 { + p.c-- + pc := p.c + if pi < pc { + p.x[pi].sep = p.x[pi+1].sep + copy(p.x[pi+1:], p.x[pi+2:pc+1]) + p.x[pc].ch = p.x[pc+1].ch + p.x[pc].sep = nil // GC + p.x[pc+1].ch = nil // GC + } + return + } + + t.r = q +} + +//Delete removes the k's KV pair, if it exists, in which case Delete returns +//true. +func (t *tree) Delete(k []interface{}) (ok bool) { + pi := -1 + var p *x + q := t.r + if q == nil { + return + } + + for { + var i int + i, ok = t.find(q, k) + if ok { + switch z := q.(type) { + case *x: + dp := z.x[i].sep + switch { + case dp.c > kd: + t.extract(dp, 0) + default: + if z.c < kx && q != t.r { + t.underflowX(p, &z, pi, &i) + } + pi = i + 1 + p = z + q = z.x[pi].ch + ok = false + continue + } + case *d: + t.extract(z, i) + if z.c >= kd { + return + } + + if q != t.r { + t.underflow(p, z, pi) + } else if t.c == 0 { + t.Clear() + } + } + return + } + + switch z := q.(type) { + case *x: + if z.c < kx && q != t.r { + t.underflowX(p, &z, pi, &i) + } + pi = i + p = z + q = z.x[i].ch + case *d: + return + } + } +} + +func (t *tree) extract(q *d, i int) { // (r []interface{}) { + t.ver++ + //r = q.d[i].v // prepared for Extract + q.c-- + if i < q.c { + copy(q.d[i:], q.d[i+1:q.c+1]) + } + q.d[q.c] = zde // GC + t.c-- + return +} + +func (t *tree) find(q interface{}, k []interface{}) (i int, ok bool) { + var mk []interface{} + l := 0 + switch z := q.(type) { + case *x: + h := z.c - 1 + for l <= h { + m := (l + h) >> 1 + mk = z.x[m].sep.d[0].k + switch cmp := t.cmp(k, mk); { + case cmp > 0: + l = m + 1 + case cmp == 0: + return m, true + default: + h = m - 1 + } + } + case *d: + h := z.c - 1 + for l <= h { + m := (l + h) >> 1 + mk = z.d[m].k + switch cmp := t.cmp(k, mk); { + case cmp > 0: + l = m + 1 + case cmp == 0: + return m, true + default: + h = m - 1 + } + } + } + return l, false +} + +// First returns the first item of the tree in the key collating order, or +// (nil, nil) if the tree is empty. +func (t *tree) First() (k []interface{}, v []interface{}) { + if q := t.first; q != nil { + q := &q.d[0] + k, v = q.k, q.v + } + return +} + +// Get returns the value associated with k and true if it exists. Otherwise Get +// returns (nil, false). +func (t *tree) Get(k []interface{}) (v []interface{}, ok bool) { + q := t.r + if q == nil { + return + } + + for { + var i int + if i, ok = t.find(q, k); ok { + switch z := q.(type) { + case *x: + return z.x[i].sep.d[0].v, true + case *d: + return z.d[i].v, true + } + } + switch z := q.(type) { + case *x: + q = z.x[i].ch + default: + return + } + } +} + +func (t *tree) insert(q *d, i int, k []interface{}, v []interface{}) *d { + t.ver++ + c := q.c + if i < c { + copy(q.d[i+1:], q.d[i:c]) + } + c++ + q.c = c + q.d[i].k, q.d[i].v = k, v + t.c++ + return q +} + +// Last returns the last item of the tree in the key collating order, or (nil, +// nil) if the tree is empty. +func (t *tree) Last() (k []interface{}, v []interface{}) { + if q := t.last; q != nil { + q := &q.d[q.c-1] + k, v = q.k, q.v + } + return +} + +// Len returns the number of items in the tree. +func (t *tree) Len() int { + return t.c +} + +func (t *tree) overflow(p *x, q *d, pi, i int, k []interface{}, v []interface{}) { + t.ver++ + l, r := p.siblings(pi) + + if l != nil && l.c < 2*kd && i > 0 { + l.mvL(q, 1) + t.insert(q, i-1, k, v) + return + } + + if r != nil && r.c < 2*kd { + if i < 2*kd { + q.mvR(r, 1) + t.insert(q, i, k, v) + } else { + t.insert(r, 0, k, v) + } + return + } + + t.split(p, q, pi, i, k, v) +} + +// Seek returns an enumerator positioned on a an item such that k >= item's +// key. ok reports if k == item.key The enumerator's position is possibly +// after the last item in the tree. +func (t *tree) Seek(k []interface{}) (e *enumerator, ok bool) { + q := t.r + if q == nil { + e = &enumerator{nil, false, 0, k, nil, t, t.ver} + return + } + + for { + var i int + if i, ok = t.find(q, k); ok { + switch z := q.(type) { + case *x: + e = &enumerator{nil, ok, 0, k, z.x[i].sep, t, t.ver} + return + case *d: + e = &enumerator{nil, ok, i, k, z, t, t.ver} + return + } + } + switch z := q.(type) { + case *x: + q = z.x[i].ch + case *d: + e = &enumerator{nil, ok, i, k, z, t, t.ver} + return + } + } +} + +// SeekFirst returns an enumerator positioned on the first KV pair in the tree, +// if any. For an empty tree, err == io.EOF is returned and e will be nil. +func (t *tree) SeekFirst() (e *enumerator, err error) { + q := t.first + if q == nil { + return nil, io.EOF + } + + return &enumerator{nil, true, 0, q.d[0].k, q, t, t.ver}, nil +} + +// SeekLast returns an enumerator positioned on the last KV pair in the tree, +// if any. For an empty tree, err == io.EOF is returned and e will be nil. +func (t *tree) SeekLast() (e *enumerator, err error) { + q := t.last + if q == nil { + return nil, io.EOF + } + + return &enumerator{nil, true, q.c - 1, q.d[q.c-1].k, q, t, t.ver}, nil +} + +// Set sets the value associated with k. +func (t *tree) Set(k []interface{}, v []interface{}) { + pi := -1 + var p *x + q := t.r + if q != nil { + for { + i, ok := t.find(q, k) + if ok { + switch z := q.(type) { + case *x: + z.x[i].sep.d[0].v = v + case *d: + z.d[i].v = v + } + return + } + + switch z := q.(type) { + case *x: + if z.c > 2*kx { + t.splitX(p, &z, pi, &i) + } + pi = i + p = z + q = z.x[i].ch + case *d: + switch { + case z.c < 2*kd: + t.insert(z, i, k, v) + default: + t.overflow(p, z, pi, i, k, v) + } + return + } + } + } + + z := t.insert(&d{}, 0, k, v) + t.r, t.first, t.last = z, z, z + return +} + +func (t *tree) split(p *x, q *d, pi, i int, k []interface{}, v []interface{}) { + t.ver++ + r := &d{} + if q.n != nil { + r.n = q.n + r.n.p = r + } else { + t.last = r + } + q.n = r + r.p = q + + copy(r.d[:], q.d[kd:2*kd]) + for i := range q.d[kd:] { + q.d[kd+i] = zde + } + q.c = kd + r.c = kd + if pi >= 0 { + p.insert(pi, r, r) + } else { + t.r = newX(q).insert(0, r, r) + } + if i > kd { + t.insert(r, i-kd, k, v) + return + } + + t.insert(q, i, k, v) +} + +func (t *tree) splitX(p *x, pp **x, pi int, i *int) { + t.ver++ + q := *pp + r := &x{} + copy(r.x[:], q.x[kx+1:]) + q.c = kx + r.c = kx + if pi >= 0 { + p.insert(pi, q.x[kx].sep, r) + } else { + t.r = newX(q).insert(0, q.x[kx].sep, r) + } + q.x[kx].sep = nil + for i := range q.x[kx+1:] { + q.x[kx+i+1] = zxe + } + if *i > kx { + *pp = r + *i -= kx + 1 + } +} + +func (t *tree) underflow(p *x, q *d, pi int) { + t.ver++ + l, r := p.siblings(pi) + + if l != nil && l.c+q.c >= 2*kd { + l.mvR(q, 1) + } else if r != nil && q.c+r.c >= 2*kd { + q.mvL(r, 1) + r.d[r.c] = zde // GC + } else if l != nil { + t.cat(p, l, q, pi-1) + } else { + t.cat(p, q, r, pi) + } +} + +func (t *tree) underflowX(p *x, pp **x, pi int, i *int) { + t.ver++ + var l, r *x + q := *pp + + if pi >= 0 { + if pi > 0 { + l = p.x[pi-1].ch.(*x) + } + if pi < p.c { + r = p.x[pi+1].ch.(*x) + } + } + + if l != nil && l.c > kx { + q.x[q.c+1].ch = q.x[q.c].ch + copy(q.x[1:], q.x[:q.c]) + q.x[0].ch = l.x[l.c].ch + q.x[0].sep = p.x[pi-1].sep + q.c++ + *i++ + l.c-- + p.x[pi-1].sep = l.x[l.c].sep + return + } + + if r != nil && r.c > kx { + q.x[q.c].sep = p.x[pi].sep + q.c++ + q.x[q.c].ch = r.x[0].ch + p.x[pi].sep = r.x[0].sep + copy(r.x[:], r.x[1:r.c]) + r.c-- + rc := r.c + r.x[rc].ch = r.x[rc+1].ch + r.x[rc].sep = nil + r.x[rc+1].ch = nil + return + } + + if l != nil { + *i += l.c + 1 + t.catX(p, l, q, pi-1) + *pp = l + return + } + + t.catX(p, q, r, pi) +} + +// ----------------------------------------------------------------- enumerator + +// Next returns the currently enumerated item, if it exists and moves to the +// next item in the key collation order. If there is no item to return, err == +// io.EOF is returned. +func (e *enumerator) Next() (k []interface{}, v []interface{}, err error) { + if err = e.err; err != nil { + return + } + + if e.ver != e.t.ver { + f, hit := e.t.Seek(e.k) + if !e.hit && hit { + if err = f.next(); err != nil { + return + } + } + + *e = *f + } + if e.q == nil { + e.err, err = io.EOF, io.EOF + return + } + + if e.i >= e.q.c { + if err = e.next(); err != nil { + return + } + } + + i := e.q.d[e.i] + k, v = i.k, i.v + e.k, e.hit = k, false + e.next() + return +} + +func (e *enumerator) next() error { + if e.q == nil { + e.err = io.EOF + return io.EOF + } + + switch { + case e.i < e.q.c-1: + e.i++ + default: + if e.q, e.i = e.q.n, 0; e.q == nil { + e.err = io.EOF + } + } + return e.err +} + +// Prev returns the currently enumerated item, if it exists and moves to the +// previous item in the key collation order. If there is no item to return, err +// == io.EOF is returned. +func (e *enumerator) Prev() (k []interface{}, v []interface{}, err error) { + if err = e.err; err != nil { + return + } + + if e.ver != e.t.ver { + f, hit := e.t.Seek(e.k) + if !e.hit && hit { + if err = f.prev(); err != nil { + return + } + } + + *e = *f + } + if e.q == nil { + e.err, err = io.EOF, io.EOF + return + } + + if e.i >= e.q.c { + if err = e.next(); err != nil { + return + } + } + + i := e.q.d[e.i] + k, v = i.k, i.v + e.k, e.hit = k, false + e.prev() + return +} + +func (e *enumerator) prev() error { + if e.q == nil { + e.err = io.EOF + return io.EOF + } + + switch { + case e.i > 0: + e.i-- + default: + if e.q = e.q.p; e.q == nil { + e.err = io.EOF + break + } + + e.i = e.q.c - 1 + } + return e.err +} diff --git a/vendor/github.com/cznic/ql/builtin.go b/vendor/github.com/cznic/ql/builtin.go new file mode 100644 index 00000000..1c4bc1c1 --- /dev/null +++ b/vendor/github.com/cznic/ql/builtin.go @@ -0,0 +1,991 @@ +// Copyright 2014 The ql 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 ql + +import ( + "fmt" + "math/rand" + "reflect" + "strconv" + "strings" + "time" +) + +//TODO agg bigint, bigrat, time, duration + +var builtin = map[string]struct { + f func([]interface{}, map[interface{}]interface{}) (interface{}, error) + minArgs int + maxArgs int + isStatic bool + isAggregate bool +}{ + "__testBlob": {builtinTestBlob, 1, 1, true, false}, + "__testString": {builtinTestString, 1, 1, true, false}, + "avg": {builtinAvg, 1, 1, false, true}, + "complex": {builtinComplex, 2, 2, true, false}, + "contains": {builtinContains, 2, 2, true, false}, + "count": {builtinCount, 0, 1, false, true}, + "date": {builtinDate, 8, 8, true, false}, + "day": {builtinDay, 1, 1, true, false}, + "formatTime": {builtinFormatTime, 2, 2, true, false}, + "formatFloat": {builtinFormatFloat, 1, 4, true, false}, + "formatInt": {builtinFormatInt, 1, 2, true, false}, + "hasPrefix": {builtinHasPrefix, 2, 2, true, false}, + "hasSuffix": {builtinHasSuffix, 2, 2, true, false}, + "hour": {builtinHour, 1, 1, true, false}, + "hours": {builtinHours, 1, 1, true, false}, + "id": {builtinID, 0, 1, false, false}, + "imag": {builtinImag, 1, 1, true, false}, + "len": {builtinLen, 1, 1, true, false}, + "max": {builtinMax, 1, 1, false, true}, + "min": {builtinMin, 1, 1, false, true}, + "minute": {builtinMinute, 1, 1, true, false}, + "minutes": {builtinMinutes, 1, 1, true, false}, + "month": {builtinMonth, 1, 1, true, false}, + "nanosecond": {builtinNanosecond, 1, 1, true, false}, + "nanoseconds": {builtinNanoseconds, 1, 1, true, false}, + "now": {builtinNow, 0, 0, false, false}, + "parseTime": {builtinParseTime, 2, 2, true, false}, + "real": {builtinReal, 1, 1, true, false}, + "second": {builtinSecond, 1, 1, true, false}, + "seconds": {builtinSeconds, 1, 1, true, false}, + "since": {builtinSince, 1, 1, false, false}, + "sum": {builtinSum, 1, 1, false, true}, + "timeIn": {builtinTimeIn, 2, 2, true, false}, + "weekday": {builtinWeekday, 1, 1, true, false}, + "year": {builtinYear, 1, 1, true, false}, + "yearDay": {builtinYearday, 1, 1, true, false}, +} + +func badNArgs(min int, s string, arg []interface{}) error { + a := []string{} + for _, v := range arg { + a = append(a, fmt.Sprintf("%v", v)) + } + switch len(arg) < min { + case true: + return fmt.Errorf("missing argument to %s(%s)", s, strings.Join(a, ", ")) + default: //case false: + return fmt.Errorf("too many arguments to %s(%s)", s, strings.Join(a, ", ")) + } +} + +func invArg(arg interface{}, s string) error { + return fmt.Errorf("invalid argument %v (type %T) for %s", arg, arg, s) +} + +func builtinTestBlob(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + n, err := intExpr(arg[0]) + if err != nil { + return nil, err + } + + rng := rand.New(rand.NewSource(n)) + b := make([]byte, n) + for i := range b { + b[i] = byte(rng.Int()) + } + return b, nil +} + +func builtinTestString(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + n, err := intExpr(arg[0]) + if err != nil { + return nil, err + } + + rng := rand.New(rand.NewSource(n)) + b := make([]byte, n) + for i := range b { + b[i] = byte(rng.Int()) + } + return string(b), nil +} + +func builtinAvg(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + type avg struct { + sum interface{} + n uint64 + } + + if _, ok := ctx["$agg0"]; ok { + return + } + + fn := ctx["$fn"] + if _, ok := ctx["$agg"]; ok { + data, ok := ctx[fn].(avg) + if !ok { + return + } + + switch x := data.sum.(type) { + case complex64: + return complex64(complex128(x) / complex(float64(data.n), 0)), nil + case complex128: + return complex64(complex128(x) / complex(float64(data.n), 0)), nil + case float32: + return float32(float64(x) / float64(data.n)), nil + case float64: + return float64(x) / float64(data.n), nil + case int8: + return int8(int64(x) / int64(data.n)), nil + case int16: + return int16(int64(x) / int64(data.n)), nil + case int32: + return int32(int64(x) / int64(data.n)), nil + case int64: + return int64(int64(x) / int64(data.n)), nil + case uint8: + return uint8(uint64(x) / data.n), nil + case uint16: + return uint16(uint64(x) / data.n), nil + case uint32: + return uint32(uint64(x) / data.n), nil + case uint64: + return uint64(uint64(x) / data.n), nil + } + + } + + data, _ := ctx[fn].(avg) + y := arg[0] + if y == nil { + return + } + + switch x := data.sum.(type) { + case nil: + switch y := y.(type) { + case float32, float64, int8, int16, int32, int64, uint8, uint16, uint32, uint64: + data = avg{y, 0} + default: + return nil, fmt.Errorf("avg: cannot accept %v (value if type %T)", y, y) + } + case complex64: + data.sum = x + y.(complex64) + case complex128: + data.sum = x + y.(complex128) + case float32: + data.sum = x + y.(float32) + case float64: + data.sum = x + y.(float64) + case int8: + data.sum = x + y.(int8) + case int16: + data.sum = x + y.(int16) + case int32: + data.sum = x + y.(int32) + case int64: + data.sum = x + y.(int64) + case uint8: + data.sum = x + y.(uint8) + case uint16: + data.sum = x + y.(uint16) + case uint32: + data.sum = x + y.(uint32) + case uint64: + data.sum = x + y.(uint64) + } + data.n++ + ctx[fn] = data + return +} + +func builtinComplex(arg []interface{}, _ map[interface{}]interface{}) (v interface{}, err error) { + re, im := arg[0], arg[1] + if re == nil || im == nil { + return nil, nil + } + + re, im = coerce(re, im) + if reflect.TypeOf(re) != reflect.TypeOf(im) { + return nil, fmt.Errorf("complex(%T(%#v), %T(%#v)): invalid types", re, re, im, im) + } + + switch re := re.(type) { + case idealFloat: + return idealComplex(complex(float64(re), float64(im.(idealFloat)))), nil + case idealInt: + return idealComplex(complex(float64(re), float64(im.(idealInt)))), nil + case idealRune: + return idealComplex(complex(float64(re), float64(im.(idealRune)))), nil + case idealUint: + return idealComplex(complex(float64(re), float64(im.(idealUint)))), nil + case float32: + return complex(float32(re), im.(float32)), nil + case float64: + return complex(float64(re), im.(float64)), nil + case int8: + return complex(float64(re), float64(im.(int8))), nil + case int16: + return complex(float64(re), float64(im.(int16))), nil + case int32: + return complex(float64(re), float64(im.(int32))), nil + case int64: + return complex(float64(re), float64(im.(int64))), nil + case uint8: + return complex(float64(re), float64(im.(uint8))), nil + case uint16: + return complex(float64(re), float64(im.(uint16))), nil + case uint32: + return complex(float64(re), float64(im.(uint32))), nil + case uint64: + return complex(float64(re), float64(im.(uint64))), nil + default: + return nil, invArg(re, "complex") + } +} + +func builtinContains(arg []interface{}, _ map[interface{}]interface{}) (v interface{}, err error) { + switch s := arg[0].(type) { + case nil: + return nil, nil + case string: + switch chars := arg[1].(type) { + case nil: + return nil, nil + case string: + return strings.Contains(s, chars), nil + default: + return nil, invArg(chars, "string") + } + default: + return nil, invArg(s, "string") + } +} + +func builtinCount(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + if _, ok := ctx["$agg0"]; ok { + return int64(0), nil + } + + fn := ctx["$fn"] + if _, ok := ctx["$agg"]; ok { + return ctx[fn].(int64), nil + } + + n, _ := ctx[fn].(int64) + switch len(arg) { + case 0: + n++ + case 1: + if arg[0] != nil { + n++ + } + default: + panic("internal error 067") + } + ctx[fn] = n + return +} + +func builtinDate(arg []interface{}, _ map[interface{}]interface{}) (v interface{}, err error) { + for i, v := range arg { + switch i { + case 7: + switch x := v.(type) { + case string: + default: + return nil, invArg(x, "date") + } + default: + switch x := v.(type) { + case int64: + case idealInt: + arg[i] = int64(x) + default: + return nil, invArg(x, "date") + } + } + } + + sloc := arg[7].(string) + loc := time.Local + switch sloc { + case "local": + default: + loc, err = time.LoadLocation(sloc) + if err != nil { + return + } + } + + return time.Date( + int(arg[0].(int64)), + time.Month(arg[1].(int64)), + int(arg[2].(int64)), + int(arg[3].(int64)), + int(arg[4].(int64)), + int(arg[5].(int64)), + int(arg[6].(int64)), + loc, + ), nil +} + +func builtinLen(arg []interface{}, _ map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case string: + return int64(len(x)), nil + default: + return nil, invArg(x, "len") + } +} + +func builtinDay(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case time.Time: + return int64(x.Day()), nil + default: + return nil, invArg(x, "day") + } +} + +func builtinFormatTime(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case time.Time: + switch y := arg[1].(type) { + case nil: + return nil, nil + case string: + return x.Format(y), nil + default: + return nil, invArg(y, "formatTime") + } + default: + return nil, invArg(x, "formatTime") + } +} + +func builtinFormatFloat(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + var val float64 + var fmt byte = 'g' + + prec := -1 + bitSize := 64 + + switch x := arg[0].(type) { + case nil: + return nil, nil + case float32: + val = float64(x) + bitSize = 32 + case float64: + val = x + default: + return nil, invArg(x, "formatFloat") + } + + switch len(arg) { + case 4: + arg3 := coerce1(arg[3], int64(0)) + switch y := arg3.(type) { + case nil: + return nil, nil + case int64: + bitSize = int(y) + default: + return nil, invArg(y, "formatFloat") + } + fallthrough + case 3: + arg2 := coerce1(arg[2], int64(0)) + switch y := arg2.(type) { + case nil: + return nil, nil + case int64: + prec = int(y) + default: + return nil, invArg(y, "formatFloat") + } + fallthrough + case 2: + arg1 := coerce1(arg[1], byte(0)) + switch y := arg1.(type) { + case nil: + return nil, nil + case byte: + fmt = y + default: + return nil, invArg(y, "formatFloat") + } + } + + return strconv.FormatFloat(val, fmt, prec, bitSize), nil +} + +func builtinFormatInt(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + var intVal int64 + var uintVal uint64 + + uintType := false + base := 10 + + switch x := arg[0].(type) { + case nil: + return nil, nil + case int8: + intVal = int64(x) + case int16: + intVal = int64(x) + case int32: + intVal = int64(x) + case int64: + intVal = x + case uint8: + uintType = true + uintVal = uint64(x) + case uint16: + uintType = true + uintVal = uint64(x) + case uint32: + uintType = true + uintVal = uint64(x) + case uint64: + uintType = true + uintVal = x + default: + return nil, invArg(x, "formatInt") + } + + switch len(arg) { + case 2: + arg1 := coerce1(arg[1], int64(0)) + switch y := arg1.(type) { + case nil: + return nil, nil + case int64: + base = int(y) + default: + return nil, invArg(y, "formatInt") + } + } + + if uintType { + return strconv.FormatUint(uintVal, base), nil + } + + return strconv.FormatInt(intVal, base), nil +} + +func builtinHasPrefix(arg []interface{}, _ map[interface{}]interface{}) (v interface{}, err error) { + switch s := arg[0].(type) { + case nil: + return nil, nil + case string: + switch prefix := arg[1].(type) { + case nil: + return nil, nil + case string: + return strings.HasPrefix(s, prefix), nil + default: + return nil, invArg(prefix, "string") + } + default: + return nil, invArg(s, "string") + } +} + +func builtinHasSuffix(arg []interface{}, _ map[interface{}]interface{}) (v interface{}, err error) { + switch s := arg[0].(type) { + case nil: + return nil, nil + case string: + switch suffix := arg[1].(type) { + case nil: + return nil, nil + case string: + return strings.HasSuffix(s, suffix), nil + default: + return nil, invArg(suffix, "string") + } + default: + return nil, invArg(s, "string") + } +} + +func builtinHour(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case time.Time: + return int64(x.Hour()), nil + default: + return nil, invArg(x, "hour") + } +} + +func builtinHours(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case time.Duration: + return x.Hours(), nil + default: + return nil, invArg(x, "hours") + } +} + +func builtinID(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := ctx["$id"].(type) { + case map[string]interface{}: + if len(arg) == 0 { + return nil, nil + } + + tab := arg[0].(*ident) + id, ok := x[tab.s] + if !ok { + return nil, fmt.Errorf("value not available: id(%s)", tab) + } + + if _, ok := id.(int64); ok { + return id, nil + } + + return nil, fmt.Errorf("value not available: id(%s)", tab) + case int64: + return x, nil + default: + return nil, nil + } +} + +func builtinImag(arg []interface{}, _ map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case idealComplex: + return imag(x), nil + case complex64: + return imag(x), nil + case complex128: + return imag(x), nil + default: + return nil, invArg(x, "imag") + } +} + +func builtinMax(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + if _, ok := ctx["$agg0"]; ok { + return + } + + fn := ctx["$fn"] + if _, ok := ctx["$agg"]; ok { + if v, ok = ctx[fn]; ok { + return + } + + return nil, nil + } + + max := ctx[fn] + y := arg[0] + if y == nil { + return + } + switch x := max.(type) { + case nil: + switch y := y.(type) { + case float32, float64, string, int8, int16, int32, int64, uint8, uint16, uint32, uint64, time.Time: + max = y + default: + return nil, fmt.Errorf("max: cannot accept %v (value if type %T)", y, y) + } + case float32: + if y := y.(float32); y > x { + max = y + } + case float64: + if y := y.(float64); y > x { + max = y + } + case string: + if y := y.(string); y > x { + max = y + } + case int8: + if y := y.(int8); y > x { + max = y + } + case int16: + if y := y.(int16); y > x { + max = y + } + case int32: + if y := y.(int32); y > x { + max = y + } + case int64: + if y := y.(int64); y > x { + max = y + } + case uint8: + if y := y.(uint8); y > x { + max = y + } + case uint16: + if y := y.(uint16); y > x { + max = y + } + case uint32: + if y := y.(uint32); y > x { + max = y + } + case uint64: + if y := y.(uint64); y > x { + max = y + } + case time.Time: + if y := y.(time.Time); y.After(x) { + max = y + } + } + ctx[fn] = max + return +} + +func builtinMin(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + if _, ok := ctx["$agg0"]; ok { + return + } + + fn := ctx["$fn"] + if _, ok := ctx["$agg"]; ok { + if v, ok = ctx[fn]; ok { + return + } + + return nil, nil + } + + min := ctx[fn] + y := arg[0] + if y == nil { + return + } + switch x := min.(type) { + case nil: + switch y := y.(type) { + case float32, float64, string, int8, int16, int32, int64, uint8, uint16, uint32, uint64, time.Time: + min = y + default: + return nil, fmt.Errorf("min: cannot accept %v (value if type %T)", y, y) + } + case float32: + if y := y.(float32); y < x { + min = y + } + case float64: + if y := y.(float64); y < x { + min = y + } + case string: + if y := y.(string); y < x { + min = y + } + case int8: + if y := y.(int8); y < x { + min = y + } + case int16: + if y := y.(int16); y < x { + min = y + } + case int32: + if y := y.(int32); y < x { + min = y + } + case int64: + if y := y.(int64); y < x { + min = y + } + case uint8: + if y := y.(uint8); y < x { + min = y + } + case uint16: + if y := y.(uint16); y < x { + min = y + } + case uint32: + if y := y.(uint32); y < x { + min = y + } + case uint64: + if y := y.(uint64); y < x { + min = y + } + case time.Time: + if y := y.(time.Time); y.Before(x) { + min = y + } + } + ctx[fn] = min + return +} + +func builtinMinute(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case time.Time: + return int64(x.Minute()), nil + default: + return nil, invArg(x, "minute") + } +} + +func builtinMinutes(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case time.Duration: + return x.Minutes(), nil + default: + return nil, invArg(x, "minutes") + } +} + +func builtinMonth(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case time.Time: + return int64(x.Month()), nil + default: + return nil, invArg(x, "month") + } +} + +func builtinNanosecond(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case time.Time: + return int64(x.Nanosecond()), nil + default: + return nil, invArg(x, "nanosecond") + } +} + +func builtinNanoseconds(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case time.Duration: + return x.Nanoseconds(), nil + default: + return nil, invArg(x, "nanoseconds") + } +} + +func builtinNow(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + return time.Now(), nil +} + +func builtinParseTime(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + var a [2]string + for i, v := range arg { + switch x := v.(type) { + case nil: + return nil, nil + case string: + a[i] = x + default: + return nil, invArg(x, "parseTime") + } + } + + t, err := time.Parse(a[0], a[1]) + if err != nil { + return nil, err + } + + ls := t.Location().String() + if ls == "UTC" { + return t, nil + } + + l, err := time.LoadLocation(ls) + if err != nil { + return t, nil + } + + return time.ParseInLocation(a[0], a[1], l) +} + +func builtinReal(arg []interface{}, _ map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case idealComplex: + return real(x), nil + case complex64: + return real(x), nil + case complex128: + return real(x), nil + default: + return nil, invArg(x, "real") + } +} + +func builtinSecond(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case time.Time: + return int64(x.Second()), nil + default: + return nil, invArg(x, "second") + } +} + +func builtinSeconds(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case time.Duration: + return x.Seconds(), nil + default: + return nil, invArg(x, "seconds") + } +} + +func builtinSince(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case time.Time: + return time.Since(x), nil + default: + return nil, invArg(x, "since") + } +} + +func builtinSum(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + if _, ok := ctx["$agg0"]; ok { + return + } + + fn := ctx["$fn"] + if _, ok := ctx["$agg"]; ok { + if v, ok = ctx[fn]; ok { + return + } + + return nil, nil + } + + sum := ctx[fn] + y := arg[0] + if y == nil { + return + } + switch x := sum.(type) { + case nil: + switch y := y.(type) { + case complex64, complex128, float32, float64, int8, int16, int32, int64, uint8, uint16, uint32, uint64: + sum = y + default: + return nil, fmt.Errorf("sum: cannot accept %v (value if type %T)", y, y) + } + case complex64: + sum = x + y.(complex64) + case complex128: + sum = x + y.(complex128) + case float32: + sum = x + y.(float32) + case float64: + sum = x + y.(float64) + case int8: + sum = x + y.(int8) + case int16: + sum = x + y.(int16) + case int32: + sum = x + y.(int32) + case int64: + sum = x + y.(int64) + case uint8: + sum = x + y.(uint8) + case uint16: + sum = x + y.(uint16) + case uint32: + sum = x + y.(uint32) + case uint64: + sum = x + y.(uint64) + } + ctx[fn] = sum + return +} + +func builtinTimeIn(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case time.Time: + switch y := arg[1].(type) { + case nil: + return nil, nil + case string: + loc := time.Local + switch y { + case "local": + default: + loc, err = time.LoadLocation(y) + if err != nil { + return + } + } + + return x.In(loc), nil + default: + return nil, invArg(x, "timeIn") + } + default: + return nil, invArg(x, "timeIn") + } +} + +func builtinWeekday(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case time.Time: + return int64(x.Weekday()), nil + default: + return nil, invArg(x, "weekday") + } +} + +func builtinYear(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case time.Time: + return int64(x.Year()), nil + default: + return nil, invArg(x, "year") + } +} + +func builtinYearday(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + switch x := arg[0].(type) { + case nil: + return nil, nil + case time.Time: + return int64(x.YearDay()), nil + default: + return nil, invArg(x, "yearDay") + } +} diff --git a/vendor/github.com/cznic/ql/coerce.go b/vendor/github.com/cznic/ql/coerce.go new file mode 100644 index 00000000..bd384f93 --- /dev/null +++ b/vendor/github.com/cznic/ql/coerce.go @@ -0,0 +1,290 @@ +// Copyright 2013 The ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// CAUTION: This file was generated automatically by +// +// $ go run helper/helper.go -o coerce.go +// +// DO NOT EDIT! + +package ql + +import ( + "math" + "math/big" + "reflect" + "time" +) + +func coerce(a, b interface{}) (x, y interface{}) { + if reflect.TypeOf(a) == reflect.TypeOf(b) { + return a, b + } + + switch a.(type) { + case idealComplex, idealFloat, idealInt, idealRune, idealUint: + switch b.(type) { + case idealComplex, idealFloat, idealInt, idealRune, idealUint: + x, y = coerce1(a, b), b + if reflect.TypeOf(x) == reflect.TypeOf(y) { + return + } + + return a, coerce1(b, a) + default: + return coerce1(a, b), b + } + default: + switch b.(type) { + case idealComplex, idealFloat, idealInt, idealRune, idealUint: + return a, coerce1(b, a) + default: + return a, b + } + } +} + +func coerce1(inVal, otherVal interface{}) (coercedInVal interface{}) { + coercedInVal = inVal + if otherVal == nil { + return + } + + switch x := inVal.(type) { + case nil: + return + case idealComplex: + switch otherVal.(type) { + //case idealComplex: + //case idealFloat: + //case idealInt: + //case idealRune: + //case idealUint: + //case bool: + case complex64: + return complex64(x) + case complex128: + return complex128(x) + //case float32: + //case float64: + //case int8: + //case int16: + //case int32: + //case int64: + //case string: + //case uint8: + //case uint16: + //case uint32: + //case uint64: + //case *big.Int: + //case *big.Rat: + //case time.Time: + //case time.Duration: + } + case idealFloat: + switch otherVal.(type) { + case idealComplex: + return idealComplex(complex(float64(x), 0)) + case idealFloat: + return idealFloat(float64(x)) + //case idealInt: + //case idealRune: + //case idealUint: + //case bool: + case complex64: + return complex64(complex(float32(x), 0)) + case complex128: + return complex128(complex(float64(x), 0)) + case float32: + return float32(float64(x)) + case float64: + return float64(float64(x)) + //case int8: + //case int16: + //case int32: + //case int64: + //case string: + //case uint8: + //case uint16: + //case uint32: + //case uint64: + //case *big.Int: + case *big.Rat: + return big.NewRat(1, 1).SetFloat64(float64(x)) + //case time.Time: + //case time.Duration: + } + case idealInt: + switch otherVal.(type) { + case idealComplex: + return idealComplex(complex(float64(x), 0)) + case idealFloat: + return idealFloat(int64(x)) + case idealInt: + return idealInt(int64(x)) + //case idealRune: + case idealUint: + if x >= 0 { + return idealUint(int64(x)) + } + //case bool: + case complex64: + return complex64(complex(float32(x), 0)) + case complex128: + return complex128(complex(float64(x), 0)) + case float32: + return float32(int64(x)) + case float64: + return float64(int64(x)) + case int8: + if x >= math.MinInt8 && x <= math.MaxInt8 { + return int8(int64(x)) + } + case int16: + if x >= math.MinInt16 && x <= math.MaxInt16 { + return int16(int64(x)) + } + case int32: + if x >= math.MinInt32 && x <= math.MaxInt32 { + return int32(int64(x)) + } + case int64: + return int64(int64(x)) + //case string: + case uint8: + if x >= 0 && x <= math.MaxUint8 { + return uint8(int64(x)) + } + case uint16: + if x >= 0 && x <= math.MaxUint16 { + return uint16(int64(x)) + } + case uint32: + if x >= 0 && x <= math.MaxUint32 { + return uint32(int64(x)) + } + case uint64: + if x >= 0 { + return uint64(int64(x)) + } + case *big.Int: + return big.NewInt(int64(x)) + case *big.Rat: + return big.NewRat(1, 1).SetInt64(int64(x)) + //case time.Time: + case time.Duration: + return time.Duration(int64(x)) + } + case idealRune: + switch otherVal.(type) { + case idealComplex: + return idealComplex(complex(float64(x), 0)) + case idealFloat: + return idealFloat(int64(x)) + case idealInt: + return idealInt(int64(x)) + case idealRune: + return idealRune(int64(x)) + case idealUint: + return idealUint(int64(x)) + //case bool: + case complex64: + return complex64(complex(float32(x), 0)) + case complex128: + return complex128(complex(float64(x), 0)) + case float32: + return float32(int64(x)) + case float64: + return float64(int64(x)) + case int8: + return int8(int64(x)) + case int16: + return int16(int64(x)) + case int32: + return int32(int64(x)) + case int64: + return int64(int64(x)) + //case string: + case uint8: + return uint8(int64(x)) + case uint16: + return uint16(int64(x)) + case uint32: + return uint32(int64(x)) + case uint64: + return uint64(int64(x)) + case *big.Int: + return big.NewInt(int64(x)) + case *big.Rat: + return big.NewRat(1, 1).SetInt64(int64(x)) + //case time.Time: + case time.Duration: + return time.Duration(int64(x)) + } + case idealUint: + switch otherVal.(type) { + case idealComplex: + return idealComplex(complex(float64(x), 0)) + case idealFloat: + return idealFloat(uint64(x)) + case idealInt: + if x <= math.MaxInt64 { + return idealInt(int64(x)) + } + //case idealRune: + case idealUint: + return idealUint(uint64(x)) + //case bool: + case complex64: + return complex64(complex(float32(x), 0)) + case complex128: + return complex128(complex(float64(x), 0)) + case float32: + return float32(uint64(x)) + case float64: + return float64(uint64(x)) + case int8: + if x <= math.MaxInt8 { + return int8(int64(x)) + } + case int16: + if x <= math.MaxInt16 { + return int16(int64(x)) + } + case int32: + if x <= math.MaxInt32 { + return int32(int64(x)) + } + case int64: + if x <= math.MaxInt64 { + return int64(int64(x)) + } + //case string: + case uint8: + if x >= 0 && x <= math.MaxUint8 { + return uint8(int64(x)) + } + case uint16: + if x >= 0 && x <= math.MaxUint16 { + return uint16(int64(x)) + } + case uint32: + if x >= 0 && x <= math.MaxUint32 { + return uint32(int64(x)) + } + case uint64: + return uint64(uint64(x)) + case *big.Int: + return big.NewInt(0).SetUint64(uint64(x)) + case *big.Rat: + return big.NewRat(1, 1).SetInt(big.NewInt(0).SetUint64(uint64(x))) + //case time.Time: + case time.Duration: + if x <= math.MaxInt64 { + return time.Duration(int64(x)) + } + } + } + return +} diff --git a/vendor/github.com/cznic/ql/design/doc.go b/vendor/github.com/cznic/ql/design/doc.go new file mode 100644 index 00000000..7e6718cf --- /dev/null +++ b/vendor/github.com/cznic/ql/design/doc.go @@ -0,0 +1,298 @@ +// Copyright 2014 The ql 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 design describes some of the data structures used in QL. + +Handles + +A handle is a 7 byte "pointer" to a block in the DB[0]. + +Scalar encoding + +Encoding of so called "scalars" provided by [1]. Unless specified otherwise, +all values discussed below are scalars, encoded scalars or encoding of scalar +arrays. + +Database root + +DB root is a 1-scalar found at a fixed handle (#1). + + +---+------+--------+-----------------------+ + | # | Name | Type | Description | + +---+------+--------+-----------------------+ + | 0 | head | handle | First table meta data | + +---+------+--------+-----------------------+ + +Head is the head of a single linked list of table of meta data. It's zero if +there are no tables in the DB. + +Table meta data + +Table meta data are a 6-scalar. + + +---+---------+--------+--------------------------+ + | # | Name | Type | Description | + +---+---------+--------+--------------------------+ + | 0 | next | handle | Next table meta data. | + | 1 | scols | string | Column defintitions | + | 2 | hhead | handle | -> head -> first record | + | 3 | name | string | Table name | + | 4 | indices | string | Index definitions | + | 5 | hxroots | handle | Index B+Trees roots list | + +---+---------+--------+--------------------------+ + +Fields #4 and #5 are optional for backward compatibility with existing +databases. OTOH, forward compatibility will not work. Once any indices are +created using a newer QL version the older versions of QL, expecting only 4 +fields of meta data will not be able to use the DB. That's the intended +behavior because the older versions of QL cannot update the indexes, which can +break queries runned by the newer QL version which expect indices to be always +actualized on any table-with-indices mutation. + +The handle of the next table meta data is in the field #0 (next). If there is +no next table meta data, the field is zero. Names and types of table columns +are stored in field #1 (scols). A single field is described by concatenating a +type tag and the column name. The type tags are + + bool 'b' + complex64 'c' + complex128 'd' + float32 'f' + float64 'g', alias float + int8 'i' + int16 'j' + int32 'k' + int64 'l', alias int + string 's' + uint8 'u', alias byte + uint16 'v' + uint32 'w' + uint64 'x', alias uint + bigInt 'I' + bigRat 'R' + blob 'B' + duration 'D' + time 'T' + +The scols value is the above described encoded fields joined using "|". For +example + + CREATE TABLE t (Foo bool, Bar string, Baz float); + +This statement adds a table meta data with scols + + "bFool|sBar|gBaz" + +Columns can be dropped from a table + + ALTER TABLE t DROP COLUMN Bar; + +This "erases" the field info in scols, so the value becomes + + "bFool||gBaz" + +Colums can be added to a table + + ALTER TABLE t ADD Count uint; + +New fields are always added to the end of scols + + "bFool||gBaz|xCount" + +Index of a field in strings.Split(scols, "|") is the index of the field in a +table record. The above discussed rules for column dropping and column adding +allow for schema evolution without a need to reshape any existing table data. +Dropped columns are left where they are and new records insert nil in their +place. The encoded nil is one byte. Added columns, when not present in +preexisting records are returned as nil values. If the overhead of dropped +columns becomes an issue and there's time/space and memory enough to move the +records of a table around: + + BEGIN TRANSACTION; + CREATE TABLE new (column definitions); + INSERT INTO new SELECT * FROM old; + DROP TABLE old; + CREATE TABLE old (column definitions); + INSERT INTO old SELECT * FROM new; + DROP TABLE new; + END TRANSACTION; + +This is not very time/space effective and for Big Data it can cause an OOM +because transactions are limited by memory resources available to the process. +Perhaps a method and/or QL statement to do this in-place should be added +(MAYBE consider adopting MySQL's OPTIMIZE TABLE syntax). + +Field #2 (hhead) is a handle to a head of table records, i.e. not a handle to +the first record in the table. It is thus always non zero even for a table +having no records. The reason for this "double pointer" schema is to enable +adding (linking) a new record by updating a single value of the (hhead pointing +to) head. + + tableMeta.hhead -> head -> firstTableRecord + +The table name is stored in field #3 (name). + +Indices + +Consider an index named N, indexing column named C. The encoding of this +particular index is a string "N". is a string "n" for non unique +indices and "u" for unique indices. There is this index information for the +index possibly indexing the record id() and for all other columns of scols. +Where the column is not indexed, the index info is an empty string. Infos for +all indexes are joined with "|". For example + + BEGIN TRANSACTION; + CREATE TABLE t (Foo int, Bar bool, Baz string); + CREATE INDEX X ON t (Baz); + CREATE UNIQUE INDEX Y ON t (Foo); + COMMIT; + +The values of fields #1 and #4 for the above are + + scols: "lFoo|bBar|sBaz" + indices: "|uY||nX" + +Aligning properly the "|" split parts + + id col #0 col#1 col#2 + +----------+----+--------+--------+--------+ + | scols: | | "lFoo" | "bBar" | "sBaz" | + +----------+----+--------+--------+--------+ + | indices: | "" | "uY" | "" | "nX" | + +----------+----+--------+--------+--------+ + +shows that the record id() is not indexed for this table while the columns Foo +and Baz are. + +Note that there cannot be two differently named indexes for the same column and +it's intended. The indices are B+Trees[2]. The list of handles to their roots +is pointed to by hxroots with zeros for non indexed columns. For the previous +example + + tableMeta.hxroots -> {0, y, 0, x} + +where x is the root of the B+Tree for the X index and y is the root of the +B+Tree for the Y index. If there would be an index for id(), its B+Tree root +will be present where the first zero is. Similarly to hhead, hxroots is never +zero, even when there are no indices for a table. + +Table record + +A table record is an N-scalar. + + +-----+------------+--------+-------------------------------+ + | # | Name | Type | Description | + +-----+------------+--------+-------------------------------+ + | 0 | next | handle | Next record or zero. | + | 1 | id | int64 | Automatically assigned unique | + | | | | value obtainable by id(). | + | 2 | field #0 | scalar | First field of the record. | + | 3 | field #1 | scalar | Second field of the record. | + ... + | N-1 | field #N-2 | scalar | Last field of the record. | + +-----+------------+--------+-------------------------------+ + +The linked "ordering" of table records has no semantics and it doesn't have to +correlate to the order of how the records were added to the table. In fact, an +efficient way of the linking leads to "ordering" which is actually reversed wrt +the insertion order. + +Non unique index + +The composite key of the B+Tree is {indexed values, record handle}. The B+Tree +value is not used. + + B+Tree key B+Tree value + +----------------+---------------+ +--------------+ + | Indexed Values | Record Handle | -> | not used | + +----------------+---------------+ +--------------+ + +Unique index + +If the indexed values are all NULL then the composite B+Tree key is {nil, +record handle} and the B+Tree value is not used. + + B+Tree key B+Tree value + +------+-----------------+ +--------------+ + | NULL | Record Handle | -> | not used | + +------+-----------------+ +--------------+ + +If the indexed values are not all NULL then key of the B+Tree key are the indexed +values and the B+Tree value is the record handle. + + B+Tree key B+Tree value + +----------------+ +---------------+ + | Indexed Values | -> | Record Handle | + +----------------+ +---------------+ + +Non scalar types + +Scalar types of [1] are bool, complex*, float*, int*, uint*, string and []byte +types. All other types are "blob-like". + + QL type Go type + ----------------------------- + blob []byte + bigint big.Int + bigrat big.Rat + time time.Time + duration time.Duration + +Memory back-end stores the Go type directly. File back-end must resort to +encode all of the above as (tagged) []byte due to the lack of more types +supported natively by lldb. NULL values of blob-like types are encoded as nil +(gbNull in lldb/gb.go), exactly the same as the already existing QL types are. + +Blob encoding + +The values of the blob-like types are first encoded into a []byte slice: + + +-----------------------+-------------------+ + | blob | raw | + | bigint, bigrat, time | gob encoded | + | duration | gob encoded int64 | + +-----------------------+-------------------+ + +The gob encoding is "differential" wrt an initial encoding of all of the +blob-like type. IOW, the initial type descriptors which gob encoding must write +out are stripped off and "resupplied" on decoding transparently. See also +blob.go. If the length of the resulting slice is <= shortBlob, the first and +only chunk is the scalar encoding of + + + []interface{}{typeTag, slice}. // initial (and last) chunk + +The length of slice can be zero (for blob("")). If the resulting slice is long +(> shortBlob), the first chunk comes from encoding + + []interface{}{typeTag, nextHandle, firstPart}. // initial, but not final chunk + +In this case len(firstPart) <= shortBlob. Second and other chunks: If the chunk +is the last one, src is + + []interface{lastPart}. // overflow chunk (last) + +In this case len(lastPart) <= 64kB. If the chunk is not the last one, src is + + []interface{}{nextHandle, part}. // overflow chunk (not last) + +In this case len(part) == 64kB. + +Links + +Referenced from above: + + [0]: http://godoc.org/github.com/cznic/exp/lldb#hdr-Block_handles + [1]: http://godoc.org/github.com/cznic/exp/lldb#EncodeScalars + [2]: http://godoc.org/github.com/cznic/exp/lldb#BTree + +Rationale + +While these notes might be useful to anyone looking at QL sources, the +specifically intended reader is my future self. + +*/ +package design diff --git a/vendor/github.com/cznic/ql/doc.go b/vendor/github.com/cznic/ql/doc.go new file mode 100644 index 00000000..832d0fc1 --- /dev/null +++ b/vendor/github.com/cznic/ql/doc.go @@ -0,0 +1,2619 @@ +// Copyright 2014 The ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//MAYBE set operations +//MAYBE +=, -=, ... + +//TODO verify there's a graceful failure for a 2G+ blob on a 32 bit machine. + +// Package ql implements a pure Go embedded SQL database engine. +// +// QL is a member of the SQL family of languages. It is less complex and less +// powerful than SQL (whichever specification SQL is considered to be). +// +// Change list +// +// 2016-04-03: Release v1.0.3 fixes a data race. +// +// https://github.com/cznic/ql/issues/126 +// +// 2016-03-23: Release v1.0.2 vendors github.com/cznic/exp/lldb and +// github.com/camlistore/go4/lock. +// +// 2016-03-17: Release v1.0.1 adjusts for latest goyacc. Parser error messages +// are improved and changed, but their exact form is not considered a API +// change. +// +// 2016-03-05: The current version has been tagged v1.0.0. +// +// 2015-06-15: To improve compatibility with other SQL implementations, the +// count built-in aggregate function now accepts * as its argument. +// +// 2015-05-29: The execution planner was rewritten from scratch. It should use +// indices in all places where they were used before plus in some additional +// situations. It is possible to investigate the plan using the newly added +// EXPLAIN statement. The QL tool is handy for such analysis. If the planner +// would have used an index, but no such exists, the plan includes hints in +// form of copy/paste ready CREATE INDEX statements. +// +// The planner is still quite simple and a lot of work on it is yet ahead. You +// can help this process by filling an issue with a schema and query which +// fails to use an index or indices when it should, in your opinion. Bonus +// points for including output of `ql 'explain '`. +// +// 2015-05-09: The grammar of the CREATE INDEX statement now accepts an +// expression list instead of a single expression, which was further limited to +// just a column name or the built-in id(). As a side effect, composite +// indices are now functional. However, the values in the expression-list style +// index are not yet used by other statements or the statement/query planner. +// The composite index is useful while having UNIQUE clause to check for +// semantically duplicate rows before they get added to the table or when such +// a row is mutated using the UPDATE statement and the expression-list style +// index tuple of the row is thus recomputed. +// +// 2015-05-02: The Schema field of table __Table now correctly reflects any +// column constraints and/or defaults. Also, the (*DB).Info method now has that +// information provided in new ColumInfo fields NotNull, Constraint and +// Default. +// +// 2015-04-20: Added support for {LEFT,RIGHT,FULL} [OUTER] JOIN. +// +// 2015-04-18: Column definitions can now have constraints and defaults. +// Details are discussed in the "Constraints and defaults" chapter below the +// CREATE TABLE statement documentation. +// +// 2015-03-06: New built-in functions formatFloat and formatInt. Thanks +// urandom! (https://github.com/urandom) +// +// 2015-02-16: IN predicate now accepts a SELECT statement. See the updated +// "Predicates" section. +// +// 2015-01-17: Logical operators || and && have now alternative spellings: OR +// and AND (case insensitive). AND was a keyword before, but OR is a new one. +// This can possibly break existing queries. For the record, it's a good idea +// to not use any name appearing in, for example, [7] in your queries as the +// list of QL's keywords may expand for gaining better compatibility with +// existing SQL "standards". +// +// 2015-01-12: ACID guarantees were tightened at the cost of performance in +// some cases. The write collecting window mechanism, a formerly used +// implementation detail, was removed. Inserting rows one by one in a +// transaction is now slow. I mean very slow. Try to avoid inserting single +// rows in a transaction. Instead, whenever possible, perform batch updates of +// tens to, say thousands of rows in a single transaction. See also: +// http://www.sqlite.org/faq.html#q19, the discussed synchronization principles +// involved are the same as for QL, modulo minor details. +// +// Note: A side effect is that closing a DB before exiting an application, both +// for the Go API and through database/sql driver, is no more required, +// strictly speaking. Beware that exiting an application while there is an open +// (uncommitted) transaction in progress means losing the transaction data. +// However, the DB will not become corrupted because of not closing it. Nor +// that was the case before, but formerly failing to close a DB could have +// resulted in losing the data of the last transaction. +// +// 2014-09-21: id() now optionally accepts a single argument - a table name. +// +// 2014-09-01: Added the DB.Flush() method and the LIKE pattern matching +// predicate. +// +// 2014-08-08: The built in functions max and min now accept also time values. +// Thanks opennota! (https://github.com/opennota) +// +// 2014-06-05: RecordSet interface extended by new methods FirstRow and Rows. +// +// 2014-06-02: Indices on id() are now used by SELECT statements. +// +// 2014-05-07: Introduction of Marshal, Schema, Unmarshal. +// +// 2014-04-15: +// +// Added optional IF NOT EXISTS clause to CREATE INDEX and optional IF EXISTS +// clause to DROP INDEX. +// +// 2014-04-12: +// +// The column Unique in the virtual table __Index was renamed to IsUnique +// because the old name is a keyword. Unfortunately, this is a breaking change, +// sorry. +// +// 2014-04-11: Introduction of LIMIT, OFFSET. +// +// 2014-04-10: Introduction of query rewriting. +// +// 2014-04-07: Introduction of indices. +// +// Building non CGO QL +// +// QL imports zappy[8], a block-based compressor, which speeds up its +// performance by using a C version of the compression/decompression +// algorithms. If a CGO-free (pure Go) version of QL, or an app using QL, is +// required, please include 'purego' in the -tags option of go +// {build,get,install}. For example: +// +// $ go get -tags purego github.com/cznic/ql +// +// If zappy was installed before installing QL, it might be necessary to +// rebuild zappy first (or rebuild QL with all its dependencies using the -a +// option): +// +// $ touch "$GOPATH"/src/github.com/cznic/zappy/*.go +// $ go install -tags purego github.com/cznic/zappy +// $ go install github.com/cznic/ql +// +// Notation +// +// The syntax is specified using Extended Backus-Naur Form (EBNF) +// +// Production = production_name "=" [ Expression ] "." . +// Expression = Alternative { "|" Alternative } . +// Alternative = Term { Term } . +// Term = production_name | token [ "…" token ] | Group | Option | Repetition . +// Group = "(" Expression ")" . +// Option = "[" Expression "]" . +// Repetition = "{" Expression "}" . +// Productions are expressions constructed from terms and the following operators, in increasing precedence +// +// | alternation +// () grouping +// [] option (0 or 1 times) +// {} repetition (0 to n times) +// +// Lower-case production names are used to identify lexical tokens. +// Non-terminals are in CamelCase. Lexical tokens are enclosed in double quotes +// "" or back quotes ``. +// +// The form a … b represents the set of characters from a through b as +// alternatives. The horizontal ellipsis … is also used elsewhere in the spec +// to informally denote various enumerations or code snippets that are not +// further specified. +// +// QL source code representation +// +// QL source code is Unicode text encoded in UTF-8. The text is not +// canonicalized, so a single accented code point is distinct from the same +// character constructed from combining an accent and a letter; those are +// treated as two code points. For simplicity, this document will use the +// unqualified term character to refer to a Unicode code point in the source +// text. +// +// Each code point is distinct; for instance, upper and lower case letters are +// different characters. +// +// Implementation restriction: For compatibility with other tools, the parser +// may disallow the NUL character (U+0000) in the statement. +// +// Implementation restriction: A byte order mark is disallowed anywhere in QL +// statements. +// +// Characters +// +// The following terms are used to denote specific character classes +// +// newline = . // the Unicode code point U+000A +// unicode_char = . // an arbitrary Unicode code point except newline +// ascii_letter = "a" … "z" | "A" … "Z" . +// +// Letters and digits +// +// The underscore character _ (U+005F) is considered a letter. +// +// letter = ascii_letter | "_" . +// decimal_digit = "0" … "9" . +// octal_digit = "0" … "7" . +// hex_digit = "0" … "9" | "A" … "F" | "a" … "f" . +// +// Lexical elements +// +// Lexical elements are comments, tokens, identifiers, keywords, operators and +// delimiters, integer, floating-point, imaginary, rune and string literals and +// QL parameters. +// +// Comments +// +// There are three forms of comments +// +// Line comments start with the character sequence // or -- and stop at the end +// of the line. A line comment acts like a space. +// +// General comments start with the character sequence /* and continue through +// the character sequence */. A general comment acts like a space. +// +// Comments do not nest. +// +// Tokens +// +// Tokens form the vocabulary of QL. There are four classes: identifiers, +// keywords, operators and delimiters, and literals. White space, formed from +// spaces (U+0020), horizontal tabs (U+0009), carriage returns (U+000D), and +// newlines (U+000A), is ignored except as it separates tokens that would +// otherwise combine into a single token. +// +// Semicolons +// +// The formal grammar uses semicolons ";" as separators of QL statements. A +// single QL statement or the last QL statement in a list of statements can +// have an optional semicolon terminator. (Actually a separator from the +// following empty statement.) +// +// Identifiers +// +// Identifiers name entities such as tables or record set columns. An +// identifier is a sequence of one or more letters and digits. The first +// character in an identifier must be a letter. +// +// identifier = letter { letter | decimal_digit } . +// +// For example +// +// price +// _tmp42 +// Sales +// +// No identifiers are predeclared, however note that no keyword can be used as +// an identifier. Identifiers starting with two underscores are used for meta +// data virtual tables names. For forward compatibility, users should generally +// avoid using any identifiers starting with two underscores. For example +// +// __Column +// __Column2 +// __Index +// __Table +// +// Keywords +// +// The following keywords are reserved and may not be used as identifiers. +// +// ADD COLUMN false int32 ORDER uint16 +// ALTER complex128 float int64 OUTER uint32 +// AND complex64 float32 int8 RIGHT uint64 +// AS CREATE float64 INTO SELECT uint8 +// ASC DEFAULT FROM JOIN SET UNIQUE +// BETWEEN DELETE GROUP LEFT string UPDATE +// bigint DESC IF LIMIT TABLE VALUES +// bigrat DISTINCT IN LIKE time WHERE +// blob DROP INDEX NOT true +// bool duration INSERT NULL OR +// BY EXISTS int OFFSET TRUNCATE +// byte EXPLAIN int16 ON uint +// +// Keywords are not case sensitive. +// +// Operators and Delimiters +// +// The following character sequences represent operators, delimiters, and other +// special tokens +// +// + & && == != ( ) +// - | || < <= [ ] +// * ^ > >= , ; +// / << = . +// % >> ! +// &^ +// +// Operators consisting of more than one character are referred to by names in +// the rest of the documentation +// +// andand = "&&" . +// andnot = "&^" . +// lsh = "<<" . +// le = "<=" . +// eq = "==" . +// ge = ">=" . +// neq = "!=" . +// oror = "||" . +// rsh = ">>" . +// +// Integer literals +// +// An integer literal is a sequence of digits representing an integer constant. +// An optional prefix sets a non-decimal base: 0 for octal, 0x or 0X for +// hexadecimal. In hexadecimal literals, letters a-f and A-F represent values +// 10 through 15. +// +// int_lit = decimal_lit | octal_lit | hex_lit . +// decimal_lit = ( "1" … "9" ) { decimal_digit } . +// octal_lit = "0" { octal_digit } . +// hex_lit = "0" ( "x" | "X" ) hex_digit { hex_digit } . +// +// For example +// +// 42 +// 0600 +// 0xBadFace +// 1701411834604692 +// +// Floating-point literals +// +// A floating-point literal is a decimal representation of a floating-point +// constant. It has an integer part, a decimal point, a fractional part, and an +// exponent part. The integer and fractional part comprise decimal digits; the +// exponent part is an e or E followed by an optionally signed decimal +// exponent. One of the integer part or the fractional part may be elided; one +// of the decimal point or the exponent may be elided. +// +// float_lit = decimals "." [ decimals ] [ exponent ] | +// decimals exponent | +// "." decimals [ exponent ] . +// decimals = decimal_digit { decimal_digit } . +// exponent = ( "e" | "E" ) [ "+" | "-" ] decimals . +// +// For example +// +// 0. +// 72.40 +// 072.40 // == 72.40 +// 2.71828 +// 1.e+0 +// 6.67428e-11 +// 1E6 +// .25 +// .12345E+5 +// +// Imaginary literals +// +// An imaginary literal is a decimal representation of the imaginary part of a +// complex constant. It consists of a floating-point literal or decimal integer +// followed by the lower-case letter i. +// +// imaginary_lit = (decimals | float_lit) "i" . +// +// For example +// +// 0i +// 011i // == 11i +// 0.i +// 2.71828i +// 1.e+0i +// 6.67428e-11i +// 1E6i +// .25i +// .12345E+5i +// +// Rune literals +// +// A rune literal represents a rune constant, an integer value identifying a +// Unicode code point. A rune literal is expressed as one or more characters +// enclosed in single quotes. Within the quotes, any character may appear +// except single quote and newline. A single quoted character represents the +// Unicode value of the character itself, while multi-character sequences +// beginning with a backslash encode values in various formats. +// +// The simplest form represents the single character within the quotes; since +// QL statements are Unicode characters encoded in UTF-8, multiple +// UTF-8-encoded bytes may represent a single integer value. For instance, the +// literal 'a' holds a single byte representing a literal a, Unicode U+0061, +// value 0x61, while 'ä' holds two bytes (0xc3 0xa4) representing a literal +// a-dieresis, U+00E4, value 0xe4. +// +// Several backslash escapes allow arbitrary values to be encoded as ASCII +// text. There are four ways to represent the integer value as a numeric +// constant: \x followed by exactly two hexadecimal digits; \u followed by +// exactly four hexadecimal digits; \U followed by exactly eight hexadecimal +// digits, and a plain backslash \ followed by exactly three octal digits. In +// each case the value of the literal is the value represented by the digits in +// the corresponding base. +// +// Although these representations all result in an integer, they have different +// valid ranges. Octal escapes must represent a value between 0 and 255 +// inclusive. Hexadecimal escapes satisfy this condition by construction. The +// escapes \u and \U represent Unicode code points so within them some values +// are illegal, in particular those above 0x10FFFF and surrogate halves. +// +// After a backslash, certain single-character escapes represent special +// values +// +// \a U+0007 alert or bell +// \b U+0008 backspace +// \f U+000C form feed +// \n U+000A line feed or newline +// \r U+000D carriage return +// \t U+0009 horizontal tab +// \v U+000b vertical tab +// \\ U+005c backslash +// \' U+0027 single quote (valid escape only within rune literals) +// \" U+0022 double quote (valid escape only within string literals) +// +// All other sequences starting with a backslash are illegal inside rune +// literals. +// +// rune_lit = "'" ( unicode_value | byte_value ) "'" . +// unicode_value = unicode_char | little_u_value | big_u_value | escaped_char . +// byte_value = octal_byte_value | hex_byte_value . +// octal_byte_value = `\` octal_digit octal_digit octal_digit . +// hex_byte_value = `\` "x" hex_digit hex_digit . +// little_u_value = `\` "u" hex_digit hex_digit hex_digit hex_digit . +// big_u_value = `\` "U" hex_digit hex_digit hex_digit hex_digit +// hex_digit hex_digit hex_digit hex_digit . +// escaped_char = `\` ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | `\` | "'" | `"` ) . +// +// For example +// +// 'a' +// 'ä' +// '本' +// '\t' +// '\000' +// '\007' +// '\377' +// '\x07' +// '\xff' +// '\u12e4' +// '\U00101234' +// 'aa' // illegal: too many characters +// '\xa' // illegal: too few hexadecimal digits +// '\0' // illegal: too few octal digits +// '\uDFFF' // illegal: surrogate half +// '\U00110000' // illegal: invalid Unicode code point +// +// String literals +// +// A string literal represents a string constant obtained from concatenating a +// sequence of characters. There are two forms: raw string literals and +// interpreted string literals. +// +// Raw string literals are character sequences between back quotes ``. Within +// the quotes, any character is legal except back quote. The value of a raw +// string literal is the string composed of the uninterpreted (implicitly +// UTF-8-encoded) characters between the quotes; in particular, backslashes +// have no special meaning and the string may contain newlines. Carriage +// returns inside raw string literals are discarded from the raw string value. +// +// Interpreted string literals are character sequences between double quotes +// "". The text between the quotes, which may not contain newlines, forms the +// value of the literal, with backslash escapes interpreted as they are in rune +// literals (except that \' is illegal and \" is legal), with the same +// restrictions. The three-digit octal (\nnn) and two-digit hexadecimal (\xnn) +// escapes represent individual bytes of the resulting string; all other +// escapes represent the (possibly multi-byte) UTF-8 encoding of individual +// characters. Thus inside a string literal \377 and \xFF represent a single +// byte of value 0xFF=255, while ÿ, \u00FF, \U000000FF and \xc3\xbf represent +// the two bytes 0xc3 0xbf of the UTF-8 encoding of character U+00FF. +// +// string_lit = raw_string_lit | interpreted_string_lit . +// raw_string_lit = "`" { unicode_char | newline } "`" . +// interpreted_string_lit = `"` { unicode_value | byte_value } `"` . +// +// For example +// +// `abc` // same as "abc" +// `\n +// \n` // same as "\\n\n\\n" +// "\n" +// "" +// "Hello, world!\n" +// "日本語" +// "\u65e5本\U00008a9e" +// "\xff\u00FF" +// "\uD800" // illegal: surrogate half +// "\U00110000" // illegal: invalid Unicode code point +// +// These examples all represent the same string +// +// "日本語" // UTF-8 input text +// `日本語` // UTF-8 input text as a raw literal +// "\u65e5\u672c\u8a9e" // the explicit Unicode code points +// "\U000065e5\U0000672c\U00008a9e" // the explicit Unicode code points +// "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e" // the explicit UTF-8 bytes +// +// If the statement source represents a character as two code points, such as a +// combining form involving an accent and a letter, the result will be an error +// if placed in a rune literal (it is not a single code point), and will appear +// as two code points if placed in a string literal. +// +// QL parameters +// +// Literals are assigned their values from the respective text representation +// at "compile" (parse) time. QL parameters provide the same functionality as +// literals, but their value is assigned at execution time from an expression +// list passed to DB.Run or DB.Execute. Using '?' or '$' is completely +// equivalent. +// +// ql_parameter = ( "?" | "$" ) "1" … "9" { "0" … "9" } . +// +// For example +// +// SELECT DepartmentID +// FROM department +// WHERE DepartmentID == ?1 +// ORDER BY DepartmentName; +// +// SELECT employee.LastName +// FROM department, employee +// WHERE department.DepartmentID == $1 && employee.LastName > $2 +// ORDER BY DepartmentID; +// +// Constants +// +// Keywords 'false' and 'true' (not case sensitive) represent the two possible +// constant values of type bool (also not case sensitive). +// +// Keyword 'NULL' (not case sensitive) represents an untyped constant which is +// assignable to any type. NULL is distinct from any other value of any type. +// +// Types +// +// A type determines the set of values and operations specific to values of +// that type. A type is specified by a type name. +// +// Type = "bigint" // http://golang.org/pkg/math/big/#Int +// | "bigrat" // http://golang.org/pkg/math/big/#Rat +// | "blob" // []byte +// | "bool" +// | "byte" // alias for uint8 +// | "complex128" +// | "complex64" +// | "duration" // http://golang.org/pkg/time/#Duration +// | "float" // alias for float64 +// | "float32" +// | "float64" +// | "int" // alias for int64 +// | "int16" +// | "int32" +// | "int64" +// | "int8" +// | "rune" // alias for int32 +// | "string" +// | "time" // http://golang.org/pkg/time/#Time +// | "uint" // alias for uint64 +// | "uint16" +// | "uint32" +// | "uint64" +// | "uint8" . +// +// Named instances of the boolean, numeric, and string types are keywords. The +// names are not case sensitive. +// +// Note: The blob type is exchanged between the back end and the API as []byte. +// On 32 bit platforms this limits the size which the implementation can handle +// to 2G. +// +// Boolean types +// +// A boolean type represents the set of Boolean truth values denoted by the +// predeclared constants true and false. The predeclared boolean type is bool. +// +// Duration type +// +// A duration type represents the elapsed time between two instants as an int64 +// nanosecond count. The representation limits the largest representable +// duration to approximately 290 years. +// +// Numeric types +// +// A numeric type represents sets of integer or floating-point values. The +// predeclared architecture-independent numeric types are +// +// uint8 the set of all unsigned 8-bit integers (0 to 255) +// uint16 the set of all unsigned 16-bit integers (0 to 65535) +// uint32 the set of all unsigned 32-bit integers (0 to 4294967295) +// uint64 the set of all unsigned 64-bit integers (0 to 18446744073709551615) +// +// int8 the set of all signed 8-bit integers (-128 to 127) +// int16 the set of all signed 16-bit integers (-32768 to 32767) +// int32 the set of all signed 32-bit integers (-2147483648 to 2147483647) +// int64 the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807) +// duration the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807) +// bigint the set of all integers +// +// bigrat the set of all rational numbers +// +// float32 the set of all IEEE-754 32-bit floating-point numbers +// float64 the set of all IEEE-754 64-bit floating-point numbers +// +// complex64 the set of all complex numbers with float32 real and imaginary parts +// complex128 the set of all complex numbers with float64 real and imaginary parts +// +// byte alias for uint8 +// float alias for float64 +// int alias for int64 +// rune alias for int32 +// uint alias for uint64 +// +// The value of an n-bit integer is n bits wide and represented using two's +// complement arithmetic. +// +// Conversions are required when different numeric types are mixed in an +// expression or assignment. +// +// String types +// +// A string type represents the set of string values. A string value is a +// (possibly empty) sequence of bytes. The case insensitive keyword for the +// string type is 'string'. +// +// The length of a string (its size in bytes) can be discovered using the +// built-in function len. +// +// Time types +// +// A time type represents an instant in time with nanosecond precision. Each +// time has associated with it a location, consulted when computing the +// presentation form of the time. +// +// Predeclared functions +// +// The following functions are implicitly declared +// +// avg complex contains count date +// day formatTime formatFloat formatInt +// hasPrefix hasSuffix hour hours id +// imag len max min minute +// minutes month nanosecond nanoseconds now +// parseTime real second seconds since +// sum timeIn weekday year yearDay +// +// Expressions +// +// An expression specifies the computation of a value by applying operators and +// functions to operands. +// +// Operands +// +// Operands denote the elementary values in an expression. An operand may be a +// literal, a (possibly qualified) identifier denoting a constant or a function +// or a table/record set column, or a parenthesized expression. +// +// Operand = Literal | QualifiedIdent | "(" Expression ")" . +// Literal = "FALSE" | "NULL" | "TRUE" +// | float_lit | imaginary_lit | int_lit | rune_lit | string_lit +// | ql_parameter . +// +// Qualified identifiers +// +// A qualified identifier is an identifier qualified with a table/record set +// name prefix. +// +// QualifiedIdent = identifier [ "." identifier ] . +// +// For example +// +// invoice.Num // might denote column 'Num' from table 'invoice' +// +// Primary expressions +// +// Primary expression are the operands for unary and binary expressions. +// +// PrimaryExpression = Operand +// | Conversion +// | PrimaryExpression Index +// | PrimaryExpression Slice +// | PrimaryExpression Call . +// +// Call = "(" [ "*" | ExpressionList ] ")" . // * only in count(*). +// Index = "[" Expression "]" . +// Slice = "[" [ Expression ] ":" [ Expression ] "]" . +// +// For example +// +// x +// 2 +// (s + ".txt") +// f(3.1415, true) +// s[i : j + 1] +// +// Index expressions +// +// A primary expression of the form +// +// s[x] +// +// denotes the element of a string indexed by x. Its type is byte. The value x +// is called the index. The following rules apply +// +// - The index x must be of integer type except bigint or duration; it is in +// range if 0 <= x < len(s), otherwise it is out of range. +// +// - A constant index must be non-negative and representable by a value of type +// int. +// +// - A constant index must be in range if the string a is a literal. +// +// - If x is out of range at run time, a run-time error occurs. +// +// - s[x] is the byte at index x and the type of s[x] is byte. +// +// If s is NULL or x is NULL then the result is NULL. +// +// Otherwise s[x] is illegal. +// +// Slices +// +// For a string, the primary expression +// +// s[low : high] +// +// constructs a substring. The indices low and high select which elements +// appear in the result. The result has indices starting at 0 and length equal +// to high - low. +// +// For convenience, any of the indices may be omitted. A missing low index +// defaults to zero; a missing high index defaults to the length of the sliced +// operand +// +// s[2:] // same s[2 : len(s)] +// s[:3] // same as s[0 : 3] +// s[:] // same as s[0 : len(s)] +// +// The indices low and high are in range if 0 <= low <= high <= len(a), +// otherwise they are out of range. A constant index must be non-negative and +// representable by a value of type int. If both indices are constant, they +// must satisfy low <= high. If the indices are out of range at run time, a +// run-time error occurs. +// +// Integer values of type bigint or duration cannot be used as indices. +// +// If s is NULL the result is NULL. If low or high is not omitted and is NULL +// then the result is NULL. +// +// Calls +// +// Given an identifier f denoting a predeclared function, +// +// f(a1, a2, … an) +// +// calls f with arguments a1, a2, … an. Arguments are evaluated before the +// function is called. The type of the expression is the result type of f. +// +// complex(x, y) +// len(name) +// +// In a function call, the function value and arguments are evaluated in the +// usual order. After they are evaluated, the parameters of the call are passed +// by value to the function and the called function begins execution. The +// return value of the function is passed by value when the function returns. +// +// Calling an undefined function causes a compile-time error. +// +// Operators +// +// Operators combine operands into expressions. +// +// Expression = Term { ( oror | "OR" ) Term } . +// +// ExpressionList = Expression { "," Expression } [ "," ]. +// Factor = PrimaryFactor { ( ge | ">" | le | "<" | neq | eq | "LIKE" ) PrimaryFactor } [ Predicate ] . +// PrimaryFactor = PrimaryTerm { ( "^" | "|" | "-" | "+" ) PrimaryTerm } . +// PrimaryTerm = UnaryExpr { ( andnot | "&" | lsh | rsh | "%" | "/" | "*" ) UnaryExpr } . +// Term = Factor { ( andand | "AND" ) Factor } . +// UnaryExpr = [ "^" | "!" | "-" | "+" ] PrimaryExpression . +// +// Comparisons are discussed elsewhere. For other binary operators, the operand +// types must be identical unless the operation involves shifts or untyped +// constants. For operations involving constants only, see the section on +// constant expressions. +// +// Except for shift operations, if one operand is an untyped constant and the +// other operand is not, the constant is converted to the type of the other +// operand. +// +// The right operand in a shift expression must have unsigned integer type or +// be an untyped constant that can be converted to unsigned integer type. If +// the left operand of a non-constant shift expression is an untyped constant, +// the type of the constant is what it would be if the shift expression were +// replaced by its left operand alone. +// +// Pattern matching +// +// Expressions of the form +// +// expr1 LIKE expr2 +// +// yeild a boolean value true if expr2, a regular expression, matches expr1 +// (see also [6]). Both expression must be of type string. If any one of the +// expressions is NULL the result is NULL. +// +// Predicates +// +// Predicates are special form expressions having a boolean result type. +// +// Expressions of the form +// +// expr IN ( expr1, expr2, expr3, ... ) // case A +// +// expr NOT IN ( expr1, expr2, expr3, ... ) // case B +// +// are equivalent, including NULL handling, to +// +// expr == expr1 || expr == expr2 || expr == expr3 || ... // case A +// +// expr != expr1 && expr != expr2 && expr != expr3 && ... // case B +// +// The types of involved expressions must be comparable as defined in +// "Comparison operators". +// +// Another form of the IN predicate creates the expression list from a result +// of a SelectStmt. +// +// DELETE FROM t WHERE id() IN (SELECT id_t FROM u WHERE inactive_days > 365) +// +// The SelectStmt must select only one column. The produced expression list is +// resource limited by the memory available to the process. NULL values +// produced by the SelectStmt are ignored, but if all records of the SelectStmt +// are NULL the predicate yields NULL. The select statement is evaluated only +// once. If the type of expr is not the same as the type of the field returned +// by the SelectStmt then the set operation yields false. The type of the +// column returned by the SelectStmt must be one of the simple (non blob-like) +// types: +// +// bool +// byte // alias uint8 +// complex128 +// complex64 +// float // alias float64 +// float32 +// float64 +// int // alias int64 +// int16 +// int32 +// int64 +// int8 +// rune // alias int32 +// string +// uint // alias uint64 +// uint16 +// uint32 +// uint64 +// uint8 +// +// Expressions of the form +// +// expr BETWEEN low AND high // case A +// +// expr NOT BETWEEN low AND high // case B +// +// are equivalent, including NULL handling, to +// +// expr >= low && expr <= high // case A +// +// expr < low || expr > high // case B +// +// The types of involved expressions must be ordered as defined in "Comparison +// operators". +// +// Predicate = ( +// [ "NOT" ] ( +// "IN" "(" ExpressionList ")" +// | "IN" "(" SelectStmt [ ";" ] ")" +// | "BETWEEN" PrimaryFactor "AND" PrimaryFactor +// ) +// | "IS" [ "NOT" ] "NULL" +// ). +// +// Expressions of the form +// +// expr IS NULL // case A +// +// expr IS NOT NULL // case B +// +// yeild a boolean value true if expr does not have a specific type (case A) or +// if expr has a specific type (case B). In other cases the result is a boolean +// value false. +// +// Operator precedence +// +// Unary operators have the highest precedence. +// +// There are five precedence levels for binary operators. Multiplication +// operators bind strongest, followed by addition operators, comparison +// operators, && (logical AND), and finally || (logical OR) +// +// Precedence Operator +// 5 * / % << >> & &^ +// 4 + - | ^ +// 3 == != < <= > >= +// 2 && +// 1 || +// +// Binary operators of the same precedence associate from left to right. For +// instance, x / y * z is the same as (x / y) * z. +// +// +x +// 23 + 3*x[i] +// x <= f() +// ^a >> b +// f() || g() +// x == y+1 && z > 0 +// +// Note that the operator precedence is reflected explicitly by the grammar. +// +// Arithmetic operators +// +// Arithmetic operators apply to numeric values and yield a result of the same +// type as the first operand. The four standard arithmetic operators (+, -, *, +// /) apply to integer, rational, floating-point, and complex types; + also +// applies to strings; +,- also applies to times. All other arithmetic +// operators apply to integers only. +// +// + sum integers, rationals, floats, complex values, strings +// - difference integers, rationals, floats, complex values, times +// * product integers, rationals, floats, complex values +// / quotient integers, rationals, floats, complex values +// % remainder integers +// +// & bitwise AND integers +// | bitwise OR integers +// ^ bitwise XOR integers +// &^ bit clear (AND NOT) integers +// +// << left shift integer << unsigned integer +// >> right shift integer >> unsigned integer +// +// Strings can be concatenated using the + operator +// +// "hi" + string(c) + " and good bye" +// +// String addition creates a new string by concatenating the operands. +// +// A value of type duration can be added to or subtracted from a value of type time. +// +// now() + duration("1h") // time after 1 hour from now +// duration("1h") + now() // time after 1 hour from now +// now() - duration("1h") // time before 1 hour from now +// duration("1h") - now() // illegal, negative times do not exist +// +// Times can subtracted from each other producing a value of type duration. +// +// now() - t0 // elapsed time since t0 +// now() + now() // illegal, operator + not defined for times +// +// For two integer values x and y, the integer quotient q = x / y and remainder +// r = x % y satisfy the following relationships +// +// x = q*y + r and |r| < |y| +// +// with x / y truncated towards zero ("truncated division"). +// +// x y x / y x % y +// 5 3 1 2 +// -5 3 -1 -2 +// 5 -3 -1 2 +// -5 -3 1 -2 +// +// As an exception to this rule, if the dividend x is the most negative value +// for the int type of x, the quotient q = x / -1 is equal to x (and r = 0). +// +// x, q +// int8 -128 +// int16 -32768 +// int32 -2147483648 +// int64 -9223372036854775808 +// +// If the divisor is a constant expression, it must not be zero. If the divisor +// is zero at run time, a run-time error occurs. If the dividend is +// non-negative and the divisor is a constant power of 2, the division may be +// replaced by a right shift, and computing the remainder may be replaced by a +// bitwise AND operation +// +// x x / 4 x % 4 x >> 2 x & 3 +// 11 2 3 2 3 +// -11 -2 -3 -3 1 +// +// The shift operators shift the left operand by the shift count specified by +// the right operand. They implement arithmetic shifts if the left operand is a +// signed integer and logical shifts if it is an unsigned integer. There is no +// upper limit on the shift count. Shifts behave as if the left operand is +// shifted n times by 1 for a shift count of n. As a result, x << 1 is the same +// as x*2 and x >> 1 is the same as x/2 but truncated towards negative +// infinity. +// +// For integer operands, the unary operators +, -, and ^ are defined as follows +// +// +x is 0 + x +// -x negation is 0 - x +// ^x bitwise complement is m ^ x with m = "all bits set to 1" for unsigned x +// and m = -1 for signed x +// +// For floating-point and complex numbers, +x is the same as x, while -x is the +// negation of x. The result of a floating-point or complex division by zero is +// not specified beyond the IEEE-754 standard; whether a run-time error occurs +// is implementation-specific. +// +// Whenever any operand of any arithmetic operation, unary or binary, is NULL, +// as well as in the case of the string concatenating operation, the result is +// NULL. +// +// 42*NULL // the result is NULL +// NULL/x // the result is NULL +// "foo"+NULL // the result is NULL +// +// Integer overflow +// +// For unsigned integer values, the operations +, -, *, and << are computed +// modulo 2n, where n is the bit width of the unsigned integer's type. Loosely +// speaking, these unsigned integer operations discard high bits upon overflow, +// and expressions may rely on ``wrap around''. +// +// For signed integers with a finite bit width, the operations +, -, *, and << +// may legally overflow and the resulting value exists and is deterministically +// defined by the signed integer representation, the operation, and its +// operands. No exception is raised as a result of overflow. An evaluator may +// not optimize an expression under the assumption that overflow does not +// occur. For instance, it may not assume that x < x + 1 is always true. +// +// Integers of type bigint and rationals do not overflow but their handling is +// limited by the memory resources available to the program. +// +// Comparison operators +// +// Comparison operators compare two operands and yield a boolean value. +// +// == equal +// != not equal +// < less +// <= less or equal +// > greater +// >= greater or equal +// +// In any comparison, the first operand must be of same type as is the second +// operand, or vice versa. +// +// The equality operators == and != apply to operands that are comparable. The +// ordering operators <, <=, >, and >= apply to operands that are ordered. +// These terms and the result of the comparisons are defined as follows +// +// - Boolean values are comparable. Two boolean values are equal if they are +// either both true or both false. +// +// - Complex values are comparable. Two complex values u and v are equal if +// both real(u) == real(v) and imag(u) == imag(v). +// +// - Integer values are comparable and ordered, in the usual way. Note that +// durations are integers. +// +// - Floating point values are comparable and ordered, as defined by the +// IEEE-754 standard. +// +// - Rational values are comparable and ordered, in the usual way. +// +// - String values are comparable and ordered, lexically byte-wise. +// +// - Time values are comparable and ordered. +// +// Whenever any operand of any comparison operation is NULL, the result is +// NULL. +// +// Note that slices are always of type string. +// +// Logical operators +// +// Logical operators apply to boolean values and yield a boolean result. The +// right operand is evaluated conditionally. +// +// && conditional AND p && q is "if p then q else false" +// || conditional OR p || q is "if p then true else q" +// ! NOT !p is "not p" +// +// The truth tables for logical operations with NULL values +// +// +-------+-------+---------+---------+ +// | p | q | p || q | p && q | +// +-------+-------+---------+---------+ +// | true | true | *true | true | +// | true | false | *true | false | +// | true | NULL | *true | NULL | +// | false | true | true | *false | +// | false | false | false | *false | +// | false | NULL | NULL | *false | +// | NULL | true | true | NULL | +// | NULL | false | NULL | false | +// | NULL | NULL | NULL | NULL | +// +-------+-------+---------+---------+ +// * indicates q is not evaluated. +// +// +-------+-------+ +// | p | !p | +// +-------+-------+ +// | true | false | +// | false | true | +// | NULL | NULL | +// +-------+-------+ +// +// Conversions +// +// Conversions are expressions of the form T(x) where T is a type and x is an +// expression that can be converted to type T. +// +// Conversion = Type "(" Expression ")" . +// +// A constant value x can be converted to type T in any of these cases: +// +// - x is representable by a value of type T. +// +// - x is a floating-point constant, T is a floating-point type, and x is +// representable by a value of type T after rounding using IEEE 754 +// round-to-even rules. The constant T(x) is the rounded value. +// +// - x is an integer constant and T is a string type. The same rule as for +// non-constant x applies in this case. +// +// Converting a constant yields a typed constant as result. +// +// float32(2.718281828) // 2.718281828 of type float32 +// complex128(1) // 1.0 + 0.0i of type complex128 +// float32(0.49999999) // 0.5 of type float32 +// string('x') // "x" of type string +// string(0x266c) // "♬" of type string +// "foo" + "bar" // "foobar" +// int(1.2) // illegal: 1.2 cannot be represented as an int +// string(65.0) // illegal: 65.0 is not an integer constant +// +// A non-constant value x can be converted to type T in any of these cases: +// +// - x has type T. +// +// - x's type and T are both integer or floating point types. +// +// - x's type and T are both complex types. +// +// - x is an integer, except bigint or duration, and T is a string type. +// +// Specific rules apply to (non-constant) conversions between numeric types or +// to and from a string type. These conversions may change the representation +// of x and incur a run-time cost. All other conversions only change the type +// but not the representation of x. +// +// A conversion of NULL to any type yields NULL. +// +// Conversions between numeric types +// +// For the conversion of non-constant numeric values, the following rules +// apply +// +// 1. When converting between integer types, if the value is a signed integer, +// it is sign extended to implicit infinite precision; otherwise it is zero +// extended. It is then truncated to fit in the result type's size. For +// example, if v == uint16(0x10F0), then uint32(int8(v)) == 0xFFFFFFF0. The +// conversion always yields a valid value; there is no indication of overflow. +// +// 2. When converting a floating-point number to an integer, the fraction is +// discarded (truncation towards zero). +// +// 3. When converting an integer or floating-point number to a floating-point +// type, or a complex number to another complex type, the result value is +// rounded to the precision specified by the destination type. For instance, +// the value of a variable x of type float32 may be stored using additional +// precision beyond that of an IEEE-754 32-bit number, but float32(x) +// represents the result of rounding x's value to 32-bit precision. Similarly, +// x + 0.1 may use more than 32 bits of precision, but float32(x + 0.1) does +// not. +// +// In all non-constant conversions involving floating-point or complex values, +// if the result type cannot represent the value the conversion succeeds but +// the result value is implementation-dependent. +// +// Conversions to and from a string type +// +// 1. Converting a signed or unsigned integer value to a string type yields a +// string containing the UTF-8 representation of the integer. Values outside +// the range of valid Unicode code points are converted to "\uFFFD". +// +// string('a') // "a" +// string(-1) // "\ufffd" == "\xef\xbf\xbd" +// string(0xf8) // "\u00f8" == "ø" == "\xc3\xb8" +// string(0x65e5) // "\u65e5" == "日" == "\xe6\x97\xa5" +// +// 2. Converting a blob to a string type yields a string whose successive bytes +// are the elements of the blob. +// +// string(b /* []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'} */) // "hellø" +// string(b /* []byte{} */) // "" +// string(b /* []byte(nil) */) // "" +// +// 3. Converting a value of a string type to a blob yields a blob whose +// successive elements are the bytes of the string. +// +// blob("hellø") // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'} +// blob("") // []byte{} +// +// 4. Converting a value of a bigint type to a string yields a string +// containing the decimal decimal representation of the integer. +// +// string(M9) // "2305843009213693951" +// +// 5. Converting a value of a string type to a bigint yields a bigint value +// containing the integer represented by the string value. A prefix of “0x” or +// “0X” selects base 16; the “0” prefix selects base 8, and a “0b” or “0B” +// prefix selects base 2. Otherwise the value is interpreted in base 10. An +// error occurs if the string value is not in any valid format. +// +// bigint("2305843009213693951") // M9 +// bigint("0x1ffffffffffffffffffffff") // M10 == 2^89-1 +// +// 6. Converting a value of a rational type to a string yields a string +// containing the decimal decimal representation of the rational in the form +// "a/b" (even if b == 1). +// +// string(bigrat(355)/bigrat(113)) // "355/113" +// +// 7. Converting a value of a string type to a bigrat yields a bigrat value +// containing the rational represented by the string value. The string can be +// given as a fraction "a/b" or as a floating-point number optionally followed +// by an exponent. An error occurs if the string value is not in any valid +// format. +// +// bigrat("1.2e-34") +// bigrat("355/113") +// +// 8. Converting a value of a duration type to a string returns a string +// representing the duration in the form "72h3m0.5s". Leading zero units are +// omitted. As a special case, durations less than one second format using a +// smaller unit (milli-, micro-, or nanoseconds) to ensure that the leading +// digit is non-zero. The zero duration formats as 0, with no unit. +// +// string(elapsed) // "1h", for example +// +// 9. Converting a string value to a duration yields a duration represented by +// the string. A duration string is a possibly signed sequence of decimal +// numbers, each with optional fraction and a unit suffix, such as "300ms", +// "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", +// "m", "h". +// +// duration("1m") // http://golang.org/pkg/time/#Minute +// +// 10. Converting a time value to a string returns the time formatted using the +// format string +// +// "2006-01-02 15:04:05.999999999 -0700 MST" +// +// Order of evaluation +// +// When evaluating the operands of an expression or of function calls, +// operations are evaluated in lexical left-to-right order. +// +// For example, in the evaluation of +// +// g(h(), i()+x[j()], c) +// +// the function calls and evaluation of c happen in the order h(), i(), j(), c. +// +// Floating-point operations within a single expression are evaluated according +// to the associativity of the operators. Explicit parentheses affect the +// evaluation by overriding the default associativity. In the expression x + (y +// + z) the addition y + z is performed before adding x. +// +// Statements +// +// Statements control execution. +// +// Statement = EmptyStmt | AlterTableStmt | BeginTransactionStmt | CommitStmt +// | CreateIndexStmt | CreateTableStmt | DeleteFromStmt | DropIndexStmt +// | DropTableStmt | InsertIntoStmt | RollbackStmt | SelectStmt +// | TruncateTableStmt | UpdateStmt | ExplainStmt. +// +// StatementList = Statement { ";" Statement } . +// +// Empty statements +// +// The empty statement does nothing. +// +// EmptyStmt = . +// +// ALTER TABLE +// +// Alter table statements modify existing tables. With the ADD clause it adds +// a new column to the table. The column must not exist. With the DROP clause +// it removes an existing column from a table. The column must exist and it +// must be not the only (last) column of the table. IOW, there cannot be a +// table with no columns. +// +// AlterTableStmt = "ALTER" "TABLE" TableName ( "ADD" ColumnDef | "DROP" "COLUMN" ColumnName ) . +// +// For example +// +// BEGIN TRANSACTION; +// ALTER TABLE Stock ADD Qty int; +// ALTER TABLE Income DROP COLUMN Taxes; +// COMMIT; +// +// When adding a column to a table with existing data, the constraint clause of +// the ColumnDef cannot be used. Adding a constrained column to an empty table +// is fine. +// +// BEGIN TRANSACTION +// +// Begin transactions statements introduce a new transaction level. Every +// transaction level must be eventually balanced by exactly one of COMMIT or +// ROLLBACK statements. Note that when a transaction is roll-backed because of +// a statement failure then no explicit balancing of the respective BEGIN +// TRANSACTION is statement is required nor permitted. +// +// Failure to properly balance any opened transaction level may cause dead +// locks and/or lose of data updated in the uppermost opened but never properly +// closed transaction level. +// +// BeginTransactionStmt = "BEGIN" "TRANSACTION" . +// +// For example +// +// BEGIN TRANSACTION; +// INSERT INTO foo VALUES (42, 3.14); +// INSERT INTO foo VALUES (-1, 2.78); +// COMMIT; +// +// Mandatory transactions +// +// A database cannot be updated (mutated) outside of a transaction. Statements +// requiring a transaction +// +// ALTER TABLE +// COMMIT +// CREATE INDEX +// CREATE TABLE +// DELETE FROM +// DROP INDEX +// DROP TABLE +// INSERT INTO +// ROLLBACK +// TRUNCATE TABLE +// UPDATE +// +// A database is effectively read only outside of a transaction. Statements not +// requiring a transaction +// +// BEGIN TRANSACTION +// SELECT FROM +// +// COMMIT +// +// The commit statement closes the innermost transaction nesting level. If +// that's the outermost level then the updates to the DB made by the +// transaction are atomically made persistent. +// +// CommitStmt = "COMMIT" . +// +// For example +// +// BEGIN TRANSACTION; +// INSERT INTO AccountA (Amount) VALUES ($1); +// INSERT INTO AccountB (Amount) VALUES (-$1); +// COMMIT; +// +// CREATE INDEX +// +// Create index statements create new indices. Index is a named projection of +// ordered values of a table column to the respective records. As a special +// case the id() of the record can be indexed. Index name must not be the same +// as any of the existing tables and it also cannot be the same as of any +// column name of the table the index is on. +// +// CreateIndexStmt = "CREATE" [ "UNIQUE" ] "INDEX" [ "IF" "NOT" "EXISTS" ] +// IndexName "ON" TableName "(" ExpressionList ")" . +// +// For example +// +// BEGIN TRANSACTION; +// CREATE TABLE Orders (CustomerID int, Date time); +// CREATE INDEX OrdersID ON Orders (id()); +// CREATE INDEX OrdersDate ON Orders (Date); +// CREATE TABLE Items (OrderID int, ProductID int, Qty int); +// CREATE INDEX ItemsOrderID ON Items (OrderID); +// COMMIT; +// +// Now certain SELECT statements may use the indices to speed up joins and/or +// to speed up record set filtering when the WHERE clause is used; or the +// indices might be used to improve the performance when the ORDER BY clause is +// present. +// +// The UNIQUE modifier requires the indexed values tuple to be index-wise +// unique or have all values NULL. +// +// The optional IF NOT EXISTS clause makes the statement a no operation if the +// index already exists. +// +// Simple index +// +// A simple index consists of only one expression which must be either a column +// name or the built-in id(). +// +// Expression list index +// +// A more complex and more general index is one that consists of more than one +// expression or its single expression does not qualify as a simple index. In +// this case the type of all expressions in the list must be one of the non +// blob-like types. +// +// Note: Blob-like types are blob, bigint, bigrat, time and duration. +// +// CREATE TABLE +// +// Create table statements create new tables. A column definition declares the +// column name and type. Table names and column names are case sensitive. +// Neither a table or an index of the same name may exist in the DB. +// +// CreateTableStmt = "CREATE" "TABLE" [ "IF" "NOT" "EXISTS" ] TableName +// "(" ColumnDef { "," ColumnDef } [ "," ] ")" . +// +// ColumnDef = ColumnName Type [ "NOT" "NULL" | Expression ] [ "DEFAULT" Expression ] . +// ColumnName = identifier . +// TableName = identifier . +// +// For example +// +// BEGIN TRANSACTION; +// CREATE TABLE department ( +// DepartmentID int, +// DepartmentName string, +// ); +// CREATE TABLE employee ( +// LastName string, +// DepartmentID int, +// ); +// COMMIT; +// +// The optional IF NOT EXISTS clause makes the statement a no operation if the +// table already exists. +// +// The optional constraint clause has two forms. The first one is found in many +// SQL dialects. +// +// BEGIN TRANSACTION; +// CREATE TABLE department ( +// DepartmentID int, +// DepartmentName string NOT NULL, +// ); +// COMMIT; +// +// This form prevents the data in column DepartmentName to be NULL. +// +// The second form allows an arbitrary boolean expression to be used to +// validate the column. If the value of the expression is true then the +// validation succeeded. If the value of the expression is false or NULL then +// the validation fails. If the value of the expression is not of type bool an +// error occurs. +// +// BEGIN TRANSACTION; +// CREATE TABLE department ( +// DepartmentID int, +// DepartmentName string DepartmentName IN ("HQ", "R/D", "Lab", "HR"), +// ); +// COMMIT; +// +// BEGIN TRANSACTION; +// CREATE TABLE t ( +// TimeStamp time TimeStamp < now() && since(TimeStamp) < duration("10s"), +// Event string Event != "" && Event like "[0-9]+:[ \t]+.*", +// ); +// COMMIT; +// +// The optional DEFAULT clause is an expression which, if present, is +// substituted instead of a NULL value when the colum is assigned a value. +// +// BEGIN TRANSACTION; +// CREATE TABLE department ( +// DepartmentID int, +// DepartmentName string DepartmentName IN ("HQ", "R/D", "Lab", "HR") DEFAULT "HQ", +// ); +// COMMIT; +// +// Note that the constraint and/or default expressions may refer to other +// columns by name: +// +// BEGIN TRANSACTION; +// CREATE TABLE t ( +// a int, +// b int b > a && b < c DEFAULT (a+c)/2, +// c int, +// ); +// COMMIT; +// +// +// Constraints and defaults +// +// When a table row is inserted by the INSERT INTO statement or when a table +// row is updated by the UPDATE statement, the order of operations is as +// follows: +// +// 1. The new values of the affected columns are set and the values of all the +// row columns become the named values which can be referred to in default +// expressions evaluated in step 2. +// +// 2. If any row column value is NULL and the DEFAULT clause is present in the +// column's definition, the default expression is evaluated and its value is +// set as the respective column value. +// +// 3. The values, potentially updated, of row columns become the named values +// which can be referred to in constraint expressions evaluated during step 4. +// +// 4. All row columns which definition has the constraint clause present will +// have that constraint checked. If any constraint violation is detected, the +// overall operation fails and no changes to the table are made. +// +// DELETE FROM +// +// Delete from statements remove rows from a table, which must exist. +// +// DeleteFromStmt = "DELETE" "FROM" TableName [ WhereClause ] . +// +// For example +// +// BEGIN TRANSACTION; +// DELETE FROM DepartmentID +// WHERE DepartmentName == "Ponies"; +// COMMIT; +// +// If the WHERE clause is not present then all rows are removed and the +// statement is equivalent to the TRUNCATE TABLE statement. +// +// DROP INDEX +// +// Drop index statements remove indices from the DB. The index must exist. +// +// DropIndexStmt = "DROP" "INDEX" [ "IF" "EXISTS" ] IndexName . +// IndexName = identifier . +// +// For example +// +// BEGIN TRANSACTION; +// DROP INDEX ItemsOrderID; +// COMMIT; +// +// The optional IF EXISTS clause makes the statement a no operation if the +// index does not exist. +// +// DROP TABLE +// +// Drop table statements remove tables from the DB. The table must exist. +// +// DropTableStmt = "DROP" "TABLE" [ "IF" "EXISTS" ] TableName . +// +// For example +// +// BEGIN TRANSACTION; +// DROP TABLE Inventory; +// COMMIT; +// +// The optional IF EXISTS clause makes the statement a no operation if the +// table does not exist. +// +// INSERT INTO +// +// Insert into statements insert new rows into tables. New rows come from +// literal data, if using the VALUES clause, or are a result of select +// statement. In the later case the select statement is fully evaluated before +// the insertion of any rows is performed, allowing to insert values calculated +// from the same table rows are to be inserted into. If the ColumnNameList part +// is omitted then the number of values inserted in the row must be the same as +// are columns in the table. If the ColumnNameList part is present then the +// number of values per row must be same as the same number of column names. +// All other columns of the record are set to NULL. The type of the value +// assigned to a column must be the same as is the column's type or the value +// must be NULL. +// +// InsertIntoStmt = "INSERT" "INTO" TableName [ "(" ColumnNameList ")" ] ( Values | SelectStmt ) . +// +// ColumnNameList = ColumnName { "," ColumnName } [ "," ] . +// Values = "VALUES" "(" ExpressionList ")" { "," "(" ExpressionList ")" } [ "," ] . +// +// For example +// +// BEGIN TRANSACTION; +// INSERT INTO department (DepartmentID) VALUES (42); +// +// INSERT INTO department ( +// DepartmentName, +// DepartmentID, +// ) +// VALUES ( +// "R&D", +// 42, +// ); +// +// INSERT INTO department VALUES +// (42, "R&D"), +// (17, "Sales"), +// ; +// COMMIT; +// +// BEGIN TRANSACTION; +// INSERT INTO department (DepartmentName, DepartmentID) +// SELECT DepartmentName+"/headquarters", DepartmentID+1000 +// FROM department; +// COMMIT; +// +// If any of the columns of the table were defined using the optional +// constraints clause or the optional defaults clause then those are processed +// on a per row basis. The details are discussed in the "Constraints and +// defaults" chapter below the CREATE TABLE statement documentation. +// +// Explain statement +// +// Explain statement produces a recordset consisting of lines of text which +// describe the execution plan of a statement, if any. +// +// ExplainStmt = "EXPLAIN" Statement . +// +// For example, the QL tool treats the explain statement specially and outputs +// the joined lines: +// +// $ ql 'create table t(i int); create table u(j int)' +// $ ql 'explain select * from t, u where t.i > 42 && u.j < 314' +// ┌Compute Cartesian product of +// │ ┌Iterate all rows of table "t" +// │ └Output field names ["i"] +// │ ┌Iterate all rows of table "u" +// │ └Output field names ["j"] +// └Output field names ["t.i" "u.j"] +// ┌Filter on t.i > 42 && u.j < 314 +// │Possibly useful indices +// │CREATE INDEX xt_i ON t(i); +// │CREATE INDEX xu_j ON u(j); +// └Output field names ["t.i" "u.j"] +// $ ql 'CREATE INDEX xt_i ON t(i); CREATE INDEX xu_j ON u(j);' +// $ ql 'explain select * from t, u where t.i > 42 && u.j < 314' +// ┌Compute Cartesian product of +// │ ┌Iterate all rows of table "t" using index "xt_i" where i > 42 +// │ └Output field names ["i"] +// │ ┌Iterate all rows of table "u" using index "xu_j" where j < 314 +// │ └Output field names ["j"] +// └Output field names ["t.i" "u.j"] +// $ ql 'explain select * from t where i > 12 and i between 10 and 20 and i < 42' +// ┌Iterate all rows of table "t" using index "xt_i" where i > 12 && i <= 20 +// └Output field names ["i"] +// $ +// +// The explanation may aid in uderstanding how a statement/query would be +// executed and if indices are used as expected - or which indices may possibly +// improve the statement performance. The create index statements above were +// directly copy/pasted in the terminal from the suggestions provided by the +// filter recordset pipeline part returned by the explain statement. +// +// If the statement has nothing special in its plan, the result is the original +// statement. +// +// $ ql 'explain delete from t where 42 < i' +// DELETE FROM t WHERE i > 42; +// $ +// +// To get an explanation of the select statement of the IN predicate, use the EXPLAIN +// statement with that particular select statement. +// +// $ ql 'explain select * from t where i in (select j from u where j > 0)' +// ┌Iterate all rows of table "t" +// └Output field names ["i"] +// ┌Filter on i IN (SELECT j FROM u WHERE j > 0;) +// └Output field names ["i"] +// $ ql 'explain select j from u where j > 0' +// ┌Iterate all rows of table "u" using index "xu_j" where j > 0 +// └Output field names ["j"] +// $ +// +// ROLLBACK +// +// The rollback statement closes the innermost transaction nesting level +// discarding any updates to the DB made by it. If that's the outermost level +// then the effects on the DB are as if the transaction never happened. +// +// RollbackStmt = "ROLLBACK" . +// +// For example +// +// // First statement list +// BEGIN TRANSACTION +// SELECT * INTO tmp FROM foo; +// INSERT INTO tmp SELECT * from bar; +// SELECT * from tmp; +// +// The (temporary) record set from the last statement is returned and can be +// processed by the client. +// +// // Second statement list +// ROLLBACK; +// +// In this case the rollback is the same as 'DROP TABLE tmp;' but it can be a +// more complex operation. +// +// SELECT FROM +// +// Select from statements produce recordsets. The optional DISTINCT modifier +// ensures all rows in the result recordset are unique. Either all of the +// resulting fields are returned ('*') or only those named in FieldList. +// +// RecordSetList is a list of table names or parenthesized select statements, +// optionally (re)named using the AS clause. +// +// The result can be filtered using a WhereClause and orderd by the OrderBy +// clause. +// +// SelectStmt = "SELECT" [ "DISTINCT" ] ( "*" | FieldList ) "FROM" RecordSetList +// [ JoinClause ] [ WhereClause ] [ GroupByClause ] [ OrderBy ] [ Limit ] [ Offset ]. +// +// JoinClause = ( "LEFT" | "RIGHT" | "FULL" ) [ "OUTER" ] "JOIN" RecordSet "ON" Expression . +// +// RecordSet = ( TableName | "(" SelectStmt [ ";" ] ")" ) [ "AS" identifier ] . +// RecordSetList = RecordSet { "," RecordSet } [ "," ] . +// +// For example +// +// SELECT * FROM Stock; +// +// SELECT DepartmentID +// FROM department +// WHERE DepartmentID == 42 +// ORDER BY DepartmentName; +// +// SELECT employee.LastName +// FROM department, employee +// WHERE department.DepartmentID == employee.DepartmentID +// ORDER BY DepartmentID; +// +// If Recordset is a nested, parenthesized SelectStmt then it must be given a +// name using the AS clause if its field are to be accessible in expressions. +// +// SELECT a.b, c.d +// FROM +// x AS a, +// ( +// SELECT * FROM y; +// ) AS c +// WHERE a.e > c.e; +// +// Fields naming rules +// +// A field is an named expression. Identifiers, not used as a type in +// conversion or a function name in the Call clause, denote names of (other) +// fields, values of which should be used in the expression. +// +// Field = Expression [ "AS" identifier ] . +// +// The expression can be named using the AS clause. If the AS clause is not +// present and the expression consists solely of a field name, then that field +// name is used as the name of the resulting field. Otherwise the field is +// unnamed. +// +// For example +// +// SELECT 314, 42 as AUQLUE, DepartmentID, DepartmentID+1000, LastName as Name from employee; +// // Fields are []string{"", "AUQLUE", "DepartmentID", "", "Name"} +// +// The SELECT statement can optionally enumerate the desired/resulting fields +// in a list. +// +// FieldList = Field { "," Field } [ "," ] . +// +// No two identical field names can appear in the list. +// +// SELECT DepartmentID, LastName, DepartmentID from employee; +// // duplicate field name "DepartmentID" +// +// SELECT DepartmentID, LastName, DepartmentID as ID2 from employee; +// // works +// +// When more than one record set is used in the FROM clause record set list, +// the result record set field names are rewritten to be qualified using +// the record set names. +// +// SELECT * FROM employee, department; +// // Fields are []string{"employee.LastName", "employee.DepartmentID", "department.DepartmentID", "department.DepartmentName" +// +// If a particular record set doesn't have a name, its respective fields became +// unnamed. +// +// SELECT * FROM employee as e, ( SELECT * FROM department); +// // Fields are []string{"e.LastName", "e.DepartmentID", "", "" +// +// SELECT * FROM employee AS e, ( SELECT * FROM department) AS d; +// // Fields are []string{"e.LastName", "e.DepartmentID", "d.DepartmentID", "d.DepartmentName" +// +// Outer joins +// +// The optional JOIN clause, for example +// +// SELECT * +// FROM a +// LEFT OUTER JOIN b ON expr; +// +// is mostly equal to +// +// SELECT * +// FROM a, b +// WHERE expr; +// +// except that the rows from a which, when they appear in the cross join, never +// made expr to evaluate to true, are combined with a virtual row from b, +// containing all nulls, and added to the result set. For the RIGHT JOIN +// variant the discussed rules are used for rows from b not satisfying expr == +// true and the virtual, all-null row "comes" from a. The FULL JOIN adds the +// respective rows which would be otherwise provided by the separate executions +// of the LEFT JOIN and RIGHT JOIN variants. For more thorough OUTER JOIN +// discussion please see the Wikipedia article at [10]. +// +// Recordset ordering +// +// Resultins rows of a SELECT statement can be optionally ordered by the ORDER +// BY clause. Collating proceeds by considering the expressions in the +// expression list left to right until a collating order is determined. Any +// possibly remaining expressions are not evaluated. +// +// OrderBy = "ORDER" "BY" ExpressionList [ "ASC" | "DESC" ] . +// +// All of the expression values must yield an ordered type or NULL. Ordered +// types are defined in "Comparison operators". Collating of elements having a +// NULL value is different compared to what the comparison operators yield in +// expression evaluation (NULL result instead of a boolean value). +// +// Below, T denotes a non NULL value of any QL type. +// +// NULL < T +// +// NULL collates before any non NULL value (is considered smaller than T). +// +// NULL == NULL +// +// Two NULLs have no collating order (are considered equal). +// +// Recordset filtering +// +// The WHERE clause restricts records considered by some statements, like +// SELECT FROM, DELETE FROM, or UPDATE. +// +// expression value consider the record +// ---------------- ------------------- +// true yes +// false or NULL no +// +// It is an error if the expression evaluates to a non null value of non bool +// type. +// +// WhereClause = "WHERE" Expression . +// +// Recordset grouping +// +// The GROUP BY clause is used to project rows having common values into a +// smaller set of rows. +// +// For example +// +// SELECT Country, sum(Qty) FROM Sales GROUP BY Country; +// +// SELECT Country, Product FROM Sales GROUP BY Country, Product; +// +// SELECT DISTINCT Country, Product FROM Sales; +// +// Using the GROUP BY without any aggregate functions in the selected fields is +// in certain cases equal to using the DISTINCT modifier. The last two examples +// above produce the same resultsets. +// +// GroupByClause = "GROUP BY" ColumnNameList . +// +// Skipping records +// +// The optional OFFSET clause allows to ignore first N records. For example +// +// SELECT * FROM t OFFSET 10; +// +// The above will produce only rows 11, 12, ... of the record set, if they +// exist. The value of the expression must a non negative integer, but not +// bigint or duration. +// +// Offset = "OFFSET" Expression . +// +// Limiting the result set size +// +// The optional LIMIT clause allows to ignore all but first N records. For +// example +// +// SELECT * FROM t LIMIT 10; +// +// The above will return at most the first 10 records of the record set. The +// value of the expression must a non negative integer, but not bigint or +// duration. +// +// Limit = "Limit" Expression . +// +// The LIMIT and OFFSET clauses can be combined. For example +// +// SELECT * FROM t LIMIT 5 OFFSET 3; +// +// Considering table t has, say 10 records, the above will produce only records +// 4 - 8. +// +// #1: Ignore 1/3 +// #2: Ignore 2/3 +// #3: Ignore 3/3 +// #4: Return 1/5 +// #5: Return 2/5 +// #6: Return 3/5 +// #7: Return 4/5 +// #8: Return 5/5 +// +// After returning record #8, no more result rows/records are computed. +// +// Select statement evaluation order +// +// 1. The FROM clause is evaluated, producing a Cartesian product of its source +// record sets (tables or nested SELECT statements). +// +// 2. If present, the JOIN cluase is evaluated on the result set of the +// previous evaluation and the recordset specified by the JOIN clause. (... +// JOIN Recordset ON ...) +// +// 3. If present, the WHERE clause is evaluated on the result set of the +// previous evaluation. +// +// 4. If present, the GROUP BY clause is evaluated on the result set of the +// previous evaluation(s). +// +// 5. The SELECT field expressions are evaluated on the result set of the +// previous evaluation(s). +// +// 6. If present, the DISTINCT modifier is evaluated on the result set of the +// previous evaluation(s). +// +// 7. If present, the ORDER BY clause is evaluated on the result set of the +// previous evaluation(s). +// +// 8. If present, the OFFSET clause is evaluated on the result set of the +// previous evaluation(s). The offset expression is evaluated once for the +// first record produced by the previous evaluations. +// +// 9. If present, the LIMIT clause is evaluated on the result set of the +// previous evaluation(s). The limit expression is evaluated once for the first +// record produced by the previous evaluations. +// +// +// TRUNCATE TABLE +// +// Truncate table statements remove all records from a table. The table must +// exist. +// +// TruncateTableStmt = "TRUNCATE" "TABLE" TableName . +// +// For example +// +// BEGIN TRANSACTION +// TRUNCATE TABLE department; +// COMMIT; +// +// UPDATE +// +// Update statements change values of fields in rows of a table. +// +// UpdateStmt = "UPDATE" TableName [ "SET" ] AssignmentList [ WhereClause ] . +// +// AssignmentList = Assignment { "," Assignment } [ "," ] . +// Assignment = ColumnName "=" Expression . +// +// For example +// +// BEGIN TRANSACTION +// UPDATE department +// DepartmentName = DepartmentName + " dpt.", +// DepartmentID = 1000+DepartmentID, +// WHERE DepartmentID < 1000; +// COMMIT; +// +// Note: The SET clause is optional. +// +// If any of the columns of the table were defined using the optional +// constraints clause or the optional defaults clause then those are processed +// on a per row basis. The details are discussed in the "Constraints and +// defaults" chapter below the CREATE TABLE statement documentation. +// +// System Tables +// +// To allow to query for DB meta data, there exist specially named tables, some +// of them being virtual. +// +// Note: Virtual system tables may have fake table-wise unique but meaningless +// and unstable record IDs. Do not apply the built-in id() to any system table. +// +// Tables Table +// +// The table __Table lists all tables in the DB. The schema is +// +// CREATE TABLE __Table (Name string, Schema string); +// +// The Schema column returns the statement to (re)create table Name. This table +// is virtual. +// +// Columns Table +// +// The table __Colum lists all columns of all tables in the DB. The schema is +// +// CREATE TABLE __Column (TableName string, Ordinal int, Name string, Type string); +// +// The Ordinal column defines the 1-based index of the column in the record. +// This table is virtual. +// +// Columns2 Table +// +// The table __Colum2 lists all columns of all tables in the DB which have the +// constraint NOT NULL or which have a constraint expression defined or which +// have a default expression defined. The schema is +// +// CREATE TABLE __Column2 (TableName string, Name string, NotNull bool, ConstraintExpr string, DefaultExpr string) +// +// It's possible to obtain a consolidated recordset for all properties of all +// DB columns using +// +// SELECT +// __Column.TableName, __Column.Ordinal, __Column.Name, __Column.Type, +// __Column2.NotNull, __Column2.ConstraintExpr, __Column2.DefaultExpr, +// FROM __Column +// LEFT JOIN __Column2 +// ON __Column.TableName == __Column2.TableName && __Column.Name == __Column2.Name +// ORDER BY __Column.TableName, __Column.Ordinal; +// +// The Name column is the column name in TableName. +// +// Indices table +// +// The table __Index lists all indices in the DB. The schema is +// +// CREATE TABLE __Index (TableName string, ColumnName string, Name string, IsUnique bool); +// +// The IsUnique columns reflects if the index was created using the optional +// UNIQUE clause. This table is virtual. +// +// Built-in functions +// +// Built-in functions are predeclared. +// +// Average +// +// The built-in aggregate function avg returns the average of values of an +// expression. Avg ignores NULL values, but returns NULL if all values of a +// column are NULL or if avg is applied to an empty record set. +// +// func avg(e numeric) typeof(e) +// +// The column values must be of a numeric type. +// +// SELECT salesperson, avg(sales) FROM salesforce GROUP BY salesperson; +// +// Contains +// +// The built-in function contains returns true if substr is within s. +// +// func contains(s, substr string) bool +// +// If any argument to contains is NULL the result is NULL. +// +// Count +// +// The built-in aggregate function count returns how many times an expression +// has a non NULL values or the number of rows in a record set. Note: count() +// returns 0 for an empty record set. +// +// func count() int // The number of rows in a record set. +// func count(*) int // Equivalent to count(). +// func count(e expression) int // The number of cases where the expression value is not NULL. +// +// For example +// +// SELECT count() FROM department; // # of rows +// +// SELECT count(*) FROM department; // # of rows +// +// SELECT count(DepartmentID) FROM department; // # of records with non NULL field DepartmentID +// +// SELECT count()-count(DepartmentID) FROM department; // # of records with NULL field DepartmentID +// +// SELECT count(foo+bar*3) AS y FROM t; // # of cases where 'foo+bar*3' is non NULL +// +// Date +// +// Date returns the time corresponding to +// +// yyyy-mm-dd hh:mm:ss + nsec nanoseconds +// +// in the appropriate zone for that time in the given location. +// +// The month, day, hour, min, sec, and nsec values may be outside their usual +// ranges and will be normalized during the conversion. For example, October 32 +// converts to November 1. +// +// A daylight savings time transition skips or repeats times. For example, in +// the United States, March 13, 2011 2:15am never occurred, while November 6, +// 2011 1:15am occurred twice. In such cases, the choice of time zone, and +// therefore the time, is not well-defined. Date returns a time that is correct +// in one of the two zones involved in the transition, but it does not +// guarantee which. +// +// func date(year, month, day, hour, min, sec, nsec int, loc string) time +// +// A location maps time instants to the zone in use at that time. Typically, +// the location represents the collection of time offsets in use in a +// geographical area, such as "CEST" and "CET" for central Europe. "local" +// represents the system's local time zone. "UTC" represents Universal +// Coordinated Time (UTC). +// +// The month specifies a month of the year (January = 1, ...). +// +// If any argument to date is NULL the result is NULL. +// +// Day +// +// The built-in function day returns the day of the month specified by t. +// +// func day(t time) int +// +// If the argument to day is NULL the result is NULL. +// +// Format time +// +// The built-in function formatTime returns a textual representation of the +// time value formatted according to layout, which defines the format by +// showing how the reference time, +// +// Mon Jan 2 15:04:05 -0700 MST 2006 +// +// would be displayed if it were the value; it serves as an example of the +// desired output. The same display rules will then be applied to the time +// value. +// +// func formatTime(t time, layout string) string +// +// If any argument to formatTime is NULL the result is NULL. +// +// NOTE: The string value of the time zone, like "CET" or "ACDT", is dependent +// on the time zone of the machine the function is run on. For example, if the +// t value is in "CET", but the machine is in "ACDT", instead of "CET" the +// result is "+0100". This is the same what Go (time.Time).String() returns and +// in fact formatTime directly calls t.String(). +// +// formatTime(date(2006, 1, 2, 15, 4, 5, 999999999, "CET")) +// +// returns +// +// 2006-01-02 15:04:05.999999999 +0100 CET +// +// on a machine in the CET time zone, but may return +// +// 2006-01-02 15:04:05.999999999 +0100 +0100 +// +// on a machine in the ACDT zone. The time value is in both cases the same so +// its ordering and comparing is correct. Only the display value can differ. +// +// Format numbers +// +// The built-in functions formatFloat and formatInt format numbers +// to strings using go's number format functions in the `strconv` package. For +// all three functions, only the first argument is mandatory. The default values +// of the rest are shown in the examples. If the first argument is NULL, the +// result is NULL. +// +// formatFloat(43.2[, 'g', -1, 64]) string +// +// returns +// +// "43.2" +// +// formatInt(-42[, 10]) string +// +// returns +// +// "-42" +// +// formatInt(uint32(42)[, 10]) string +// +// returns +// +// "42" +// +// Unlike the `strconv` equivalent, the formatInt function handles all integer +// types, both signed and unsigned. +// +// HasPrefix +// +// The built-in function hasPrefix tests whether the string s begins with prefix. +// +// func hasPrefix(s, prefix string) bool +// +// If any argument to hasPrefix is NULL the result is NULL. +// +// HasSuffix +// +// The built-in function hasSuffix tests whether the string s ends with suffix. +// +// func hasSuffix(s, suffix string) bool +// +// If any argument to hasSuffix is NULL the result is NULL. +// +// Hour +// +// The built-in function hour returns the hour within the day specified by t, +// in the range [0, 23]. +// +// func hour(t time) int +// +// If the argument to hour is NULL the result is NULL. +// +// Hours +// +// The built-in function hours returns the duration as a floating point number +// of hours. +// +// func hours(d duration) float +// +// If the argument to hours is NULL the result is NULL. +// +// Record id +// +// The built-in function id takes zero or one arguments. If no argument is +// provided, id() returns a table-unique automatically assigned numeric +// identifier of type int. Ids of deleted records are not reused unless the DB +// becomes completely empty (has no tables). +// +// func id() int +// +// For example +// +// SELECT id(), LastName +// FROM employee; +// +// If id() without arguments is called for a row which is not a table record +// then the result value is NULL. +// +// For example +// +// SELECT id(), e.LastName, e.DepartmentID, d.DepartmentID +// FROM +// employee AS e, +// department AS d, +// WHERE e.DepartmentID == d.DepartmentID; +// // Will always return NULL in first field. +// +// SELECT e.ID, e.LastName, e.DepartmentID, d.DepartmentID +// FROM +// (SELECT id() AS ID, LastName, DepartmentID FROM employee) AS e, +// department as d, +// WHERE e.DepartmentID == d.DepartmentID; +// // Will work. +// +// If id() has one argument it must be a table name of a table in a cross join. +// +// For example +// +// SELECT * +// FROM foo, bar +// WHERE bar.fooID == id(foo) +// ORDER BY id(foo); +// +// Length +// +// The built-in function len takes a string argument and returns the lentgh of +// the string in bytes. +// +// func len(s string) int +// +// The expression len(s) is constant if s is a string constant. +// +// If the argument to len is NULL the result is NULL. +// +// Maximum +// +// The built-in aggregate function max returns the largest value of an +// expression in a record set. Max ignores NULL values, but returns NULL if +// all values of a column are NULL or if max is applied to an empty record set. +// +// func max(e expression) typeof(e) // The largest value of the expression. +// +// The expression values must be of an ordered type. +// +// For example +// +// SELECT department, max(sales) FROM t GROUP BY department; +// +// Minimum +// +// The built-in aggregate function min returns the smallest value of an +// expression in a record set. Min ignores NULL values, but returns NULL if +// all values of a column are NULL or if min is applied to an empty record set. +// +// func min(e expression) typeof(e) // The smallest value of the expression. +// +// For example +// +// SELECT a, min(b) FROM t GROUP BY a; +// +// The column values must be of an ordered type. +// +// Minute +// +// The built-in function minute returns the minute offset within the hour +// specified by t, in the range [0, 59]. +// +// func minute(t time) int +// +// If the argument to minute is NULL the result is NULL. +// +// Minutes +// +// The built-in function minutes returns the duration as a floating point +// number of minutes. +// +// func minutes(d duration) float +// +// If the argument to minutes is NULL the result is NULL. +// +// Month +// +// The built-in function month returns the month of the year specified by t +// (January = 1, ...). +// +// func month(t time) int +// +// If the argument to month is NULL the result is NULL. +// +// Nanosecond +// +// The built-in function nanosecond returns the nanosecond offset within the +// second specified by t, in the range [0, 999999999]. +// +// func nanosecond(t time) int +// +// If the argument to nanosecond is NULL the result is NULL. +// +// Nanoseconds +// +// The built-in function nanoseconds returns the duration as an integer +// nanosecond count. +// +// func nanoseconds(d duration) float +// +// If the argument to nanoseconds is NULL the result is NULL. +// +// Now +// +// The built-in function now returns the current local time. +// +// func now() time +// +// Parse time +// +// The built-in function parseTime parses a formatted string and returns the +// time value it represents. The layout defines the format by showing how the +// reference time, +// +// Mon Jan 2 15:04:05 -0700 MST 2006 +// +// would be interpreted if it were the value; it serves as an example of the +// input format. The same interpretation will then be made to the input string. +// +// Elements omitted from the value are assumed to be zero or, when zero is +// impossible, one, so parsing "3:04pm" returns the time corresponding to Jan +// 1, year 0, 15:04:00 UTC (note that because the year is 0, this time is +// before the zero Time). Years must be in the range 0000..9999. The day of the +// week is checked for syntax but it is otherwise ignored. +// +// In the absence of a time zone indicator, parseTime returns a time in UTC. +// +// When parsing a time with a zone offset like -0700, if the offset corresponds +// to a time zone used by the current location, then parseTime uses that +// location and zone in the returned time. Otherwise it records the time as +// being in a fabricated location with time fixed at the given zone offset. +// +// When parsing a time with a zone abbreviation like MST, if the zone +// abbreviation has a defined offset in the current location, then that offset +// is used. The zone abbreviation "UTC" is recognized as UTC regardless of +// location. If the zone abbreviation is unknown, Parse records the time as +// being in a fabricated location with the given zone abbreviation and a zero +// offset. This choice means that such a time can be parses and reformatted +// with the same layout losslessly, but the exact instant used in the +// representation will differ by the actual zone offset. To avoid such +// problems, prefer time layouts that use a numeric zone offset. +// +// func parseTime(layout, value string) time +// +// If any argument to parseTime is NULL the result is NULL. +// +// Second +// +// The built-in function second returns the second offset within the minute +// specified by t, in the range [0, 59]. +// +// func second(t time) int +// +// If the argument to second is NULL the result is NULL. +// +// Seconds +// +// The built-in function seconds returns the duration as a floating point +// number of seconds. +// +// func seconds(d duration) float +// +// If the argument to seconds is NULL the result is NULL. +// +// Since +// +// The built-in function since returns the time elapsed since t. It is +// shorthand for now()-t. +// +// func since(t time) duration +// +// If the argument to since is NULL the result is NULL. +// +// Sum +// +// The built-in aggregate function sum returns the sum of values of an +// expression for all rows of a record set. Sum ignores NULL values, but +// returns NULL if all values of a column are NULL or if sum is applied to an +// empty record set. +// +// func sum(e expression) typeof(e) // The sum of the values of the expression. +// +// The column values must be of a numeric type. +// +// SELECT salesperson, sum(sales) FROM salesforce GROUP BY salesperson; +// +// Time in a specific zone +// +// The built-in function timeIn returns t with the location information set to +// loc. For discussion of the loc argument please see date(). +// +// func timeIn(t time, loc string) time +// +// If any argument to timeIn is NULL the result is NULL. +// +// Weekday +// +// The built-in function weekday returns the day of the week specified by t. +// Sunday == 0, Monday == 1, ... +// +// func weekday(t time) int +// +// If the argument to weekday is NULL the result is NULL. +// +// Year +// +// The built-in function year returns the year in which t occurs. +// +// func year(t time) int +// +// If the argument to year is NULL the result is NULL. +// +// Year day +// +// The built-in function yearDay returns the day of the year specified by t, in +// the range [1,365] for non-leap years, and [1,366] in leap years. +// +// func yearDay(t time) int +// +// If the argument to yearDay is NULL the result is NULL. +// +// Manipulating complex numbers +// +// Three functions assemble and disassemble complex numbers. The built-in +// function complex constructs a complex value from a floating-point real and +// imaginary part, while real and imag extract the real and imaginary parts of +// a complex value. +// +// complex(realPart, imaginaryPart floatT) complexT +// real(complexT) floatT +// imag(complexT) floatT +// +// The type of the arguments and return value correspond. For complex, the two +// arguments must be of the same floating-point type and the return type is the +// complex type with the corresponding floating-point constituents: complex64 +// for float32, complex128 for float64. The real and imag functions together +// form the inverse, so for a complex value z, z == complex(real(z), imag(z)). +// +// If the operands of these functions are all constants, the return value is a +// constant. +// +// complex(2, -2) // complex128 +// complex(1.0, -1.4) // complex128 +// float32(math.Cos(math.Pi/2)) // float32 +// complex(5, float32(-x)) // complex64 +// imag(b) // float64 +// real(complex(5, float32(-x))) // float32 +// +// If any argument to any of complex, real, imag functions is NULL the result +// is NULL. +// +// Size guarantees +// +// For the numeric types, the following sizes are guaranteed +// +// type size in bytes +// +// byte, uint8, int8 1 +// uint16, int16 2 +// uint32, int32, float32 4 +// uint, uint64, int, int64, float64, complex64 8 +// complex128 16 +// +// License +// +// Portions of this specification page are modifications based on work[2] +// created and shared by Google[3] and used according to terms described in the +// Creative Commons 3.0 Attribution License[4]. +// +// This specification is licensed under the Creative Commons Attribution 3.0 +// License, and code is licensed under a BSD license[5]. +// +// References +// +// Links from the above documentation +// +// [1]: http://golang.org/ref/spec#Notation +// [2]: http://golang.org/ref/spec +// [3]: http://code.google.com/policies.html +// [4]: http://creativecommons.org/licenses/by/3.0/ +// [5]: http://golang.org/LICENSE +// [6]: http://golang.org/pkg/regexp/#Regexp.MatchString +// [7]: http://developer.mimer.com/validator/sql-reserved-words.tml +// [8]: http://godoc.org/github.com/cznic/zappy +// [9]: http://www.w3schools.com/sql/sql_default.asp +// [10]: http://en.wikipedia.org/wiki/Join_(SQL)#Outer_join +// +// Implementation details +// +// This section is not part of the specification. +// +// Indices +// +// WARNING: The implementation of indices is new and it surely needs more time +// to become mature. +// +// Indices are used currently used only by the WHERE clause. The following +// expression patterns of 'WHERE expression' are recognized and trigger index +// use. +// +// - WHERE c // For bool typed indexed column c +// - WHERE !c // For bool typed indexed column c +// - WHERE c relOp constExpr // For indexed column c +// - WHERE c relOp parameter // For indexed column c +// - WHERE parameter relOp c // For indexed column c +// - WHERE constExpr relOp c // For indexed column c +// +// The relOp is one of the relation operators <, <=, ==, >=, >. For the +// equality operator both operands must be of comparable types. For all other +// operators both operands must be of ordered types. The constant expression is +// a compile time constant expression. Some constant folding is still a TODO. +// Parameter is a QL parameter ($1 etc.). +// +// Query rewriting +// +// Consider tables t and u, both with an indexed field f. The WHERE expression +// doesn't comply with the above simple detected cases. +// +// SELECT * FROM t, u WHERE t.f < x && u.f < y; +// +// However, such query is now automatically rewritten to +// +// SELECT * FROM +// (SELECT * FROM t WHERE f < x), +// (SELECT * FROM u WHERE f < y); +// +// which will use both of the indices. The impact of using the indices can be +// substantial (cf. BenchmarkCrossJoin*) if the resulting rows have low +// "selectivity", ie. only few rows from both tables are selected by the +// respective WHERE filtering. +// +// Note: Existing QL DBs can be used and indices can be added to them. However, +// once any indices are present in the DB, the old QL versions cannot work with +// such DB anymore. +// +// Benchmarks +// +// Running a benchmark with -v (-test.v) outputs information about the scale +// used to report records/s and a brief description of the benchmark. For +// example +// +// $ go test -run NONE -bench 'SelectMem.*1e[23]' -v +// PASS +// BenchmarkSelectMem1kBx1e2 50000 67680 ns/op 1477537.05 MB/s +// --- BENCH: BenchmarkSelectMem1kBx1e2 +// all_test.go:310: +// ============================================================= +// NOTE: All benchmarks report records/s as 1000000 bytes/s. +// ============================================================= +// all_test.go:321: Having a table of 100 records, each of size 1kB, measure the performance of +// SELECT * FROM t; +// +// BenchmarkSelectMem1kBx1e3 5000 634819 ns/op 1575251.01 MB/s +// --- BENCH: BenchmarkSelectMem1kBx1e3 +// all_test.go:321: Having a table of 1000 records, each of size 1kB, measure the performance of +// SELECT * FROM t; +// +// ok github.com/cznic/ql 7.496s +// $ +// +// Running the full suite of benchmarks takes a lot of time. Use the -timeout +// flag to avoid them being killed after the default time limit (10 minutes). +package ql diff --git a/vendor/github.com/cznic/ql/driver.go b/vendor/github.com/cznic/ql/driver.go new file mode 100644 index 00000000..b660e4cb --- /dev/null +++ b/vendor/github.com/cznic/ql/driver.go @@ -0,0 +1,523 @@ +// Copyright 2014 The ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// database/sql/driver + +package ql + +import ( + "bytes" + "database/sql" + "database/sql/driver" + "errors" + "fmt" + "io" + "math/big" + "os" + "path/filepath" + "strings" + "sync" + "time" +) + +var ( + _ driver.Conn = (*driverConn)(nil) + _ driver.Driver = (*sqlDriver)(nil) + _ driver.Execer = (*driverConn)(nil) + _ driver.Queryer = (*driverConn)(nil) + _ driver.Result = (*driverResult)(nil) + _ driver.Rows = (*driverRows)(nil) + _ driver.Stmt = (*driverStmt)(nil) + _ driver.Tx = (*driverConn)(nil) + + txBegin = MustCompile("BEGIN TRANSACTION;") + txCommit = MustCompile("COMMIT;") + txRollback = MustCompile("ROLLBACK;") + + errNoResult = errors.New("query statement does not produce a result set (no top level SELECT)") +) + +type errList []error + +func (e *errList) append(err error) { + if err != nil { + *e = append(*e, err) + } +} + +func (e errList) error() error { + if len(e) == 0 { + return nil + } + + return e +} + +func (e errList) Error() string { + a := make([]string, len(e)) + for i, v := range e { + a[i] = v.Error() + } + return strings.Join(a, "\n") +} + +func params(args []driver.Value) []interface{} { + r := make([]interface{}, len(args)) + for i, v := range args { + r[i] = interface{}(v) + } + return r +} + +var ( + fileDriver = &sqlDriver{dbs: map[string]*driverDB{}} + fileDriverOnce sync.Once + memDriver = &sqlDriver{isMem: true, dbs: map[string]*driverDB{}} + memDriverOnce sync.Once +) + +// RegisterDriver registers a QL database/sql/driver[0] named "ql". The name +// parameter of +// +// sql.Open("ql", name) +// +// is interpreted as a path name to a named DB file which will be created if +// not present. The underlying QL database data are persisted on db.Close(). +// RegisterDriver can be safely called multiple times, it'll register the +// driver only once. +// +// The name argument can be optionally prefixed by "file://". In that case the +// prefix is stripped before interpreting it as a file name. +// +// The name argument can be optionally prefixed by "memory://". In that case +// the prefix is stripped before interpreting it as a name of a memory-only, +// volatile DB. +// +// [0]: http://golang.org/pkg/database/sql/driver/ +func RegisterDriver() { + fileDriverOnce.Do(func() { sql.Register("ql", fileDriver) }) +} + +// RegisterMemDriver registers a QL memory database/sql/driver[0] named +// "ql-mem". The name parameter of +// +// sql.Open("ql-mem", name) +// +// is interpreted as an unique memory DB name which will be created if not +// present. The underlying QL memory database data are not persisted on +// db.Close(). RegisterMemDriver can be safely called multiple times, it'll +// register the driver only once. +// +// [0]: http://golang.org/pkg/database/sql/driver/ +func RegisterMemDriver() { + memDriverOnce.Do(func() { sql.Register("ql-mem", memDriver) }) +} + +type driverDB struct { + db *DB + name string + refcount int +} + +func newDriverDB(db *DB, name string) *driverDB { + return &driverDB{db: db, name: name, refcount: 1} +} + +// sqlDriver implements the interface required by database/sql/driver. +type sqlDriver struct { + dbs map[string]*driverDB + isMem bool + mu sync.Mutex +} + +func (d *sqlDriver) lock() func() { + d.mu.Lock() + return d.mu.Unlock +} + +// Open returns a new connection to the database. The name is a string in a +// driver-specific format. +// +// Open may return a cached connection (one previously closed), but doing so is +// unnecessary; the sql package maintains a pool of idle connections for +// efficient re-use. +// +// The returned connection is only used by one goroutine at a time. +func (d *sqlDriver) Open(name string) (driver.Conn, error) { + if d != fileDriver && d != memDriver { + return nil, fmt.Errorf("open: unexpected/unsupported instance of driver.Driver: %p", d) + } + + switch { + case d == fileDriver && strings.HasPrefix(name, "file://"): + name = name[len("file://"):] + case d == fileDriver && strings.HasPrefix(name, "memory://"): + d = memDriver + name = name[len("memory://"):] + } + name = filepath.Clean(name) + if name == "" || name == "." || name == string(os.PathSeparator) { + return nil, fmt.Errorf("invalid DB name %q", name) + } + + defer d.lock()() + db := d.dbs[name] + if db == nil { + var err error + var db0 *DB + switch d.isMem { + case true: + db0, err = OpenMem() + default: + db0, err = OpenFile(name, &Options{CanCreate: true}) + } + if err != nil { + return nil, err + } + + db = newDriverDB(db0, name) + d.dbs[name] = db + return newDriverConn(d, db), nil + } + + db.refcount++ + return newDriverConn(d, db), nil +} + +// driverConn is a connection to a database. It is not used concurrently by +// multiple goroutines. +// +// Conn is assumed to be stateful. +type driverConn struct { + ctx *TCtx + db *driverDB + driver *sqlDriver + stop map[*driverStmt]struct{} + tnl int +} + +func newDriverConn(d *sqlDriver, ddb *driverDB) driver.Conn { + r := &driverConn{ + db: ddb, + driver: d, + stop: map[*driverStmt]struct{}{}, + } + return r +} + +// Prepare returns a prepared statement, bound to this connection. +func (c *driverConn) Prepare(query string) (driver.Stmt, error) { + list, err := Compile(query) + if err != nil { + return nil, err + } + + s := &driverStmt{conn: c, stmt: list} + c.stop[s] = struct{}{} + return s, nil +} + +// Close invalidates and potentially stops any current prepared statements and +// transactions, marking this connection as no longer in use. +// +// Because the sql package maintains a free pool of connections and only calls +// Close when there's a surplus of idle connections, it shouldn't be necessary +// for drivers to do their own connection caching. +func (c *driverConn) Close() error { + var err errList + for s := range c.stop { + err.append(s.Close()) + } + defer c.driver.lock()() + dbs, name := c.driver.dbs, c.db.name + v := dbs[name] + v.refcount-- + if v.refcount == 0 { + err.append(c.db.db.Close()) + delete(dbs, name) + } + return err.error() +} + +// Begin starts and returns a new transaction. +func (c *driverConn) Begin() (driver.Tx, error) { + if c.ctx == nil { + c.ctx = NewRWCtx() + } + + if _, _, err := c.db.db.Execute(c.ctx, txBegin); err != nil { + return nil, err + } + + c.tnl++ + return c, nil +} + +func (c *driverConn) Commit() error { + if c.tnl == 0 || c.ctx == nil { + return errCommitNotInTransaction + } + + if _, _, err := c.db.db.Execute(c.ctx, txCommit); err != nil { + return err + } + + c.tnl-- + if c.tnl == 0 { + c.ctx = nil + } + return nil +} + +func (c *driverConn) Rollback() error { + if c.tnl == 0 || c.ctx == nil { + return errRollbackNotInTransaction + } + + if _, _, err := c.db.db.Execute(c.ctx, txRollback); err != nil { + return err + } + + c.tnl-- + if c.tnl == 0 { + c.ctx = nil + } + return nil +} + +// Execer is an optional interface that may be implemented by a Conn. +// +// If a Conn does not implement Execer, the sql package's DB.Exec will first +// prepare a query, execute the statement, and then close the statement. +// +// Exec may return driver.ErrSkip. +func (c *driverConn) Exec(query string, args []driver.Value) (driver.Result, error) { + list, err := Compile(query) + if err != nil { + return nil, err + } + + return driverExec(c.db, c.ctx, list, args) +} + +func driverExec(db *driverDB, ctx *TCtx, list List, args []driver.Value) (driver.Result, error) { + if _, _, err := db.db.Execute(ctx, list, params(args)...); err != nil { + return nil, err + } + + if len(list.l) == 1 { + switch list.l[0].(type) { + case *createTableStmt, *dropTableStmt, *alterTableAddStmt, + *alterTableDropColumnStmt, *truncateTableStmt: + return driver.ResultNoRows, nil + } + } + + r := &driverResult{} + if ctx != nil { + r.lastInsertID, r.rowsAffected = ctx.LastInsertID, ctx.RowsAffected + } + return r, nil +} + +// Queryer is an optional interface that may be implemented by a Conn. +// +// If a Conn does not implement Queryer, the sql package's DB.Query will first +// prepare a query, execute the statement, and then close the statement. +// +// Query may return driver.ErrSkip. +func (c *driverConn) Query(query string, args []driver.Value) (driver.Rows, error) { + list, err := Compile(query) + if err != nil { + return nil, err + } + + return driverQuery(c.db, c.ctx, list, args) +} + +func driverQuery(db *driverDB, ctx *TCtx, list List, args []driver.Value) (driver.Rows, error) { + rss, _, err := db.db.Execute(ctx, list, params(args)...) + if err != nil { + return nil, err + } + + switch n := len(rss); n { + case 0: + return nil, errNoResult + case 1: + return newdriverRows(rss[len(rss)-1]), nil + default: + return nil, fmt.Errorf("query produced %d result sets, expected only one", n) + } +} + +// driverResult is the result of a query execution. +type driverResult struct { + lastInsertID int64 + rowsAffected int64 +} + +// LastInsertId returns the database's auto-generated ID after, for example, an +// INSERT into a table with primary key. +func (r *driverResult) LastInsertId() (int64, error) { // -golint + return r.lastInsertID, nil +} + +// RowsAffected returns the number of rows affected by the query. +func (r *driverResult) RowsAffected() (int64, error) { + return r.rowsAffected, nil +} + +// driverRows is an iterator over an executed query's results. +type driverRows struct { + rs Recordset + done chan int + rows chan interface{} +} + +func newdriverRows(rs Recordset) *driverRows { + r := &driverRows{ + rs: rs, + done: make(chan int), + rows: make(chan interface{}, 500), + } + go func() { + err := io.EOF + if e := r.rs.Do(false, func(data []interface{}) (bool, error) { + select { + case r.rows <- data: + return true, nil + case <-r.done: + return false, nil + } + }); e != nil { + err = e + } + + select { + case r.rows <- err: + case <-r.done: + } + }() + return r +} + +// Columns returns the names of the columns. The number of columns of the +// result is inferred from the length of the slice. If a particular column +// name isn't known, an empty string should be returned for that entry. +func (r *driverRows) Columns() []string { + f, _ := r.rs.Fields() + return f +} + +// Close closes the rows iterator. +func (r *driverRows) Close() error { + close(r.done) + return nil +} + +// Next is called to populate the next row of data into the provided slice. The +// provided slice will be the same size as the Columns() are wide. +// +// The dest slice may be populated only with a driver Value type, but excluding +// string. All string values must be converted to []byte. +// +// Next should return io.EOF when there are no more rows. +func (r *driverRows) Next(dest []driver.Value) error { + select { + case rx := <-r.rows: + switch x := rx.(type) { + case error: + return x + case []interface{}: + if g, e := len(x), len(dest); g != e { + return fmt.Errorf("field count mismatch: got %d, need %d", g, e) + } + + for i, xi := range x { + switch v := xi.(type) { + case nil, int64, float64, bool, []byte, time.Time: + dest[i] = v + case complex64, complex128, *big.Int, *big.Rat: + var buf bytes.Buffer + fmt.Fprintf(&buf, "%v", v) + dest[i] = buf.Bytes() + case int8: + dest[i] = int64(v) + case int16: + dest[i] = int64(v) + case int32: + dest[i] = int64(v) + case int: + dest[i] = int64(v) + case uint8: + dest[i] = int64(v) + case uint16: + dest[i] = int64(v) + case uint32: + dest[i] = int64(v) + case uint64: + dest[i] = int64(v) + case uint: + dest[i] = int64(v) + case time.Duration: + dest[i] = int64(v) + case string: + dest[i] = []byte(v) + default: + return fmt.Errorf("internal error 004") + } + } + return nil + default: + return fmt.Errorf("internal error 005") + } + case <-r.done: + return io.EOF + } +} + +// driverStmt is a prepared statement. It is bound to a driverConn and not used +// by multiple goroutines concurrently. +type driverStmt struct { + conn *driverConn + stmt List +} + +// Close closes the statement. +// +// As of Go 1.1, a Stmt will not be closed if it's in use by any queries. +func (s *driverStmt) Close() error { + delete(s.conn.stop, s) + return nil +} + +// NumInput returns the number of placeholder parameters. +// +// If NumInput returns >= 0, the sql package will sanity check argument counts +// from callers and return errors to the caller before the statement's Exec or +// Query methods are called. +// +// NumInput may also return -1, if the driver doesn't know its number of +// placeholders. In that case, the sql package will not sanity check Exec or +// Query argument counts. +func (s *driverStmt) NumInput() int { + if x := s.stmt; len(x.l) == 1 { + return x.params + } + + return -1 +} + +// Exec executes a query that doesn't return rows, such as an INSERT or UPDATE. +func (s *driverStmt) Exec(args []driver.Value) (driver.Result, error) { + c := s.conn + return driverExec(c.db, c.ctx, s.stmt, args) +} + +// Exec executes a query that may return rows, such as a SELECT. +func (s *driverStmt) Query(args []driver.Value) (driver.Rows, error) { + c := s.conn + return driverQuery(c.db, c.ctx, s.stmt, args) +} diff --git a/vendor/github.com/cznic/ql/driver/driver.go b/vendor/github.com/cznic/ql/driver/driver.go new file mode 100644 index 00000000..557c70d8 --- /dev/null +++ b/vendor/github.com/cznic/ql/driver/driver.go @@ -0,0 +1,61 @@ +// Copyright 2014 The ql 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 driver registers a QL sql/driver named "ql" and a memory driver named "ql-mem". + +See also [0], [1] and [3]. + +Usage + +A skeleton program using ql/driver. + + package main + + import ( + "database/sql" + + _ "github.com/cznic/ql/driver" + ) + + func main() { + ... + // Disk file DB + db, err := sql.Open("ql", "ql.db") // [2] + // alternatively + db, err := sql.Open("ql", "file://ql.db") + + // and/or + + // RAM DB + mdb, err := sql.Open("ql-mem", "mem.db") + // alternatively + mdb, err := sql.Open("ql", "memory://mem.db") + if err != nil { + log.Fatal(err) + } + + // Use db/mdb here + ... + } + +This package exports nothing. + +Links + +Referenced from above: + + [0]: http://godoc.org/github.com/cznic/ql + [1]: http://golang.org/pkg/database/sql/ + [2]: http://golang.org/pkg/database/sql/#Open + [3]: http://golang.org/pkg/database/sql/driver +*/ +package driver + +import "github.com/cznic/ql" + +func init() { + ql.RegisterDriver() + ql.RegisterMemDriver() +} diff --git a/vendor/github.com/cznic/ql/errors.go b/vendor/github.com/cznic/ql/errors.go new file mode 100644 index 00000000..305414f4 --- /dev/null +++ b/vendor/github.com/cznic/ql/errors.go @@ -0,0 +1,18 @@ +// Copyright 2014 The ql 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 ql + +import ( + "errors" +) + +var ( + errBeginTransNoCtx = errors.New("BEGIN TRANSACTION: Must use R/W context, have nil") + errCommitNotInTransaction = errors.New("COMMIT: Not in transaction") + errDivByZero = errors.New("division by zero") + errIncompatibleDBFormat = errors.New("incompatible DB format") + errNoDataForHandle = errors.New("read: no data for handle") + errRollbackNotInTransaction = errors.New("ROLLBACK: Not in transaction") +) diff --git a/vendor/github.com/cznic/ql/etc.go b/vendor/github.com/cznic/ql/etc.go new file mode 100644 index 00000000..c2e1524a --- /dev/null +++ b/vendor/github.com/cznic/ql/etc.go @@ -0,0 +1,2805 @@ +// Copyright 2014 The ql 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 ql + +import ( + "bytes" + "fmt" + "io" + "math" + "math/big" + "strings" + "time" +) + +// QL types. +const ( + qBool = 0x62 // 'b' + qComplex64 = 0x63 // 'c' + qComplex128 = 0x64 // 'd' + qFloat32 = 0x66 // 'f' + qFloat64 = 0x67 // 'g', alias float + qInt8 = 0x69 // 'i' + qInt16 = 0x6a // 'j' + qInt32 = 0x6b // 'k' + qInt64 = 0x6c // 'l', alias int + qString = 0x73 // 's' + qUint8 = 0x75 // 'u', alias byte + qUint16 = 0x76 // 'v' + qUint32 = 0x77 // 'w' + qUint64 = 0x78 // 'x', alias uint + + qBigInt = 0x49 // 'I' + qBigRat = 0x52 // 'R' + qBlob = 0x42 // 'B' + qDuration = 0x44 // 'D' + qTime = 0x54 // 'T' +) + +var ( + type2Str = map[int]string{ + qBigInt: "bigint", + qBigRat: "bigrat", + qBlob: "blob", + qBool: "bool", + qComplex128: "complex128", + qComplex64: "complex64", + qDuration: "duration", + qFloat32: "float32", + qFloat64: "float64", + qInt16: "int16", + qInt32: "int32", + qInt64: "int64", + qInt8: "int8", + qString: "string", + qTime: "time", + qUint16: "uint16", + qUint32: "uint32", + qUint64: "uint64", + qUint8: "uint8", + } +) + +func typeStr(typ int) (r string) { + return type2Str[typ] +} + +func noEOF(err error) error { + if err == io.EOF { + err = nil + } + return err +} + +func runErr(err error) error { return fmt.Errorf("run time error: %s", err) } + +func invXOp(s, x interface{}) error { + return fmt.Errorf("invalid operation: %v[%v] (index of type %T)", s, x, x) +} + +func invSOp(s interface{}) error { + return fmt.Errorf("cannot slice %s (type %T)", s, s) +} + +func invNegX(x interface{}) error { + return fmt.Errorf("invalid string index %v (index must be non-negative)", x) +} + +func invNegLO(x interface{}) error { + return fmt.Errorf("invalid LIMIT or OFFSET value %v (must be non-negative)", x) +} + +func invSliceNegX(x interface{}) error { + return fmt.Errorf("invalid slice index %v (index must be non-negative)", x) +} + +func invBoundX(s string, x uint64) error { + return fmt.Errorf("invalid string index %d (out of bounds for %d-byte string)", x, len(s)) +} + +func invSliceBoundX(s string, x uint64) error { + return fmt.Errorf("invalid slice index %d (out of bounds for %d-byte string)", x, len(s)) +} + +func intExpr(x interface{}) (i int64, err error) { + switch x := x.(type) { + case idealInt: + if x < 0 { + return 0, invNegLO(x) + } + + return int64(x), nil + case idealRune: + if x < 0 { + return 0, invNegLO(x) + } + + return int64(x), nil + case idealUint: + if x < 0 { + return 0, invNegLO(x) + } + + return int64(x), nil + case int8: + if x < 0 { + return 0, invNegLO(x) + } + + return int64(x), nil + case int16: + if x < 0 { + return 0, invNegLO(x) + } + + return int64(x), nil + case int32: + if x < 0 { + return 0, invNegLO(x) + } + + return int64(x), nil + case int64: + if x < 0 { + return 0, invNegLO(x) + } + + return int64(x), nil + case uint8: + return int64(x), nil + case uint16: + return int64(x), nil + case uint32: + return int64(x), nil + case uint64: + return int64(x), nil + default: + return 0, fmt.Errorf("non-integer expression: %v (value of type %T)", x, x) + } +} + +func limOffExpr(x interface{}) (i uint64, err error) { + switch x := x.(type) { + case idealInt: + if x < 0 { + return 0, invNegLO(x) + } + + return uint64(x), nil + case idealRune: + if x < 0 { + return 0, invNegLO(x) + } + + return uint64(x), nil + case idealUint: + if x < 0 { + return 0, invNegLO(x) + } + + return uint64(x), nil + case int8: + if x < 0 { + return 0, invNegLO(x) + } + + return uint64(x), nil + case int16: + if x < 0 { + return 0, invNegLO(x) + } + + return uint64(x), nil + case int32: + if x < 0 { + return 0, invNegLO(x) + } + + return uint64(x), nil + case int64: + if x < 0 { + return 0, invNegLO(x) + } + + return uint64(x), nil + case uint8: + return uint64(x), nil + case uint16: + return uint64(x), nil + case uint32: + return uint64(x), nil + case uint64: + return uint64(x), nil + default: + return 0, fmt.Errorf("non-integer used in LIMIT or OFFSET: %v (value of type %T)", x, x) + } +} + +func indexExpr(s *string, x interface{}) (i uint64, err error) { + switch x := x.(type) { + case idealFloat: + if x < 0 { + return 0, invNegX(x) + } + + if s != nil && int(x) >= len(*s) { + return 0, invBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case idealInt: + if x < 0 { + return 0, invNegX(x) + } + + if s != nil && int64(x) >= int64(len(*s)) { + return 0, invBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case idealRune: + if x < 0 { + return 0, invNegX(x) + } + + if s != nil && int32(x) >= int32(len(*s)) { + return 0, invBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case idealUint: + if x < 0 { + return 0, invNegX(x) + } + + if s != nil && uint64(x) >= uint64(len(*s)) { + return 0, invBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case int8: + if x < 0 { + return 0, invNegX(x) + } + + if s != nil && int(x) >= len(*s) { + return 0, invBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case int16: + if x < 0 { + return 0, invNegX(x) + } + + if s != nil && int(x) >= len(*s) { + return 0, invBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case int32: + if x < 0 { + return 0, invNegX(x) + } + + if s != nil && int(x) >= len(*s) { + return 0, invBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case int64: + if x < 0 { + return 0, invNegX(x) + } + + if s != nil && x >= int64(len(*s)) { + return 0, invBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case uint8: + if s != nil && int(x) >= len(*s) { + return 0, invBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case uint16: + if s != nil && int(x) >= len(*s) { + return 0, invBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case uint32: + if s != nil && x >= uint32(len(*s)) { + return 0, invBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case uint64: + if s != nil && x >= uint64(len(*s)) { + return 0, invBoundX(*s, uint64(x)) + } + + return uint64(x), nil + default: + return 0, fmt.Errorf("non-integer string index %v (value of type %T)", x, x) + } +} + +func sliceExpr(s *string, x interface{}, mod int) (i uint64, err error) { + switch x := x.(type) { + case idealFloat: + if x < 0 { + return 0, invSliceNegX(x) + } + + if s != nil && int(x) >= len(*s)+mod { + return 0, invSliceBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case idealInt: + if x < 0 { + return 0, invSliceNegX(x) + } + + if s != nil && int64(x) >= int64(len(*s)+mod) { + return 0, invSliceBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case idealRune: + if x < 0 { + return 0, invSliceNegX(x) + } + + if s != nil && int32(x) >= int32(len(*s)+mod) { + return 0, invSliceBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case idealUint: + if x < 0 { + return 0, invSliceNegX(x) + } + + if s != nil && uint64(x) >= uint64(len(*s)+mod) { + return 0, invSliceBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case int8: + if x < 0 { + return 0, invSliceNegX(x) + } + + if s != nil && int(x) >= len(*s)+mod { + return 0, invSliceBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case int16: + if x < 0 { + return 0, invSliceNegX(x) + } + + if s != nil && int(x) >= len(*s)+mod { + return 0, invSliceBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case int32: + if x < 0 { + return 0, invSliceNegX(x) + } + + if s != nil && int(x) >= len(*s)+mod { + return 0, invSliceBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case int64: + if x < 0 { + return 0, invSliceNegX(x) + } + + if s != nil && x >= int64(len(*s)+mod) { + return 0, invSliceBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case uint8: + if s != nil && int(x) >= len(*s)+mod { + return 0, invSliceBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case uint16: + if s != nil && int(x) >= len(*s)+mod { + return 0, invSliceBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case uint32: + if s != nil && x >= uint32(len(*s)+mod) { + return 0, invSliceBoundX(*s, uint64(x)) + } + + return uint64(x), nil + case uint64: + if s != nil && x >= uint64(len(*s)+mod) { + return 0, invSliceBoundX(*s, uint64(x)) + } + + return uint64(x), nil + default: + return 0, fmt.Errorf("invalid slice index %s (type %T)", x, x) + } +} + +type iop int + +func (o iop) String() string { + switch i := int(o); i { + case andand: + return "&&" + case andnot: + return "&^" + case lsh: + return "<<" + case le: + return "<=" + case eq: + return "==" + case ge: + return ">=" + case neq: + return "!=" + case oror: + return "||" + case rsh: + return ">>" + default: + return string(i) + } +} + +func ideal(v interface{}) interface{} { + switch x := v.(type) { + case idealComplex: + return complex128(x) + case idealFloat: + return float64(x) + case idealInt: + return int64(x) + case idealRune: + return int64(x) + case idealUint: + return uint64(x) + default: + return v + } +} + +func eval(v expression, execCtx *execCtx, ctx map[interface{}]interface{}) (y interface{}) { + y, err := expand1(v.eval(execCtx, ctx)) + if err != nil { + panic(err) // panic ok here + } + return +} + +func eval2(a, b expression, execCtx *execCtx, ctx map[interface{}]interface{}) (x, y interface{}) { + return eval(a, execCtx, ctx), eval(b, execCtx, ctx) +} + +func invOp2(x, y interface{}, o int) (interface{}, error) { + return nil, fmt.Errorf("invalid operation: %v %v %v (mismatched types %T and %T)", x, iop(o), y, ideal(x), ideal(y)) +} + +func undOp(x interface{}, o int) (interface{}, error) { + return nil, fmt.Errorf("invalid operation: %v%v (operator %v not defined on %T)", iop(o), x, iop(o), x) +} + +func undOp2(x, y interface{}, o int) (interface{}, error) { + return nil, fmt.Errorf("invalid operation: %v %v %v (operator %v not defined on %T)", x, iop(o), y, iop(o), x) +} + +func invConv(val interface{}, typ int) (interface{}, error) { + return nil, fmt.Errorf("cannot convert %v (type %T) to type %s", val, val, typeStr(typ)) +} + +func truncConv(val interface{}) (interface{}, error) { + return nil, fmt.Errorf("constant %v truncated to integer", val) +} + +func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE + if val == nil { + return nil, nil + } + + switch typ { + case qBool: + switch x := val.(type) { + //case nil: + //case idealComplex: + //case idealFloat: + //case idealInt: + //case idealRune: + //case idealUint: + case bool: + return bool(x), nil + //case complex64: + //case complex128: + //case float32: + //case float64: + //case int8: + //case int16: + //case int32: + //case int64: + //case string: + //case uint8: + //case uint16: + //case uint32: + //case uint64: + default: + return invConv(val, typ) + } + case qComplex64: + switch x := val.(type) { + //case nil: + case idealComplex: + return complex64(x), nil + case idealFloat: + return complex(float32(x), 0), nil + case idealInt: + return complex(float32(x), 0), nil + case idealRune: + return complex(float32(x), 0), nil + case idealUint: + return complex(float32(x), 0), nil + //case bool: + case complex64: + return complex64(x), nil + case complex128: + return complex64(x), nil + //case float32: + //case float64: + //case int8: + //case int16: + //case int32: + //case int64: + //case string: + //case uint8: + //case uint16: + //case uint32: + //case uint64: + default: + return invConv(val, typ) + } + case qComplex128: + switch x := val.(type) { + //case nil: + case idealComplex: + return complex128(x), nil + case idealFloat: + return complex(float64(x), 0), nil + case idealInt: + return complex(float64(x), 0), nil + case idealRune: + return complex(float64(x), 0), nil + case idealUint: + return complex(float64(x), 0), nil + //case bool: + case complex64: + return complex128(x), nil + case complex128: + return complex128(x), nil + //case float32: + //case float64: + //case int8: + //case int16: + //case int32: + //case int64: + //case string: + //case uint8: + //case uint16: + //case uint32: + //case uint64: + default: + return invConv(val, typ) + } + case qFloat32: + switch x := val.(type) { + //case nil: + //case idealComplex: + case idealFloat: + return float32(x), nil + case idealInt: + return float32(x), nil + case idealRune: + return float32(x), nil + case idealUint: + return float32(x), nil + //case bool: + //case complex64: + //case complex128: + case float32: + return float32(x), nil + case float64: + return float32(x), nil + case int8: + return float32(x), nil + case int16: + return float32(x), nil + case int32: + return float32(x), nil + case int64: + return float32(x), nil + //case string: + case uint8: + return float32(x), nil + case uint16: + return float32(x), nil + case uint32: + return float32(x), nil + case uint64: + return float32(x), nil + case *big.Int: + v, _ := big.NewRat(1, 1).SetInt(x).Float64() + return float32(v), nil + case *big.Rat: + v, _ := x.Float64() + return float32(v), nil + case time.Duration: + return float32(x), nil + default: + return invConv(val, typ) + } + case qFloat64: + switch x := val.(type) { + //case nil: + //case idealComplex: + case idealFloat: + return float64(x), nil + case idealInt: + return float64(x), nil + case idealRune: + return float64(x), nil + case idealUint: + return float64(x), nil + //case bool: + //case complex64: + //case complex128: + case float32: + return float64(x), nil + case float64: + return float64(x), nil + case int8: + return float64(x), nil + case int16: + return float64(x), nil + case int32: + return float64(x), nil + case int64: + return float64(x), nil + //case string: + case uint8: + return float64(x), nil + case uint16: + return float64(x), nil + case uint32: + return float64(x), nil + case uint64: + return float64(x), nil + case *big.Int: + v, _ := big.NewRat(1, 1).SetInt(x).Float64() + return v, nil + case *big.Rat: + v, _ := x.Float64() + return v, nil + case time.Duration: + return float64(x), nil + default: + return invConv(val, typ) + } + case qInt8: + switch x := val.(type) { + //case nil: + //case idealComplex: + case idealFloat: + if _, frac := math.Modf(float64(x)); frac != 0 { + return truncConv(x) + } + + return int8(x), nil + case idealInt: + return int8(x), nil + case idealRune: + return int8(x), nil + case idealUint: + return int8(x), nil + //case bool: + //case complex64: + //case complex128: + case float32: + return int8(x), nil + case float64: + return int8(x), nil + case int8: + return int8(x), nil + case int16: + return int8(x), nil + case int32: + return int8(x), nil + case int64: + return int8(x), nil + //case string: + case uint8: + return int8(x), nil + case uint16: + return int8(x), nil + case uint32: + return int8(x), nil + case uint64: + return int8(x), nil + case *big.Int: + return int8(x.Int64()), nil + case time.Duration: + return int8(x), nil + default: + return invConv(val, typ) + } + case qInt16: + switch x := val.(type) { + //case nil: + //case idealComplex: + case idealFloat: + if _, frac := math.Modf(float64(x)); frac != 0 { + return truncConv(x) + } + + return int16(x), nil + case idealInt: + return int16(x), nil + case idealRune: + return int16(x), nil + case idealUint: + return int16(x), nil + //case bool: + //case complex64: + //case complex128: + case float32: + return int16(x), nil + case float64: + return int16(x), nil + case int8: + return int16(x), nil + case int16: + return int16(x), nil + case int32: + return int16(x), nil + case int64: + return int16(x), nil + //case string: + case uint8: + return int16(x), nil + case uint16: + return int16(x), nil + case uint32: + return int16(x), nil + case uint64: + return int16(x), nil + case *big.Int: + return int16(x.Int64()), nil + case time.Duration: + return int16(x), nil + default: + return invConv(val, typ) + } + case qInt32: + switch x := val.(type) { + //case nil: + //case idealComplex: + case idealFloat: + if _, frac := math.Modf(float64(x)); frac != 0 { + return truncConv(x) + } + + return int32(x), nil + case idealInt: + return int32(x), nil + case idealRune: + return int32(x), nil + case idealUint: + return int32(x), nil + //case bool: + //case complex64: + //case complex128: + case float32: + return int32(x), nil + case float64: + return int32(x), nil + case int8: + return int32(x), nil + case int16: + return int32(x), nil + case int32: + return int32(x), nil + case int64: + return int32(x), nil + //case string: + case uint8: + return int32(x), nil + case uint16: + return int32(x), nil + case uint32: + return int32(x), nil + case uint64: + return int32(x), nil + case *big.Int: + return int32(x.Int64()), nil + case time.Duration: + return int32(x), nil + default: + return invConv(val, typ) + } + case qInt64: + switch x := val.(type) { + //case nil: + //case idealComplex: + case idealFloat: + if _, frac := math.Modf(float64(x)); frac != 0 { + return truncConv(x) + } + + return int64(x), nil + case idealInt: + return int64(x), nil + case idealRune: + return int64(x), nil + case idealUint: + return int64(x), nil + //case bool: + //case complex64: + //case complex128: + case float32: + return int64(x), nil + case float64: + return int64(x), nil + case int8: + return int64(x), nil + case int16: + return int64(x), nil + case int32: + return int64(x), nil + case int64: + return int64(x), nil + //case string: + case uint8: + return int64(x), nil + case uint16: + return int64(x), nil + case uint32: + return int64(x), nil + case uint64: + return int64(x), nil + case *big.Int: + return x.Int64(), nil + case time.Duration: + return int64(x), nil + default: + return invConv(val, typ) + } + case qString: + switch x := val.(type) { + //case nil: + //case idealComplex: + //case idealFloat: + case idealInt: + return string(x), nil + case idealRune: + return string(x), nil + case idealUint: + return string(x), nil + //case bool: + //case complex64: + //case complex128: + //case float32: + //case float64: + case int8: + return string(x), nil + case int16: + return string(x), nil + case int32: + return string(x), nil + case int64: + return string(x), nil + case string: + return string(x), nil + case uint8: + return string(x), nil + case uint16: + return string(x), nil + case uint32: + return string(x), nil + case uint64: + return string(x), nil + case []byte: + return string(x), nil + case *big.Int: + return x.String(), nil + case time.Time: + return x.String(), nil + case time.Duration: + return x.String(), nil + default: + return invConv(val, typ) + } + case qUint8: + switch x := val.(type) { + //case nil: + //case idealComplex: + case idealFloat: + if _, frac := math.Modf(float64(x)); frac != 0 { + return truncConv(x) + } + + return uint8(x), nil + case idealInt: + return uint8(x), nil + case idealRune: + return uint8(x), nil + case idealUint: + return uint8(x), nil + //case bool: + //case complex64: + //case complex128: + case float32: + return uint8(x), nil + case float64: + return uint8(x), nil + case int8: + return uint8(x), nil + case int16: + return uint8(x), nil + case int32: + return uint8(x), nil + case int64: + return uint8(x), nil + //case string: + case uint8: + return uint8(x), nil + case uint16: + return uint8(x), nil + case uint32: + return uint8(x), nil + case uint64: + return uint8(x), nil + case *big.Int: + return uint8(x.Int64()), nil + case time.Duration: + return uint8(x), nil + default: + return invConv(val, typ) + } + case qUint16: + switch x := val.(type) { + //case nil: + //case idealComplex: + case idealFloat: + if _, frac := math.Modf(float64(x)); frac != 0 { + return truncConv(x) + } + + return uint16(x), nil + case idealInt: + return uint16(x), nil + case idealRune: + return uint16(x), nil + case idealUint: + return uint16(x), nil + //case bool: + //case complex64: + //case complex128: + case float32: + return uint16(x), nil + case float64: + return uint16(x), nil + case int8: + return uint16(x), nil + case int16: + return uint16(x), nil + case int32: + return uint16(x), nil + case int64: + return uint16(x), nil + //case string: + case uint8: + return uint16(x), nil + case uint16: + return uint16(x), nil + case uint32: + return uint16(x), nil + case uint64: + return uint16(x), nil + case *big.Int: + return uint16(x.Int64()), nil + case time.Duration: + return uint16(x), nil + default: + return invConv(val, typ) + } + case qUint32: + switch x := val.(type) { + //case nil: + //case idealComplex: + case idealFloat: + if _, frac := math.Modf(float64(x)); frac != 0 { + return truncConv(x) + } + + return uint32(x), nil + case idealInt: + return uint32(x), nil + case idealRune: + return uint32(x), nil + case idealUint: + return uint32(x), nil + //case bool: + //case complex64: + //case complex128: + case float32: + return uint32(x), nil + case float64: + return uint32(x), nil + case int8: + return uint32(x), nil + case int16: + return uint32(x), nil + case int32: + return uint32(x), nil + case int64: + return uint32(x), nil + //case string: + case uint8: + return uint32(x), nil + case uint16: + return uint32(x), nil + case uint32: + return uint32(x), nil + case uint64: + return uint32(x), nil + case *big.Int: + return uint32(x.Int64()), nil + case time.Duration: + return uint32(x), nil + default: + return invConv(val, typ) + } + case qUint64: + switch x := val.(type) { + //case nil: + //case idealComplex: + case idealFloat: + if _, frac := math.Modf(float64(x)); frac != 0 { + return truncConv(x) + } + + return uint64(x), nil + case idealInt: + return uint64(x), nil + case idealRune: + return uint64(x), nil + case idealUint: + return uint64(x), nil + //case bool: + //case complex64: + //case complex128: + case float32: + return uint64(x), nil + case float64: + return uint64(x), nil + case int8: + return uint64(x), nil + case int16: + return uint64(x), nil + case int32: + return uint64(x), nil + case int64: + return uint64(x), nil + //case string: + case uint8: + return uint64(x), nil + case uint16: + return uint64(x), nil + case uint32: + return uint64(x), nil + case uint64: + return uint64(x), nil + case *big.Int: + return x.Uint64(), nil + case time.Duration: + return uint64(x), nil + default: + return invConv(val, typ) + } + case qBlob: + switch x := val.(type) { + case string: + return []byte(x), nil + case []byte: + return x, nil + default: + return invConv(val, typ) + } + case qBigInt: + switch x := val.(type) { + // case blob + // case bool + //case idealComplex: + case idealFloat: + if _, frac := math.Modf(float64(x)); frac != 0 { + return truncConv(x) + } + + rr := big.NewRat(1, 1).SetFloat64(float64(x)) + ii := big.NewInt(0).Set(rr.Num()) + ii.Quo(ii, rr.Denom()) + return ii, nil + case idealInt: + return big.NewInt(0).SetInt64(int64(x)), nil + case idealRune: + return big.NewInt(0).SetInt64(int64(x)), nil + case idealUint: + return big.NewInt(0).SetUint64(uint64(x)), nil + //case complex64 + //case complex128 + case float32: + rr := big.NewRat(1, 1).SetFloat64(float64(x)) + ii := big.NewInt(0).Set(rr.Num()) + ii.Quo(ii, rr.Denom()) + return ii, nil + case float64: + rr := big.NewRat(1, 1).SetFloat64(float64(x)) + ii := big.NewInt(0).Set(rr.Num()) + ii.Quo(ii, rr.Denom()) + return ii, nil + case int8: + return big.NewInt(0).SetInt64(int64(x)), nil + case int16: + return big.NewInt(0).SetInt64(int64(x)), nil + case int32: + return big.NewInt(0).SetInt64(int64(x)), nil + case int64: + return big.NewInt(0).SetInt64(x), nil + case string: + y := big.NewInt(0) + if _, ok := y.SetString(x, 0); !ok { + return invConv(val, typ) + } + + return y, nil + case uint8: + return big.NewInt(0).SetUint64(uint64(x)), nil + case uint16: + return big.NewInt(0).SetUint64(uint64(x)), nil + case uint32: + return big.NewInt(0).SetUint64(uint64(x)), nil + case uint64: + return big.NewInt(0).SetUint64(x), nil + case *big.Int: + return x, nil + case *big.Rat: + ii := big.NewInt(0).Set(x.Num()) + ii.Div(ii, x.Denom()) + return ii, nil + default: + return invConv(val, typ) + } + case qBigRat: + switch x := val.(type) { + // case blob + // case bool + //case idealComplex: + case idealFloat: + return big.NewRat(1, 1).SetFloat64(float64(x)), nil + case idealInt: + return big.NewRat(1, 1).SetInt64(int64(x)), nil + case idealRune: + return big.NewRat(1, 1).SetInt64(int64(x)), nil + case idealUint: + return big.NewRat(1, 1).SetInt(big.NewInt(0).SetUint64(uint64(x))), nil + //case complex64 + //case complex128 + case float32: + return big.NewRat(1, 1).SetFloat64(float64(x)), nil + case float64: + return big.NewRat(1, 1).SetFloat64(x), nil + case int8: + return big.NewRat(1, 1).SetInt64(int64(x)), nil + case int16: + return big.NewRat(1, 1).SetInt64(int64(x)), nil + case int32: + return big.NewRat(1, 1).SetInt64(int64(x)), nil + case int64: + return big.NewRat(1, 1).SetInt64(x), nil + case string: + y := big.NewRat(1, 1) + if _, ok := y.SetString(x); !ok { + return invConv(val, typ) + } + + return y, nil + case uint8: + return big.NewRat(1, 1).SetInt64(int64(x)), nil + case uint16: + return big.NewRat(1, 1).SetInt64(int64(x)), nil + case uint32: + return big.NewRat(1, 1).SetInt64(int64(x)), nil + case uint64: + return big.NewRat(1, 1).SetInt(big.NewInt(0).SetUint64(x)), nil + case *big.Int: + return big.NewRat(1, 1).SetInt(x), nil + case *big.Rat: + return x, nil + default: + return invConv(val, typ) + } + case qDuration: + switch x := val.(type) { + // case blob + // case bool + //case idealComplex: + case idealFloat: + return time.Duration(x), nil + case idealInt: + return time.Duration(x), nil + case idealRune: + return time.Duration(x), nil + case idealUint: + return time.Duration(x), nil + //case complex64 + //case complex128 + case float32: + return time.Duration(x), nil + case float64: + return time.Duration(x), nil + case int8: + return time.Duration(x), nil + case int16: + return time.Duration(x), nil + case int32: + return time.Duration(x), nil + case int64: + return time.Duration(x), nil + case string: + return time.ParseDuration(x) + case uint8: + return time.Duration(x), nil + case uint16: + return time.Duration(x), nil + case uint32: + return time.Duration(x), nil + case uint64: + return time.Duration(x), nil + case *big.Int: + return time.Duration(x.Int64()), nil + case *big.Rat: + f, _ := x.Float64() + return time.Duration(f), nil + case time.Duration: + return x, nil + default: + return invConv(val, typ) + } + case qTime: + switch x := val.(type) { + // case blob + // case bool + //case idealComplex: + //case idealFloat: + //case idealInt: + //case idealRune: + //case idealUint: + //case complex64 + //case complex128 + //case float32: + //case float64: + //case int8: + //case int16: + //case int32: + //case int64: + //case string: + //case uint8: + //case uint16: + //case uint32: + //case uint64: + //case *big.Int: + //case *big.Rat: + //case time.Duration: + case time.Time: + return x, nil + default: + return invConv(val, typ) + } + default: + panic("internal error 006") + } +} + +func invShiftRHS(lhs, rhs interface{}) (interface{}, error) { + return nil, fmt.Errorf("invalid operation: %v << %v (shift count type %T, must be unsigned integer)", lhs, rhs, rhs) +} + +func invTruncInt(v interface{}) error { + return fmt.Errorf("constant %v truncated to integer", v) +} + +func overflow(v interface{}, typ int) error { + return fmt.Errorf("constant %v overflows %s", v, typeStr(typ)) +} + +func typeCheck1(val interface{}, c *col) (interface{}, error) { + rec := []interface{}{val} + c = c.clone() + c.index = 0 + if err := typeCheck(rec, []*col{c}); err != nil { + return nil, err + } + + return rec[0], nil +} + +func typeCheck(rec []interface{}, cols []*col) (err error) { + for _, c := range cols { + i := c.index + if v := rec[i]; !c.typeCheck(v) { + switch v.(type) { + case idealComplex: + y := complex128(v.(idealComplex)) + switch c.typ { + case qBool: + case qComplex64: + rec[i] = complex64(y) + continue + case qComplex128: + rec[i] = complex128(y) + continue + case qFloat32, qFloat64, qInt8, qInt16, qInt32, qInt64, qUint8, qUint16, qUint32, qUint64: + return fmt.Errorf("constant %v truncated to real", y) + } + case idealFloat: + y := float64(v.(idealFloat)) + switch c.typ { + case qBool: + case qComplex64: + rec[i] = complex(float32(y), 0) + continue + case qComplex128: + rec[i] = complex(float64(y), 0) + continue + case qFloat32: + rec[i] = float32(y) + continue + case qFloat64: + rec[i] = float64(y) + continue + case qInt8: + if math.Floor(y) != y { + return invTruncInt(y) + } + + if y < math.MinInt8 || y > math.MaxInt8 { + return overflow(y, c.typ) + } + + rec[i] = int8(y) + continue + case qInt16: + if math.Floor(y) != y { + return invTruncInt(y) + } + + if y < math.MinInt16 || y > math.MaxInt16 { + return overflow(y, c.typ) + } + + rec[i] = int16(y) + continue + case qInt32: + if math.Floor(y) != y { + return invTruncInt(y) + } + + if y < math.MinInt32 || y > math.MaxInt32 { + return overflow(y, c.typ) + } + + rec[i] = int32(y) + continue + case qInt64: + if math.Floor(y) != y { + return invTruncInt(y) + } + + if y < math.MinInt64 || y > math.MaxInt64 { + return overflow(y, c.typ) + } + + rec[i] = int64(y) + continue + case qString: + case qUint8: + if math.Floor(y) != y { + return invTruncInt(y) + } + + if y < 0 || y > math.MaxUint8 { + return overflow(y, c.typ) + } + + rec[i] = uint8(y) + continue + case qUint16: + if math.Floor(y) != y { + return invTruncInt(y) + } + + if y < 0 || y > math.MaxUint16 { + return overflow(y, c.typ) + } + + rec[i] = uint16(y) + continue + case qUint32: + if math.Floor(y) != y { + return invTruncInt(y) + } + + if y < 0 || y > math.MaxUint32 { + return overflow(y, c.typ) + } + + rec[i] = uint32(y) + continue + case qUint64: + if math.Floor(y) != y { + return invTruncInt(y) + } + + if y < 0 || y > math.MaxUint64 { + return overflow(y, c.typ) + } + + rec[i] = uint64(y) + continue + case qBigInt: + if math.Floor(y) != y { + return invTruncInt(y) + } + + rr := big.NewRat(1, 1).SetFloat64(y) + ii := big.NewInt(0) + ii.Set(rr.Num()) + ii.Quo(ii, rr.Denom()) + rec[i] = ii + continue + case qBigRat: + rec[i] = big.NewRat(1, 1).SetFloat64(y) + continue + } + case idealInt: + y := int64(v.(idealInt)) + switch c.typ { + case qBool: + case qComplex64: + rec[i] = complex(float32(y), 0) + continue + case qComplex128: + rec[i] = complex(float64(y), 0) + continue + case qFloat32: + rec[i] = float32(y) + continue + case qFloat64: + rec[i] = float64(y) + continue + case qInt8: + if y < math.MinInt8 || y > math.MaxInt8 { + return overflow(y, c.typ) + } + + rec[i] = int8(y) + continue + case qInt16: + if y < math.MinInt16 || y > math.MaxInt16 { + return overflow(y, c.typ) + } + + rec[i] = int16(y) + continue + case qInt32: + if y < math.MinInt32 || y > math.MaxInt32 { + return overflow(y, c.typ) + } + + rec[i] = int32(y) + continue + case qInt64: + if y < math.MinInt64 || y > math.MaxInt64 { + return overflow(y, c.typ) + } + + rec[i] = int64(y) + continue + case qString: + case qUint8: + if y < 0 || y > math.MaxUint8 { + return overflow(y, c.typ) + } + + rec[i] = uint8(y) + continue + case qUint16: + if y < 0 || y > math.MaxUint16 { + return overflow(y, c.typ) + } + + rec[i] = uint16(y) + continue + case qUint32: + if y < 0 || y > math.MaxUint32 { + return overflow(y, c.typ) + } + + rec[i] = uint32(y) + continue + case qUint64: + if y < 0 { + return overflow(y, c.typ) + } + + rec[i] = uint64(y) + continue + case qBigInt: + rec[i] = big.NewInt(y) + continue + case qBigRat: + rec[i] = big.NewRat(1, 1).SetInt64(y) + continue + } + case idealRune: + y := int64(v.(idealRune)) + switch c.typ { + case qBool: + case qComplex64: + rec[i] = complex(float32(y), 0) + continue + case qComplex128: + rec[i] = complex(float64(y), 0) + continue + case qFloat32: + rec[i] = float32(y) + continue + case qFloat64: + rec[i] = float64(y) + continue + case qInt8: + if y < math.MinInt8 || y > math.MaxInt8 { + return overflow(y, c.typ) + } + + rec[i] = int8(y) + continue + case qInt16: + if y < math.MinInt16 || y > math.MaxInt16 { + return overflow(y, c.typ) + } + + rec[i] = int16(y) + continue + case qInt32: + if y < math.MinInt32 || y > math.MaxInt32 { + return overflow(y, c.typ) + } + + rec[i] = int32(y) + continue + case qInt64: + if y < math.MinInt64 || y > math.MaxInt64 { + return overflow(y, c.typ) + } + + rec[i] = int64(y) + continue + case qString: + case qUint8: + if y < 0 || y > math.MaxUint8 { + return overflow(y, c.typ) + } + + rec[i] = uint8(y) + continue + case qUint16: + if y < 0 || y > math.MaxUint16 { + return overflow(y, c.typ) + } + + rec[i] = uint16(y) + continue + case qUint32: + if y < 0 { + return overflow(y, c.typ) + } + + rec[i] = uint32(y) + continue + case qUint64: + if y < 0 { + return overflow(y, c.typ) + } + + rec[i] = uint64(y) + continue + case qBigInt: + rec[i] = big.NewInt(y) + continue + case qBigRat: + rec[i] = big.NewRat(1, 1).SetInt64(y) + continue + } + case idealUint: + y := uint64(v.(idealUint)) + switch c.typ { + case qBool: + case qComplex64: + rec[i] = complex(float32(y), 0) + continue + case qComplex128: + rec[i] = complex(float64(y), 0) + continue + case qFloat32: + rec[i] = float32(y) + continue + case qFloat64: + rec[i] = float64(y) + continue + case qInt8: + if y > math.MaxInt8 { + return overflow(y, c.typ) + } + + rec[i] = int8(y) + continue + case qInt16: + if y > math.MaxInt16 { + return overflow(y, c.typ) + } + + rec[i] = int16(y) + continue + case qInt32: + if y > math.MaxInt32 { + return overflow(y, c.typ) + } + + rec[i] = int32(y) + continue + case qInt64: + if y > math.MaxInt64 { + return overflow(y, c.typ) + } + + rec[i] = int64(y) + continue + case qString: + rec[i] = string(y) + continue + case qUint8: + if y > math.MaxUint8 { + return overflow(y, c.typ) + } + + rec[i] = uint8(y) + continue + case qUint16: + if y > math.MaxUint16 { + return overflow(y, c.typ) + } + + rec[i] = uint16(y) + continue + case qUint32: + if y > math.MaxUint32 { + return overflow(y, c.typ) + } + + rec[i] = uint32(y) + continue + case qUint64: + rec[i] = uint64(y) + continue + case qBigInt: + rec[i] = big.NewInt(0).SetUint64(y) + continue + case qBigRat: + ii := big.NewInt(0).SetUint64(y) + rec[i] = big.NewRat(1, 1).SetInt(ii) + continue + } + } + return fmt.Errorf("cannot use %v (type %T) in assignment to, or comparison with, column %s (type %s)", v, ideal(v), c.name, typeStr(c.typ)) + } + } + return +} + +//TODO collate1 should return errors instead of panicing +func collate1(a, b interface{}) int { + switch x := a.(type) { + case nil: + if b != nil { + return -1 + } + + return 0 + case bool: + switch y := b.(type) { + case nil: + return 1 + case bool: + if !x && y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + default: + // Make bool collate before anything except nil and + // other bool for index seeking first non NULL value. + return -1 + } + case idealComplex: + switch y := b.(type) { + case nil: + return 1 + case idealComplex: + if x == y { + return 0 + } + + if real(x) < real(y) { + return -1 + } + + if real(x) > real(y) { + return 1 + } + + if imag(x) < imag(y) { + return -1 + } + + return 1 + case complex64: + { + x, y := complex64(x), complex64(y) + if x == y { + return 0 + } + + if real(x) < real(y) { + return -1 + } + + if real(x) > real(y) { + return 1 + } + + if imag(x) < imag(y) { + return -1 + } + + return 1 + } + case complex128: + { + x := complex128(x) + if x == y { + return 0 + } + + if real(x) < real(y) { + return -1 + } + + if real(x) > real(y) { + return 1 + } + + if imag(x) < imag(y) { + return -1 + } + + return 1 + } + default: + panic("internal error 012") + } + case idealUint: + switch y := b.(type) { + case nil: + return 1 + case idealUint: + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + case uint8: + { + x, y := uint64(x), uint64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case uint16: + { + x, y := uint64(x), uint64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case uint32: + { + x, y := uint64(x), uint64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case uint64: + { + x, y := uint64(x), uint64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case uint: + { + x, y := uint64(x), uint64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + default: + panic("internal error 013") + } + case idealRune: + switch y := b.(type) { + case nil: + return 1 + case idealRune: + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + case int8: + { + x, y := int64(x), int64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case int16: + { + x, y := int64(x), int64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case int32: + { + x, y := int64(x), int64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case int64: + { + x, y := int64(x), int64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case int: + { + x, y := int64(x), int64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + default: + panic("internal error 014") + } + case idealInt: + switch y := b.(type) { + case nil: + return 1 + case idealInt: + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + case int8: + { + x, y := int64(x), int64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case int16: + { + x, y := int64(x), int64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case int32: + { + x, y := int64(x), int64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case int64: + { + x, y := int64(x), int64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case int: + { + x, y := int64(x), int64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + default: + panic("internal error 015") + } + case idealFloat: + switch y := b.(type) { + case nil: + return 1 + case idealFloat: + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + case float32: + { + x, y := float64(x), float64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case float64: + { + x, y := float64(x), float64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + default: + panic("internal error 016") + } + case complex64: + switch y := b.(type) { + case nil: + return 1 + case complex64: + if x == y { + return 0 + } + + if real(x) < real(y) { + return -1 + } + + if real(x) > real(y) { + return 1 + } + + if imag(x) < imag(y) { + return -1 + } + + return 1 + case idealComplex: + { + x, y := complex64(x), complex64(y) + if x == y { + return 0 + } + + if real(x) < real(y) { + return -1 + } + + if real(x) > real(y) { + return 1 + } + + if imag(x) < imag(y) { + return -1 + } + + return 1 + } + default: + panic("internal error 017") + } + case complex128: + switch y := b.(type) { + case nil: + return 1 + case complex128: + if x == y { + return 0 + } + + if real(x) < real(y) { + return -1 + } + + if real(x) > real(y) { + return 1 + } + + if imag(x) < imag(y) { + return -1 + } + + return 1 + case idealComplex: + { + x, y := complex128(x), complex128(y) + if x == y { + return 0 + } + + if real(x) < real(y) { + return -1 + } + + if real(x) > real(y) { + return 1 + } + + if imag(x) < imag(y) { + return -1 + } + + return 1 + } + default: + panic("internal error 018") + } + case float32: + switch y := b.(type) { + case nil: + return 1 + case float32: + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + case idealFloat: + { + x, y := float32(x), float32(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + default: + panic("internal error 019") + } + case float64: + switch y := b.(type) { + case nil: + return 1 + case float64: + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + case idealFloat: + { + x, y := float64(x), float64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + default: + panic("internal error 020") + } + case int8: + switch y := b.(type) { + case nil: + return 1 + case int8: + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + case idealInt: + { + x, y := int64(x), int64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + default: + panic("internal error 021") + } + case int16: + switch y := b.(type) { + case nil: + return 1 + case int16: + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + case idealInt: + { + x, y := int64(x), int64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + default: + panic("internal error 022") + } + case int32: + switch y := b.(type) { + case nil: + return 1 + case int32: + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + case idealInt: + { + x, y := int64(x), int64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + default: + panic("internal error 023") + } + case int64: + switch y := b.(type) { + case nil: + return 1 + case int64: + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + case idealInt: + { + x, y := int64(x), int64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + default: + panic("internal error 024") + } + case uint8: + switch y := b.(type) { + case nil: + return 1 + case uint8: + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + case idealInt: + { + x, y := uint64(x), uint64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case idealUint: + { + x, y := uint64(x), uint64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + default: + panic("internal error 025") + } + case uint16: + switch y := b.(type) { + case nil: + return 1 + case uint16: + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + case idealInt: + { + x, y := uint64(x), uint64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case idealUint: + { + x, y := uint64(x), uint64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + default: + panic("internal error 026") + } + case uint32: + switch y := b.(type) { + case nil: + return 1 + case uint32: + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + case idealInt: + { + x, y := uint64(x), uint64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case idealUint: + { + x, y := uint64(x), uint64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + default: + panic("internal error 027") + } + case uint64: + switch y := b.(type) { + case nil: + return 1 + case uint64: + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + case idealInt: + { + x, y := uint64(x), uint64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + case idealUint: + { + x, y := uint64(x), uint64(y) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + } + default: + panic("internal error 028") + } + case string: + switch y := b.(type) { + case nil: + return 1 + case string: + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + default: + panic("internal error 029") + } + case []byte: + switch y := b.(type) { + case nil: + return 1 + case []byte: + return bytes.Compare(x, y) + default: + panic("internal error 030") + } + case *big.Int: + switch y := b.(type) { + case nil: + return 1 + case *big.Int: + return x.Cmp(y) + case idealInt: + { + y := big.NewInt(int64(y)) + return x.Cmp(y) + } + case idealUint: + { + u := big.NewInt(0) + u.SetUint64(uint64(y)) + return x.Cmp(u) + } + default: + panic("internal error 031") + } + case *big.Rat: + switch y := b.(type) { + case nil: + return 1 + case *big.Rat: + return x.Cmp(y) + case idealInt: + { + y := big.NewRat(int64(y), 1) + return x.Cmp(y) + } + case idealUint: + { + u := big.NewInt(0) + u.SetUint64(uint64(y)) + var y big.Rat + y.SetInt(u) + return x.Cmp(&y) + } + default: + panic("internal error 032") + } + case time.Time: + switch y := b.(type) { + case nil: + return 1 + case time.Time: + if x.Before(y) { + return -1 + } + + if x.Equal(y) { + return 0 + } + + return 1 + default: + panic("internal error 033") + } + case time.Duration: + switch y := b.(type) { + case nil: + return 1 + case time.Duration: + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + default: + panic("internal error 034") + } + case chunk: + switch y := b.(type) { + case nil: + return 1 + case chunk: + a, err := x.expand() + if err != nil { + panic(err) + } + + b, err := y.expand() + if err != nil { + panic(err) + } + + return collate1(a, b) + default: + panic("internal error 035") + } + default: + //dbg("%T(%v) %T(%v)", a, a, b, b) + panic("internal error 036") + } +} + +//TODO collate should return errors from collate1 +func collate(x, y []interface{}) (r int) { + //defer func() { dbg("%v %v -> %v", x, y, r) }() + nx, ny := len(x), len(y) + + switch { + case nx == 0 && ny != 0: + return -1 + case nx == 0 && ny == 0: + return 0 + case nx != 0 && ny == 0: + return 1 + } + + r = 1 + if nx > ny { + x, y, r = y, x, -r + } + + for i, xi := range x { + if c := collate1(xi, y[i]); c != 0 { + return c * r + } + } + + if nx == ny { + return 0 + } + + return -r +} + +var collators = map[bool]func(a, b []interface{}) int{false: collateDesc, true: collate} + +func collateDesc(a, b []interface{}) int { + return -collate(a, b) +} + +func isOrderedType(v interface{}) (y interface{}, r bool, err error) { + //dbg("====") + //dbg("%T(%v)", v, v) + //defer func() { dbg("%T(%v)", y, y) }() + switch x := v.(type) { + case idealFloat, idealInt, idealRune, idealUint, + float32, float64, + int8, int16, int32, int64, + uint8, uint16, uint32, uint64, + string: + return v, true, nil + case *big.Int, *big.Rat, time.Time, time.Duration: + return x, true, nil + case chunk: + if y, err = x.expand(); err != nil { + return + } + + return isOrderedType(y) + } + + return v, false, nil +} + +var isSystemName = map[string]bool{ + "__Column": true, + "__Column2": true, + "__Index": true, + "__Index2": true, + "__Index2_Column": true, + "__Index2_Expr": true, + "__Table": true, +} + +func qualifier(s string) string { + if pos := strings.IndexByte(s, '.'); pos >= 0 { + s = s[:pos] + } + return s +} + +func mustQualifier(s string) string { + q := qualifier(s) + if q == s { + panic("internal error 068") + } + + return q +} + +func selector(s string) string { + if pos := strings.IndexByte(s, '.'); pos >= 0 { + s = s[pos+1:] + } + return s +} + +func mustSelector(s string) string { + q := selector(s) + if q == s { + panic("internal error 053") + } + + return q +} + +func qnames(l []string) []string { + r := make([]string, len(l)) + for i, v := range l { + r[i] = fmt.Sprintf("%q", v) + } + return r +} diff --git a/vendor/github.com/cznic/ql/expr.go b/vendor/github.com/cznic/ql/expr.go new file mode 100644 index 00000000..f0e53af4 --- /dev/null +++ b/vendor/github.com/cznic/ql/expr.go @@ -0,0 +1,4025 @@ +// Copyright 2014 The ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found pIn the LICENSE file. + +package ql + +import ( + "fmt" + "math/big" + "regexp" + "strings" + "time" +) + +var ( + _ expression = (*binaryOperation)(nil) + _ expression = (*call)(nil) + _ expression = (*conversion)(nil) + _ expression = (*ident)(nil) + _ expression = (*indexOp)(nil) + _ expression = (*isNull)(nil) + _ expression = (*pIn)(nil) + _ expression = (*pLike)(nil) + _ expression = (*parameter)(nil) + _ expression = (*pexpr)(nil) + _ expression = (*slice)(nil) + _ expression = (*unaryOperation)(nil) + _ expression = value{} +) + +type expression interface { + clone(arg []interface{}, unqualify ...string) (expression, error) + eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) + isStatic() bool + String() string +} + +func cloneExpressionList(arg []interface{}, list []expression, unqualify ...string) ([]expression, error) { + r := make([]expression, len(list)) + var err error + for i, v := range list { + if r[i], err = v.clone(arg, unqualify...); err != nil { + return nil, err + } + } + return r, nil +} + +func isConstValue(v interface{}) interface{} { + switch x := v.(type) { + case value: + return x.val + case + idealComplex, + idealFloat, + idealInt, + idealRune, + idealUint: + return v + default: + return nil + } +} + +func isColumnExpression(v expression) (bool, string) { + x, ok := v.(*ident) + if ok { + return true, x.s + } + + c, ok := v.(*call) + if !ok || c.f != "id" || len(c.arg) != 0 { + return false, "" + } + + return true, "id()" +} + +func mentionedColumns0(e expression, q, nq bool, m map[string]struct{}) { + switch x := e.(type) { + case parameter, + value: + // nop + case *binaryOperation: + mentionedColumns0(x.l, q, nq, m) + mentionedColumns0(x.r, q, nq, m) + case *call: + if x.f != "id" { + for _, e := range x.arg { + mentionedColumns0(e, q, nq, m) + } + } + case *conversion: + mentionedColumns0(x.val, q, nq, m) + case *ident: + if q && x.isQualified() { + m[x.s] = struct{}{} + } + if nq && !x.isQualified() { + m[x.s] = struct{}{} + } + case *indexOp: + mentionedColumns0(x.expr, q, nq, m) + mentionedColumns0(x.x, q, nq, m) + case *isNull: + mentionedColumns0(x.expr, q, nq, m) + case *pexpr: + mentionedColumns0(x.expr, q, nq, m) + case *pIn: + mentionedColumns0(x.expr, q, nq, m) + for _, e := range x.list { + mentionedColumns0(e, q, nq, m) + } + case *pLike: + mentionedColumns0(x.expr, q, nq, m) + mentionedColumns0(x.pattern, q, nq, m) + case *slice: + mentionedColumns0(x.expr, q, nq, m) + if y := x.lo; y != nil { + mentionedColumns0(*y, q, nq, m) + } + if y := x.hi; y != nil { + mentionedColumns0(*y, q, nq, m) + } + case *unaryOperation: + mentionedColumns0(x.v, q, nq, m) + default: + panic("internal error 052") + } +} + +func mentionedColumns(e expression) map[string]struct{} { + m := map[string]struct{}{} + mentionedColumns0(e, false, true, m) + return m +} + +func mentionedQColumns(e expression) map[string]struct{} { + m := map[string]struct{}{} + mentionedColumns0(e, true, false, m) + return m +} + +func staticExpr(e expression) (expression, error) { + if e.isStatic() { + v, err := e.eval(nil, nil) + if err != nil { + return nil, err + } + + if v == nil { + return value{nil}, nil + } + + return value{v}, nil + } + + return e, nil +} + +type ( + idealComplex complex128 + idealFloat float64 + idealInt int64 + idealRune int32 + idealUint uint64 +) + +type exprTab struct { + expr expression + table string +} + +type pexpr struct { + expr expression +} + +func (p *pexpr) clone(arg []interface{}, unqualify ...string) (expression, error) { + expr, err := p.expr.clone(arg, unqualify...) + if err != nil { + return nil, err + } + + return &pexpr{expr: expr}, nil +} + +func (p *pexpr) isStatic() bool { return p.expr.isStatic() } + +func (p *pexpr) String() string { + return fmt.Sprintf("(%s)", p.expr) +} + +func (p *pexpr) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) { + return p.expr.eval(execCtx, ctx) +} + +//DONE newBetween +//LATER like newBetween, check all others have and use new* + +func newBetween(expr, lo, hi interface{}, not bool) (expression, error) { + e, err := staticExpr(expr.(expression)) + if err != nil { + return nil, err + } + + l, err := staticExpr(lo.(expression)) + if err != nil { + return nil, err + } + + h, err := staticExpr(hi.(expression)) + if err != nil { + return nil, err + } + + var a, b expression + op := andand + switch { + case not: // e < l || e > h + op = oror + if a, err = newBinaryOperation('<', e, l); err != nil { + return nil, err + } + + if b, err = newBinaryOperation('>', e, h); err != nil { + return nil, err + } + default: // e >= l && e <= h + if a, err = newBinaryOperation(ge, e, l); err != nil { + return nil, err + } + + if b, err = newBinaryOperation(le, e, h); err != nil { + return nil, err + } + } + + if a, err = staticExpr(a); err != nil { + return nil, err + } + + if b, err = staticExpr(b); err != nil { + return nil, err + } + + ret, err := newBinaryOperation(op, a, b) + if err != nil { + return nil, err + } + + return staticExpr(ret) +} + +type pLike struct { + expr expression + pattern expression + re *regexp.Regexp + sexpr *string +} + +func (p *pLike) clone(arg []interface{}, unqualify ...string) (expression, error) { + expr, err := p.expr.clone(arg, unqualify...) + if err != nil { + return nil, err + } + + pattern, err := p.pattern.clone(arg, unqualify...) + if err != nil { + return nil, err + } + + return &pLike{ + expr: expr, + pattern: pattern, + re: p.re, + sexpr: p.sexpr, + }, nil +} + +func (p *pLike) isStatic() bool { return p.expr.isStatic() && p.pattern.isStatic() } +func (p *pLike) String() string { return fmt.Sprintf("%s LIKE %s", p.expr, p.pattern) } + +func (p *pLike) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) { + var sexpr string + var ok bool + switch { + case p.sexpr != nil: + sexpr = *p.sexpr + default: + expr, err := expand1(p.expr.eval(execCtx, ctx)) + if err != nil { + return nil, err + } + + if expr == nil { + return nil, nil + } + + sexpr, ok = expr.(string) + if !ok { + return nil, fmt.Errorf("non-string expression in LIKE: %v (value of type %T)", expr, expr) + } + + if p.expr.isStatic() { + p.sexpr = new(string) + *p.sexpr = sexpr + } + } + + re := p.re + if re == nil { + pattern, err := expand1(p.pattern.eval(execCtx, ctx)) + if err != nil { + return nil, err + } + + if pattern == nil { + return nil, nil + } + + spattern, ok := pattern.(string) + if !ok { + return nil, fmt.Errorf("non-string pattern in LIKE: %v (value of type %T)", pattern, pattern) + } + + if re, err = regexp.Compile(spattern); err != nil { + return nil, err + } + + if p.pattern.isStatic() { + p.re = re + } + } + + return re.MatchString(sexpr), nil +} + +type binaryOperation struct { + op int + l, r expression +} + +func newBinaryOperation0(op int, x, y interface{}) (v expression, err error) { + if op == eq { + if l, ok := x.(value); ok { + if b, ok := l.val.(bool); ok { + if b { // true == y: y + return y.(expression), nil + } + + // false == y: !y + return newUnaryOperation('!', y) + } + } + + if r, ok := y.(value); ok { + if b, ok := r.val.(bool); ok { + if b { // x == true: x + return x.(expression), nil + } + + // x == false: !x + return newUnaryOperation('!', x) + } + } + } + + if op == neq { + if l, ok := x.(value); ok { + if b, ok := l.val.(bool); ok { + if b { // true != y: !y + return newUnaryOperation('!', y) + } + + // false != y: y + return y.(expression), nil + } + } + + if r, ok := y.(value); ok { + if b, ok := r.val.(bool); ok { + if b { // x != true: !x + return newUnaryOperation('!', x) + } + + // x != false: x + return x.(expression), nil + } + } + } + + b := binaryOperation{op, x.(expression), y.(expression)} + var lv interface{} + if e := b.l; e.isStatic() { + if lv, err = e.eval(nil, nil); err != nil { + return nil, err + } + + b.l = value{lv} + } + + if e := b.r; e.isStatic() { + v, err := e.eval(nil, nil) + if err != nil { + return nil, err + } + + if v == nil { + return value{nil}, nil + } + + if op == '/' || op == '%' { + rb := binaryOperation{eq, e, value{idealInt(0)}} + val, err := rb.eval(nil, nil) + if err != nil { + return nil, err + } + + if val.(bool) { + return nil, errDivByZero + } + } + + if b.l.isStatic() && lv == nil { + return value{nil}, nil + } + + b.r = value{v} + } + + if !b.isStatic() { + return &b, nil + } + + val, err := b.eval(nil, nil) + return value{val}, err +} + +func newBinaryOperation(op int, x, y interface{}) (v expression, err error) { + expr, err := newBinaryOperation0(op, x, y) + if err != nil { + return nil, err + } + + b, ok := expr.(*binaryOperation) + if !ok { + return expr, nil + } + + if _, ok := b.l.(*ident); ok { + return expr, nil + } + + if c, ok := b.l.(*call); ok && c.f == "id" { + return expr, nil + } + + var r expression + if r, ok = b.r.(*ident); !ok { + r1, ok := b.r.(*call) + if !ok || r1.f != "id" || len(r1.arg) != 0 { + return expr, nil + } + + r = r1 + } + + // Normalize expr relOp indent: ident invRelOp expr + switch b.op { + case '<': + return &binaryOperation{'>', r, b.l}, nil + case le: + return &binaryOperation{ge, r, b.l}, nil + case '>': + return &binaryOperation{'<', r, b.l}, nil + case ge: + return &binaryOperation{le, r, b.l}, nil + case eq, neq: + return &binaryOperation{b.op, r, b.l}, nil + default: + return expr, nil + } +} + +func (o *binaryOperation) isIdentRelOpVal() (bool, string, interface{}, error) { + sid := "" + id, ok := o.l.(*ident) + if !ok { + f, ok := o.l.(*call) + if !ok || f.f != "id" || len(f.arg) != 0 { + return false, "", nil, nil + } + + sid = "id()" + } else { + if id.isQualified() { + return false, "", nil, nil + } + + sid = id.s + } + + if v, ok := o.r.(value); ok { + switch o.op { + case '<', + le, + '>', + ge, + eq, + neq: + return true, sid, v.val, nil + default: + return false, "", nil, nil + } + } + + return false, "", nil, nil +} + +func (o *binaryOperation) clone(arg []interface{}, unqualify ...string) (expression, error) { + l, err := o.l.clone(arg, unqualify...) + if err != nil { + return nil, err + } + + r, err := o.r.clone(arg, unqualify...) + if err != nil { + return nil, err + } + + return newBinaryOperation(o.op, l, r) +} + +func (o *binaryOperation) isStatic() bool { return o.l.isStatic() && o.r.isStatic() } + +func (o *binaryOperation) String() string { + return fmt.Sprintf("%s %s %s", o.l, iop(o.op), o.r) +} + +func (o *binaryOperation) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (r interface{}, err error) { + defer func() { + if e := recover(); e != nil { + switch x := e.(type) { + case error: + r, err = nil, x + default: + r, err = nil, fmt.Errorf("%v", x) + } + } + }() + + switch op := o.op; op { + case andand: + a, err := expand1(o.l.eval(execCtx, ctx)) + if err != nil { + return nil, err + } + + switch x := a.(type) { + case nil: + b, err := expand1(o.r.eval(execCtx, ctx)) + if err != nil { + return nil, err + } + + switch y := b.(type) { + case nil: + return nil, nil + case bool: + if !y { + return false, nil + } + + return nil, nil + default: + return invOp2(x, y, op) + } + case bool: + if !x { + return false, nil + } + + b, err := expand1(o.r.eval(execCtx, ctx)) + if err != nil { + return nil, err + } + + switch y := b.(type) { + case nil: + return nil, nil + case bool: + return y, nil + default: + return invOp2(x, y, op) + } + default: + return undOp(x, op) + } + case oror: + a, err := expand1(o.l.eval(execCtx, ctx)) + if err != nil { + return nil, err + } + + switch x := a.(type) { + case nil: + b, err := expand1(o.r.eval(execCtx, ctx)) + if err != nil { + return nil, err + } + + switch y := b.(type) { + case nil: + return nil, nil + case bool: + if y { + return y, nil + } + + return nil, nil + default: + return invOp2(x, y, op) + } + case bool: + if x { + return x, nil + } + + b, err := expand1(o.r.eval(execCtx, ctx)) + if err != nil { + return nil, err + } + + switch y := b.(type) { + case nil: + return nil, nil + case bool: + return y, nil + default: + return invOp2(x, y, op) + } + default: + return undOp(x, op) + } + case '>': + a, b := o.get2(execCtx, ctx) + if a == nil || b == nil { + return + } + switch x := a.(type) { + //case nil: + case idealComplex: + return undOp2(a, b, op) + case idealFloat: + switch y := b.(type) { + case idealFloat: + return x > y, nil + default: + return invOp2(x, y, op) + } + case idealInt: + switch y := b.(type) { + case idealInt: + return x > y, nil + default: + return invOp2(x, y, op) + } + case idealRune: + switch y := b.(type) { + case idealRune: + return x > y, nil + default: + return invOp2(x, y, op) + } + case idealUint: + switch y := b.(type) { + case idealUint: + return x > y, nil + default: + return invOp2(x, y, op) + } + case bool: + return undOp2(a, b, op) + case complex64: + return undOp2(a, b, op) + case complex128: + return undOp2(a, b, op) + case float32: + switch y := b.(type) { + case float32: + return x > y, nil + default: + return invOp2(x, y, op) + } + case float64: + switch y := b.(type) { + case float64: + return x > y, nil + default: + return invOp2(x, y, op) + } + case int8: + switch y := b.(type) { + case int8: + return x > y, nil + default: + return invOp2(x, y, op) + } + case int16: + switch y := b.(type) { + case int16: + return x > y, nil + default: + return invOp2(x, y, op) + } + case int32: + switch y := b.(type) { + case int32: + return x > y, nil + default: + return invOp2(x, y, op) + } + case int64: + switch y := b.(type) { + case int64: + return x > y, nil + default: + return invOp2(x, y, op) + } + case string: + switch y := b.(type) { + case string: + return x > y, nil + default: + return invOp2(x, y, op) + } + case uint8: + switch y := b.(type) { + case uint8: + return x > y, nil + default: + return invOp2(x, y, op) + } + case uint16: + switch y := b.(type) { + case uint16: + return x > y, nil + default: + return invOp2(x, y, op) + } + case uint32: + switch y := b.(type) { + case uint32: + return x > y, nil + default: + return invOp2(x, y, op) + } + case uint64: + switch y := b.(type) { + case uint64: + return x > y, nil + default: + return invOp2(x, y, op) + } + case *big.Int: + switch y := b.(type) { + case *big.Int: + return x.Cmp(y) > 0, nil + default: + return invOp2(x, y, op) + } + case *big.Rat: + switch y := b.(type) { + case *big.Rat: + return x.Cmp(y) > 0, nil + default: + return invOp2(x, y, op) + } + case time.Duration: + switch y := b.(type) { + case time.Duration: + return x > y, nil + default: + return invOp2(x, y, op) + } + case time.Time: + switch y := b.(type) { + case time.Time: + return x.After(y), nil + default: + return invOp2(x, y, op) + } + default: + return invOp2(a, b, op) + } + case '<': + a, b := o.get2(execCtx, ctx) + if a == nil || b == nil { + return + } + switch x := a.(type) { + //case nil: + case idealComplex: + return undOp2(a, b, op) + case idealFloat: + switch y := b.(type) { + case idealFloat: + return x < y, nil + default: + return invOp2(x, y, op) + } + case idealInt: + switch y := b.(type) { + case idealInt: + return x < y, nil + default: + return invOp2(x, y, op) + } + case idealRune: + switch y := b.(type) { + case idealRune: + return x < y, nil + default: + return invOp2(x, y, op) + } + case idealUint: + switch y := b.(type) { + case idealUint: + return x < y, nil + default: + return invOp2(x, y, op) + } + case bool: + return undOp2(a, b, op) + case complex64: + return undOp2(a, b, op) + case complex128: + return undOp2(a, b, op) + case float32: + switch y := b.(type) { + case float32: + return x < y, nil + default: + return invOp2(x, y, op) + } + case float64: + switch y := b.(type) { + case float64: + return x < y, nil + default: + return invOp2(x, y, op) + } + case int8: + switch y := b.(type) { + case int8: + return x < y, nil + default: + return invOp2(x, y, op) + } + case int16: + switch y := b.(type) { + case int16: + return x < y, nil + default: + return invOp2(x, y, op) + } + case int32: + switch y := b.(type) { + case int32: + return x < y, nil + default: + return invOp2(x, y, op) + } + case int64: + switch y := b.(type) { + case int64: + return x < y, nil + default: + return invOp2(x, y, op) + } + case string: + switch y := b.(type) { + case string: + return x < y, nil + default: + return invOp2(x, y, op) + } + case uint8: + switch y := b.(type) { + case uint8: + return x < y, nil + default: + return invOp2(x, y, op) + } + case uint16: + switch y := b.(type) { + case uint16: + return x < y, nil + default: + return invOp2(x, y, op) + } + case uint32: + switch y := b.(type) { + case uint32: + return x < y, nil + default: + return invOp2(x, y, op) + } + case uint64: + switch y := b.(type) { + case uint64: + return x < y, nil + default: + return invOp2(x, y, op) + } + case *big.Int: + switch y := b.(type) { + case *big.Int: + return x.Cmp(y) < 0, nil + default: + return invOp2(x, y, op) + } + case *big.Rat: + switch y := b.(type) { + case *big.Rat: + return x.Cmp(y) < 0, nil + default: + return invOp2(x, y, op) + } + case time.Duration: + switch y := b.(type) { + case time.Duration: + return x < y, nil + default: + return invOp2(x, y, op) + } + case time.Time: + switch y := b.(type) { + case time.Time: + return x.Before(y), nil + default: + return invOp2(x, y, op) + } + default: + return invOp2(a, b, op) + } + case le: + a, b := o.get2(execCtx, ctx) + if a == nil || b == nil { + return + } + switch x := a.(type) { + //case nil: + case idealComplex: + return undOp2(a, b, op) + case idealFloat: + switch y := b.(type) { + case idealFloat: + return x <= y, nil + default: + return invOp2(x, y, op) + } + case idealInt: + switch y := b.(type) { + case idealInt: + return x <= y, nil + default: + return invOp2(x, y, op) + } + case idealRune: + switch y := b.(type) { + case idealRune: + return x <= y, nil + default: + return invOp2(x, y, op) + } + case idealUint: + switch y := b.(type) { + case idealUint: + return x <= y, nil + default: + return invOp2(x, y, op) + } + case bool: + return undOp2(a, b, op) + case complex64: + return undOp2(a, b, op) + case complex128: + return undOp2(a, b, op) + case float32: + switch y := b.(type) { + case float32: + return x <= y, nil + default: + return invOp2(x, y, op) + } + case float64: + switch y := b.(type) { + case float64: + return x <= y, nil + default: + return invOp2(x, y, op) + } + case int8: + switch y := b.(type) { + case int8: + return x <= y, nil + default: + return invOp2(x, y, op) + } + case int16: + switch y := b.(type) { + case int16: + return x <= y, nil + default: + return invOp2(x, y, op) + } + case int32: + switch y := b.(type) { + case int32: + return x <= y, nil + default: + return invOp2(x, y, op) + } + case int64: + switch y := b.(type) { + case int64: + return x <= y, nil + default: + return invOp2(x, y, op) + } + case string: + switch y := b.(type) { + case string: + return x <= y, nil + default: + return invOp2(x, y, op) + } + case uint8: + switch y := b.(type) { + case uint8: + return x <= y, nil + default: + return invOp2(x, y, op) + } + case uint16: + switch y := b.(type) { + case uint16: + return x <= y, nil + default: + return invOp2(x, y, op) + } + case uint32: + switch y := b.(type) { + case uint32: + return x <= y, nil + default: + return invOp2(x, y, op) + } + case uint64: + switch y := b.(type) { + case uint64: + return x <= y, nil + default: + return invOp2(x, y, op) + } + case *big.Int: + switch y := b.(type) { + case *big.Int: + return x.Cmp(y) <= 0, nil + default: + return invOp2(x, y, op) + } + case *big.Rat: + switch y := b.(type) { + case *big.Rat: + return x.Cmp(y) <= 0, nil + default: + return invOp2(x, y, op) + } + case time.Duration: + switch y := b.(type) { + case time.Duration: + return x <= y, nil + default: + return invOp2(x, y, op) + } + case time.Time: + switch y := b.(type) { + case time.Time: + return x.Before(y) || x.Equal(y), nil + default: + return invOp2(x, y, op) + } + default: + return invOp2(a, b, op) + } + case ge: + a, b := o.get2(execCtx, ctx) + if a == nil || b == nil { + return + } + switch x := a.(type) { + //case nil: + case idealComplex: + return undOp2(a, b, op) + case idealFloat: + switch y := b.(type) { + case idealFloat: + return x >= y, nil + default: + return invOp2(x, y, op) + } + case idealInt: + switch y := b.(type) { + case idealInt: + return x >= y, nil + default: + return invOp2(x, y, op) + } + case idealRune: + switch y := b.(type) { + case idealRune: + return x >= y, nil + default: + return invOp2(x, y, op) + } + case idealUint: + switch y := b.(type) { + case idealUint: + return x >= y, nil + default: + return invOp2(x, y, op) + } + case bool: + return undOp2(a, b, op) + case complex64: + return undOp2(a, b, op) + case complex128: + return undOp2(a, b, op) + case float32: + switch y := b.(type) { + case float32: + return x >= y, nil + default: + return invOp2(x, y, op) + } + case float64: + switch y := b.(type) { + case float64: + return x >= y, nil + default: + return invOp2(x, y, op) + } + case int8: + switch y := b.(type) { + case int8: + return x >= y, nil + default: + return invOp2(x, y, op) + } + case int16: + switch y := b.(type) { + case int16: + return x >= y, nil + default: + return invOp2(x, y, op) + } + case int32: + switch y := b.(type) { + case int32: + return x >= y, nil + default: + return invOp2(x, y, op) + } + case int64: + switch y := b.(type) { + case int64: + return x >= y, nil + default: + return invOp2(x, y, op) + } + case string: + switch y := b.(type) { + case string: + return x >= y, nil + default: + return invOp2(x, y, op) + } + case uint8: + switch y := b.(type) { + case uint8: + return x >= y, nil + default: + return invOp2(x, y, op) + } + case uint16: + switch y := b.(type) { + case uint16: + return x >= y, nil + default: + return invOp2(x, y, op) + } + case uint32: + switch y := b.(type) { + case uint32: + return x >= y, nil + default: + return invOp2(x, y, op) + } + case uint64: + switch y := b.(type) { + case uint64: + return x >= y, nil + default: + return invOp2(x, y, op) + } + case *big.Int: + switch y := b.(type) { + case *big.Int: + return x.Cmp(y) >= 0, nil + default: + return invOp2(x, y, op) + } + case *big.Rat: + switch y := b.(type) { + case *big.Rat: + return x.Cmp(y) >= 0, nil + default: + return invOp2(x, y, op) + } + case time.Duration: + switch y := b.(type) { + case time.Duration: + return x >= y, nil + default: + return invOp2(x, y, op) + } + case time.Time: + switch y := b.(type) { + case time.Time: + return x.After(y) || x.Equal(y), nil + default: + return invOp2(x, y, op) + } + default: + return invOp2(a, b, op) + } + case neq: + a, b := o.get2(execCtx, ctx) + if a == nil || b == nil { + return + } + switch x := a.(type) { + //case nil: + case idealComplex: + switch y := b.(type) { + case idealComplex: + return x != y, nil + default: + return invOp2(x, y, op) + } + case idealFloat: + switch y := b.(type) { + case idealFloat: + return x != y, nil + default: + return invOp2(x, y, op) + } + case idealInt: + switch y := b.(type) { + case idealInt: + return x != y, nil + default: + return invOp2(x, y, op) + } + case idealRune: + switch y := b.(type) { + case idealRune: + return x != y, nil + default: + return invOp2(x, y, op) + } + case idealUint: + switch y := b.(type) { + case idealUint: + return x != y, nil + default: + return invOp2(x, y, op) + } + case bool: + switch y := b.(type) { + case bool: + return x != y, nil + default: + return invOp2(x, y, op) + } + case complex64: + switch y := b.(type) { + case complex64: + return x != y, nil + default: + return invOp2(x, y, op) + } + case complex128: + switch y := b.(type) { + case complex128: + return x != y, nil + default: + return invOp2(x, y, op) + } + case float32: + switch y := b.(type) { + case float32: + return x != y, nil + default: + return invOp2(x, y, op) + } + case float64: + switch y := b.(type) { + case float64: + return x != y, nil + default: + return invOp2(x, y, op) + } + case int8: + switch y := b.(type) { + case int8: + return x != y, nil + default: + return invOp2(x, y, op) + } + case int16: + switch y := b.(type) { + case int16: + return x != y, nil + default: + return invOp2(x, y, op) + } + case int32: + switch y := b.(type) { + case int32: + return x != y, nil + default: + return invOp2(x, y, op) + } + case int64: + switch y := b.(type) { + case int64: + return x != y, nil + default: + return invOp2(x, y, op) + } + case string: + switch y := b.(type) { + case string: + return x != y, nil + default: + return invOp2(x, y, op) + } + case uint8: + switch y := b.(type) { + case uint8: + return x != y, nil + default: + return invOp2(x, y, op) + } + case uint16: + switch y := b.(type) { + case uint16: + return x != y, nil + default: + return invOp2(x, y, op) + } + case uint32: + switch y := b.(type) { + case uint32: + return x != y, nil + default: + return invOp2(x, y, op) + } + case uint64: + switch y := b.(type) { + case uint64: + return x != y, nil + default: + return invOp2(x, y, op) + } + case *big.Int: + switch y := b.(type) { + case *big.Int: + return x.Cmp(y) != 0, nil + default: + return invOp2(x, y, op) + } + case *big.Rat: + switch y := b.(type) { + case *big.Rat: + return x.Cmp(y) != 0, nil + default: + return invOp2(x, y, op) + } + case time.Duration: + switch y := b.(type) { + case time.Duration: + return x != y, nil + default: + return invOp2(x, y, op) + } + case time.Time: + switch y := b.(type) { + case time.Time: + return !x.Equal(y), nil + default: + return invOp2(x, y, op) + } + default: + return invOp2(a, b, op) + } + case eq: + a, b := o.get2(execCtx, ctx) + if a == nil || b == nil { + return + } + switch x := a.(type) { + //case nil: + case idealComplex: + switch y := b.(type) { + case idealComplex: + return x == y, nil + default: + return invOp2(x, y, op) + } + case idealFloat: + switch y := b.(type) { + case idealFloat: + return x == y, nil + default: + return invOp2(x, y, op) + } + case idealInt: + switch y := b.(type) { + case idealInt: + return x == y, nil + default: + return invOp2(x, y, op) + } + case idealRune: + switch y := b.(type) { + case idealRune: + return x == y, nil + default: + return invOp2(x, y, op) + } + case idealUint: + switch y := b.(type) { + case idealUint: + return x == y, nil + default: + return invOp2(x, y, op) + } + case bool: + switch y := b.(type) { + case bool: + return x == y, nil + default: + return invOp2(x, y, op) + } + case complex64: + switch y := b.(type) { + case complex64: + return x == y, nil + default: + return invOp2(x, y, op) + } + case complex128: + switch y := b.(type) { + case complex128: + return x == y, nil + default: + return invOp2(x, y, op) + } + case float32: + switch y := b.(type) { + case float32: + return x == y, nil + default: + return invOp2(x, y, op) + } + case float64: + switch y := b.(type) { + case float64: + return x == y, nil + default: + return invOp2(x, y, op) + } + case int8: + switch y := b.(type) { + case int8: + return x == y, nil + default: + return invOp2(x, y, op) + } + case int16: + switch y := b.(type) { + case int16: + return x == y, nil + default: + return invOp2(x, y, op) + } + case int32: + switch y := b.(type) { + case int32: + return x == y, nil + default: + return invOp2(x, y, op) + } + case int64: + switch y := b.(type) { + case int64: + return x == y, nil + default: + return invOp2(x, y, op) + } + case string: + switch y := b.(type) { + case string: + return x == y, nil + default: + return invOp2(x, y, op) + } + case uint8: + switch y := b.(type) { + case uint8: + return x == y, nil + default: + return invOp2(x, y, op) + } + case uint16: + switch y := b.(type) { + case uint16: + return x == y, nil + default: + return invOp2(x, y, op) + } + case uint32: + switch y := b.(type) { + case uint32: + return x == y, nil + default: + return invOp2(x, y, op) + } + case uint64: + switch y := b.(type) { + case uint64: + return x == y, nil + default: + return invOp2(x, y, op) + } + case *big.Int: + switch y := b.(type) { + case *big.Int: + return x.Cmp(y) == 0, nil + default: + return invOp2(x, y, op) + } + case *big.Rat: + switch y := b.(type) { + case *big.Rat: + return x.Cmp(y) == 0, nil + default: + return invOp2(x, y, op) + } + case time.Duration: + switch y := b.(type) { + case time.Duration: + return x == y, nil + default: + return invOp2(x, y, op) + } + case time.Time: + switch y := b.(type) { + case time.Time: + return x.Equal(y), nil + default: + return invOp2(x, y, op) + } + default: + return invOp2(a, b, op) + } + case '+': + a, b := o.get2(execCtx, ctx) + if a == nil || b == nil { + return + } + switch x := a.(type) { + //case nil: + case idealComplex: + switch y := b.(type) { + case idealComplex: + return idealComplex(complex64(x) + complex64(y)), nil + default: + return invOp2(x, y, op) + } + case idealFloat: + switch y := b.(type) { + case idealFloat: + return idealFloat(float64(x) + float64(y)), nil + default: + return invOp2(x, y, op) + } + case idealInt: + switch y := b.(type) { + case idealInt: + return idealInt(int64(x) + int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealRune: + switch y := b.(type) { + case idealRune: + return idealRune(int64(x) + int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealUint: + switch y := b.(type) { + case idealUint: + return idealUint(uint64(x) + uint64(y)), nil + default: + return invOp2(x, y, op) + } + case bool: + return undOp2(a, b, op) + case complex64: + switch y := b.(type) { + case complex64: + return x + y, nil + default: + return invOp2(x, y, op) + } + case complex128: + switch y := b.(type) { + case complex128: + return x + y, nil + default: + return invOp2(x, y, op) + } + case float32: + switch y := b.(type) { + case float32: + return x + y, nil + default: + return invOp2(x, y, op) + } + case float64: + switch y := b.(type) { + case float64: + return x + y, nil + default: + return invOp2(x, y, op) + } + case int8: + switch y := b.(type) { + case int8: + return x + y, nil + default: + return invOp2(x, y, op) + } + case int16: + switch y := b.(type) { + case int16: + return x + y, nil + default: + return invOp2(x, y, op) + } + case int32: + switch y := b.(type) { + case int32: + return x + y, nil + default: + return invOp2(x, y, op) + } + case int64: + switch y := b.(type) { + case int64: + return x + y, nil + default: + return invOp2(x, y, op) + } + case string: + switch y := b.(type) { + case string: + return x + y, nil + default: + return invOp2(x, y, op) + } + case uint8: + switch y := b.(type) { + case uint8: + return x + y, nil + default: + return invOp2(x, y, op) + } + case uint16: + switch y := b.(type) { + case uint16: + return x + y, nil + default: + return invOp2(x, y, op) + } + case uint32: + switch y := b.(type) { + case uint32: + return x + y, nil + default: + return invOp2(x, y, op) + } + case uint64: + switch y := b.(type) { + case uint64: + return x + y, nil + default: + return invOp2(x, y, op) + } + case *big.Int: + switch y := b.(type) { + case *big.Int: + var z big.Int + return z.Add(x, y), nil + default: + return invOp2(x, y, op) + } + case *big.Rat: + switch y := b.(type) { + case *big.Rat: + var z big.Rat + return z.Add(x, y), nil + default: + return invOp2(x, y, op) + } + case time.Duration: + switch y := b.(type) { + case time.Duration: + return x + y, nil + case time.Time: + return y.Add(x), nil + default: + return invOp2(x, y, op) + } + case time.Time: + switch y := b.(type) { + case time.Duration: + return x.Add(y), nil + default: + return invOp2(x, y, op) + } + default: + return invOp2(a, b, op) + } + case '-': + a, b := o.get2(execCtx, ctx) + if a == nil || b == nil { + return + } + switch x := a.(type) { + //case nil: + case idealComplex: + switch y := b.(type) { + case idealComplex: + return idealComplex(complex64(x) - complex64(y)), nil + default: + return invOp2(x, y, op) + } + case idealFloat: + switch y := b.(type) { + case idealFloat: + return idealFloat(float64(x) - float64(y)), nil + default: + return invOp2(x, y, op) + } + case idealInt: + switch y := b.(type) { + case idealInt: + return idealInt(int64(x) - int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealRune: + switch y := b.(type) { + case idealRune: + return idealRune(int64(x) - int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealUint: + switch y := b.(type) { + case idealUint: + return idealUint(uint64(x) - uint64(y)), nil + default: + return invOp2(x, y, op) + } + case bool: + return undOp2(a, b, op) + case complex64: + switch y := b.(type) { + case complex64: + return x - y, nil + default: + return invOp2(x, y, op) + } + case complex128: + switch y := b.(type) { + case complex128: + return x - y, nil + default: + return invOp2(x, y, op) + } + case float32: + switch y := b.(type) { + case float32: + return x - y, nil + default: + return invOp2(x, y, op) + } + case float64: + switch y := b.(type) { + case float64: + return x - y, nil + default: + return invOp2(x, y, op) + } + case int8: + switch y := b.(type) { + case int8: + return x - y, nil + default: + return invOp2(x, y, op) + } + case int16: + switch y := b.(type) { + case int16: + return x - y, nil + default: + return invOp2(x, y, op) + } + case int32: + switch y := b.(type) { + case int32: + return x - y, nil + default: + return invOp2(x, y, op) + } + case int64: + switch y := b.(type) { + case int64: + return x - y, nil + default: + return invOp2(x, y, op) + } + case string: + return undOp2(a, b, op) + case uint8: + switch y := b.(type) { + case uint8: + return x - y, nil + default: + return invOp2(x, y, op) + } + case uint16: + switch y := b.(type) { + case uint16: + return x - y, nil + default: + return invOp2(x, y, op) + } + case uint32: + switch y := b.(type) { + case uint32: + return x - y, nil + default: + return invOp2(x, y, op) + } + case uint64: + switch y := b.(type) { + case uint64: + return x - y, nil + default: + return invOp2(x, y, op) + } + case *big.Int: + switch y := b.(type) { + case *big.Int: + var z big.Int + return z.Sub(x, y), nil + default: + return invOp2(x, y, op) + } + case *big.Rat: + switch y := b.(type) { + case *big.Rat: + var z big.Rat + return z.Sub(x, y), nil + default: + return invOp2(x, y, op) + } + case time.Duration: + switch y := b.(type) { + case time.Duration: + return x - y, nil + default: + return invOp2(x, y, op) + } + case time.Time: + switch y := b.(type) { + case time.Duration: + return x.Add(-y), nil + case time.Time: + return x.Sub(y), nil + default: + return invOp2(x, y, op) + } + default: + return invOp2(a, b, op) + } + case rsh: + a, b := eval2(o.l, o.r, execCtx, ctx) + if a == nil || b == nil { + return + } + + var cnt uint64 + switch y := b.(type) { + //case nil: + case idealComplex: + return invShiftRHS(a, b) + case idealFloat: + return invShiftRHS(a, b) + case idealInt: + cnt = uint64(y) + case idealRune: + cnt = uint64(y) + case idealUint: + cnt = uint64(y) + case bool: + return invShiftRHS(a, b) + case complex64: + return invShiftRHS(a, b) + case complex128: + return invShiftRHS(a, b) + case float32: + return invShiftRHS(a, b) + case float64: + return invShiftRHS(a, b) + case int8: + return invShiftRHS(a, b) + case int16: + return invShiftRHS(a, b) + case int32: + return invShiftRHS(a, b) + case int64: + return invShiftRHS(a, b) + case string: + return invShiftRHS(a, b) + case uint8: + cnt = uint64(y) + case uint16: + cnt = uint64(y) + case uint32: + cnt = uint64(y) + case uint64: + cnt = uint64(y) + default: + return invOp2(a, b, op) + } + + switch x := a.(type) { + //case nil: + case idealComplex: + return undOp2(a, b, op) + case idealFloat: + return undOp2(a, b, op) + case idealInt: + return idealInt(int64(x) >> cnt), nil + case idealRune: + return idealRune(int64(x) >> cnt), nil + case idealUint: + return idealUint(uint64(x) >> cnt), nil + case bool: + return undOp2(a, b, op) + case complex64: + return undOp2(a, b, op) + case complex128: + return undOp2(a, b, op) + case float32: + return undOp2(a, b, op) + case float64: + return undOp2(a, b, op) + case int8: + return x >> cnt, nil + case int16: + return x >> cnt, nil + case int32: + return x >> cnt, nil + case int64: + return x >> cnt, nil + case string: + return undOp2(a, b, op) + case uint8: + return x >> cnt, nil + case uint16: + return x >> cnt, nil + case uint32: + return x >> cnt, nil + case uint64: + return x >> cnt, nil + case *big.Int: + var z big.Int + return z.Rsh(x, uint(cnt)), nil + case time.Duration: + return x >> cnt, nil + default: + return invOp2(a, b, op) + } + case lsh: + a, b := eval2(o.l, o.r, execCtx, ctx) + if a == nil || b == nil { + return + } + + var cnt uint64 + switch y := b.(type) { + //case nil: + case idealComplex: + return invShiftRHS(a, b) + case idealFloat: + return invShiftRHS(a, b) + case idealInt: + cnt = uint64(y) + case idealRune: + cnt = uint64(y) + case idealUint: + cnt = uint64(y) + case bool: + return invShiftRHS(a, b) + case complex64: + return invShiftRHS(a, b) + case complex128: + return invShiftRHS(a, b) + case float32: + return invShiftRHS(a, b) + case float64: + return invShiftRHS(a, b) + case int8: + return invShiftRHS(a, b) + case int16: + return invShiftRHS(a, b) + case int32: + return invShiftRHS(a, b) + case int64: + return invShiftRHS(a, b) + case string: + return invShiftRHS(a, b) + case uint8: + cnt = uint64(y) + case uint16: + cnt = uint64(y) + case uint32: + cnt = uint64(y) + case uint64: + cnt = uint64(y) + default: + return invOp2(a, b, op) + } + + switch x := a.(type) { + //case nil: + case idealComplex: + return undOp2(a, b, op) + case idealFloat: + return undOp2(a, b, op) + case idealInt: + return idealInt(int64(x) << cnt), nil + case idealRune: + return idealRune(int64(x) << cnt), nil + case idealUint: + return idealUint(uint64(x) << cnt), nil + case bool: + return undOp2(a, b, op) + case complex64: + return undOp2(a, b, op) + case complex128: + return undOp2(a, b, op) + case float32: + return undOp2(a, b, op) + case float64: + return undOp2(a, b, op) + case int8: + return x << cnt, nil + case int16: + return x << cnt, nil + case int32: + return x << cnt, nil + case int64: + return x << cnt, nil + case string: + return undOp2(a, b, op) + case uint8: + return x << cnt, nil + case uint16: + return x << cnt, nil + case uint32: + return x << cnt, nil + case uint64: + return x << cnt, nil + case *big.Int: + var z big.Int + return z.Lsh(x, uint(cnt)), nil + case time.Duration: + return x << cnt, nil + default: + return invOp2(a, b, op) + } + case '&': + a, b := o.get2(execCtx, ctx) + if a == nil || b == nil { + return + } + switch x := a.(type) { + //case nil: + case idealComplex: + return undOp2(a, b, op) + case idealFloat: + return undOp2(a, b, op) + case idealInt: + switch y := b.(type) { + case idealInt: + return idealInt(int64(x) & int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealRune: + switch y := b.(type) { + case idealRune: + return idealRune(int64(x) & int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealUint: + switch y := b.(type) { + case idealUint: + return idealUint(uint64(x) & uint64(y)), nil + default: + return invOp2(x, y, op) + } + case bool: + return undOp2(a, b, op) + case complex64: + return undOp2(a, b, op) + case complex128: + return undOp2(a, b, op) + case float32: + return undOp2(a, b, op) + case float64: + return undOp2(a, b, op) + case int8: + switch y := b.(type) { + case int8: + return x & y, nil + default: + return invOp2(x, y, op) + } + case int16: + switch y := b.(type) { + case int16: + return x & y, nil + default: + return invOp2(x, y, op) + } + case int32: + switch y := b.(type) { + case int32: + return x & y, nil + default: + return invOp2(x, y, op) + } + case int64: + switch y := b.(type) { + case int64: + return x & y, nil + default: + return invOp2(x, y, op) + } + case string: + return undOp2(a, b, op) + case uint8: + switch y := b.(type) { + case uint8: + return x & y, nil + default: + return invOp2(x, y, op) + } + case uint16: + switch y := b.(type) { + case uint16: + return x & y, nil + default: + return invOp2(x, y, op) + } + case uint32: + switch y := b.(type) { + case uint32: + return x & y, nil + default: + return invOp2(x, y, op) + } + case uint64: + switch y := b.(type) { + case uint64: + return x & y, nil + default: + return invOp2(x, y, op) + } + case *big.Int: + switch y := b.(type) { + case *big.Int: + var z big.Int + return z.And(x, y), nil + default: + return invOp2(x, y, op) + } + case time.Duration: + switch y := b.(type) { + case time.Duration: + return x & y, nil + default: + return invOp2(x, y, op) + } + default: + return invOp2(a, b, op) + } + case '|': + a, b := o.get2(execCtx, ctx) + if a == nil || b == nil { + return + } + switch x := a.(type) { + //case nil: + case idealComplex: + return undOp2(a, b, op) + case idealFloat: + return undOp2(a, b, op) + case idealInt: + switch y := b.(type) { + case idealInt: + return idealInt(int64(x) | int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealRune: + switch y := b.(type) { + case idealRune: + return idealRune(int64(x) | int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealUint: + switch y := b.(type) { + case idealUint: + return idealUint(uint64(x) | uint64(y)), nil + default: + return invOp2(x, y, op) + } + case bool: + return undOp2(a, b, op) + case complex64: + return undOp2(a, b, op) + case complex128: + return undOp2(a, b, op) + case float32: + return undOp2(a, b, op) + case float64: + return undOp2(a, b, op) + case int8: + switch y := b.(type) { + case int8: + return x | y, nil + default: + return invOp2(x, y, op) + } + case int16: + switch y := b.(type) { + case int16: + return x | y, nil + default: + return invOp2(x, y, op) + } + case int32: + switch y := b.(type) { + case int32: + return x | y, nil + default: + return invOp2(x, y, op) + } + case int64: + switch y := b.(type) { + case int64: + return x | y, nil + default: + return invOp2(x, y, op) + } + case string: + return undOp2(a, b, op) + case uint8: + switch y := b.(type) { + case uint8: + return x | y, nil + default: + return invOp2(x, y, op) + } + case uint16: + switch y := b.(type) { + case uint16: + return x | y, nil + default: + return invOp2(x, y, op) + } + case uint32: + switch y := b.(type) { + case uint32: + return x | y, nil + default: + return invOp2(x, y, op) + } + case uint64: + switch y := b.(type) { + case uint64: + return x | y, nil + default: + return invOp2(x, y, op) + } + case *big.Int: + switch y := b.(type) { + case *big.Int: + var z big.Int + return z.Or(x, y), nil + default: + return invOp2(x, y, op) + } + case time.Duration: + switch y := b.(type) { + case time.Duration: + return x | y, nil + default: + return invOp2(x, y, op) + } + default: + return invOp2(a, b, op) + } + case andnot: + a, b := o.get2(execCtx, ctx) + if a == nil || b == nil { + return + } + switch x := a.(type) { + //case nil: + case idealComplex: + return undOp2(a, b, op) + case idealFloat: + return undOp2(a, b, op) + case idealInt: + switch y := b.(type) { + case idealInt: + return idealInt(int64(x) &^ int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealRune: + switch y := b.(type) { + case idealRune: + return idealRune(int64(x) &^ int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealUint: + switch y := b.(type) { + case idealUint: + return idealUint(uint64(x) &^ uint64(y)), nil + default: + return invOp2(x, y, op) + } + case bool: + return undOp2(a, b, op) + case complex64: + return undOp2(a, b, op) + case complex128: + return undOp2(a, b, op) + case float32: + return undOp2(a, b, op) + case float64: + return undOp2(a, b, op) + case int8: + switch y := b.(type) { + case int8: + return x &^ y, nil + default: + return invOp2(x, y, op) + } + case int16: + switch y := b.(type) { + case int16: + return x &^ y, nil + default: + return invOp2(x, y, op) + } + case int32: + switch y := b.(type) { + case int32: + return x &^ y, nil + default: + return invOp2(x, y, op) + } + case int64: + switch y := b.(type) { + case int64: + return x &^ y, nil + default: + return invOp2(x, y, op) + } + case string: + return undOp2(a, b, op) + case uint8: + switch y := b.(type) { + case uint8: + return x &^ y, nil + default: + return invOp2(x, y, op) + } + case uint16: + switch y := b.(type) { + case uint16: + return x &^ y, nil + default: + return invOp2(x, y, op) + } + case uint32: + switch y := b.(type) { + case uint32: + return x &^ y, nil + default: + return invOp2(x, y, op) + } + case uint64: + switch y := b.(type) { + case uint64: + return x &^ y, nil + default: + return invOp2(x, y, op) + } + case *big.Int: + switch y := b.(type) { + case *big.Int: + var z big.Int + return z.AndNot(x, y), nil + default: + return invOp2(x, y, op) + } + case time.Duration: + switch y := b.(type) { + case time.Duration: + return x &^ y, nil + default: + return invOp2(x, y, op) + } + default: + return invOp2(a, b, op) + } + case '^': + a, b := o.get2(execCtx, ctx) + if a == nil || b == nil { + return + } + switch x := a.(type) { + //case nil: + case idealComplex: + return undOp2(a, b, op) + case idealFloat: + return undOp2(a, b, op) + case idealInt: + switch y := b.(type) { + case idealInt: + return idealInt(int64(x) ^ int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealRune: + switch y := b.(type) { + case idealRune: + return idealRune(int64(x) ^ int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealUint: + switch y := b.(type) { + case idealUint: + return idealUint(uint64(x) ^ uint64(y)), nil + default: + return invOp2(x, y, op) + } + case bool: + return undOp2(a, b, op) + case complex64: + return undOp2(a, b, op) + case complex128: + return undOp2(a, b, op) + case float32: + return undOp2(a, b, op) + case float64: + return undOp2(a, b, op) + case int8: + switch y := b.(type) { + case int8: + return x ^ y, nil + default: + return invOp2(x, y, op) + } + case int16: + switch y := b.(type) { + case int16: + return x ^ y, nil + default: + return invOp2(x, y, op) + } + case int32: + switch y := b.(type) { + case int32: + return x ^ y, nil + default: + return invOp2(x, y, op) + } + case int64: + switch y := b.(type) { + case int64: + return x ^ y, nil + default: + return invOp2(x, y, op) + } + case string: + return undOp2(a, b, op) + case uint8: + switch y := b.(type) { + case uint8: + return x ^ y, nil + default: + return invOp2(x, y, op) + } + case uint16: + switch y := b.(type) { + case uint16: + return x ^ y, nil + default: + return invOp2(x, y, op) + } + case uint32: + switch y := b.(type) { + case uint32: + return x ^ y, nil + default: + return invOp2(x, y, op) + } + case uint64: + switch y := b.(type) { + case uint64: + return x ^ y, nil + default: + return invOp2(x, y, op) + } + case *big.Int: + switch y := b.(type) { + case *big.Int: + var z big.Int + return z.Xor(x, y), nil + default: + return invOp2(x, y, op) + } + case time.Duration: + switch y := b.(type) { + case time.Duration: + return x ^ y, nil + default: + return invOp2(x, y, op) + } + default: + return invOp2(a, b, op) + } + case '%': + a, b := o.get2(execCtx, ctx) + if a == nil || b == nil { + return + } + switch x := a.(type) { + //case nil: + case idealComplex: + return undOp2(a, b, op) + case idealFloat: + return undOp2(a, b, op) + case idealInt: + switch y := b.(type) { + case idealInt: + return idealInt(int64(x) % int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealRune: + switch y := b.(type) { + case idealRune: + return idealRune(int64(x) % int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealUint: + switch y := b.(type) { + case idealUint: + return idealUint(uint64(x) % uint64(y)), nil + default: + return invOp2(x, y, op) + } + case bool: + return undOp2(a, b, op) + case complex64: + return undOp2(a, b, op) + case complex128: + return undOp2(a, b, op) + case float32: + return undOp2(a, b, op) + case float64: + return undOp2(a, b, op) + case int8: + switch y := b.(type) { + case int8: + return x % y, nil + default: + return invOp2(x, y, op) + } + case int16: + switch y := b.(type) { + case int16: + return x % y, nil + default: + return invOp2(x, y, op) + } + case int32: + switch y := b.(type) { + case int32: + return x % y, nil + default: + return invOp2(x, y, op) + } + case int64: + switch y := b.(type) { + case int64: + return x % y, nil + default: + return invOp2(x, y, op) + } + case string: + return undOp2(a, b, op) + case uint8: + switch y := b.(type) { + case uint8: + return x % y, nil + default: + return invOp2(x, y, op) + } + case uint16: + switch y := b.(type) { + case uint16: + return x % y, nil + default: + return invOp2(x, y, op) + } + case uint32: + switch y := b.(type) { + case uint32: + return x % y, nil + default: + return invOp2(x, y, op) + } + case uint64: + switch y := b.(type) { + case uint64: + return x % y, nil + default: + return invOp2(x, y, op) + } + case *big.Int: + switch y := b.(type) { + case *big.Int: + if y.Sign() == 0 { + return nil, errDivByZero + } + + var z big.Int + return z.Mod(x, y), nil + default: + return invOp2(x, y, op) + } + case time.Duration: + switch y := b.(type) { + case time.Duration: + return x % y, nil + default: + return invOp2(x, y, op) + } + default: + return invOp2(a, b, op) + } + case '/': + a, b := o.get2(execCtx, ctx) + if a == nil || b == nil { + return + } + switch x := a.(type) { + //case nil: + case idealComplex: + switch y := b.(type) { + case idealComplex: + return idealComplex(complex64(x) / complex64(y)), nil + default: + return invOp2(x, y, op) + } + case idealFloat: + switch y := b.(type) { + case idealFloat: + return idealFloat(float64(x) / float64(y)), nil + default: + return invOp2(x, y, op) + } + case idealInt: + switch y := b.(type) { + case idealInt: + return idealInt(int64(x) / int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealRune: + switch y := b.(type) { + case idealRune: + return idealRune(int64(x) / int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealUint: + switch y := b.(type) { + case idealUint: + return idealUint(uint64(x) / uint64(y)), nil + default: + return invOp2(x, y, op) + } + case bool: + return undOp2(a, b, op) + case complex64: + switch y := b.(type) { + case complex64: + return x / y, nil + default: + return invOp2(x, y, op) + } + case complex128: + switch y := b.(type) { + case complex128: + return x / y, nil + default: + return invOp2(x, y, op) + } + case float32: + switch y := b.(type) { + case float32: + return x / y, nil + default: + return invOp2(x, y, op) + } + case float64: + switch y := b.(type) { + case float64: + return x / y, nil + default: + return invOp2(x, y, op) + } + case int8: + switch y := b.(type) { + case int8: + return x / y, nil + default: + return invOp2(x, y, op) + } + case int16: + switch y := b.(type) { + case int16: + return x / y, nil + default: + return invOp2(x, y, op) + } + case int32: + switch y := b.(type) { + case int32: + return x / y, nil + default: + return invOp2(x, y, op) + } + case int64: + switch y := b.(type) { + case int64: + return x / y, nil + default: + return invOp2(x, y, op) + } + case string: + return undOp2(a, b, op) + case uint8: + switch y := b.(type) { + case uint8: + return x / y, nil + default: + return invOp2(x, y, op) + } + case uint16: + switch y := b.(type) { + case uint16: + return x / y, nil + default: + return invOp2(x, y, op) + } + case uint32: + switch y := b.(type) { + case uint32: + return x / y, nil + default: + return invOp2(x, y, op) + } + case uint64: + switch y := b.(type) { + case uint64: + return x / y, nil + default: + return invOp2(x, y, op) + } + case *big.Int: + switch y := b.(type) { + case *big.Int: + if y.Sign() == 0 { + return nil, errDivByZero + } + + var z big.Int + return z.Quo(x, y), nil + default: + return invOp2(x, y, op) + } + case *big.Rat: + switch y := b.(type) { + case *big.Rat: + if y.Sign() == 0 { + return nil, errDivByZero + } + + var z big.Rat + return z.Quo(x, y), nil + default: + return invOp2(x, y, op) + } + case time.Duration: + switch y := b.(type) { + case time.Duration: + return x / y, nil + default: + return invOp2(x, y, op) + } + default: + return invOp2(a, b, op) + } + case '*': + a, b := o.get2(execCtx, ctx) + if a == nil || b == nil { + return + } + switch x := a.(type) { + //case nil: + case idealComplex: + switch y := b.(type) { + case idealComplex: + return idealComplex(complex64(x) * complex64(y)), nil + default: + return invOp2(x, y, op) + } + case idealFloat: + switch y := b.(type) { + case idealFloat: + return idealFloat(float64(x) * float64(y)), nil + default: + return invOp2(x, y, op) + } + case idealInt: + switch y := b.(type) { + case idealInt: + return idealInt(int64(x) * int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealRune: + switch y := b.(type) { + case idealRune: + return idealRune(int64(x) * int64(y)), nil + default: + return invOp2(x, y, op) + } + case idealUint: + switch y := b.(type) { + case idealUint: + return idealUint(uint64(x) * uint64(y)), nil + default: + return invOp2(x, y, op) + } + case bool: + return undOp2(a, b, op) + case complex64: + switch y := b.(type) { + case complex64: + return x * y, nil + default: + return invOp2(x, y, op) + } + case complex128: + switch y := b.(type) { + case complex128: + return x * y, nil + default: + return invOp2(x, y, op) + } + case float32: + switch y := b.(type) { + case float32: + return x * y, nil + default: + return invOp2(x, y, op) + } + case float64: + switch y := b.(type) { + case float64: + return x * y, nil + default: + return invOp2(x, y, op) + } + case int8: + switch y := b.(type) { + case int8: + return x * y, nil + default: + return invOp2(x, y, op) + } + case int16: + switch y := b.(type) { + case int16: + return x * y, nil + default: + return invOp2(x, y, op) + } + case int32: + switch y := b.(type) { + case int32: + return x * y, nil + default: + return invOp2(x, y, op) + } + case int64: + switch y := b.(type) { + case int64: + return x * y, nil + default: + return invOp2(x, y, op) + } + case string: + return undOp2(a, b, op) + case uint8: + switch y := b.(type) { + case uint8: + return x * y, nil + default: + return invOp2(x, y, op) + } + case uint16: + switch y := b.(type) { + case uint16: + return x * y, nil + default: + return invOp2(x, y, op) + } + case uint32: + switch y := b.(type) { + case uint32: + return x * y, nil + default: + return invOp2(x, y, op) + } + case uint64: + switch y := b.(type) { + case uint64: + return x * y, nil + default: + return invOp2(x, y, op) + } + case *big.Int: + switch y := b.(type) { + case *big.Int: + var z big.Int + return z.Mul(x, y), nil + default: + return invOp2(x, y, op) + } + case *big.Rat: + switch y := b.(type) { + case *big.Rat: + var z big.Rat + return z.Mul(x, y), nil + default: + return invOp2(x, y, op) + } + case time.Duration: + switch y := b.(type) { + case time.Duration: + return x * y, nil + default: + return invOp2(x, y, op) + } + default: + return invOp2(a, b, op) + } + default: + panic("internal error 037") + } +} + +func (o *binaryOperation) get2(execCtx *execCtx, ctx map[interface{}]interface{}) (x, y interface{}) { + x, y = eval2(o.l, o.r, execCtx, ctx) + //dbg("get2 pIn - ", x, y) + //defer func() {dbg("get2 coerced ", x, y)}() + return coerce(x, y) +} + +type ident struct { + s string +} + +func (i *ident) clone(arg []interface{}, unqualify ...string) (expression, error) { + x := strings.IndexByte(i.s, '.') + if x < 0 { + return &ident{s: i.s}, nil + } + + q := i.s[:x] + for _, v := range unqualify { + if q == v { + return &ident{i.s[x+1:]}, nil + } + } + return &ident{s: i.s}, nil +} + +func (i *ident) isQualified() bool { return strings.Contains(i.s, ".") } + +func (i *ident) isStatic() bool { return false } + +func (i *ident) String() string { return i.s } + +func (i *ident) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) { + if _, ok := ctx["$agg0"]; ok { + return int64(0), nil + } + + //defer func() { dbg("ident %q -> %v %v", i.s, v, err) }() + v, ok := ctx[i.s] + if !ok { + err = fmt.Errorf("unknown field %s", i.s) + } + return +} + +type pInEval struct { + m map[interface{}]struct{} // IN (SELECT...) results + sample interface{} +} + +type pIn struct { + expr expression + list []expression + not bool + sel *selectStmt +} + +func (n *pIn) clone(arg []interface{}, unqualify ...string) (expression, error) { + expr, err := n.expr.clone(arg, unqualify...) + if err != nil { + return nil, err + } + + list, err := cloneExpressionList(arg, n.list) + if err != nil { + return nil, err + } + + return &pIn{ + expr: expr, + list: list, + not: n.not, + sel: n.sel, + }, nil +} + +func (n *pIn) isStatic() bool { + if !n.expr.isStatic() || n.sel != nil { + return false + } + + for _, v := range n.list { + if !v.isStatic() { + return false + } + } + return true +} + +//LATER newIn + +func (n *pIn) String() string { + if n.sel == nil { + a := []string{} + for _, v := range n.list { + a = append(a, v.String()) + } + if n.not { + return fmt.Sprintf("%s NOT IN (%s)", n.expr, strings.Join(a, ",")) + } + + return fmt.Sprintf("%s IN (%s)", n.expr, strings.Join(a, ",")) + } + + if n.not { + return fmt.Sprintf("%s NOT IN (%s)", n.expr, n.sel) + } + + return fmt.Sprintf("%s IN (%s)", n.expr, n.sel) +} + +func (n *pIn) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) { + lhs, err := expand1(n.expr.eval(execCtx, ctx)) + if err != nil { + return nil, err + } + + if lhs == nil { + return nil, nil //TODO Add test for NULL LHS. + } + + if n.sel == nil { + for _, v := range n.list { + b, err := newBinaryOperation(eq, value{lhs}, v) + if err != nil { + return nil, err + } + + eval, err := b.eval(execCtx, ctx) + if err != nil { + return nil, err + } + + if x, ok := eval.(bool); ok && x { + return !n.not, nil + } + } + return n.not, nil + } + + var ev *pInEval + ev0 := ctx[n] + if ev0 == nil { // SELECT not yet evaluated. + r, err := n.sel.plan(execCtx) + if err != nil { + return nil, err + } + + if g, e := len(r.fieldNames()), 1; g != e { + return false, fmt.Errorf("IN (%s): mismatched field count, have %d, need %d", n.sel, g, e) + } + + ev = &pInEval{m: map[interface{}]struct{}{}} + ctx[n] = ev + m := ev.m + typechecked := false + if err := r.do(execCtx, func(id interface{}, data []interface{}) (more bool, err error) { + if typechecked { + if data[0] == nil { + return true, nil + } + + m[data[0]] = struct{}{} + } + + if data[0] == nil { + return true, nil + } + + ev.sample = data[0] + switch ev.sample.(type) { + case bool, byte, complex128, complex64, float32, + float64, int16, int32, int64, int8, + string, uint16, uint32, uint64: + typechecked = true + m[ev.sample] = struct{}{} + return true, nil + default: + return false, fmt.Errorf("IN (%s): invalid field type: %T", n.sel, data[0]) + } + + }); err != nil { + return nil, err + } + } else { + ev = ev0.(*pInEval) + } + + if ev.sample == nil { + return nil, nil + } + + _, ok := ev.m[coerce1(lhs, ev.sample)] + return ok != n.not, nil +} + +type value struct { + val interface{} +} + +func (l value) clone(arg []interface{}, unqualify ...string) (expression, error) { + return value{val: l.val}, nil +} + +func (l value) isStatic() bool { return true } + +func (l value) String() string { + switch x := l.val.(type) { + case nil: + return "NULL" + case idealComplex: + s := fmt.Sprint(x) + return s[1 : len(s)-1] + case complex64: + s := fmt.Sprint(x) + return s[1 : len(s)-1] + case complex128: + s := fmt.Sprint(x) + return s[1 : len(s)-1] + case string: + return fmt.Sprintf("%q", x) + case time.Duration: + return fmt.Sprintf("duration(%q)", l.val) + case time.Time: + y, m, d := x.Date() + zone, _ := x.Zone() + return fmt.Sprintf("date(%v, %v, %v, %v, %v, %v, %v, %v)", y, m, d, x.Hour(), x.Minute(), x.Second(), x.Nanosecond(), zone) + case *big.Rat: + return fmt.Sprintf("bigrat(%q)", l.val) + case *big.Int: + return fmt.Sprintf(`bigint("%v")`, l.val) + default: + return fmt.Sprintf("%v", l.val) + } +} + +func (l value) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (interface{}, error) { + return l.val, nil +} + +type conversion struct { + typ int + val expression +} + +func (c *conversion) clone(arg []interface{}, unqualify ...string) (expression, error) { + val, err := c.val.clone(arg, unqualify...) + if err != nil { + return nil, err + } + + return &conversion{typ: c.typ, val: val}, nil +} + +func (c *conversion) isStatic() bool { + return c.val.isStatic() +} + +//LATER newConversion or fake unary op + +func (c *conversion) String() string { + return fmt.Sprintf("%s(%s)", typeStr(c.typ), c.val) +} + +func (c *conversion) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) { + val, err := expand1(c.val.eval(execCtx, ctx)) + if err != nil { + return + } + + return convert(val, c.typ) +} + +type unaryOperation struct { + op int + v expression +} + +func newUnaryOperation(op int, x interface{}) (v expression, err error) { + l, ok := x.(expression) + if !ok { + panic("internal error 038") + } + + for { + pe, ok := l.(*pexpr) + if ok { + l = pe.expr + continue + } + + break + } + + if l.isStatic() { + val, err := l.eval(nil, nil) + if err != nil { + return nil, err + } + + l = value{val} + } + + if op == '!' { + b, ok := l.(*binaryOperation) + if ok { + switch b.op { + case eq: + b.op = neq + return b, nil + case neq: + b.op = eq + return b, nil + case '>': + b.op = le + return b, nil + case ge: + b.op = '<' + return b, nil + case '<': + b.op = ge + return b, nil + case le: + b.op = '>' + return b, nil + } + } + + u, ok := l.(*unaryOperation) + if ok && u.op == '!' { // !!x: x + return u.v, nil + } + } + + return &unaryOperation{op, l}, nil +} + +func (u *unaryOperation) clone(arg []interface{}, unqualify ...string) (expression, error) { + v, err := u.v.clone(arg, unqualify...) + if err != nil { + return nil, err + } + + return &unaryOperation{op: u.op, v: v}, nil +} + +func (u *unaryOperation) isStatic() bool { return u.v.isStatic() } + +func (u *unaryOperation) String() string { + switch u.v.(type) { + case *binaryOperation: + return fmt.Sprintf("%s(%s)", iop(u.op), u.v) + default: + return fmt.Sprintf("%s%s", iop(u.op), u.v) + } +} + +// !ident +func (u *unaryOperation) isNotQIdent() (bool, string, expression) { + if u.op != '!' { + return false, "", nil + } + + id, ok := u.v.(*ident) + if ok && id.isQualified() { + return true, mustQualifier(id.s), &unaryOperation{'!', &ident{mustSelector(id.s)}} + } + + return false, "", nil +} + +func (u *unaryOperation) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (r interface{}, err error) { + defer func() { + if e := recover(); e != nil { + switch x := e.(type) { + case error: + r, err = nil, x + default: + r, err = nil, fmt.Errorf("%v", x) + } + } + }() + + switch op := u.op; op { + case '!': + a := eval(u.v, execCtx, ctx) + if a == nil { + return + } + + switch x := a.(type) { + case bool: + return !x, nil + default: + return undOp(a, op) + } + case '^': + a := eval(u.v, execCtx, ctx) + if a == nil { + return + } + + switch x := a.(type) { + //case nil: + case idealComplex: + return undOp(a, op) + case idealFloat: + return undOp(a, op) + case idealInt: + return ^x, nil + case idealRune: + return ^x, nil + case idealUint: + return ^x, nil + case bool: + return undOp(a, op) + case complex64: + return undOp(a, op) + case complex128: + return undOp(a, op) + case float32: + return undOp(a, op) + case float64: + return undOp(a, op) + case int8: + return ^x, nil + case int16: + return ^x, nil + case int32: + return ^x, nil + case int64: + return ^x, nil + case string: + return undOp(a, op) + case uint8: + return ^x, nil + case uint16: + return ^x, nil + case uint32: + return ^x, nil + case uint64: + return ^x, nil + case *big.Int: + var z big.Int + return z.Not(x), nil + case time.Duration: + return ^x, nil + default: + return undOp(a, op) + } + case '+': + a := eval(u.v, execCtx, ctx) + if a == nil { + return + } + + switch x := a.(type) { + //case nil: + case idealComplex: + return +x, nil + case idealFloat: + return +x, nil + case idealInt: + return +x, nil + case idealRune: + return +x, nil + case idealUint: + return +x, nil + case bool: + return undOp(a, op) + case complex64: + return +x, nil + case complex128: + return +x, nil + case float32: + return +x, nil + case float64: + return +x, nil + case int8: + return +x, nil + case int16: + return +x, nil + case int32: + return +x, nil + case int64: + return +x, nil + case string: + return undOp(a, op) + case uint8: + return +x, nil + case uint16: + return +x, nil + case uint32: + return +x, nil + case uint64: + return +x, nil + case *big.Int: + var z big.Int + return z.Set(x), nil + case *big.Rat: + var z big.Rat + return z.Set(x), nil + case time.Duration: + return x, nil + default: + return undOp(a, op) + } + case '-': + a := eval(u.v, execCtx, ctx) + if a == nil { + return + } + + switch x := a.(type) { + //case nil: + case idealComplex: + return -x, nil + case idealFloat: + return -x, nil + case idealInt: + return -x, nil + case idealRune: + return -x, nil + case idealUint: + return -x, nil + case bool: + return undOp(a, op) + case complex64: + return -x, nil + case complex128: + return -x, nil + case float32: + return -x, nil + case float64: + return -x, nil + case int8: + return -x, nil + case int16: + return -x, nil + case int32: + return -x, nil + case int64: + return -x, nil + case string: + return undOp(a, op) + case uint8: + return -x, nil + case uint16: + return -x, nil + case uint32: + return -x, nil + case uint64: + return -x, nil + case *big.Int: + var z big.Int + return z.Neg(x), nil + case *big.Rat: + var z big.Rat + return z.Neg(x), nil + case time.Duration: + return -x, nil + default: + return undOp(a, op) + } + default: + panic("internal error 039") + } +} + +type call struct { + f string + arg []expression +} + +func newCall(f string, arg []expression) (v expression, isAgg bool, err error) { + x := builtin[f] + if x.f == nil { + return nil, false, fmt.Errorf("undefined: %s", f) + } + + isAgg = x.isAggregate + if g, min, max := len(arg), x.minArgs, x.maxArgs; g < min || g > max { + a := []interface{}{} + for _, v := range arg { + a = append(a, v) + } + return nil, false, badNArgs(min, f, a) + } + + c := call{f: f} + for _, val := range arg { + if !val.isStatic() { + c.arg = append(c.arg, val) + continue + } + + eval, err := val.eval(nil, nil) + if err != nil { + return nil, isAgg, err + } + + c.arg = append(c.arg, value{eval}) + } + + return &c, isAgg, nil +} + +func (c *call) clone(arg []interface{}, unqualify ...string) (expression, error) { + list, err := cloneExpressionList(arg, c.arg) + if err != nil { + return nil, err + } + + return &call{f: c.f, arg: list}, nil +} + +func (c *call) isStatic() bool { + v := builtin[c.f] + if v.f == nil || !v.isStatic { + return false + } + + for _, v := range c.arg { + if !v.isStatic() { + return false + } + } + return true +} + +func (c *call) String() string { + a := []string{} + for _, v := range c.arg { + a = append(a, v.String()) + } + return fmt.Sprintf("%s(%s)", c.f, strings.Join(a, ", ")) +} + +func (c *call) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) { + f, ok := builtin[c.f] + if !ok { + return nil, fmt.Errorf("unknown function %s", c.f) + } + + isID := c.f == "id" + a := make([]interface{}, len(c.arg)) + for i, arg := range c.arg { + if v, err = expand1(arg.eval(execCtx, ctx)); err != nil { + if !isID { + return nil, err + } + + if _, ok := arg.(*ident); !ok { + return nil, err + } + + a[i] = arg + continue + } + + a[i] = v + } + + if ctx != nil { + ctx["$fn"] = c + } + return f.f(a, ctx) +} + +type parameter struct { + n int +} + +func (p parameter) clone(arg []interface{}, unqualify ...string) (expression, error) { + i := p.n - 1 + if i < len(arg) { + return value{val: arg[i]}, nil + } + + return nil, fmt.Errorf("missing %s", p) +} + +func (parameter) isStatic() bool { return false } + +func (p parameter) String() string { return fmt.Sprintf("$%d", p.n) } + +func (p parameter) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) { + i := p.n - 1 + if i < len(execCtx.arg) { + return execCtx.arg[i], nil + } + + return nil, fmt.Errorf("missing %s", p) +} + +//MAYBE make it an unary operation +type isNull struct { + expr expression + not bool +} + +//LATER newIsNull + +func (is *isNull) clone(arg []interface{}, unqualify ...string) (expression, error) { + expr, err := is.expr.clone(arg, unqualify...) + if err != nil { + return nil, err + } + + return &isNull{expr: expr, not: is.not}, nil +} + +func (is *isNull) isStatic() bool { return is.expr.isStatic() } + +func (is *isNull) String() string { + if is.not { + return fmt.Sprintf("%s IS NOT NULL", is.expr) + } + + return fmt.Sprintf("%s IS NULL", is.expr) +} + +func (is *isNull) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) { + val, err := is.expr.eval(execCtx, ctx) + if err != nil { + return + } + + return val == nil != is.not, nil +} + +type indexOp struct { + expr, x expression +} + +func newIndex(sv, xv expression) (v expression, err error) { + s, fs, i := "", false, uint64(0) + x := indexOp{sv, xv} + if x.expr.isStatic() { + v, err := x.expr.eval(nil, nil) + if err != nil { + return nil, err + } + + if v == nil { + return value{nil}, nil + } + + if s, fs = v.(string); !fs { + return nil, invXOp(sv, xv) + } + + x.expr = value{s} + } + + if x.x.isStatic() { + v, err := x.x.eval(nil, nil) + if err != nil { + return nil, err + } + + if v == nil { + return value{nil}, nil + } + + var p *string + if fs { + p = &s + } + if i, err = indexExpr(p, v); err != nil { + return nil, err + } + + x.x = value{i} + } + + return &x, nil +} + +func (x *indexOp) clone(arg []interface{}, unqualify ...string) (expression, error) { + expr, err := x.expr.clone(arg, unqualify...) + if err != nil { + return nil, err + } + + x2, err := x.x.clone(arg, unqualify...) + if err != nil { + return nil, err + } + + return &indexOp{expr: expr, x: x2}, nil +} + +func (x *indexOp) isStatic() bool { + return x.expr.isStatic() && x.x.isStatic() +} + +func (x *indexOp) String() string { return fmt.Sprintf("%s[%s]", x.expr, x.x) } + +func (x *indexOp) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) { + s0, err := x.expr.eval(execCtx, ctx) + if err != nil { + return nil, runErr(err) + } + + s, ok := s0.(string) + if !ok { + return nil, runErr(invXOp(s0, x.x)) + } + + i0, err := x.x.eval(execCtx, ctx) + if err != nil { + return nil, runErr(err) + } + + if i0 == nil { + return nil, nil + } + + i, err := indexExpr(&s, i0) + if err != nil { + return nil, runErr(err) + } + + return s[i], nil +} + +type slice struct { + expr expression + lo, hi *expression +} + +func newSlice(e expression, lo, hi *expression) (v expression, err error) { + y := slice{e, lo, hi} + var val interface{} + if e := y.expr; e.isStatic() { + if val, err = e.eval(nil, nil); err != nil { + return nil, err + } + + if val == nil { + return value{nil}, nil + } + + y.expr = value{val} + } + + if p := y.lo; p != nil { + if e := expr(*p); e.isStatic() { + if val, err = e.eval(nil, nil); err != nil { + return nil, err + } + + if val == nil { + return value{nil}, nil + } + + v := expression(value{val}) + y.lo = &v + } + } + + if p := y.hi; p != nil { + if e := expr(*p); e.isStatic() { + if val, err = e.eval(nil, nil); err != nil { + return nil, err + } + + if val == nil { + return value{nil}, nil + } + + v := expression(value{val}) + y.hi = &v + } + } + return &y, nil +} + +func (s *slice) clone(arg []interface{}, unqualify ...string) (expression, error) { + expr, err := s.expr.clone(arg, unqualify...) + if err != nil { + return nil, err + } + + r := &slice{expr: expr, lo: s.lo, hi: s.hi} + if s.lo != nil { + e, err := (*s.lo).clone(arg, unqualify...) + if err != nil { + return nil, err + } + + r.lo = &e + } + if s.hi != nil { + e, err := (*s.hi).clone(arg, unqualify...) + if err != nil { + return nil, err + } + + r.hi = &e + } + return r, nil +} + +func (s *slice) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) { + s0, err := s.expr.eval(execCtx, ctx) + if err != nil { + return + } + + if s0 == nil { + return + } + + ss, ok := s0.(string) + if !ok { + return nil, runErr(invSOp(s0)) + } + + var iLo, iHi uint64 + if s.lo != nil { + i, err := (*s.lo).eval(execCtx, ctx) + if err != nil { + return nil, err + } + + if i == nil { + return nil, err + } + + if iLo, err = sliceExpr(&ss, i, 0); err != nil { + return nil, err + } + } + + iHi = uint64(len(ss)) + if s.hi != nil { + i, err := (*s.hi).eval(execCtx, ctx) + if err != nil { + return nil, err + } + + if i == nil { + return nil, err + } + + if iHi, err = sliceExpr(&ss, i, 1); err != nil { + return nil, err + } + } + + return ss[iLo:iHi], nil +} + +func (s *slice) isStatic() bool { + if !s.expr.isStatic() { + return false + } + + if p := s.lo; p != nil && !(*p).isStatic() { + return false + } + + if p := s.hi; p != nil && !(*p).isStatic() { + return false + } + + return false +} + +func (s *slice) String() string { + switch { + case s.lo == nil && s.hi == nil: + return fmt.Sprintf("%v[:]", s.expr) + case s.lo == nil && s.hi != nil: + return fmt.Sprintf("%v[:%v]", s.expr, *s.hi) + case s.lo != nil && s.hi == nil: + return fmt.Sprintf("%v[%v:]", s.expr, *s.lo) + default: //case s.lo != nil && s.hi != nil: + return fmt.Sprintf("%v[%v:%v]", s.expr, *s.lo, *s.hi) + } +} diff --git a/vendor/github.com/cznic/ql/file.go b/vendor/github.com/cznic/ql/file.go new file mode 100644 index 00000000..3180caa2 --- /dev/null +++ b/vendor/github.com/cznic/ql/file.go @@ -0,0 +1,1323 @@ +// Copyright 2014 The ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Well known handles +// 1: root +// 2: id + +package ql + +import ( + "crypto/sha1" + "fmt" + "io" + "io/ioutil" + "math/big" + "os" + "path/filepath" + "sync" + "time" + + "github.com/cznic/mathutil" + "github.com/cznic/ql/vendored/github.com/camlistore/go4/lock" + "github.com/cznic/ql/vendored/github.com/cznic/exp/lldb" +) + +const ( + magic = "\x60\xdbql" +) + +var ( + _ btreeIndex = (*fileIndex)(nil) + _ btreeIterator = (*fileBTreeIterator)(nil) + _ indexIterator = (*fileIndexIterator)(nil) + _ storage = (*file)(nil) + _ temp = (*fileTemp)(nil) +) + +type chunk struct { // expanded to blob types lazily + f *file + b []byte +} + +func (c chunk) expand() (v interface{}, err error) { + return c.f.loadChunks(c.b) +} + +func expand1(data interface{}, e error) (v interface{}, err error) { + if e != nil { + return nil, e + } + + c, ok := data.(chunk) + if !ok { + return data, nil + } + + return c.expand() +} + +func expand(data []interface{}) (err error) { + for i, v := range data { + if data[i], err = expand1(v, nil); err != nil { + return + } + } + return +} + +// OpenFile returns a DB backed by a named file. The back end limits the size +// of a record to about 64 kB. +func OpenFile(name string, opt *Options) (db *DB, err error) { + var f lldb.OSFile + if f = opt.OSFile; f == nil { + f, err = os.OpenFile(name, os.O_RDWR, 0666) + if err != nil { + if !os.IsNotExist(err) { + return nil, err + } + + if !opt.CanCreate { + return nil, err + } + + f, err = os.OpenFile(name, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666) + if err != nil { + return nil, err + } + } + } + + fi, err := newFileFromOSFile(f) // always ACID + if err != nil { + return + } + + if fi.tempFile = opt.TempFile; fi.tempFile == nil { + fi.tempFile = func(dir, prefix string) (f lldb.OSFile, err error) { + f0, err := ioutil.TempFile(dir, prefix) + return f0, err + } + } + + return newDB(fi) +} + +// Options amend the behavior of OpenFile. +// +// CanCreate +// +// The CanCreate option enables OpenFile to create the DB file if it does not +// exists. +// +// OSFile +// +// OSFile allows to pass an os.File like back end providing, for example, +// encrypted storage. If this field is nil then OpenFile uses the file named by +// the 'name' parameter instead. +// +// TempFile +// +// TempFile provides a temporary file used for evaluating the GROUP BY, ORDER +// BY, ... clauses. The hook is intended to be used by encrypted DB back ends +// to avoid leaks of unecrypted data to such temp files by providing temp files +// which are encrypted as well. Note that *os.File satisfies the lldb.OSFile +// interface. +// +// If TempFile is nil it defaults to ioutil.TempFile. +type Options struct { + CanCreate bool + OSFile lldb.OSFile + TempFile func(dir, prefix string) (f lldb.OSFile, err error) +} + +type fileBTreeIterator struct { + en *lldb.BTreeEnumerator + t *fileTemp +} + +func (it *fileBTreeIterator) Next() (k, v []interface{}, err error) { + bk, bv, err := it.en.Next() + if err != nil { + return + } + + if k, err = lldb.DecodeScalars(bk); err != nil { + return + } + + for i, val := range k { + b, ok := val.([]byte) + if !ok { + continue + } + + c := chunk{it.t.file, b} + if k[i], err = c.expand(); err != nil { + return nil, nil, err + } + } + + if err = enforce(k, it.t.colsK); err != nil { + return + } + + if v, err = lldb.DecodeScalars(bv); err != nil { + return + } + + for i, val := range v { + b, ok := val.([]byte) + if !ok { + continue + } + + c := chunk{it.t.file, b} + if v[i], err = c.expand(); err != nil { + return nil, nil, err + } + } + + err = enforce(v, it.t.colsV) + return +} + +func enforce(val []interface{}, cols []*col) (err error) { + for i, v := range val { + if val[i], err = convert(v, cols[i].typ); err != nil { + return + } + } + return +} + +//NTYPE +func infer(from []interface{}, to *[]*col) { + if len(*to) == 0 { + *to = make([]*col, len(from)) + for i := range *to { + (*to)[i] = &col{} + } + } + for i, c := range *to { + if f := from[i]; f != nil { + switch x := f.(type) { + //case nil: + case idealComplex: + c.typ = qComplex128 + from[i] = complex128(x) + case idealFloat: + c.typ = qFloat64 + from[i] = float64(x) + case idealInt: + c.typ = qInt64 + from[i] = int64(x) + case idealRune: + c.typ = qInt32 + from[i] = int32(x) + case idealUint: + c.typ = qUint64 + from[i] = uint64(x) + case bool: + c.typ = qBool + case complex128: + c.typ = qComplex128 + case complex64: + c.typ = qComplex64 + case float64: + c.typ = qFloat64 + case float32: + c.typ = qFloat32 + case int8: + c.typ = qInt8 + case int16: + c.typ = qInt16 + case int32: + c.typ = qInt32 + case int64: + c.typ = qInt64 + case string: + c.typ = qString + case uint8: + c.typ = qUint8 + case uint16: + c.typ = qUint16 + case uint32: + c.typ = qUint32 + case uint64: + c.typ = qUint64 + case []byte: + c.typ = qBlob + case *big.Int: + c.typ = qBigInt + case *big.Rat: + c.typ = qBigRat + case time.Time: + c.typ = qTime + case time.Duration: + c.typ = qDuration + case chunk: + vals, err := lldb.DecodeScalars([]byte(x.b)) + if err != nil { + panic(err) + } + + if len(vals) == 0 { + panic("internal error 040") + } + + i, ok := vals[0].(int64) + if !ok { + panic("internal error 041") + } + + c.typ = int(i) + case map[string]interface{}: // map of ids of a cross join + default: + panic("internal error 042") + } + } + } +} + +type fileTemp struct { + *file + colsK []*col + colsV []*col + t *lldb.BTree +} + +func (t *fileTemp) BeginTransaction() error { + return nil +} + +func (t *fileTemp) Get(k []interface{}) (v []interface{}, err error) { + if err = expand(k); err != nil { + return + } + + if err = t.flatten(k); err != nil { + return nil, err + } + + bk, err := lldb.EncodeScalars(k...) + if err != nil { + return + } + + bv, err := t.t.Get(nil, bk) + if err != nil { + return + } + + return lldb.DecodeScalars(bv) +} + +func (t *fileTemp) Drop() (err error) { + if t.f0 == nil { + return + } + + fn := t.f0.Name() + if err = t.f0.Close(); err != nil { + return + } + + if fn == "" { + return + } + + return os.Remove(fn) +} + +func (t *fileTemp) SeekFirst() (it btreeIterator, err error) { + en, err := t.t.SeekFirst() + if err != nil { + return + } + + return &fileBTreeIterator{t: t, en: en}, nil +} + +func (t *fileTemp) Set(k, v []interface{}) (err error) { + if err = expand(k); err != nil { + return + } + + if err = expand(v); err != nil { + return + } + + infer(k, &t.colsK) + infer(v, &t.colsV) + + if err = t.flatten(k); err != nil { + return + } + + bk, err := lldb.EncodeScalars(k...) + if err != nil { + return + } + + if err = t.flatten(v); err != nil { + return + } + + bv, err := lldb.EncodeScalars(v...) + if err != nil { + return + } + + return t.t.Set(bk, bv) +} + +type file struct { + a *lldb.Allocator + codec *gobCoder + f lldb.Filer + f0 lldb.OSFile + id int64 + lck io.Closer + mu sync.Mutex + name string + tempFile func(dir, prefix string) (f lldb.OSFile, err error) + wal *os.File +} + +func newFileFromOSFile(f lldb.OSFile) (fi *file, err error) { + nm := lockName(f.Name()) + lck, err := lock.Lock(nm) + if err != nil { + if lck != nil { + lck.Close() + } + return nil, err + } + + close := true + defer func() { + if close && lck != nil { + lck.Close() + } + }() + + var w *os.File + closew := false + wn := walName(f.Name()) + w, err = os.OpenFile(wn, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666) + closew = true + defer func() { + if closew { + nm := w.Name() + w.Close() + os.Remove(nm) + w = nil + } + }() + + if err != nil { + if !os.IsExist(err) { + return nil, err + } + + closew = false + w, err = os.OpenFile(wn, os.O_RDWR, 0666) + if err != nil { + return nil, err + } + + closew = true + st, err := w.Stat() + if err != nil { + return nil, err + } + + if st.Size() != 0 { + return nil, fmt.Errorf("(file-001) non empty WAL file %s exists", wn) + } + } + + info, err := f.Stat() + if err != nil { + return nil, err + } + + switch sz := info.Size(); { + case sz == 0: + b := make([]byte, 16) + copy(b, []byte(magic)) + if _, err := f.Write(b); err != nil { + return nil, err + } + + filer := lldb.Filer(lldb.NewOSFiler(f)) + filer = lldb.NewInnerFiler(filer, 16) + if filer, err = lldb.NewACIDFiler(filer, w); err != nil { + return nil, err + } + + a, err := lldb.NewAllocator(filer, &lldb.Options{}) + if err != nil { + return nil, err + } + + a.Compress = true + s := &file{ + a: a, + codec: newGobCoder(), + f0: f, + f: filer, + lck: lck, + name: f.Name(), + wal: w, + } + if err = s.BeginTransaction(); err != nil { + return nil, err + } + + h, err := s.Create() + if err != nil { + return nil, err + } + + if h != 1 { // root + panic("internal error 043") + } + + if h, err = s.a.Alloc(make([]byte, 8)); err != nil { + return nil, err + } + + if h != 2 { // id + panic("internal error 044") + } + + close, closew = false, false + return s, s.Commit() + default: + b := make([]byte, 16) + if _, err := f.Read(b); err != nil { + return nil, err + } + + if string(b[:len(magic)]) != magic { + return nil, fmt.Errorf("(file-002) unknown file format") + } + + filer := lldb.Filer(lldb.NewOSFiler(f)) + filer = lldb.NewInnerFiler(filer, 16) + if filer, err = lldb.NewACIDFiler(filer, w); err != nil { + return nil, err + } + + a, err := lldb.NewAllocator(filer, &lldb.Options{}) + if err != nil { + return nil, err + } + + bid, err := a.Get(nil, 2) // id + if err != nil { + return nil, err + } + + if len(bid) != 8 { + return nil, fmt.Errorf("(file-003) corrupted DB: id |% x|", bid) + } + + id := int64(0) + for _, v := range bid { + id = (id << 8) | int64(v) + } + + a.Compress = true + s := &file{ + a: a, + codec: newGobCoder(), + f0: f, + f: filer, + id: id, + lck: lck, + name: f.Name(), + wal: w, + } + + close, closew = false, false + return s, nil + } +} + +func (s *file) OpenIndex(unique bool, handle int64) (btreeIndex, error) { + t, err := lldb.OpenBTree(s.a, s.collate, handle) + if err != nil { + return nil, err + } + + return &fileIndex{s, handle, t, unique, newGobCoder()}, nil +} + +func (s *file) CreateIndex(unique bool) ( /* handle */ int64, btreeIndex, error) { + t, h, err := lldb.CreateBTree(s.a, s.collate) + if err != nil { + return -1, nil, err + } + + return h, &fileIndex{s, h, t, unique, newGobCoder()}, nil +} + +func (s *file) Acid() bool { return s.wal != nil } + +func errSet(p *error, errs ...error) (err error) { + err = *p + for _, e := range errs { + if err != nil { + return + } + *p, err = e, e + } + return +} + +func (s *file) lock() func() { + s.mu.Lock() + return s.mu.Unlock +} + +func (s *file) Close() (err error) { + defer s.lock()() + + es := s.f0.Sync() + ef := s.f0.Close() + var ew error + if s.wal != nil { + ew = s.wal.Close() + } + el := s.lck.Close() + return errSet(&err, es, ef, ew, el) +} + +func (s *file) Name() string { return s.name } + +func (s *file) Verify() (allocs int64, err error) { + defer s.lock()() + var stat lldb.AllocStats + if err = s.a.Verify(lldb.NewMemFiler(), nil, &stat); err != nil { + return + } + + allocs = stat.AllocAtoms + return +} + +func (s *file) expandBytes(d []interface{}) (err error) { + for i, v := range d { + b, ok := v.([]byte) + if !ok { + continue + } + + d[i], err = s.loadChunks(b) + if err != nil { + return + } + } + return +} + +func (s *file) collate(a, b []byte) int { //TODO w/ error return + da, err := lldb.DecodeScalars(a) + if err != nil { + panic(err) + } + + if err = s.expandBytes(da); err != nil { + panic(err) + } + + db, err := lldb.DecodeScalars(b) + if err != nil { + panic(err) + } + + if err = s.expandBytes(db); err != nil { + panic(err) + } + + //dbg("da: %v, db: %v", da, db) + return collate(da, db) +} + +func (s *file) CreateTemp(asc bool) (bt temp, err error) { + f, err := s.tempFile("", "ql-tmp-") + if err != nil { + return nil, err + } + + fn := f.Name() + filer := lldb.NewOSFiler(f) + a, err := lldb.NewAllocator(filer, &lldb.Options{}) + if err != nil { + f.Close() + os.Remove(fn) + return nil, err + } + + k := 1 + if !asc { + k = -1 + } + + t, _, err := lldb.CreateBTree(a, func(a, b []byte) int { //TODO w/ error return + return k * s.collate(a, b) + }) + if err != nil { + f.Close() + if fn != "" { + os.Remove(fn) + } + return nil, err + } + + x := &fileTemp{file: &file{ + a: a, + codec: newGobCoder(), + f0: f, + }, + t: t} + return x, nil +} + +func (s *file) BeginTransaction() (err error) { + defer s.lock()() + return s.f.BeginUpdate() +} + +func (s *file) Rollback() (err error) { + defer s.lock()() + return s.f.Rollback() +} + +func (s *file) Commit() (err error) { + defer s.lock()() + return s.f.EndUpdate() +} + +func (s *file) Create(data ...interface{}) (h int64, err error) { + if err = expand(data); err != nil { + return + } + + if err = s.flatten(data); err != nil { + return + } + + b, err := lldb.EncodeScalars(data...) + if err != nil { + return + } + + defer s.lock()() + return s.a.Alloc(b) +} + +func (s *file) Delete(h int64, blobCols ...*col) (err error) { + switch len(blobCols) { + case 0: + defer s.lock()() + return s.a.Free(h) + default: + return s.free(h, blobCols) + } +} + +func (s *file) ResetID() (err error) { + s.id = 0 + return +} + +func (s *file) ID() (int64, error) { + defer s.lock()() + + s.id++ + b := make([]byte, 8) + id := s.id + for i := 7; i >= 0; i-- { + b[i] = byte(id) + id >>= 8 + } + + return s.id, s.a.Realloc(2, b) +} + +func (s *file) free(h int64, blobCols []*col) (err error) { + b, err := s.a.Get(nil, h) //LATER +bufs + if err != nil { + return + } + + rec, err := lldb.DecodeScalars(b) + if err != nil { + return + } + + for _, col := range blobCols { + if col.index >= len(rec) { + return fmt.Errorf("(file-004) file.free: corrupted DB (record len)") + } + if col.index+2 >= len(rec) { + continue + } + + switch x := rec[col.index+2].(type) { + case nil: + // nop + case []byte: + if err = s.freeChunks(x); err != nil { + return + } + } + } + defer s.lock()() + return s.a.Free(h) +} + +func (s *file) Read(dst []interface{}, h int64, cols ...*col) (data []interface{}, err error) { //NTYPE + b, err := s.a.Get(nil, h) //LATER +bufs + if err != nil { + return + } + + rec, err := lldb.DecodeScalars(b) + if err != nil { + return + } + + for _, col := range cols { + i := col.index + 2 + if i >= len(rec) || rec[i] == nil { + continue + } + + switch col.typ { + case 0: + case qBool: + case qComplex64: + rec[i] = complex64(rec[i].(complex128)) + case qComplex128: + case qFloat32: + rec[i] = float32(rec[i].(float64)) + case qFloat64: + case qInt8: + rec[i] = int8(rec[i].(int64)) + case qInt16: + rec[i] = int16(rec[i].(int64)) + case qInt32: + rec[i] = int32(rec[i].(int64)) + case qInt64: + case qString: + case qUint8: + rec[i] = uint8(rec[i].(uint64)) + case qUint16: + rec[i] = uint16(rec[i].(uint64)) + case qUint32: + rec[i] = uint32(rec[i].(uint64)) + case qUint64: + case qBlob, qBigInt, qBigRat, qTime, qDuration: + switch x := rec[i].(type) { + case []byte: + rec[i] = chunk{f: s, b: x} + default: + return nil, fmt.Errorf("(file-006) corrupted DB: non nil chunk type is not []byte") + } + default: + panic("internal error 045") + } + } + + if cols != nil { + for n, dn := len(cols)+2, len(rec); dn < n; dn++ { + rec = append(rec, nil) + } + } + + return rec, nil +} + +func (s *file) freeChunks(enc []byte) (err error) { + items, err := lldb.DecodeScalars(enc) + if err != nil { + return + } + + var ok bool + var next int64 + switch len(items) { + case 2: + return + case 3: + if next, ok = items[1].(int64); !ok || next == 0 { + return fmt.Errorf("(file-007) corrupted DB: first chunk link") + } + default: + return fmt.Errorf("(file-008) corrupted DB: first chunk") + } + + for next != 0 { + b, err := s.a.Get(nil, next) + if err != nil { + return err + } + + if items, err = lldb.DecodeScalars(b); err != nil { + return err + } + + var h int64 + switch len(items) { + case 1: + // nop + case 2: + if h, ok = items[0].(int64); !ok { + return fmt.Errorf("(file-009) corrupted DB: chunk link") + } + + default: + return fmt.Errorf("(file-010) corrupted DB: chunk items %d (%v)", len(items), items) + } + + s.mu.Lock() + if err = s.a.Free(next); err != nil { + s.mu.Unlock() + return err + } + + s.mu.Unlock() + next = h + } + return +} + +func (s *file) loadChunks(enc []byte) (v interface{}, err error) { + items, err := lldb.DecodeScalars(enc) + if err != nil { + return + } + + var ok bool + var next int64 + switch len(items) { + case 2: + // nop + case 3: + if next, ok = items[1].(int64); !ok || next == 0 { + return nil, fmt.Errorf("(file-011) corrupted DB: first chunk link") + } + default: + //fmt.Printf("%d: %#v\n", len(items), items) + return nil, fmt.Errorf("(file-012) corrupted DB: first chunk") + } + + typ, ok := items[0].(int64) + if !ok { + return nil, fmt.Errorf("(file-013) corrupted DB: first chunk tag") + } + + buf, ok := items[len(items)-1].([]byte) + if !ok { + return nil, fmt.Errorf("(file-014) corrupted DB: first chunk data") + } + + for next != 0 { + b, err := s.a.Get(nil, next) + if err != nil { + return nil, err + } + + if items, err = lldb.DecodeScalars(b); err != nil { + return nil, err + } + + switch len(items) { + case 1: + next = 0 + case 2: + if next, ok = items[0].(int64); !ok { + return nil, fmt.Errorf("(file-015) corrupted DB: chunk link") + } + + items = items[1:] + default: + return nil, fmt.Errorf("(file-016) corrupted DB: chunk items %d (%v)", len(items), items) + } + + if b, ok = items[0].([]byte); !ok { + return nil, fmt.Errorf("(file-017) corrupted DB: chunk data") + } + + buf = append(buf, b...) + } + return s.codec.decode(buf, int(typ)) +} + +func (s *file) Update(h int64, data ...interface{}) (err error) { + b, err := lldb.EncodeScalars(data...) + if err != nil { + return + } + + defer s.lock()() + return s.a.Realloc(h, b) +} + +func (s *file) UpdateRow(h int64, blobCols []*col, data ...interface{}) (err error) { + if len(blobCols) == 0 { + return s.Update(h, data...) + } + + if err = expand(data); err != nil { + return + } + + data0, err := s.Read(nil, h, blobCols...) + if err != nil { + return + } + + for _, c := range blobCols { + if c.index+2 >= len(data0) { + continue + } + + if x := data0[c.index+2]; x != nil { + if err = s.freeChunks(x.(chunk).b); err != nil { + return + } + } + } + + if err = s.flatten(data); err != nil { + return + } + + return s.Update(h, data...) +} + +// []interface{}{qltype, ...}->[]interface{}{lldb scalar type, ...} +// + long blobs are (pre)written to a chain of chunks. +func (s *file) flatten(data []interface{}) (err error) { + for i, v := range data { + tag := 0 + var b []byte + switch x := v.(type) { + case []byte: + tag = qBlob + b = x + case *big.Int: + tag = qBigInt + b, err = s.codec.encode(x) + case *big.Rat: + tag = qBigRat + b, err = s.codec.encode(x) + case time.Time: + tag = qTime + b, err = s.codec.encode(x) + case time.Duration: + tag = qDuration + b, err = s.codec.encode(x) + default: + continue + } + if err != nil { + return + } + + const chunk = 1 << 16 + chunks := 0 + var next int64 + var buf []byte + for rem := len(b); rem > shortBlob; { + n := mathutil.Min(rem, chunk) + part := b[rem-n:] + b = b[:rem-n] + rem -= n + switch next { + case 0: // last chunk + buf, err = lldb.EncodeScalars([]interface{}{part}...) + default: // middle chunk + buf, err = lldb.EncodeScalars([]interface{}{next, part}...) + } + if err != nil { + return + } + + s.mu.Lock() + h, err := s.a.Alloc(buf) + s.mu.Unlock() + if err != nil { + return err + } + + next = h + chunks++ + } + + switch next { + case 0: // single chunk + buf, err = lldb.EncodeScalars([]interface{}{tag, b}...) + default: // multi chunks + buf, err = lldb.EncodeScalars([]interface{}{tag, next, b}...) + } + if err != nil { + return + } + + data[i] = buf + } + return +} + +func lockName(dbname string) string { + base := filepath.Base(filepath.Clean(dbname)) + "lockfile" + h := sha1.New() + io.WriteString(h, base) + return filepath.Join(filepath.Dir(dbname), fmt.Sprintf(".%x", h.Sum(nil))) +} + +func walName(dbname string) (r string) { + base := filepath.Base(filepath.Clean(dbname)) + h := sha1.New() + io.WriteString(h, base) + return filepath.Join(filepath.Dir(dbname), fmt.Sprintf(".%x", h.Sum(nil))) +} + +type fileIndex struct { + f *file + h int64 + t *lldb.BTree + unique bool + codec *gobCoder +} + +func (x *fileIndex) Clear() error { + return x.t.Clear() +} + +var gbZeroInt64 []byte + +func init() { + var err error + if gbZeroInt64, err = lldb.EncodeScalars(int64(0)); err != nil { + panic(err) + } +} + +func isIndexNull(data []interface{}) bool { + for _, v := range data { + if v != nil { + return false + } + } + return true +} + +// The []byte version of the key in the BTree shares chunks, if any, with +// the value stored in the record. +func (x *fileIndex) Create(indexedValues []interface{}, h int64) error { + for i, indexedValue := range indexedValues { + chunk, ok := indexedValue.(chunk) + if ok { + indexedValues[i] = chunk.b + } + } + + t := x.t + switch { + case !x.unique: + k, err := lldb.EncodeScalars(append(indexedValues, h)...) + if err != nil { + return err + } + + return t.Set(k, gbZeroInt64) + case isIndexNull(indexedValues): // unique, NULL + k, err := lldb.EncodeScalars(nil, h) + if err != nil { + return err + } + + return t.Set(k, gbZeroInt64) + default: // unique, non NULL + k, err := lldb.EncodeScalars(append(indexedValues, int64(0))...) + if err != nil { + return err + } + + v, err := lldb.EncodeScalars(h) + if err != nil { + return err + } + + _, _, err = t.Put(nil, k, func(key, old []byte) (new []byte, write bool, err error) { + if old == nil { + return v, true, nil + } + + return nil, false, fmt.Errorf("(file-018) cannot insert into unique index: duplicate value(s): %v", indexedValues) + }) + return err + } +} + +func (x *fileIndex) Delete(indexedValues []interface{}, h int64) error { + for i, indexedValue := range indexedValues { + chunk, ok := indexedValue.(chunk) + if ok { + indexedValues[i] = chunk.b + } + } + + t := x.t + var k []byte + var err error + switch { + case !x.unique: + k, err = lldb.EncodeScalars(append(indexedValues, h)...) + case isIndexNull(indexedValues): // unique, NULL + k, err = lldb.EncodeScalars(nil, h) + default: // unique, non NULL + k, err = lldb.EncodeScalars(append(indexedValues, int64(0))...) + } + if err != nil { + return err + } + + return t.Delete(k) +} + +func (x *fileIndex) Drop() error { + if err := x.Clear(); err != nil { + return err + } + + return x.f.a.Free(x.h) +} + +// []interface{}{qltype, ...}->[]interface{}{lldb scalar type, ...} +func (x *fileIndex) flatten(data []interface{}) (err error) { + for i, v := range data { + tag := 0 + var b []byte + switch xx := v.(type) { + case []byte: + tag = qBlob + b = xx + case *big.Int: + tag = qBigInt + b, err = x.codec.encode(xx) + case *big.Rat: + tag = qBigRat + b, err = x.codec.encode(xx) + case time.Time: + tag = qTime + b, err = x.codec.encode(xx) + case time.Duration: + tag = qDuration + b, err = x.codec.encode(xx) + default: + continue + } + if err != nil { + return + } + + var buf []byte + if buf, err = lldb.EncodeScalars([]interface{}{tag, b}...); err != nil { + return + } + + data[i] = buf + } + return +} + +func (x *fileIndex) Seek(indexedValues []interface{}) (indexIterator, bool, error) { + data := append(indexedValues, 0) + if err := x.flatten(data); err != nil { + return nil, false, err + } + + k, err := lldb.EncodeScalars(data...) + if err != nil { + return nil, false, err + } + + en, hit, err := x.t.Seek(k) + if err != nil { + return nil, false, err + } + + return &fileIndexIterator{x.f, en, x.unique}, hit, nil +} + +func (x *fileIndex) SeekFirst() (iter indexIterator, err error) { + en, err := x.t.SeekFirst() + return &fileIndexIterator{x.f, en, x.unique}, err +} + +func (x *fileIndex) SeekLast() (iter indexIterator, err error) { + en, err := x.t.SeekLast() + return &fileIndexIterator{x.f, en, x.unique}, err +} + +type fileIndexIterator struct { + f *file + en *lldb.BTreeEnumerator + unique bool +} + +func (i *fileIndexIterator) nextPrev(f func() ([]byte, []byte, error)) ([]interface{}, int64, error) { //TODO(indices) blobs: +test + bk, bv, err := f() + if err != nil { + return nil, -1, err + } + + dk, err := lldb.DecodeScalars(bk) + if err != nil { + return nil, -1, err + } + + b, ok := dk[0].([]byte) + if ok { + dk[0] = chunk{i.f, b} + if expand(dk[:1]); err != nil { + return nil, -1, err + } + } + + var k indexKey + k.value = dk[:len(dk)-1] + switch i.unique { + case true: + if isIndexNull(k.value) { + return nil, dk[len(dk)-1].(int64), nil + } + + dv, err := lldb.DecodeScalars(bv) + if err != nil { + return nil, -1, err + } + + return k.value, dv[0].(int64), nil + default: + return k.value, dk[len(dk)-1].(int64), nil + } +} + +func (i *fileIndexIterator) Next() ([]interface{}, int64, error) { //TODO(indices) blobs: +test + return i.nextPrev(i.en.Next) +} + +func (i *fileIndexIterator) Prev() ([]interface{}, int64, error) { //TODO(indices) blobs: +test + return i.nextPrev(i.en.Prev) +} diff --git a/vendor/github.com/cznic/ql/helper/helper.go b/vendor/github.com/cznic/ql/helper/helper.go new file mode 100644 index 00000000..7ce30153 --- /dev/null +++ b/vendor/github.com/cznic/ql/helper/helper.go @@ -0,0 +1,338 @@ +// +build ignore + +// Copyright 2014 The ql 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 main + +import ( + "bufio" + "flag" + "fmt" + "io" + "log" + "os" +) + +type t int + +const ( + qNil t = iota + idealComplex + idealFloat + idealInt + idealRune + idealUint + qBool + qComplex64 + qComplex128 + qFloat32 + qFloat64 + qInt8 + qInt16 + qInt32 + qInt64 + qString + qUint8 + qUint16 + qUint32 + qUint64 + qBigInt + qBigRat + qTime + qDuration + + qEnd +) + +func (n t) String() string { + switch n { + case qNil: + return "nil" + case idealComplex: + return "idealComplex" + case idealFloat: + return "idealFloat" + case idealInt: + return "idealInt" + case idealRune: + return "idealRune" + case idealUint: + return "idealUint" + case qBool: + return "bool" + case qComplex64: + return "complex64" + case qComplex128: + return "complex128" + case qFloat32: + return "float32" + case qFloat64: + return "float64" + case qInt8: + return "int8" + case qInt16: + return "int16" + case qInt32: + return "int32" + case qInt64: + return "int64" + case qString: + return "string" + case qUint8: + return "uint8" + case qUint16: + return "uint16" + case qUint32: + return "uint32" + case qUint64: + return "uint64" + case qBigInt: + return "*big.Int" + case qBigRat: + return "*big.Rat" + case qTime: + return "time.Time" + case qDuration: + return "time.Duration" + default: + panic("internal error 046") + } +} + +func coerceIdealComplex(typ t) string { + switch typ { + case qComplex64, qComplex128: + return fmt.Sprintf("return %s(x)\n", typ) + default: + return "" + } +} + +func coerceIdealFloat(typ t) string { + switch typ { + case idealComplex: + return fmt.Sprintf("return %s(complex(float64(x), 0))\n", typ) + case qComplex64: + return fmt.Sprintf("return %s(complex(float32(x), 0))\n", typ) + case qComplex128: + return fmt.Sprintf("return %s(complex(float64(x), 0))\n", typ) + case idealFloat, qFloat32, qFloat64: + return fmt.Sprintf("return %s(float64(x))\n", typ) + case qBigRat: + return fmt.Sprintf("return big.NewRat(1, 1).SetFloat64(float64(x))\n") + default: + return "" + } + return "" +} + +func coerceIdealInt(typ t) string { + switch typ { + case idealComplex: + return fmt.Sprintf("return %s(complex(float64(x), 0))\n", typ) + case qComplex64: + return fmt.Sprintf("return %s(complex(float32(x), 0))\n", typ) + case qComplex128: + return fmt.Sprintf("return %s(complex(float64(x), 0))\n", typ) + case idealFloat, idealInt, qFloat32, qFloat64, qInt64: + return fmt.Sprintf("return %s(int64(x))\n", typ) + case idealUint: + return fmt.Sprintf("if x >= 0 { return %s(int64(x)) }\n", typ) + case qInt8: + return fmt.Sprintf("if x >= math.MinInt8 && x<= math.MaxInt8 { return %s(int64(x)) }\n", typ) + case qInt16: + return fmt.Sprintf("if x >= math.MinInt16 && x<= math.MaxInt16 { return %s(int64(x)) }\n", typ) + case qInt32: + return fmt.Sprintf("if x >= math.MinInt32 && x<= math.MaxInt32 { return %s(int64(x)) }\n", typ) + case qUint8: + return fmt.Sprintf("if x >= 0 && x<= math.MaxUint8 { return %s(int64(x)) }\n", typ) + case qUint16: + return fmt.Sprintf("if x >= 0 && x<= math.MaxUint16 { return %s(int64(x)) }\n", typ) + case qUint32: + return fmt.Sprintf("if x >= 0 && x<= math.MaxUint32 { return %s(int64(x)) }\n", typ) + case qUint64: + return fmt.Sprintf("if x >= 0 { return %s(int64(x)) }\n", typ) + case qBigInt: + return fmt.Sprintf("return big.NewInt(int64(x))\n") + case qBigRat: + return fmt.Sprintf("return big.NewRat(1, 1).SetInt64(int64(x))\n") + case qDuration: + return fmt.Sprintf("return time.Duration(int64(x))\n") + default: + return "" + } + return "" +} + +func coerceIdealRune(typ t) string { + switch typ { + case idealComplex: + return fmt.Sprintf("return %s(complex(float64(x), 0))\n", typ) + case qComplex64: + return fmt.Sprintf("return %s(complex(float32(x), 0))\n", typ) + case qComplex128: + return fmt.Sprintf("return %s(complex(float64(x), 0))\n", typ) + case idealFloat, idealInt, idealRune, idealUint, qFloat32, qFloat64, qInt8, qInt16, qInt32, qInt64, qUint8, qUint16, qUint32, qUint64: + return fmt.Sprintf("return %s(int64(x))\n", typ) + case qBigInt: + return fmt.Sprintf("return big.NewInt(int64(x))\n") + case qBigRat: + return fmt.Sprintf("return big.NewRat(1, 1).SetInt64(int64(x))\n") + case qDuration: + return fmt.Sprintf("return time.Duration(int64(x))\n") + default: + return "" + } + return "" +} + +func coerceIdealUint(typ t) string { + switch typ { + case idealComplex: + return fmt.Sprintf("return %s(complex(float64(x), 0))\n", typ) + case qComplex64: + return fmt.Sprintf("return %s(complex(float32(x), 0))\n", typ) + case qComplex128: + return fmt.Sprintf("return %s(complex(float64(x), 0))\n", typ) + case idealFloat, idealUint, qFloat32, qFloat64, qUint64: + return fmt.Sprintf("return %s(uint64(x))\n", typ) + case idealInt: + return fmt.Sprintf("if x <= math.MaxInt64 { return %s(int64(x)) }\n", typ) + case qInt8: + return fmt.Sprintf("if x <= math.MaxInt8 { return %s(int64(x)) }\n", typ) + case qInt16: + return fmt.Sprintf("if x<= math.MaxInt16 { return %s(int64(x)) }\n", typ) + case qInt32: + return fmt.Sprintf("if x<= math.MaxInt32 { return %s(int64(x)) }\n", typ) + case qInt64: + return fmt.Sprintf("if x<= math.MaxInt64 { return %s(int64(x)) }\n", typ) + case qUint8: + return fmt.Sprintf("if x >= 0 && x<= math.MaxUint8 { return %s(int64(x)) }\n", typ) + case qUint16: + return fmt.Sprintf("if x >= 0 && x<= math.MaxUint16 { return %s(int64(x)) }\n", typ) + case qUint32: + return fmt.Sprintf("if x >= 0 && x<= math.MaxUint32 { return %s(int64(x)) }\n", typ) + case qBigInt: + return fmt.Sprintf("return big.NewInt(0).SetUint64(uint64(x))\n") + case qBigRat: + return fmt.Sprintf("return big.NewRat(1, 1).SetInt(big.NewInt(0).SetUint64(uint64(x)))\n") + case qDuration: + return fmt.Sprintf("if x <= math.MaxInt64 { return time.Duration(int64(x)) }\n") + default: + return "" + } + return "" +} + +func genCoerce1(w io.Writer, in t, f func(out t) string) { + fmt.Fprintf(w, "\tcase %s:\n", in) + fmt.Fprintf(w, "\t\tswitch otherVal.(type) {\n") + + for i := idealComplex; i < qEnd; i++ { + s := f(i) + switch s { + case "": + fmt.Fprintf(w, "\t\t//case %s:\n", i) + default: + fmt.Fprintf(w, "\t\tcase %s:\n", i) + fmt.Fprintf(w, "\t\t\t%s", s) + } + } + + fmt.Fprintf(w, "\t\t}\n") // switch +} + +func genCoerce(w io.Writer) { + fmt.Fprintf(w, + ` +func coerce1(inVal, otherVal interface{}) (coercedInVal interface{}) { + coercedInVal = inVal + if otherVal == nil { + return + } + + switch x := inVal.(type) { + case nil: + return +`) + genCoerce1(w, idealComplex, coerceIdealComplex) + genCoerce1(w, idealFloat, coerceIdealFloat) + genCoerce1(w, idealInt, coerceIdealInt) + genCoerce1(w, idealRune, coerceIdealRune) + genCoerce1(w, idealUint, coerceIdealUint) + fmt.Fprintf(w, "\t}\n") // switch + + fmt.Fprintf(w, "\treturn\n}\n") // func +} + +func main() { + ofn := flag.String("o", "", "") + flag.Parse() + _, err := os.Stat(*ofn) + if err == nil { + log.Fatalf("%s exists", *ofn) + } + + w := bufio.NewWriter(os.Stdout) + if s := *ofn; s != "" { + f, err := os.Create(s) + if err != nil { + log.Fatal(err) + } + + defer f.Close() + w = bufio.NewWriter(f) + } + defer w.Flush() + + fmt.Fprintf(w, `// Copyright 2013 The ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// CAUTION: This file was generated automatically by +// +// $ go run helper/helper.go -o coerce.go +// +// DO NOT EDIT! + + package ql + +import ( + "math" + "math/big" + "reflect" + "time" +) + +func coerce(a, b interface{}) (x, y interface{}) { + if reflect.TypeOf(a) == reflect.TypeOf(b) { + return a, b + } + + switch a.(type) { + case idealComplex, idealFloat, idealInt, idealRune, idealUint: + switch b.(type) { + case idealComplex, idealFloat, idealInt, idealRune, idealUint: + x, y = coerce1(a, b), b + if reflect.TypeOf(x) == reflect.TypeOf(y) { + return + } + + return a, coerce1(b, a) + default: + return coerce1(a, b), b + } + default: + switch b.(type) { + case idealComplex, idealFloat, idealInt, idealRune, idealUint: + return a, coerce1(b, a) + default: + return a, b + } + } +} +`) + genCoerce(w) +} diff --git a/vendor/github.com/cznic/ql/httpfs.go b/vendor/github.com/cznic/ql/httpfs.go new file mode 100644 index 00000000..89c6f89c --- /dev/null +++ b/vendor/github.com/cznic/ql/httpfs.go @@ -0,0 +1,302 @@ +// Copyright (c) 2014 ql 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 ql + +import ( + "fmt" + "io" + "net/http" + "os" + "path" + "path/filepath" + "strings" + "time" + + "github.com/cznic/mathutil" +) + +var ( + _ http.FileSystem = (*HTTPFS)(nil) + _ http.File = (*HTTPFile)(nil) + _ os.FileInfo = (*HTTPFile)(nil) + _ os.FileInfo = (*dirEntry)(nil) +) + +type dirEntry string + +func (d dirEntry) Name() string { return string(d) } +func (d dirEntry) Size() int64 { return -1 } +func (d dirEntry) Mode() os.FileMode { return os.ModeDir } +func (d dirEntry) ModTime() time.Time { return time.Time{} } +func (d dirEntry) IsDir() bool { return true } +func (d dirEntry) Sys() interface{} { return interface{}(nil) } + +// A HTTPFile is returned by the HTTPFS's Open method and can be served by the +// http.FileServer implementation. +type HTTPFile struct { + closed bool + content []byte + dirEntries []os.FileInfo + isFile bool + name string + off int + sz int +} + +// Close implements http.File. +func (f *HTTPFile) Close() error { + if f.closed { + return os.ErrInvalid + } + + f.closed = true + return nil +} + +// IsDir implements os.FileInfo +func (f *HTTPFile) IsDir() bool { return !f.isFile } + +// Mode implements os.FileInfo +func (f *HTTPFile) Mode() os.FileMode { + switch f.isFile { + case false: + return os.FileMode(0444) + default: + return os.ModeDir + } +} + +// ModTime implements os.FileInfo +func (f *HTTPFile) ModTime() time.Time { + return time.Time{} +} + +// Name implements os.FileInfo +func (f *HTTPFile) Name() string { return path.Base(f.name) } + +// Size implements os.FileInfo +func (f *HTTPFile) Size() int64 { + switch f.isFile { + case false: + return -1 + default: + return int64(len(f.content)) + } +} + +// Stat implements http.File. +func (f *HTTPFile) Stat() (os.FileInfo, error) { return f, nil } + +// Sys implements os.FileInfo +func (f *HTTPFile) Sys() interface{} { return interface{}(nil) } + +// Readdir implements http.File. +func (f *HTTPFile) Readdir(count int) ([]os.FileInfo, error) { + if f.isFile { + return nil, fmt.Errorf("not a directory: %s", f.name) + } + + if count <= 0 { + r := f.dirEntries + f.dirEntries = f.dirEntries[:0] + return r, nil + } + + rq := mathutil.Min(count, len(f.dirEntries)) + r := f.dirEntries[:rq] + f.dirEntries = f.dirEntries[rq:] + if len(r) != 0 { + return r, nil + } + + return nil, io.EOF +} + +// Read implements http.File. +func (f *HTTPFile) Read(b []byte) (int, error) { + if f.closed { + return 0, os.ErrInvalid + } + + n := copy(b, f.content[f.off:]) + f.off += n + if n != 0 { + return n, nil + } + + return 0, io.EOF +} + +// Seek implements http.File. +func (f *HTTPFile) Seek(offset int64, whence int) (int64, error) { + if f.closed { + return 0, os.ErrInvalid + } + + if offset < 0 { + return int64(f.off), fmt.Errorf("cannot seek before start of file") + } + + switch whence { + case 0: + noff := int64(f.off) + offset + if noff > mathutil.MaxInt { + return int64(f.off), fmt.Errorf("seek target overflows int: %d", noff) + } + + f.off = mathutil.Min(int(offset), len(f.content)) + if f.off == int(offset) { + return offset, nil + } + + return int64(f.off), io.EOF + case 1: + noff := int64(f.off) + offset + if noff > mathutil.MaxInt { + return int64(f.off), fmt.Errorf("seek target overflows int: %d", noff) + } + + off := mathutil.Min(f.off+int(offset), len(f.content)) + if off == f.off+int(offset) { + f.off = off + return int64(off), nil + } + + f.off = off + return int64(off), io.EOF + case 2: + noff := int64(f.off) - offset + if noff < 0 { + return int64(f.off), fmt.Errorf("cannot seek before start of file") + } + + f.off = len(f.content) - int(offset) + return int64(f.off), nil + default: + return int64(f.off), fmt.Errorf("seek: invalid whence %d", whence) + } +} + +// HTTPFS implements a http.FileSystem backed by data in a DB. +type HTTPFS struct { + db *DB + dir, get List +} + +// NewHTTPFS returns a http.FileSystem backed by a result record set of query. +// The record set provides two mandatory fields: path and content (the field +// names are case sensitive). Type of name must be string and type of content +// must be blob (ie. []byte). Field 'path' value is the "file" pathname, which +// must be rooted; and field 'content' value is its "data". +func (db *DB) NewHTTPFS(query string) (*HTTPFS, error) { + if _, err := Compile(query); err != nil { + return nil, err + } + + dir, err := Compile(fmt.Sprintf("SELECT path FROM (%s) WHERE hasPrefix(path, $1)", query)) + if err != nil { + return nil, err + } + + get, err := Compile(fmt.Sprintf("SELECT content FROM (%s) WHERE path == $1", query)) + if err != nil { + return nil, err + } + + return &HTTPFS{db: db, dir: dir, get: get}, nil +} + +// Open implements http.FileSystem. The name parameter represents a file path. +// The elements in a file path are separated by slash ('/', U+002F) characters, +// regardless of host operating system convention. +func (f *HTTPFS) Open(name string) (http.File, error) { + if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 || + strings.Contains(name, "\x00") { + return nil, fmt.Errorf("invalid character in file path: %q", name) + } + + name = path.Clean("/" + name) + rs, _, err := f.db.Execute(nil, f.get, name) + if err != nil { + return nil, err + } + + n := 0 + var fdata []byte + if err = rs[0].Do(false, func(data []interface{}) (more bool, err error) { + switch n { + case 0: + var ok bool + fdata, ok = data[0].([]byte) + if !ok { + return false, fmt.Errorf("open: expected blob, got %T", data[0]) + } + n++ + return true, nil + default: + return false, fmt.Errorf("open: more than one result was returned for %s", name) + } + }); err != nil { + return nil, err + } + + if n == 1 { // file found + return &HTTPFile{name: name, isFile: true, content: fdata}, nil + } + + dirName := name + if dirName[len(dirName)-1] != filepath.Separator { + dirName += string(filepath.Separator) + } + // Open("/a/b"): {/a/b/c.x,/a/b/d.x,/a/e.x,/a/b/f/g.x} -> {c.x,d.x,f} + rs, _, err = f.db.Execute(nil, f.dir, dirName) + if err != nil { + return nil, err + } + + n = 0 + r := &HTTPFile{name: dirName} + m := map[string]bool{} + x := len(dirName) + if err = rs[0].Do(false, func(data []interface{}) (more bool, err error) { + n++ + switch name := data[0].(type) { + case string: + if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 || + strings.Contains(name, "\x00") { + return false, fmt.Errorf("invalid character in file path: %q", name) + } + + name = path.Clean("/" + name) + rest := name[x:] + parts := strings.Split(rest, "/") + if len(parts) == 0 { + return true, nil + } + + nm := parts[0] + switch len(parts) { + case 1: // file + r.dirEntries = append(r.dirEntries, &HTTPFile{isFile: true, name: nm}) + default: // directory + if !m[nm] { + r.dirEntries = append(r.dirEntries, dirEntry(nm)) + } + m[nm] = true + } + return true, nil + default: + return false, fmt.Errorf("expected string path, got %T(%v)", name, name) + } + }); err != nil { + return nil, err + } + + if n != 0 { + return r, nil + } + + return nil, os.ErrNotExist +} diff --git a/vendor/github.com/cznic/ql/introspection.go b/vendor/github.com/cznic/ql/introspection.go new file mode 100644 index 00000000..61ac9a92 --- /dev/null +++ b/vendor/github.com/cznic/ql/introspection.go @@ -0,0 +1,625 @@ +// Copyright 2014 The ql 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 ql + +import ( + "bytes" + "fmt" + "go/ast" + "reflect" + "strings" + "sync" +) + +var ( + schemaCache = map[reflect.Type]*StructInfo{} + schemaMu sync.RWMutex +) + +// StructInfo describes a struct type. An instance of StructInfo obtained from +// StructSchema is shared and must not be mutated. That includes the values +// pointed to by the elements of Fields and Indices. +type StructInfo struct { + Fields []*StructField // Fields describe the considered fields of a struct type. + HasID bool // Whether the struct has a considered field named ID of type int64. + Indices []*StructIndex // Indices describe indices defined by the index or uindex ql tags. + IsPtr bool // Whether the StructInfo was derived from a pointer to a struct. +} + +// StructIndex describes an index defined by the ql tag index or uindex. +type StructIndex struct { + ColumnName string // Name of the column the index is on. + Name string // Name of the index. + Unique bool // Whether the index is unique. +} + +// StructField describes a considered field of a struct type. +type StructField struct { + Index int // Index is the index of the field for reflect.Value.Field. + IsID bool // Whether the field corresponds to record id(). + IsPtr bool // Whether the field is a pointer type. + MarshalType reflect.Type // The reflect.Type a field must be converted to when marshaling or nil when it is assignable directly. (Field->value) + Name string // Field name or value of the name tag (like in `ql:"name foo"`). + ReflectType reflect.Type // The reflect.Type of the field. + Tags map[string]string // QL tags of this field. (`ql:"a, b c, d"` -> {"a": "", "b": "c", "d": ""}) + Type Type // QL type of the field. + UnmarshalType reflect.Type // The reflect.Type a value must be converted to when unmarshaling or nil when it is assignable directly. (Field<-value) + ZeroPtr reflect.Value // The reflect.Zero value of the field if it's a pointer type. +} + +func (s *StructField) check(v interface{}) error { + t := reflect.TypeOf(v) + if !s.ReflectType.AssignableTo(t) { + if !s.ReflectType.ConvertibleTo(t) { + return fmt.Errorf("type %s (%v) cannot be converted to %T", s.ReflectType.Name(), s.ReflectType.Kind(), t.Name()) + } + + s.MarshalType = t + } + + if !t.AssignableTo(s.ReflectType) { + if !t.ConvertibleTo(s.ReflectType) { + return fmt.Errorf("type %s (%v) cannot be converted to %T", t.Name(), t.Kind(), s.ReflectType.Name()) + } + + s.UnmarshalType = s.ReflectType + } + return nil +} + +func parseTag(s string) map[string]string { + m := map[string]string{} + for _, v := range strings.Split(s, ",") { + v = strings.TrimSpace(v) + switch n := strings.IndexRune(v, ' '); { + case n < 0: + m[v] = "" + default: + m[v[:n]] = v[n+1:] + } + } + return m +} + +// StructSchema returns StructInfo for v which must be a struct instance or a +// pointer to a struct. The info is computed only once for every type. +// Subsequent calls to StructSchema for the same type return a cached +// StructInfo. +// +// Note: The returned StructSchema is shared and must be not mutated, including +// any other data structures it may point to. +func StructSchema(v interface{}) (*StructInfo, error) { + if v == nil { + return nil, fmt.Errorf("cannot derive schema for %T(%v)", v, v) + } + + typ := reflect.TypeOf(v) + schemaMu.RLock() + if r, ok := schemaCache[typ]; ok { + schemaMu.RUnlock() + return r, nil + } + + schemaMu.RUnlock() + var schemaPtr bool + t := typ + if t.Kind() == reflect.Ptr { + t = t.Elem() + schemaPtr = true + } + if k := t.Kind(); k != reflect.Struct { + return nil, fmt.Errorf("cannot derive schema for type %T (%v)", v, k) + } + + r := &StructInfo{IsPtr: schemaPtr} + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + fn := f.Name + if !ast.IsExported(fn) { + continue + } + + tags := parseTag(f.Tag.Get("ql")) + if _, ok := tags["-"]; ok { + continue + } + + if s := tags["name"]; s != "" { + fn = s + } + + if fn == "ID" && f.Type.Kind() == reflect.Int64 { + r.HasID = true + } + var ix, unique bool + var xn string + xfn := fn + if s := tags["index"]; s != "" { + if _, ok := tags["uindex"]; ok { + return nil, fmt.Errorf("both index and uindex in QL struct tag") + } + + ix, xn = true, s + } else if s := tags["uindex"]; s != "" { + if _, ok := tags["index"]; ok { + return nil, fmt.Errorf("both index and uindex in QL struct tag") + } + + ix, unique, xn = true, true, s + } + if ix { + if fn == "ID" && r.HasID { + xfn = "id()" + } + r.Indices = append(r.Indices, &StructIndex{Name: xn, ColumnName: xfn, Unique: unique}) + } + + sf := &StructField{Index: i, Name: fn, Tags: tags, Type: Type(-1), ReflectType: f.Type} + fk := sf.ReflectType.Kind() + if fk == reflect.Ptr { + sf.IsPtr = true + sf.ZeroPtr = reflect.Zero(sf.ReflectType) + sf.ReflectType = sf.ReflectType.Elem() + fk = sf.ReflectType.Kind() + } + + switch fk { + case reflect.Bool: + sf.Type = Bool + if err := sf.check(false); err != nil { + return nil, err + } + case reflect.Int, reflect.Uint: + return nil, fmt.Errorf("only integers of fixed size can be used to derive a schema: %v", fk) + case reflect.Int8: + sf.Type = Int8 + if err := sf.check(int8(0)); err != nil { + return nil, err + } + case reflect.Int16: + if err := sf.check(int16(0)); err != nil { + return nil, err + } + sf.Type = Int16 + case reflect.Int32: + if err := sf.check(int32(0)); err != nil { + return nil, err + } + sf.Type = Int32 + case reflect.Int64: + if sf.ReflectType.Name() == "Duration" && sf.ReflectType.PkgPath() == "time" { + sf.Type = Duration + break + } + + sf.Type = Int64 + if err := sf.check(int64(0)); err != nil { + return nil, err + } + case reflect.Uint8: + sf.Type = Uint8 + if err := sf.check(uint8(0)); err != nil { + return nil, err + } + case reflect.Uint16: + sf.Type = Uint16 + if err := sf.check(uint16(0)); err != nil { + return nil, err + } + case reflect.Uint32: + sf.Type = Uint32 + if err := sf.check(uint32(0)); err != nil { + return nil, err + } + case reflect.Uint64: + sf.Type = Uint64 + if err := sf.check(uint64(0)); err != nil { + return nil, err + } + case reflect.Float32: + sf.Type = Float32 + if err := sf.check(float32(0)); err != nil { + return nil, err + } + case reflect.Float64: + sf.Type = Float64 + if err := sf.check(float64(0)); err != nil { + return nil, err + } + case reflect.Complex64: + sf.Type = Complex64 + if err := sf.check(complex64(0)); err != nil { + return nil, err + } + case reflect.Complex128: + sf.Type = Complex128 + if err := sf.check(complex128(0)); err != nil { + return nil, err + } + case reflect.Slice: + sf.Type = Blob + if err := sf.check([]byte(nil)); err != nil { + return nil, err + } + case reflect.Struct: + switch sf.ReflectType.PkgPath() { + case "math/big": + switch sf.ReflectType.Name() { + case "Int": + sf.Type = BigInt + case "Rat": + sf.Type = BigRat + } + case "time": + switch sf.ReflectType.Name() { + case "Time": + sf.Type = Time + } + } + case reflect.String: + sf.Type = String + if err := sf.check(""); err != nil { + return nil, err + } + } + + if sf.Type < 0 { + return nil, fmt.Errorf("cannot derive schema for type %s (%v)", sf.ReflectType.Name(), fk) + } + + sf.IsID = fn == "ID" && r.HasID + r.Fields = append(r.Fields, sf) + } + + schemaMu.Lock() + schemaCache[typ] = r + if t != typ { + r2 := *r + r2.IsPtr = false + schemaCache[t] = &r2 + } + schemaMu.Unlock() + return r, nil +} + +// MustStructSchema is like StructSchema but panics on error. It simplifies +// safe initialization of global variables holding StructInfo. +// +// MustStructSchema is safe for concurrent use by multiple goroutines. +func MustStructSchema(v interface{}) *StructInfo { + s, err := StructSchema(v) + if err != nil { + panic(err) + } + + return s +} + +// SchemaOptions amend the result of Schema. +type SchemaOptions struct { + // Don't wrap the CREATE statement(s) in a transaction. + NoTransaction bool + + // Don't insert the IF NOT EXISTS clause in the CREATE statement(s). + NoIfNotExists bool + + // Do not strip the "pkg." part from type name "pkg.Type", produce + // "pkg_Type" table name instead. Applies only when no name is passed + // to Schema(). + KeepPrefix bool +} + +var zeroSchemaOptions SchemaOptions + +// Schema returns a CREATE TABLE/INDEX statement(s) for a table derived from a +// struct or an error, if any. The table is named using the name parameter. If +// name is an empty string then the type name of the struct is used while non +// conforming characters are replaced by underscores. Value v can be also a +// pointer to a struct. +// +// Every considered struct field type must be one of the QL types or a type +// convertible to string, bool, int*, uint*, float* or complex* type or pointer +// to such type. Integers with a width dependent on the architecture can not be +// used. Only exported fields are considered. If an exported field QL tag +// contains "-" (`ql:"-"`) then such field is not considered. A field with name +// ID, having type int64, corresponds to id() - and is thus not a part of the +// CREATE statement. A field QL tag containing "index name" or "uindex name" +// triggers additionally creating an index or unique index on the respective +// field. Fields can be renamed using a QL tag "name newName". Fields are +// considered in the order of appearance. A QL tag is a struct tag part +// prefixed by "ql:". Tags can be combined, for example: +// +// type T struct { +// Foo string `ql:"index xFoo, name Bar"` +// } +// +// If opts.NoTransaction == true then the statement(s) are not wrapped in a +// transaction. If opt.NoIfNotExists == true then the CREATE statement(s) omits +// the IF NOT EXISTS clause. Passing nil opts is equal to passing +// &SchemaOptions{} +// +// Schema is safe for concurrent use by multiple goroutines. +func Schema(v interface{}, name string, opt *SchemaOptions) (List, error) { + if opt == nil { + opt = &zeroSchemaOptions + } + s, err := StructSchema(v) + if err != nil { + return List{}, err + } + + var buf bytes.Buffer + if !opt.NoTransaction { + buf.WriteString("BEGIN TRANSACTION; ") + } + buf.WriteString("CREATE TABLE ") + if !opt.NoIfNotExists { + buf.WriteString("IF NOT EXISTS ") + } + if name == "" { + name = fmt.Sprintf("%T", v) + if !opt.KeepPrefix { + a := strings.Split(name, ".") + if l := len(a); l > 1 { + name = a[l-1] + } + } + nm := []rune{} + for _, v := range name { + switch { + case v >= '0' && v <= '9' || v == '_' || v >= 'a' && v <= 'z' || v >= 'A' && v <= 'Z': + // ok + default: + v = '_' + } + nm = append(nm, v) + } + name = string(nm) + } + buf.WriteString(name + " (") + for _, v := range s.Fields { + if v.IsID { + continue + } + + buf.WriteString(fmt.Sprintf("%s %s, ", v.Name, v.Type)) + } + buf.WriteString("); ") + for _, v := range s.Indices { + buf.WriteString("CREATE ") + if v.Unique { + buf.WriteString("UNIQUE ") + } + buf.WriteString("INDEX ") + if !opt.NoIfNotExists { + buf.WriteString("IF NOT EXISTS ") + } + buf.WriteString(fmt.Sprintf("%s ON %s (%s); ", v.Name, name, v.ColumnName)) + } + if !opt.NoTransaction { + buf.WriteString("COMMIT; ") + } + l, err := Compile(buf.String()) + if err != nil { + return List{}, fmt.Errorf("%s: %v", buf.String(), err) + } + + return l, nil +} + +// MustSchema is like Schema but panics on error. It simplifies safe +// initialization of global variables holding compiled schemas. +// +// MustSchema is safe for concurrent use by multiple goroutines. +func MustSchema(v interface{}, name string, opt *SchemaOptions) List { + l, err := Schema(v, name, opt) + if err != nil { + panic(err) + } + + return l +} + +// Marshal converts, in the order of appearance, fields of a struct instance v +// to []interface{} or an error, if any. Value v can be also a pointer to a +// struct. +// +// Every considered struct field type must be one of the QL types or a type +// convertible to string, bool, int*, uint*, float* or complex* type or pointer +// to such type. Integers with a width dependent on the architecture can not be +// used. Only exported fields are considered. If an exported field QL tag +// contains "-" then such field is not considered. A QL tag is a struct tag +// part prefixed by "ql:". Field with name ID, having type int64, corresponds +// to id() - and is thus not part of the result. +// +// Marshal is safe for concurrent use by multiple goroutines. +func Marshal(v interface{}) ([]interface{}, error) { + s, err := StructSchema(v) + if err != nil { + return nil, err + } + + val := reflect.ValueOf(v) + if s.IsPtr { + val = val.Elem() + } + n := len(s.Fields) + if s.HasID { + n-- + } + r := make([]interface{}, n) + j := 0 + for _, v := range s.Fields { + if v.IsID { + continue + } + + f := val.Field(v.Index) + if v.IsPtr { + if f.IsNil() { + r[j] = nil + j++ + continue + } + + f = f.Elem() + } + if m := v.MarshalType; m != nil { + f = f.Convert(m) + } + r[j] = f.Interface() + j++ + } + return r, nil +} + +// MustMarshal is like Marshal but panics on error. It simplifies marshaling of +// "safe" types, like eg. those which were already verified by Schema or +// MustSchema. When the underlying Marshal returns an error, MustMarshal +// panics. +// +// MustMarshal is safe for concurrent use by multiple goroutines. +func MustMarshal(v interface{}) []interface{} { + r, err := Marshal(v) + if err != nil { + panic(err) + } + + return r +} + +// Unmarshal stores data from []interface{} in the struct value pointed to by +// v. +// +// Every considered struct field type must be one of the QL types or a type +// convertible to string, bool, int*, uint*, float* or complex* type or pointer +// to such type. Integers with a width dependent on the architecture can not be +// used. Only exported fields are considered. If an exported field QL tag +// contains "-" then such field is not considered. A QL tag is a struct tag +// part prefixed by "ql:". Fields are considered in the order of appearance. +// Types of values in data must be compatible with the corresponding considered +// field of v. +// +// If the struct has no ID field then the number of values in data must be equal +// to the number of considered fields of v. +// +// type T struct { +// A bool +// B string +// } +// +// Assuming the schema is +// +// CREATE TABLE T (A bool, B string); +// +// Data might be a result of queries like +// +// SELECT * FROM T; +// SELECT A, B FROM T; +// +// If the struct has a considered ID field then the number of values in data +// must be equal to the number of considered fields in v - or one less. In the +// later case the ID field is not set. +// +// type U struct { +// ID int64 +// A bool +// B string +// } +// +// Assuming the schema is +// +// CREATE TABLE T (A bool, B string); +// +// Data might be a result of queries like +// +// SELECT * FROM T; // ID not set +// SELECT A, B FROM T; // ID not set +// SELECT id(), A, B FROM T; // ID is set +// +// To unmarshal a value from data into a pointer field of v, Unmarshal first +// handles the case of the value being nil. In that case, Unmarshal sets the +// pointer to nil. Otherwise, Unmarshal unmarshals the data value into value +// pointed at by the pointer. If the pointer is nil, Unmarshal allocates a new +// value for it to point to. +// +// Unmarshal is safe for concurrent use by multiple goroutines. +func Unmarshal(v interface{}, data []interface{}) (err error) { + defer func() { + if r := recover(); r != nil { + var ok bool + if err, ok = r.(error); !ok { + err = fmt.Errorf("%v", r) + } + err = fmt.Errorf("unmarshal: %v", err) + } + }() + + s, err := StructSchema(v) + if err != nil { + return err + } + + if !s.IsPtr { + return fmt.Errorf("unmarshal: need a pointer to a struct") + } + + id := false + nv, nf := len(data), len(s.Fields) + switch s.HasID { + case true: + switch { + case nv == nf: + id = true + case nv == nf-1: + // ok + default: + return fmt.Errorf("unmarshal: got %d values, need %d or %d", nv, nf-1, nf) + } + default: + switch { + case nv == nf: + // ok + default: + return fmt.Errorf("unmarshal: got %d values, need %d", nv, nf) + } + } + + j := 0 + vVal := reflect.ValueOf(v) + if s.IsPtr { + vVal = vVal.Elem() + } + for _, sf := range s.Fields { + if sf.IsID && !id { + continue + } + + d := data[j] + val := reflect.ValueOf(d) + j++ + + fVal := vVal.Field(sf.Index) + if u := sf.UnmarshalType; u != nil { + val = val.Convert(u) + } + if !sf.IsPtr { + fVal.Set(val) + continue + } + + if d == nil { + fVal.Set(sf.ZeroPtr) + continue + } + + if fVal.IsNil() { + fVal.Set(reflect.New(sf.ReflectType)) + } + + fVal.Elem().Set(val) + } + return nil +} diff --git a/vendor/github.com/cznic/ql/mem.go b/vendor/github.com/cznic/ql/mem.go new file mode 100644 index 00000000..bd2a2dd2 --- /dev/null +++ b/vendor/github.com/cznic/ql/mem.go @@ -0,0 +1,1277 @@ +// Copyright (c) 2014 ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Plain memory storage back end. + +package ql + +import ( + "bytes" + "fmt" + "io" + "math/big" + "time" +) + +var ( + _ btreeIndex = (*memIndex)(nil) + _ btreeIterator = (*memBTreeIterator)(nil) + _ indexIterator = (*xenumerator2)(nil) + _ storage = (*mem)(nil) + _ temp = (*memTemp)(nil) +) + +type memIndex struct { + m *mem + t *xtree + unique bool +} + +func newMemIndex(m *mem, unique bool) *memIndex { + r := &memIndex{t: xtreeNew(), unique: unique, m: m} + //dbg("newMemIndex %p, %p", r, m) + return r +} + +func (x *memIndex) Clear() error { + //dbg("memIndex(%p, %p).Clear", x, x.m) + x.m.newUndo(undoClearX, 0, []interface{}{x, x.t}) + x.t = xtreeNew() + return nil +} + +func (x *memIndex) Create(indexedValues []interface{}, h int64) error { + //dbg("memIndex(%p, %p).Create %v, %v", x, x.m, indexedValues, h) + t := x.t + switch { + case !x.unique: + k := indexKey{indexedValues, h} + x.m.newUndo(undoCreateX, 0, []interface{}{x, k}) //TODO why is old value, if any, not saved? + t.Set(k, 0) + case isIndexNull(indexedValues): // unique, NULL + k := indexKey{nil, h} + x.m.newUndo(undoCreateX, 0, []interface{}{x, k}) //TODO why is old value, if any, not saved? + t.Set(k, 0) + default: // unique, non NULL + k := indexKey{indexedValues, 0} + if _, ok := t.Get(k); ok { //LATER need .Put + return fmt.Errorf("cannot insert into unique index: duplicate value(s): %v", indexedValues) + } + + x.m.newUndo(undoCreateX, 0, []interface{}{x, k}) //TODO why is old value, if any, not saved? + t.Set(k, int(h)) + } + return nil +} + +func (x *memIndex) Delete(indexedValues []interface{}, h int64) error { + //dbg("memIndex(%p, %p).Delete %v, %v", x, x.m, indexedValues, h) + t := x.t + var k indexKey + var v interface{} + var ok, okv bool + switch { + case !x.unique: + k = indexKey{indexedValues, h} + v, okv = t.Get(k) + ok = t.delete(k) + case isIndexNull(indexedValues): // unique, NULL + k = indexKey{nil, h} + v, okv = t.Get(k) + ok = t.delete(k) + default: // unique, non NULL + k = indexKey{indexedValues, 0} + v, okv = t.Get(k) + ok = t.delete(k) + } + if ok { + if okv { + x.m.newUndo(undoDeleteX, int64(v.(int)), []interface{}{x, k}) + } + return nil + } + + return fmt.Errorf("internal error 047") +} + +func (x *memIndex) Drop() error { + x.m.newUndo(undoDropX, 0, []interface{}{x, *x}) + *x = memIndex{} + return nil +} + +func (x *memIndex) Seek(indexedValues []interface{}) (indexIterator, bool, error) { + it, hit := x.t.Seek(indexKey{indexedValues, 0}) + return &xenumerator2{*it, x.unique}, hit, nil +} + +func (x *memIndex) SeekFirst() (iter indexIterator, err error) { + it, err := x.t.SeekFirst() + if err != nil { + return nil, err + } + + return &xenumerator2{*it, x.unique}, nil +} + +func (x *memIndex) SeekLast() (iter indexIterator, err error) { + it, err := x.t.SeekLast() + if err != nil { + return nil, err + } + + return &xenumerator2{*it, x.unique}, nil +} + +type xenumerator2 struct { + it xenumerator + unique bool +} + +func (it *xenumerator2) Next() ([]interface{}, int64, error) { + k, h, err := it.it.Next() + if err != nil { + return nil, -1, err + } + + switch it.unique { + case true: + if k.value == nil { + return nil, k.h, nil + } + + return k.value, h, nil + default: + return k.value, k.h, nil + } +} + +func (it *xenumerator2) Prev() ([]interface{}, int64, error) { + k, h, err := it.it.Prev() + if err != nil { + return nil, -1, err + } + + switch it.unique { + case true: + if k.value == nil { + return nil, k.h, nil + } + + return k.value, h, nil + default: + return k.value, k.h, nil + } +} + +type memBTreeIterator enumerator + +func (it *memBTreeIterator) Next() (k, v []interface{}, err error) { + return (*enumerator)(it).Next() +} + +type memTemp struct { + tree *tree + store *mem +} + +func (t *memTemp) BeginTransaction() (err error) { + return nil +} + +func (t *memTemp) Get(k []interface{}) (v []interface{}, err error) { + v, _ = t.tree.Get(k) + return +} + +func (t *memTemp) Create(data ...interface{}) (h int64, err error) { + s := t.store + switch n := len(s.recycler); { + case n != 0: + h = int64(s.recycler[n-1]) + s.recycler = s.recycler[:n-1] + s.data[h] = s.clone(data...) + default: + h = int64(len(s.data)) + s.data = append(s.data, s.clone(data...)) + } + return +} + +func (t *memTemp) Read(dst []interface{}, h int64, cols ...*col) (data []interface{}, err error) { + return t.store.Read(dst, h, cols...) +} + +func (*memTemp) Drop() (err error) { return } + +func (t *memTemp) Set(k, v []interface{}) (err error) { + t.tree.Set(append([]interface{}(nil), k...), t.store.clone(v...)) + return +} + +func (t *memTemp) SeekFirst() (e btreeIterator, err error) { + en, err := t.tree.SeekFirst() + if err != nil { + return + } + + return (*memBTreeIterator)(en), nil +} + +const ( + undoCreateNewHandle = iota + undoCreateRecycledHandle + undoUpdate + undoDelete + undoClearX // {0: *memIndex, 1: *xtree} + undoCreateX // {0: *memIndex, 1: indexKey} + undoDeleteX // {0: *memIndex, 1: indexKey} + undoDropX // {0: *memIndex, 1: memIndex} +) + +type undo struct { + tag int + h int64 + data []interface{} +} + +type undos struct { + list []undo + parent *undos +} + +type mem struct { + data [][]interface{} + id int64 + recycler []int + tnl int + rollback *undos +} + +func newMemStorage() (s *mem, err error) { + s = &mem{data: [][]interface{}{nil}} + if err = s.BeginTransaction(); err != nil { + return nil, err + } + + h, err := s.Create() + if h != 1 { + panic("internal error 048") + } + + if err = s.Commit(); err != nil { + return nil, err + } + + return +} + +func (s *mem) OpenIndex(unique bool, handle int64) (btreeIndex, error) { // Never called on the memory backend. + panic("internal error 049") +} + +func (s *mem) newUndo(tag int, h int64, data []interface{}) { + s.rollback.list = append(s.rollback.list, undo{tag, h, data}) +} + +func (s *mem) Acid() bool { return false } + +func (s *mem) Close() (err error) { + if s.tnl != 0 { + return fmt.Errorf("cannot close DB while open transaction exist") + } + *s = mem{} + return +} + +func (s *mem) CreateIndex(unique bool) ( /* handle */ int64, btreeIndex, error) { + return -1, newMemIndex(s, unique), nil // handle of memIndex should never be used +} + +func (s *mem) Name() string { return fmt.Sprintf("/proc/self/mem/%p", s) } // fake, non existing name + +// OpenMem returns a new, empty DB backed by the process' memory. The back end +// has no limits on field/record/table/DB size other than memory available to +// the process. +func OpenMem() (db *DB, err error) { + s, err := newMemStorage() + if err != nil { + return + } + + if db, err = newDB(s); err != nil { + return nil, err + } + + db.isMem = true + return db, nil +} + +func (s *mem) Verify() (allocs int64, err error) { + for _, v := range s.recycler { + if s.data[v] != nil { + return 0, fmt.Errorf("corrupted: non nil free handle %d", s.data[v]) + } + } + + for _, v := range s.data { + if v != nil { + allocs++ + } + } + + if allocs != int64(len(s.data))-1-int64(len(s.recycler)) { + return 0, fmt.Errorf("corrupted: len(data) %d, len(recycler) %d, allocs %d", len(s.data), len(s.recycler), allocs) + } + + return +} + +func (s *mem) String() string { + var b bytes.Buffer + for i, v := range s.data { + b.WriteString(fmt.Sprintf("s.data[%d] %#v\n", i, v)) + } + for i, v := range s.recycler { + b.WriteString(fmt.Sprintf("s.recycler[%d] %v\n", i, v)) + } + return b.String() +} + +func (s *mem) CreateTemp(asc bool) (_ temp, err error) { + st, err := newMemStorage() + if err != nil { + return + } + + return &memTemp{ + tree: treeNew(collators[asc]), + store: st, + }, nil +} + +func (s *mem) ResetID() (err error) { + s.id = 0 + return +} + +func (s *mem) ID() (id int64, err error) { + s.id++ + return s.id, nil +} + +func (s *mem) clone(data ...interface{}) []interface{} { + r := make([]interface{}, len(data)) + for i, v := range data { + switch x := v.(type) { + case nil: + // nop + case idealComplex: + r[i] = complex128(x) + case idealFloat: + r[i] = float64(x) + case idealInt: + r[i] = int64(x) + case idealRune: + r[i] = int32(x) + case idealUint: + r[i] = uint64(x) + case bool: + r[i] = x + case complex64: + r[i] = x + case complex128: + r[i] = x + case float32: + r[i] = x + case float64: + r[i] = x + case int: + r[i] = int64(x) + case int8: + r[i] = x + case int16: + r[i] = x + case int32: + r[i] = x + case int64: + r[i] = x + case string: + r[i] = x + case uint: + r[i] = uint64(x) + case uint8: + r[i] = x + case uint16: + r[i] = x + case uint32: + r[i] = x + case uint64: + r[i] = x + case []byte: + r[i] = append([]byte(nil), x...) + case *big.Int: + r[i] = big.NewInt(0).Set(x) + case *big.Rat: + r[i] = big.NewRat(1, 2).Set(x) + case time.Time: + t := x + r[i] = t + case time.Duration: + r[i] = x + case map[string]interface{}: // map of ids of a cross join + r[i] = x + default: + panic("internal error 050") + } + } + return r +} + +func (s *mem) Create(data ...interface{}) (h int64, err error) { + switch n := len(s.recycler); { + case n != 0: + h = int64(s.recycler[n-1]) + s.recycler = s.recycler[:n-1] + s.data[h] = s.clone(data...) + r := s.rollback + r.list = append(r.list, undo{ + tag: undoCreateRecycledHandle, + h: h, + }) + default: + h = int64(len(s.data)) + s.data = append(s.data, s.clone(data...)) + r := s.rollback + r.list = append(r.list, undo{ + tag: undoCreateNewHandle, + h: h, + }) + } + return +} + +func (s *mem) Read(dst []interface{}, h int64, cols ...*col) (data []interface{}, err error) { + if i := int(h); i != 0 && i < len(s.data) { + d := s.clone(s.data[h]...) + if cols == nil { + return d, nil + } + + for n, dn := len(cols)+2, len(d); dn < n; dn++ { + d = append(d, nil) + } + return d, nil + } + + return nil, errNoDataForHandle +} + +func (s *mem) UpdateRow(h int64, _ []*col, data ...interface{}) (err error) { + return s.Update(h, data...) +} + +func (s *mem) Update(h int64, data ...interface{}) (err error) { + r := s.rollback + r.list = append(r.list, undo{ + tag: undoUpdate, + h: h, + data: s.data[h], + }) + s.data[h] = s.clone(data...) + return +} + +func (s *mem) Delete(h int64, _ ...*col) (err error) { + r := s.rollback + r.list = append(r.list, undo{ + tag: undoDelete, + h: h, + data: s.data[h], + }) + s.recycler = append(s.recycler, int(h)) + s.data[h] = nil + return +} + +func (s *mem) BeginTransaction() (err error) { + s.rollback = &undos{parent: s.rollback} + s.tnl++ + return nil +} + +func (s *mem) Rollback() (err error) { + if s.tnl == 0 { + return errRollbackNotInTransaction + } + + list := s.rollback.list + for i := len(list) - 1; i >= 0; i-- { + undo := list[i] + switch h, data := int(undo.h), undo.data; undo.tag { + case undoCreateNewHandle: + d := s.data + s.data = d[:len(d)-1] + case undoCreateRecycledHandle: + s.data[h] = nil + r := s.recycler + s.recycler = append(r, h) + case undoUpdate: + s.data[h] = data + case undoDelete: + s.data[h] = data + s.recycler = s.recycler[:len(s.recycler)-1] + case undoClearX: + x, t := data[0].(*memIndex), data[1].(*xtree) + x.t = t + case undoCreateX: + x, k := data[0].(*memIndex), data[1].(indexKey) + x.t.delete(k) + case undoDeleteX: + x, k := data[0].(*memIndex), data[1].(indexKey) + x.t.Set(k, h) + case undoDropX: + x, v := data[0].(*memIndex), data[1].(memIndex) + *x = v + default: + panic("internal error 051") + } + } + + s.tnl-- + s.rollback = s.rollback.parent + return nil +} + +func (s *mem) Commit() (err error) { + if s.tnl == 0 { + return errCommitNotInTransaction + } + + s.tnl-- + s.rollback = s.rollback.parent + return nil +} + +// Transaction index B+Tree +//LATER make it just a wrapper of the implementation in btree.go. + +type ( + xd struct { // data page + c int + xd [2*kd + 1]xde + n *xd + p *xd + } + + xde struct { // xd element + k indexKey + v int + } + + // xenumerator captures the state of enumerating a tree. It is returned + // from the Seek* methods. The enumerator is aware of any mutations + // made to the tree in the process of enumerating it and automatically + // resumes the enumeration at the proper key, if possible. + // + // However, once an xenumerator returns io.EOF to signal "no more + // items", it does no more attempt to "resync" on tree mutation(s). In + // other words, io.EOF from an Enumaretor is "sticky" (idempotent). + xenumerator struct { + err error + hit bool + i int + k indexKey + q *xd + t *xtree + ver int64 + } + + // xtree is a B+tree. + xtree struct { + c int + first *xd + last *xd + r interface{} + ver int64 + } + + xxe struct { // xx element + ch interface{} + sep *xd + } + + xx struct { // index page + c int + xx [2*kx + 2]xxe + } +) + +func (a *indexKey) cmp(b *indexKey) int { + r := collate(a.value, b.value) + if r != 0 { + return r + } + + return int(a.h) - int(b.h) +} + +var ( // R/O zero values + zxd xd + zxde xde + zxx xx + zxxe xxe +) + +func xclr(q interface{}) { + switch xx := q.(type) { + case *xx: + for i := 0; i <= xx.c; i++ { // Ch0 Sep0 ... Chn-1 Sepn-1 Chn + xclr(xx.xx[i].ch) + } + *xx = zxx // GC + case *xd: + *xx = zxd // GC + } +} + +// -------------------------------------------------------------------------- xx + +func xnewX(ch0 interface{}) *xx { + r := &xx{} + r.xx[0].ch = ch0 + return r +} + +func (q *xx) extract(i int) { + q.c-- + if i < q.c { + copy(q.xx[i:], q.xx[i+1:q.c+1]) + q.xx[q.c].ch = q.xx[q.c+1].ch + q.xx[q.c].sep = nil // GC + q.xx[q.c+1] = zxxe // GC + } +} + +func (q *xx) insert(i int, xd *xd, ch interface{}) *xx { + c := q.c + if i < c { + q.xx[c+1].ch = q.xx[c].ch + copy(q.xx[i+2:], q.xx[i+1:c]) + q.xx[i+1].sep = q.xx[i].sep + } + c++ + q.c = c + q.xx[i].sep = xd + q.xx[i+1].ch = ch + return q +} + +func (q *xx) siblings(i int) (l, r *xd) { + if i >= 0 { + if i > 0 { + l = q.xx[i-1].ch.(*xd) + } + if i < q.c { + r = q.xx[i+1].ch.(*xd) + } + } + return +} + +// -------------------------------------------------------------------------- xd + +func (l *xd) mvL(r *xd, c int) { + copy(l.xd[l.c:], r.xd[:c]) + copy(r.xd[:], r.xd[c:r.c]) + l.c += c + r.c -= c +} + +func (l *xd) mvR(r *xd, c int) { + copy(r.xd[c:], r.xd[:r.c]) + copy(r.xd[:c], l.xd[l.c-c:]) + r.c += c + l.c -= c +} + +// ----------------------------------------------------------------------- xtree + +// xtreeNew returns a newly created, empty xtree. The compare function is used +// for key collation. +func xtreeNew() *xtree { + return &xtree{} +} + +// Clear removes all K/V pairs from the tree. +func (t *xtree) Clear() { + if t.r == nil { + return + } + + xclr(t.r) + t.c, t.first, t.last, t.r = 0, nil, nil, nil + t.ver++ +} + +func (t *xtree) cat(p *xx, q, r *xd, pi int) { + t.ver++ + q.mvL(r, r.c) + if r.n != nil { + r.n.p = q + } else { + t.last = q + } + q.n = r.n + if p.c > 1 { + p.extract(pi) + p.xx[pi].ch = q + } else { + t.r = q + } +} + +func (t *xtree) catX(p, q, r *xx, pi int) { + t.ver++ + q.xx[q.c].sep = p.xx[pi].sep + copy(q.xx[q.c+1:], r.xx[:r.c]) + q.c += r.c + 1 + q.xx[q.c].ch = r.xx[r.c].ch + if p.c > 1 { + p.c-- + pc := p.c + if pi < pc { + p.xx[pi].sep = p.xx[pi+1].sep + copy(p.xx[pi+1:], p.xx[pi+2:pc+1]) + p.xx[pc].ch = p.xx[pc+1].ch + p.xx[pc].sep = nil // GC + p.xx[pc+1].ch = nil // GC + } + return + } + + t.r = q +} + +//Delete removes the k's KV pair, if it exists, in which case Delete returns +//true. +func (t *xtree) delete(k indexKey) (ok bool) { + pi := -1 + var p *xx + q := t.r + if q == nil { + return + } + + for { + var i int + i, ok = t.find(q, k) + if ok { + switch xx := q.(type) { + case *xx: + dp := xx.xx[i].sep + switch { + case dp.c > kd: + t.extract(dp, 0) + default: + if xx.c < kx && q != t.r { + t.underflowX(p, &xx, pi, &i) + } + pi = i + 1 + p = xx + q = xx.xx[pi].ch + ok = false + continue + } + case *xd: + t.extract(xx, i) + if xx.c >= kd { + return + } + + if q != t.r { + t.underflow(p, xx, pi) + } else if t.c == 0 { + t.Clear() + } + } + return + } + + switch xx := q.(type) { + case *xx: + if xx.c < kx && q != t.r { + t.underflowX(p, &xx, pi, &i) + } + pi = i + p = xx + q = xx.xx[i].ch + case *xd: + return + } + } +} + +func (t *xtree) extract(q *xd, i int) { // (r int64) { + t.ver++ + //r = q.xd[i].v // prepared for Extract + q.c-- + if i < q.c { + copy(q.xd[i:], q.xd[i+1:q.c+1]) + } + q.xd[q.c] = zxde // GC + t.c-- + return +} + +func (t *xtree) find(q interface{}, k indexKey) (i int, ok bool) { + var mk indexKey + l := 0 + switch xx := q.(type) { + case *xx: + h := xx.c - 1 + for l <= h { + m := (l + h) >> 1 + mk = xx.xx[m].sep.xd[0].k + switch cmp := k.cmp(&mk); { + case cmp > 0: + l = m + 1 + case cmp == 0: + return m, true + default: + h = m - 1 + } + } + case *xd: + h := xx.c - 1 + for l <= h { + m := (l + h) >> 1 + mk = xx.xd[m].k + switch cmp := k.cmp(&mk); { + case cmp > 0: + l = m + 1 + case cmp == 0: + return m, true + default: + h = m - 1 + } + } + } + return l, false +} + +// First returns the first item of the tree in the key collating order, or +// (nil, nil) if the tree is empty. +func (t *xtree) First() (k indexKey, v int) { + if q := t.first; q != nil { + q := &q.xd[0] + k, v = q.k, q.v + } + return +} + +// Get returns the value associated with k and true if it exists. Otherwise Get +// returns (nil, false). +func (t *xtree) Get(k indexKey) (v int, ok bool) { + q := t.r + if q == nil { + return + } + + for { + var i int + if i, ok = t.find(q, k); ok { + switch xx := q.(type) { + case *xx: + return xx.xx[i].sep.xd[0].v, true + case *xd: + return xx.xd[i].v, true + } + } + switch xx := q.(type) { + case *xx: + q = xx.xx[i].ch + default: + return + } + } +} + +func (t *xtree) insert(q *xd, i int, k indexKey, v int) *xd { + t.ver++ + c := q.c + if i < c { + copy(q.xd[i+1:], q.xd[i:c]) + } + c++ + q.c = c + q.xd[i].k, q.xd[i].v = k, v + t.c++ + return q +} + +// Last returns the last item of the tree in the key collating order, or (nil, +// nil) if the tree is empty. +func (t *xtree) Last() (k indexKey, v int) { + if q := t.last; q != nil { + q := &q.xd[q.c-1] + k, v = q.k, q.v + } + return +} + +// Len returns the number of items in the tree. +func (t *xtree) Len() int { + return t.c +} + +func (t *xtree) overflow(p *xx, q *xd, pi, i int, k indexKey, v int) { + t.ver++ + l, r := p.siblings(pi) + + if l != nil && l.c < 2*kd { + l.mvL(q, 1) + t.insert(q, i-1, k, v) + return + } + + if r != nil && r.c < 2*kd { + if i < 2*kd { + q.mvR(r, 1) + t.insert(q, i, k, v) + } else { + t.insert(r, 0, k, v) + } + return + } + + t.split(p, q, pi, i, k, v) +} + +// Seek returns an xenumerator positioned on a an item such that k >= item's +// key. ok reports if k == item.key The xenumerator's position is possibly +// after the last item in the tree. +func (t *xtree) Seek(k indexKey) (e *xenumerator, ok bool) { + q := t.r + if q == nil { + e = &xenumerator{nil, false, 0, k, nil, t, t.ver} + return + } + + for { + var i int + if i, ok = t.find(q, k); ok { + switch xx := q.(type) { + case *xx: + e = &xenumerator{nil, ok, 0, k, xx.xx[i].sep, t, t.ver} + return + case *xd: + e = &xenumerator{nil, ok, i, k, xx, t, t.ver} + return + } + } + switch xx := q.(type) { + case *xx: + q = xx.xx[i].ch + case *xd: + e = &xenumerator{nil, ok, i, k, xx, t, t.ver} + return + } + } +} + +// SeekFirst returns an enumerator positioned on the first KV pair in the tree, +// if any. For an empty tree, err == io.EOF is returned and e will be nil. +func (t *xtree) SeekFirst() (e *xenumerator, err error) { + q := t.first + if q == nil { + return nil, io.EOF + } + + return &xenumerator{nil, true, 0, q.xd[0].k, q, t, t.ver}, nil +} + +// SeekLast returns an enumerator positioned on the last KV pair in the tree, +// if any. For an empty tree, err == io.EOF is returned and e will be nil. +func (t *xtree) SeekLast() (e *xenumerator, err error) { + q := t.last + if q == nil { + return nil, io.EOF + } + + return &xenumerator{nil, true, q.c - 1, q.xd[q.c-1].k, q, t, t.ver}, nil +} + +// Set sets the value associated with k. +func (t *xtree) Set(k indexKey, v int) { + pi := -1 + var p *xx + q := t.r + if q != nil { + for { + i, ok := t.find(q, k) + if ok { + switch xx := q.(type) { + case *xx: + xx.xx[i].sep.xd[0].v = v + case *xd: + xx.xd[i].v = v + } + return + } + + switch xx := q.(type) { + case *xx: + if xx.c > 2*kx { + t.splitX(p, &xx, pi, &i) + } + pi = i + p = xx + q = xx.xx[i].ch + case *xd: + switch { + case xx.c < 2*kd: + t.insert(xx, i, k, v) + default: + t.overflow(p, xx, pi, i, k, v) + } + return + } + } + } + + z := t.insert(&xd{}, 0, k, v) + t.r, t.first, t.last = z, z, z + return +} + +func (t *xtree) split(p *xx, q *xd, pi, i int, k indexKey, v int) { + t.ver++ + r := &xd{} + if q.n != nil { + r.n = q.n + r.n.p = r + } else { + t.last = r + } + q.n = r + r.p = q + + copy(r.xd[:], q.xd[kd:2*kd]) + for i := range q.xd[kd:] { + q.xd[kd+i] = zxde + } + q.c = kd + r.c = kd + if pi >= 0 { + p.insert(pi, r, r) + } else { + t.r = xnewX(q).insert(0, r, r) + } + if i > kd { + t.insert(r, i-kd, k, v) + return + } + + t.insert(q, i, k, v) +} + +func (t *xtree) splitX(p *xx, pp **xx, pi int, i *int) { + t.ver++ + q := *pp + r := &xx{} + copy(r.xx[:], q.xx[kx+1:]) + q.c = kx + r.c = kx + if pi >= 0 { + p.insert(pi, q.xx[kx].sep, r) + } else { + t.r = xnewX(q).insert(0, q.xx[kx].sep, r) + } + q.xx[kx].sep = nil + for i := range q.xx[kx+1:] { + q.xx[kx+i+1] = zxxe + } + if *i > kx { + *pp = r + *i -= kx + 1 + } +} + +func (t *xtree) underflow(p *xx, q *xd, pi int) { + t.ver++ + l, r := p.siblings(pi) + + if l != nil && l.c+q.c >= 2*kd { + l.mvR(q, 1) + } else if r != nil && q.c+r.c >= 2*kd { + q.mvL(r, 1) + r.xd[r.c] = zxde // GC + } else if l != nil { + t.cat(p, l, q, pi-1) + } else { + t.cat(p, q, r, pi) + } +} + +func (t *xtree) underflowX(p *xx, pp **xx, pi int, i *int) { + t.ver++ + var l, r *xx + q := *pp + + if pi >= 0 { + if pi > 0 { + l = p.xx[pi-1].ch.(*xx) + } + if pi < p.c { + r = p.xx[pi+1].ch.(*xx) + } + } + + if l != nil && l.c > kx { + q.xx[q.c+1].ch = q.xx[q.c].ch + copy(q.xx[1:], q.xx[:q.c]) + q.xx[0].ch = l.xx[l.c].ch + q.xx[0].sep = p.xx[pi-1].sep + q.c++ + *i++ + l.c-- + p.xx[pi-1].sep = l.xx[l.c].sep + return + } + + if r != nil && r.c > kx { + q.xx[q.c].sep = p.xx[pi].sep + q.c++ + q.xx[q.c].ch = r.xx[0].ch + p.xx[pi].sep = r.xx[0].sep + copy(r.xx[:], r.xx[1:r.c]) + r.c-- + rc := r.c + r.xx[rc].ch = r.xx[rc+1].ch + r.xx[rc].sep = nil + r.xx[rc+1].ch = nil + return + } + + if l != nil { + *i += l.c + 1 + t.catX(p, l, q, pi-1) + *pp = l + return + } + + t.catX(p, q, r, pi) +} + +// ----------------------------------------------------------------- xenumerator + +// Next returns the currently enumerated item, if it exists and moves to the +// next item in the key collation order. If there is no item to return, err == +// io.EOF is returned. +func (e *xenumerator) Next() (k indexKey, v int64, err error) { + if err = e.err; err != nil { + return + } + + if e.ver != e.t.ver { + f, hit := e.t.Seek(e.k) + if !e.hit && hit { + if err = f.next(); err != nil { + return + } + } + + *e = *f + } + if e.q == nil { + e.err, err = io.EOF, io.EOF + return + } + + if e.i >= e.q.c { + if err = e.next(); err != nil { + return + } + } + + i := e.q.xd[e.i] + k, v = i.k, int64(i.v) + e.k, e.hit = k, false + e.next() + return +} + +func (e *xenumerator) next() error { + if e.q == nil { + e.err = io.EOF + return io.EOF + } + + switch { + case e.i < e.q.c-1: + e.i++ + default: + if e.q, e.i = e.q.n, 0; e.q == nil { + e.err = io.EOF + } + } + return e.err +} + +// Prev returns the currently enumerated item, if it exists and moves to the +// previous item in the key collation order. If there is no item to return, err +// == io.EOF is returned. +func (e *xenumerator) Prev() (k indexKey, v int64, err error) { + if err = e.err; err != nil { + return + } + + if e.ver != e.t.ver { + f, hit := e.t.Seek(e.k) + if !e.hit && hit { + if err = f.prev(); err != nil { + return + } + } + + *e = *f + } + if e.q == nil { + e.err, err = io.EOF, io.EOF + return + } + + if e.i >= e.q.c { + if err = e.next(); err != nil { + return + } + } + + i := e.q.xd[e.i] + k, v = i.k, int64(i.v) + e.k, e.hit = k, false + e.prev() + return +} + +func (e *xenumerator) prev() error { + if e.q == nil { + e.err = io.EOF + return io.EOF + } + + switch { + case e.i > 0: + e.i-- + default: + if e.q = e.q.p; e.q == nil { + e.err = io.EOF + break + } + + e.i = e.q.c - 1 + } + return e.err +} diff --git a/vendor/github.com/cznic/ql/parser.go b/vendor/github.com/cznic/ql/parser.go new file mode 100644 index 00000000..0edb803f --- /dev/null +++ b/vendor/github.com/cznic/ql/parser.go @@ -0,0 +1,2749 @@ +// CAUTION: Generated file - DO NOT EDIT. + +// Copyright (c) 2014 The ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Inital yacc source generated by ebnf2y[1] +// at 2013-10-04 23:10:47.861401015 +0200 CEST +// +// $ ebnf2y -o ql.y -oe ql.ebnf -start StatementList -pkg ql -p _ +// +// [1]: http://github.com/cznic/ebnf2y + +package ql + +import __yyfmt__ "fmt" + +import ( + "fmt" + + "github.com/cznic/mathutil" +) + +type yySymType struct { + yys int + line int + col int + item interface{} + list []interface{} +} + +type yyXError struct { + state, xsym int +} + +const ( + yyDefault = 57437 + yyEOFCode = 57344 + add = 57352 + alter = 57353 + and = 57354 + andand = 57355 + andnot = 57356 + as = 57357 + asc = 57358 + begin = 57359 + between = 57360 + bigIntType = 57361 + bigRatType = 57362 + blobType = 57363 + boolType = 57364 + by = 57365 + byteType = 57366 + column = 57367 + commit = 57368 + complex128Type = 57369 + complex64Type = 57370 + create = 57371 + defaultKwd = 57372 + deleteKwd = 57373 + desc = 57374 + distinct = 57375 + drop = 57376 + durationType = 57377 + eq = 57378 + yyErrCode = 57345 + exists = 57379 + explain = 57380 + falseKwd = 57381 + float32Type = 57383 + float64Type = 57384 + floatLit = 57346 + floatType = 57382 + from = 57385 + full = 57386 + ge = 57387 + group = 57388 + identifier = 57347 + ifKwd = 57389 + imaginaryLit = 57348 + in = 57390 + index = 57391 + insert = 57392 + int16Type = 57394 + int32Type = 57395 + int64Type = 57396 + int8Type = 57397 + intLit = 57349 + intType = 57393 + into = 57398 + is = 57399 + join = 57400 + le = 57401 + left = 57402 + like = 57403 + limit = 57404 + lsh = 57405 + neq = 57406 + not = 57407 + null = 57408 + offset = 57409 + on = 57410 + or = 57411 + order = 57412 + oror = 57413 + outer = 57414 + parseExpression = 57436 + qlParam = 57350 + right = 57415 + rollback = 57416 + rsh = 57417 + runeType = 57418 + selectKwd = 57419 + set = 57420 + stringLit = 57351 + stringType = 57421 + tableKwd = 57422 + timeType = 57423 + transaction = 57424 + trueKwd = 57425 + truncate = 57426 + uint16Type = 57428 + uint32Type = 57429 + uint64Type = 57430 + uint8Type = 57431 + uintType = 57427 + unique = 57432 + update = 57433 + values = 57434 + where = 57435 + + yyMaxDepth = 200 + yyTabOfs = -216 +) + +var ( + yyXLAT = map[int]int{ + 59: 0, // ';' (192x) + 57344: 1, // $end (191x) + 41: 2, // ')' (164x) + 43: 3, // '+' (133x) + 45: 4, // '-' (133x) + 94: 5, // '^' (133x) + 44: 6, // ',' (130x) + 40: 7, // '(' (125x) + 57347: 8, // identifier (116x) + 57409: 9, // offset (103x) + 57404: 10, // limit (101x) + 57372: 11, // defaultKwd (94x) + 57412: 12, // order (90x) + 57435: 13, // where (87x) + 57408: 14, // null (84x) + 57361: 15, // bigIntType (83x) + 57362: 16, // bigRatType (83x) + 57363: 17, // blobType (83x) + 57364: 18, // boolType (83x) + 57366: 19, // byteType (83x) + 57369: 20, // complex128Type (83x) + 57370: 21, // complex64Type (83x) + 57377: 22, // durationType (83x) + 57383: 23, // float32Type (83x) + 57384: 24, // float64Type (83x) + 57382: 25, // floatType (83x) + 57394: 26, // int16Type (83x) + 57395: 27, // int32Type (83x) + 57396: 28, // int64Type (83x) + 57397: 29, // int8Type (83x) + 57393: 30, // intType (83x) + 57418: 31, // runeType (83x) + 57421: 32, // stringType (83x) + 57423: 33, // timeType (83x) + 57428: 34, // uint16Type (83x) + 57429: 35, // uint32Type (83x) + 57430: 36, // uint64Type (83x) + 57431: 37, // uint8Type (83x) + 57427: 38, // uintType (83x) + 57381: 39, // falseKwd (81x) + 57346: 40, // floatLit (81x) + 57388: 41, // group (81x) + 57348: 42, // imaginaryLit (81x) + 57349: 43, // intLit (81x) + 57407: 44, // not (81x) + 57411: 45, // or (81x) + 57413: 46, // oror (81x) + 57350: 47, // qlParam (81x) + 57351: 48, // stringLit (81x) + 57425: 49, // trueKwd (81x) + 33: 50, // '!' (77x) + 57385: 51, // from (75x) + 57358: 52, // asc (71x) + 57374: 53, // desc (71x) + 93: 54, // ']' (70x) + 57357: 55, // as (69x) + 58: 56, // ':' (67x) + 57354: 57, // and (67x) + 57355: 58, // andand (65x) + 124: 59, // '|' (56x) + 57360: 60, // between (54x) + 57390: 61, // in (54x) + 60: 62, // '<' (53x) + 62: 63, // '>' (53x) + 57378: 64, // eq (53x) + 57387: 65, // ge (53x) + 57399: 66, // is (53x) + 57401: 67, // le (53x) + 57403: 68, // like (53x) + 57406: 69, // neq (53x) + 57513: 70, // Type (52x) + 57453: 71, // Conversion (51x) + 57483: 72, // Literal (51x) + 57484: 73, // Operand (51x) + 57488: 74, // PrimaryExpression (51x) + 57491: 75, // QualifiedIdent (51x) + 42: 76, // '*' (48x) + 57514: 77, // UnaryExpr (47x) + 37: 78, // '%' (44x) + 38: 79, // '&' (44x) + 47: 80, // '/' (44x) + 57356: 81, // andnot (44x) + 57405: 82, // lsh (44x) + 57417: 83, // rsh (44x) + 57490: 84, // PrimaryTerm (40x) + 57489: 85, // PrimaryFactor (36x) + 91: 86, // '[' (31x) + 57470: 87, // Factor (25x) + 57471: 88, // Factor1 (25x) + 57511: 89, // Term (24x) + 57467: 90, // Expression (23x) + 57519: 91, // logOr (16x) + 57446: 92, // ColumnName (10x) + 57386: 93, // full (10x) + 57402: 94, // left (10x) + 57415: 95, // right (10x) + 57419: 96, // selectKwd (10x) + 57510: 97, // TableName (9x) + 57449: 98, // CommaOpt (7x) + 57468: 99, // ExpressionList (7x) + 57410: 100, // on (7x) + 57497: 101, // SelectStmt (7x) + 57400: 102, // join (6x) + 57443: 103, // Call (5x) + 57376: 104, // drop (5x) + 57476: 105, // Index (5x) + 57506: 106, // Slice (5x) + 57445: 107, // ColumnDef (4x) + 57379: 108, // exists (4x) + 57389: 109, // ifKwd (4x) + 57391: 110, // index (4x) + 57414: 111, // outer (4x) + 57422: 112, // tableKwd (4x) + 57434: 113, // values (4x) + 57353: 114, // alter (3x) + 57438: 115, // AlterTableStmt (3x) + 57359: 116, // begin (3x) + 57442: 117, // BeginTransactionStmt (3x) + 57368: 118, // commit (3x) + 57450: 119, // CommitStmt (3x) + 57371: 120, // create (3x) + 57455: 121, // CreateIndexStmt (3x) + 57457: 122, // CreateTableStmt (3x) + 57461: 123, // DeleteFromStmt (3x) + 57373: 124, // deleteKwd (3x) + 57463: 125, // DropIndexStmt (3x) + 57464: 126, // DropTableStmt (3x) + 57465: 127, // EmptyStmt (3x) + 57380: 128, // explain (3x) + 57466: 129, // ExplainStmt (3x) + 57392: 130, // insert (3x) + 57477: 131, // InsertIntoStmt (3x) + 57492: 132, // RecordSet (3x) + 57493: 133, // RecordSet1 (3x) + 57416: 134, // rollback (3x) + 57496: 135, // RollbackStmt (3x) + 57520: 136, // semiOpt (3x) + 57508: 137, // Statement (3x) + 57426: 138, // truncate (3x) + 57512: 139, // TruncateTableStmt (3x) + 57433: 140, // update (3x) + 57515: 141, // UpdateStmt (3x) + 57517: 142, // WhereClause (3x) + 61: 143, // '=' (2x) + 57352: 144, // add (2x) + 57439: 145, // Assignment (2x) + 57365: 146, // by (2x) + 57447: 147, // ColumnNameList (2x) + 57458: 148, // CreateTableStmt1 (2x) + 57472: 149, // Field (2x) + 57518: 150, // logAnd (2x) + 57420: 151, // set (2x) + 46: 152, // '.' (1x) + 57440: 153, // AssignmentList (1x) + 57441: 154, // AssignmentList1 (1x) + 57444: 155, // Call1 (1x) + 57367: 156, // column (1x) + 57448: 157, // ColumnNameList1 (1x) + 57451: 158, // Constraint (1x) + 57452: 159, // ConstraintOpt (1x) + 57454: 160, // CreateIndexIfNotExists (1x) + 57456: 161, // CreateIndexStmtUnique (1x) + 57459: 162, // Default (1x) + 57460: 163, // DefaultOpt (1x) + 57375: 164, // distinct (1x) + 57462: 165, // DropIndexIfExists (1x) + 57469: 166, // ExpressionList1 (1x) + 57473: 167, // Field1 (1x) + 57474: 168, // FieldList (1x) + 57475: 169, // GroupByClause (1x) + 57478: 170, // InsertIntoStmt1 (1x) + 57479: 171, // InsertIntoStmt2 (1x) + 57398: 172, // into (1x) + 57480: 173, // JoinClause (1x) + 57481: 174, // JoinClauseOpt (1x) + 57482: 175, // JoinType (1x) + 57485: 176, // OrderBy (1x) + 57486: 177, // OrderBy1 (1x) + 57487: 178, // OuterOpt (1x) + 57436: 179, // parseExpression (1x) + 57494: 180, // RecordSet2 (1x) + 57495: 181, // RecordSetList (1x) + 57498: 182, // SelectStmtDistinct (1x) + 57499: 183, // SelectStmtFieldList (1x) + 57500: 184, // SelectStmtGroup (1x) + 57501: 185, // SelectStmtLimit (1x) + 57502: 186, // SelectStmtOffset (1x) + 57503: 187, // SelectStmtOrder (1x) + 57504: 188, // SelectStmtWhere (1x) + 57505: 189, // SetOpt (1x) + 57507: 190, // Start (1x) + 57509: 191, // StatementList (1x) + 57424: 192, // transaction (1x) + 57432: 193, // unique (1x) + 57516: 194, // UpdateStmt1 (1x) + 57437: 195, // $default (0x) + 57345: 196, // error (0x) + } + + yySymNames = []string{ + "';'", + "$end", + "')'", + "'+'", + "'-'", + "'^'", + "','", + "'('", + "identifier", + "offset", + "limit", + "defaultKwd", + "order", + "where", + "null", + "bigIntType", + "bigRatType", + "blobType", + "boolType", + "byteType", + "complex128Type", + "complex64Type", + "durationType", + "float32Type", + "float64Type", + "floatType", + "int16Type", + "int32Type", + "int64Type", + "int8Type", + "intType", + "runeType", + "stringType", + "timeType", + "uint16Type", + "uint32Type", + "uint64Type", + "uint8Type", + "uintType", + "falseKwd", + "floatLit", + "group", + "imaginaryLit", + "intLit", + "not", + "or", + "oror", + "qlParam", + "stringLit", + "trueKwd", + "'!'", + "from", + "asc", + "desc", + "']'", + "as", + "':'", + "and", + "andand", + "'|'", + "between", + "in", + "'<'", + "'>'", + "eq", + "ge", + "is", + "le", + "like", + "neq", + "Type", + "Conversion", + "Literal", + "Operand", + "PrimaryExpression", + "QualifiedIdent", + "'*'", + "UnaryExpr", + "'%'", + "'&'", + "'/'", + "andnot", + "lsh", + "rsh", + "PrimaryTerm", + "PrimaryFactor", + "'['", + "Factor", + "Factor1", + "Term", + "Expression", + "logOr", + "ColumnName", + "full", + "left", + "right", + "selectKwd", + "TableName", + "CommaOpt", + "ExpressionList", + "on", + "SelectStmt", + "join", + "Call", + "drop", + "Index", + "Slice", + "ColumnDef", + "exists", + "ifKwd", + "index", + "outer", + "tableKwd", + "values", + "alter", + "AlterTableStmt", + "begin", + "BeginTransactionStmt", + "commit", + "CommitStmt", + "create", + "CreateIndexStmt", + "CreateTableStmt", + "DeleteFromStmt", + "deleteKwd", + "DropIndexStmt", + "DropTableStmt", + "EmptyStmt", + "explain", + "ExplainStmt", + "insert", + "InsertIntoStmt", + "RecordSet", + "RecordSet1", + "rollback", + "RollbackStmt", + "semiOpt", + "Statement", + "truncate", + "TruncateTableStmt", + "update", + "UpdateStmt", + "WhereClause", + "'='", + "add", + "Assignment", + "by", + "ColumnNameList", + "CreateTableStmt1", + "Field", + "logAnd", + "set", + "'.'", + "AssignmentList", + "AssignmentList1", + "Call1", + "column", + "ColumnNameList1", + "Constraint", + "ConstraintOpt", + "CreateIndexIfNotExists", + "CreateIndexStmtUnique", + "Default", + "DefaultOpt", + "distinct", + "DropIndexIfExists", + "ExpressionList1", + "Field1", + "FieldList", + "GroupByClause", + "InsertIntoStmt1", + "InsertIntoStmt2", + "into", + "JoinClause", + "JoinClauseOpt", + "JoinType", + "OrderBy", + "OrderBy1", + "OuterOpt", + "parseExpression", + "RecordSet2", + "RecordSetList", + "SelectStmtDistinct", + "SelectStmtFieldList", + "SelectStmtGroup", + "SelectStmtLimit", + "SelectStmtOffset", + "SelectStmtOrder", + "SelectStmtWhere", + "SetOpt", + "Start", + "StatementList", + "transaction", + "unique", + "UpdateStmt1", + "$default", + "error", + } + + yyTokenLiteralStrings = map[int]string{ + 57347: "identifier", + 57409: "OFFSET", + 57404: "LIMIT", + 57372: "DEFAULT", + 57412: "ORDER", + 57435: "WHERE", + 57408: "NULL", + 57361: "bigint", + 57362: "bigrat", + 57363: "blob", + 57364: "bool", + 57366: "byte", + 57369: "complex128", + 57370: "complex64", + 57377: "duration", + 57383: "float32", + 57384: "float64", + 57382: "float", + 57394: "int16", + 57395: "int32", + 57396: "int64", + 57397: "int8", + 57393: "int", + 57418: "rune", + 57421: "string", + 57423: "time", + 57428: "uint16", + 57429: "uint32", + 57430: "uint64", + 57431: "uint8", + 57427: "uint", + 57381: "false", + 57346: "floating-point literal", + 57388: "GROUP", + 57348: "imaginary literal", + 57349: "integer literal", + 57407: "NOT", + 57411: "OR", + 57413: "||", + 57350: "QL parameter", + 57351: "string literal", + 57425: "true", + 57385: "FROM", + 57358: "ASC", + 57374: "DESC", + 57357: "AS", + 57354: "AND", + 57355: "&&", + 57360: "BETWEEN", + 57390: "IN", + 57378: "==", + 57387: ">=", + 57399: "IS", + 57401: "<=", + 57403: "LIKE", + 57406: "!=", + 57356: "&^", + 57405: "<<", + 57417: ">>", + 57386: "FULL", + 57402: "LEFT", + 57415: "RIGHT", + 57419: "SELECT", + 57410: "ON", + 57400: "JOIN", + 57376: "DROP", + 57379: "EXISTS", + 57389: "IF", + 57391: "INDEX", + 57414: "OUTER", + 57422: "TABLE", + 57434: "VALUES", + 57353: "ALTER", + 57359: "BEGIN", + 57368: "COMMIT", + 57371: "CREATE", + 57373: "DELETE", + 57380: "EXPLAIN", + 57392: "INSERT", + 57416: "ROLLBACK", + 57426: "TRUNCATE", + 57433: "UPDATE", + 57352: "ADD", + 57365: "BY", + 57420: "SET", + 57367: "COLUMN", + 57375: "DISTINCT", + 57398: "INTO", + 57436: "parse expression prefix", + 57424: "TRANSACTION", + 57432: "UNIQUE", + } + + yyReductions = map[int]struct{ xsym, components int }{ + 0: {0, 1}, + 1: {190, 1}, + 2: {190, 2}, + 3: {115, 5}, + 4: {115, 6}, + 5: {145, 3}, + 6: {153, 3}, + 7: {154, 0}, + 8: {154, 3}, + 9: {117, 2}, + 10: {103, 3}, + 11: {103, 3}, + 12: {155, 0}, + 13: {155, 1}, + 14: {107, 4}, + 15: {92, 1}, + 16: {147, 3}, + 17: {157, 0}, + 18: {157, 3}, + 19: {119, 1}, + 20: {158, 2}, + 21: {158, 1}, + 22: {159, 0}, + 23: {159, 1}, + 24: {71, 4}, + 25: {121, 10}, + 26: {160, 0}, + 27: {160, 3}, + 28: {161, 0}, + 29: {161, 1}, + 30: {122, 8}, + 31: {122, 11}, + 32: {148, 0}, + 33: {148, 3}, + 34: {162, 2}, + 35: {163, 0}, + 36: {163, 1}, + 37: {123, 3}, + 38: {123, 4}, + 39: {125, 4}, + 40: {165, 0}, + 41: {165, 2}, + 42: {126, 3}, + 43: {126, 5}, + 44: {127, 0}, + 45: {129, 2}, + 46: {90, 1}, + 47: {90, 3}, + 48: {91, 1}, + 49: {91, 1}, + 50: {99, 3}, + 51: {166, 0}, + 52: {166, 3}, + 53: {87, 1}, + 54: {87, 5}, + 55: {87, 6}, + 56: {87, 6}, + 57: {87, 7}, + 58: {87, 5}, + 59: {87, 6}, + 60: {87, 3}, + 61: {87, 4}, + 62: {88, 1}, + 63: {88, 3}, + 64: {88, 3}, + 65: {88, 3}, + 66: {88, 3}, + 67: {88, 3}, + 68: {88, 3}, + 69: {88, 3}, + 70: {149, 2}, + 71: {167, 0}, + 72: {167, 2}, + 73: {168, 1}, + 74: {168, 3}, + 75: {169, 3}, + 76: {105, 3}, + 77: {131, 10}, + 78: {131, 5}, + 79: {170, 0}, + 80: {170, 3}, + 81: {171, 0}, + 82: {171, 5}, + 83: {72, 1}, + 84: {72, 1}, + 85: {72, 1}, + 86: {72, 1}, + 87: {72, 1}, + 88: {72, 1}, + 89: {72, 1}, + 90: {73, 1}, + 91: {73, 1}, + 92: {73, 1}, + 93: {73, 3}, + 94: {176, 4}, + 95: {177, 0}, + 96: {177, 1}, + 97: {177, 1}, + 98: {74, 1}, + 99: {74, 1}, + 100: {74, 2}, + 101: {74, 2}, + 102: {74, 2}, + 103: {85, 1}, + 104: {85, 3}, + 105: {85, 3}, + 106: {85, 3}, + 107: {85, 3}, + 108: {84, 1}, + 109: {84, 3}, + 110: {84, 3}, + 111: {84, 3}, + 112: {84, 3}, + 113: {84, 3}, + 114: {84, 3}, + 115: {84, 3}, + 116: {75, 1}, + 117: {75, 3}, + 118: {132, 2}, + 119: {133, 1}, + 120: {133, 4}, + 121: {136, 0}, + 122: {136, 1}, + 123: {180, 0}, + 124: {180, 2}, + 125: {181, 1}, + 126: {181, 3}, + 127: {135, 1}, + 128: {175, 1}, + 129: {175, 1}, + 130: {175, 1}, + 131: {178, 0}, + 132: {178, 1}, + 133: {173, 6}, + 134: {174, 0}, + 135: {174, 1}, + 136: {101, 12}, + 137: {185, 0}, + 138: {185, 2}, + 139: {186, 0}, + 140: {186, 2}, + 141: {182, 0}, + 142: {182, 1}, + 143: {183, 1}, + 144: {183, 1}, + 145: {183, 2}, + 146: {188, 0}, + 147: {188, 1}, + 148: {184, 0}, + 149: {184, 1}, + 150: {187, 0}, + 151: {187, 1}, + 152: {106, 3}, + 153: {106, 4}, + 154: {106, 4}, + 155: {106, 5}, + 156: {137, 1}, + 157: {137, 1}, + 158: {137, 1}, + 159: {137, 1}, + 160: {137, 1}, + 161: {137, 1}, + 162: {137, 1}, + 163: {137, 1}, + 164: {137, 1}, + 165: {137, 1}, + 166: {137, 1}, + 167: {137, 1}, + 168: {137, 1}, + 169: {137, 1}, + 170: {137, 1}, + 171: {191, 1}, + 172: {191, 3}, + 173: {97, 1}, + 174: {89, 1}, + 175: {89, 3}, + 176: {150, 1}, + 177: {150, 1}, + 178: {139, 3}, + 179: {70, 1}, + 180: {70, 1}, + 181: {70, 1}, + 182: {70, 1}, + 183: {70, 1}, + 184: {70, 1}, + 185: {70, 1}, + 186: {70, 1}, + 187: {70, 1}, + 188: {70, 1}, + 189: {70, 1}, + 190: {70, 1}, + 191: {70, 1}, + 192: {70, 1}, + 193: {70, 1}, + 194: {70, 1}, + 195: {70, 1}, + 196: {70, 1}, + 197: {70, 1}, + 198: {70, 1}, + 199: {70, 1}, + 200: {70, 1}, + 201: {70, 1}, + 202: {70, 1}, + 203: {141, 5}, + 204: {194, 0}, + 205: {194, 1}, + 206: {77, 1}, + 207: {77, 2}, + 208: {77, 2}, + 209: {77, 2}, + 210: {77, 2}, + 211: {142, 2}, + 212: {189, 0}, + 213: {189, 1}, + 214: {98, 0}, + 215: {98, 1}, + } + + yyXErrors = map[yyXError]string{ + yyXError{1, -1}: "expected $end", + yyXError{43, -1}: "expected '('", + yyXError{157, -1}: "expected '('", + yyXError{181, -1}: "expected '('", + yyXError{281, -1}: "expected '('", + yyXError{309, -1}: "expected '('", + yyXError{313, -1}: "expected '('", + yyXError{344, -1}: "expected '('", + yyXError{118, -1}: "expected ')'", + yyXError{119, -1}: "expected ')'", + yyXError{120, -1}: "expected ')'", + yyXError{187, -1}: "expected ')'", + yyXError{189, -1}: "expected ')'", + yyXError{190, -1}: "expected ')'", + yyXError{194, -1}: "expected ')'", + yyXError{196, -1}: "expected ')'", + yyXError{265, -1}: "expected ')'", + yyXError{279, -1}: "expected ')'", + yyXError{284, -1}: "expected ')'", + yyXError{290, -1}: "expected ')'", + yyXError{318, -1}: "expected ')'", + yyXError{335, -1}: "expected ')'", + yyXError{346, -1}: "expected ')'", + yyXError{36, -1}: "expected '='", + yyXError{233, -1}: "expected BY", + yyXError{236, -1}: "expected BY", + yyXError{352, -1}: "expected COLUMN", + yyXError{7, -1}: "expected CREATE INDEX optional UNIQUE clause or one of [INDEX, TABLE, UNIQUE]", + yyXError{337, -1}: "expected CREATE INDEX statement optional IF NOT EXISTS cluse or one of [IF, identifier]", + yyXError{316, -1}: "expected CREATE TABLE statement colum definition list or optional comma or one of [')', ',']", + yyXError{333, -1}: "expected CREATE TABLE statement colum definition list or optional comma or one of [')', ',']", + yyXError{293, -1}: "expected DROP INDEX statement optional IF EXISTS clause or one of [IF, identifier]", + yyXError{296, -1}: "expected EXISTS", + yyXError{300, -1}: "expected EXISTS", + yyXError{311, -1}: "expected EXISTS", + yyXError{340, -1}: "expected EXISTS", + yyXError{8, -1}: "expected FROM", + yyXError{215, -1}: "expected FROM", + yyXError{216, -1}: "expected FROM", + yyXError{306, -1}: "expected INDEX", + yyXError{307, -1}: "expected INDEX", + yyXError{276, -1}: "expected INSERT INTO statement optional column list clause or SELECT statement or one of ['(', SELECT, VALUES]", + yyXError{285, -1}: "expected INSERT INTO statement optional values list or optional comma or one of [$end, ',', ';']", + yyXError{11, -1}: "expected INTO", + yyXError{257, -1}: "expected JOIN", + yyXError{258, -1}: "expected JOIN", + yyXError{310, -1}: "expected NOT", + yyXError{339, -1}: "expected NOT", + yyXError{176, -1}: "expected NULL", + yyXError{324, -1}: "expected NULL", + yyXError{260, -1}: "expected ON", + yyXError{342, -1}: "expected ON", + yyXError{246, -1}: "expected ORDER BY clause optional collation specification or one of [$end, ')', ';', ASC, DESC, LIMIT, OFFSET]", + yyXError{217, -1}: "expected RecordSetList or one of ['(', identifier]", + yyXError{13, -1}: "expected SELECT statement field list or SELECT statement optional DISTINCT clause or one of ['!', '(', '*', '+', '-', '^', DISTINCT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{210, -1}: "expected SELECT statement field list or one of ['!', '(', '*', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{224, -1}: "expected SELECT statement optional GROUP BY clause or SELECT statement optional JOIN clause or SELECT statement optional LIMIT clause or SELECT statement optional OFFSET clause or SELECT statement optional ORDER BY clause or SELECT statement optional WHERE clause or one of [$end, ')', ';', FULL, GROUP, LEFT, LIMIT, OFFSET, ORDER, RIGHT, WHERE]", + yyXError{222, -1}: "expected SELECT statement optional GROUP BY clause or SELECT statement optional JOIN clause or SELECT statement optional LIMIT clause or SELECT statement optional OFFSET clause or SELECT statement optional ORDER BY clause or SELECT statement optional WHERE clause or optional comma or one of [$end, ')', ',', ';', FULL, GROUP, LEFT, LIMIT, OFFSET, ORDER, RIGHT, WHERE]", + yyXError{230, -1}: "expected SELECT statement optional GROUP BY clause or SELECT statement optional LIMIT clause or SELECT statement optional OFFSET clause or SELECT statement optional ORDER BY clause or SELECT statement optional WHERE clause or one of [$end, ')', ';', GROUP, LIMIT, OFFSET, ORDER, WHERE]", + yyXError{231, -1}: "expected SELECT statement optional GROUP BY clause or SELECT statement optional LIMIT clause or SELECT statement optional OFFSET clause or SELECT statement optional ORDER BY clause or one of [$end, ')', ';', GROUP, LIMIT, OFFSET, ORDER]", + yyXError{234, -1}: "expected SELECT statement optional LIMIT clause or SELECT statement optional OFFSET clause or SELECT statement optional ORDER BY clause or one of [$end, ')', ';', LIMIT, OFFSET, ORDER]", + yyXError{237, -1}: "expected SELECT statement optional LIMIT clause or SELECT statement optional OFFSET clause or one of [$end, ')', ';', LIMIT, OFFSET]", + yyXError{239, -1}: "expected SELECT statement optional OFFSET clause or one of [$end, ')', ';', OFFSET]", + yyXError{220, -1}: "expected SELECT statement or SELECT", + yyXError{186, -1}: "expected SELECT statement or expression list or one of ['!', '(', '+', '-', '^', NULL, QL parameter, SELECT, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{193, -1}: "expected SELECT statement or expression list or one of ['!', '(', '+', '-', '^', NULL, QL parameter, SELECT, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{277, -1}: "expected SELECT statement or one of [SELECT, VALUES]", + yyXError{33, -1}: "expected SetOpt or assignment list or one of [SET, identifier]", + yyXError{0, -1}: "expected Start or one of [$end, ';', ALTER, BEGIN, COMMIT, CREATE, DELETE, DROP, EXPLAIN, INSERT, ROLLBACK, SELECT, TRUNCATE, UPDATE, parse expression prefix]", + yyXError{4, -1}: "expected TABLE", + yyXError{30, -1}: "expected TABLE", + yyXError{5, -1}: "expected TRANSACTION", + yyXError{39, -1}: "expected UPDATE statement optional WHERE clause or one of [$end, ';', WHERE]", + yyXError{304, -1}: "expected WHERE clause or one of [$end, ';', WHERE]", + yyXError{37, -1}: "expected assignment list optional trailing comma or optional comma or one of [$end, ',', ';', WHERE]", + yyXError{34, -1}: "expected assignment list or identifier", + yyXError{204, -1}: "expected assignment or one of [$end, ';', WHERE, identifier]", + yyXError{250, -1}: "expected column name list or identifier", + yyXError{278, -1}: "expected column name list or identifier", + yyXError{251, -1}: "expected column name list with optional trailing comma or optional comma or one of [$end, ')', ',', ';', LIMIT, OFFSET, ORDER]", + yyXError{353, -1}: "expected column name or identifier", + yyXError{255, -1}: "expected column name or one of [$end, ')', ';', LIMIT, OFFSET, ORDER, identifier]", + yyXError{109, -1}: "expected expression factor or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{121, -1}: "expected expression list expression or logical or operator or optional comma or one of [$end, ')', ',', ';', ASC, DESC, LIMIT, OFFSET, OR, ||]", + yyXError{245, -1}: "expected expression list or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{283, -1}: "expected expression list or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{289, -1}: "expected expression list or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{345, -1}: "expected expression list or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{124, -1}: "expected expression or one of [$end, '!', '(', ')', '+', '-', ';', '^', ASC, DESC, LIMIT, NULL, OFFSET, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{96, -1}: "expected expression or one of ['!', '(', '+', '-', ':', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{101, -1}: "expected expression or one of ['!', '(', '+', '-', ']', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{114, -1}: "expected expression or one of ['!', '(', '+', '-', ']', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{3, -1}: "expected expression or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{42, -1}: "expected expression or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{58, -1}: "expected expression or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{199, -1}: "expected expression or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{206, -1}: "expected expression or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{240, -1}: "expected expression or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{243, -1}: "expected expression or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{261, -1}: "expected expression or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{329, -1}: "expected expression or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{104, -1}: "expected expression term or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{212, -1}: "expected field expression optional AS clause or logical or operator or one of [',', AS, FROM, OR, ||]", + yyXError{270, -1}: "expected field expression or one of ['!', '(', '+', '-', '^', FROM, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{95, -1}: "expected function call optional argument list or one of ['!', '(', ')', '*', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{61, -1}: "expected function call or string index or string slice or one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{94, -1}: "expected function call or string index or string slice or one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{128, -1}: "expected function call or string index or string slice or one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{129, -1}: "expected function call or string index or string slice or one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{130, -1}: "expected function call or string index or string slice or one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{35, -1}: "expected identifier", + yyXError{131, -1}: "expected identifier", + yyXError{268, -1}: "expected identifier", + yyXError{273, -1}: "expected identifier", + yyXError{299, -1}: "expected identifier", + yyXError{301, -1}: "expected identifier", + yyXError{338, -1}: "expected identifier", + yyXError{341, -1}: "expected identifier", + yyXError{343, -1}: "expected identifier", + yyXError{44, -1}: "expected logical and operator or one of [$end, &&, ')', ',', ':', ';', ']', AND, AS, ASC, DEFAULT, DESC, FROM, GROUP, LIMIT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{108, -1}: "expected logical and operator or one of [$end, &&, ')', ',', ':', ';', ']', AND, AS, ASC, DEFAULT, DESC, FROM, GROUP, LIMIT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{125, -1}: "expected logical or operator or one of [$end, ')', ',', ';', ASC, DESC, LIMIT, OFFSET, OR, ||]", + yyXError{325, -1}: "expected logical or operator or one of [$end, ')', ',', ';', DEFAULT, OR, ||]", + yyXError{331, -1}: "expected logical or operator or one of [$end, ')', ',', ';', OR, ||]", + yyXError{262, -1}: "expected logical or operator or one of [$end, ')', ';', GROUP, LIMIT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{45, -1}: "expected logical or operator or one of [$end, ')', ';', GROUP, LIMIT, OFFSET, OR, ORDER, ||]", + yyXError{241, -1}: "expected logical or operator or one of [$end, ')', ';', OFFSET, OR, ||]", + yyXError{244, -1}: "expected logical or operator or one of [$end, ')', ';', OR, ||]", + yyXError{207, -1}: "expected logical or operator or one of [$end, ',', ';', OR, WHERE, ||]", + yyXError{356, -1}: "expected logical or operator or one of [$end, OR, ||]", + yyXError{147, -1}: "expected logical or operator or one of [')', OR, ||]", + yyXError{200, -1}: "expected logical or operator or one of [')', OR, ||]", + yyXError{100, -1}: "expected logical or operator or one of [':', ']', OR, ||]", + yyXError{102, -1}: "expected logical or operator or one of [']', OR, ||]", + yyXError{115, -1}: "expected logical or operator or one of [']', OR, ||]", + yyXError{64, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{48, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{49, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{50, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{51, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{52, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{53, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{54, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{55, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{56, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{57, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{59, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{60, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{97, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{98, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{99, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{103, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{107, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{113, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{116, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{117, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{126, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{127, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{132, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{148, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{201, -1}: "expected one of [!=, $end, &&, &^, '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', '[', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{62, -1}: "expected one of [!=, $end, &&, &^, '%', '&', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{63, -1}: "expected one of [!=, $end, &&, &^, '%', '&', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{140, -1}: "expected one of [!=, $end, &&, &^, '%', '&', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{141, -1}: "expected one of [!=, $end, &&, &^, '%', '&', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{142, -1}: "expected one of [!=, $end, &&, &^, '%', '&', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{143, -1}: "expected one of [!=, $end, &&, &^, '%', '&', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{144, -1}: "expected one of [!=, $end, &&, &^, '%', '&', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{145, -1}: "expected one of [!=, $end, &&, &^, '%', '&', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{146, -1}: "expected one of [!=, $end, &&, &^, '%', '&', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{153, -1}: "expected one of [!=, $end, &&, &^, '%', '&', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{154, -1}: "expected one of [!=, $end, &&, &^, '%', '&', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{155, -1}: "expected one of [!=, $end, &&, &^, '%', '&', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{156, -1}: "expected one of [!=, $end, &&, &^, '%', '&', ')', '*', '+', ',', '-', '/', ':', ';', '<', '>', ']', '^', '|', <<, <=, ==, >=, >>, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{47, -1}: "expected one of [!=, $end, &&, ')', '+', ',', '-', ':', ';', '<', '>', ']', '^', '|', <=, ==, >=, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{168, -1}: "expected one of [!=, $end, &&, ')', '+', ',', '-', ':', ';', '<', '>', ']', '^', '|', <=, ==, >=, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{169, -1}: "expected one of [!=, $end, &&, ')', '+', ',', '-', ':', ';', '<', '>', ']', '^', '|', <=, ==, >=, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{170, -1}: "expected one of [!=, $end, &&, ')', '+', ',', '-', ':', ';', '<', '>', ']', '^', '|', <=, ==, >=, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{171, -1}: "expected one of [!=, $end, &&, ')', '+', ',', '-', ':', ';', '<', '>', ']', '^', '|', <=, ==, >=, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{172, -1}: "expected one of [!=, $end, &&, ')', '+', ',', '-', ':', ';', '<', '>', ']', '^', '|', <=, ==, >=, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{173, -1}: "expected one of [!=, $end, &&, ')', '+', ',', '-', ':', ';', '<', '>', ']', '^', '|', <=, ==, >=, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{174, -1}: "expected one of [!=, $end, &&, ')', '+', ',', '-', ':', ';', '<', '>', ']', '^', '|', <=, ==, >=, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{46, -1}: "expected one of [!=, $end, &&, ')', ',', ':', ';', '<', '>', ']', <=, ==, >=, AND, AS, ASC, BETWEEN, DEFAULT, DESC, FROM, GROUP, IN, IS, LIKE, LIMIT, NOT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{180, -1}: "expected one of [$end, &&, ')', '+', ',', '-', ':', ';', ']', '^', '|', AND, AS, ASC, DEFAULT, DESC, FROM, GROUP, LIMIT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{185, -1}: "expected one of [$end, &&, ')', '+', ',', '-', ':', ';', ']', '^', '|', AND, AS, ASC, DEFAULT, DESC, FROM, GROUP, LIMIT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{65, -1}: "expected one of [$end, &&, ')', ',', ':', ';', ']', AND, AS, ASC, DEFAULT, DESC, FROM, GROUP, LIMIT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{112, -1}: "expected one of [$end, &&, ')', ',', ':', ';', ']', AND, AS, ASC, DEFAULT, DESC, FROM, GROUP, LIMIT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{175, -1}: "expected one of [$end, &&, ')', ',', ':', ';', ']', AND, AS, ASC, DEFAULT, DESC, FROM, GROUP, LIMIT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{177, -1}: "expected one of [$end, &&, ')', ',', ':', ';', ']', AND, AS, ASC, DEFAULT, DESC, FROM, GROUP, LIMIT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{191, -1}: "expected one of [$end, &&, ')', ',', ':', ';', ']', AND, AS, ASC, DEFAULT, DESC, FROM, GROUP, LIMIT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{192, -1}: "expected one of [$end, &&, ')', ',', ':', ';', ']', AND, AS, ASC, DEFAULT, DESC, FROM, GROUP, LIMIT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{197, -1}: "expected one of [$end, &&, ')', ',', ':', ';', ']', AND, AS, ASC, DEFAULT, DESC, FROM, GROUP, LIMIT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{198, -1}: "expected one of [$end, &&, ')', ',', ':', ';', ']', AND, AS, ASC, DEFAULT, DESC, FROM, GROUP, LIMIT, OFFSET, OR, ORDER, WHERE, ||]", + yyXError{66, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{67, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{68, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{69, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{70, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{71, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{72, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{73, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{74, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{75, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{76, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{77, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{78, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{79, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{80, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{81, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{82, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{83, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{84, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{85, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{86, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{87, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{88, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{89, -1}: "expected one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{32, -1}: "expected one of [$end, '(', ';', ADD, DROP, SELECT, SET, VALUES, WHERE, identifier]", + yyXError{288, -1}: "expected one of [$end, '(', ';']", + yyXError{38, -1}: "expected one of [$end, ')', ',', ';', '=', LIMIT, OFFSET, ORDER, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, float, float32, float64, int, int16, int32, int64, int8, rune, string, time, uint, uint16, uint32, uint64, uint8]", + yyXError{219, -1}: "expected one of [$end, ')', ',', ';', AS, FULL, GROUP, LEFT, LIMIT, OFFSET, ON, ORDER, RIGHT, WHERE]", + yyXError{266, -1}: "expected one of [$end, ')', ',', ';', AS, FULL, GROUP, LEFT, LIMIT, OFFSET, ON, ORDER, RIGHT, WHERE]", + yyXError{326, -1}: "expected one of [$end, ')', ',', ';', DEFAULT]", + yyXError{327, -1}: "expected one of [$end, ')', ',', ';', DEFAULT]", + yyXError{267, -1}: "expected one of [$end, ')', ',', ';', FULL, GROUP, LEFT, LIMIT, OFFSET, ON, ORDER, RIGHT, WHERE]", + yyXError{269, -1}: "expected one of [$end, ')', ',', ';', FULL, GROUP, LEFT, LIMIT, OFFSET, ON, ORDER, RIGHT, WHERE]", + yyXError{221, -1}: "expected one of [$end, ')', ',', ';', FULL, GROUP, LEFT, LIMIT, OFFSET, ORDER, RIGHT, WHERE]", + yyXError{263, -1}: "expected one of [$end, ')', ',', ';', FULL, GROUP, LEFT, LIMIT, OFFSET, ORDER, RIGHT, WHERE]", + yyXError{256, -1}: "expected one of [$end, ')', ',', ';', LIMIT, OFFSET, ORDER]", + yyXError{328, -1}: "expected one of [$end, ')', ',', ';']", + yyXError{330, -1}: "expected one of [$end, ')', ',', ';']", + yyXError{123, -1}: "expected one of [$end, ')', ';', ASC, DESC, LIMIT, OFFSET]", + yyXError{229, -1}: "expected one of [$end, ')', ';', GROUP, LIMIT, OFFSET, ORDER, WHERE]", + yyXError{232, -1}: "expected one of [$end, ')', ';', GROUP, LIMIT, OFFSET, ORDER]", + yyXError{235, -1}: "expected one of [$end, ')', ';', LIMIT, OFFSET, ORDER]", + yyXError{252, -1}: "expected one of [$end, ')', ';', LIMIT, OFFSET, ORDER]", + yyXError{254, -1}: "expected one of [$end, ')', ';', LIMIT, OFFSET, ORDER]", + yyXError{238, -1}: "expected one of [$end, ')', ';', LIMIT, OFFSET]", + yyXError{247, -1}: "expected one of [$end, ')', ';', LIMIT, OFFSET]", + yyXError{248, -1}: "expected one of [$end, ')', ';', LIMIT, OFFSET]", + yyXError{249, -1}: "expected one of [$end, ')', ';', LIMIT, OFFSET]", + yyXError{242, -1}: "expected one of [$end, ')', ';']", + yyXError{205, -1}: "expected one of [$end, ',', ';', WHERE]", + yyXError{291, -1}: "expected one of [$end, ',', ';']", + yyXError{203, -1}: "expected one of [$end, ';', WHERE]", + yyXError{2, -1}: "expected one of [$end, ';']", + yyXError{6, -1}: "expected one of [$end, ';']", + yyXError{12, -1}: "expected one of [$end, ';']", + yyXError{14, -1}: "expected one of [$end, ';']", + yyXError{15, -1}: "expected one of [$end, ';']", + yyXError{16, -1}: "expected one of [$end, ';']", + yyXError{17, -1}: "expected one of [$end, ';']", + yyXError{18, -1}: "expected one of [$end, ';']", + yyXError{19, -1}: "expected one of [$end, ';']", + yyXError{20, -1}: "expected one of [$end, ';']", + yyXError{21, -1}: "expected one of [$end, ';']", + yyXError{22, -1}: "expected one of [$end, ';']", + yyXError{23, -1}: "expected one of [$end, ';']", + yyXError{24, -1}: "expected one of [$end, ';']", + yyXError{25, -1}: "expected one of [$end, ';']", + yyXError{26, -1}: "expected one of [$end, ';']", + yyXError{27, -1}: "expected one of [$end, ';']", + yyXError{28, -1}: "expected one of [$end, ';']", + yyXError{29, -1}: "expected one of [$end, ';']", + yyXError{40, -1}: "expected one of [$end, ';']", + yyXError{41, -1}: "expected one of [$end, ';']", + yyXError{209, -1}: "expected one of [$end, ';']", + yyXError{282, -1}: "expected one of [$end, ';']", + yyXError{287, -1}: "expected one of [$end, ';']", + yyXError{292, -1}: "expected one of [$end, ';']", + yyXError{295, -1}: "expected one of [$end, ';']", + yyXError{298, -1}: "expected one of [$end, ';']", + yyXError{302, -1}: "expected one of [$end, ';']", + yyXError{305, -1}: "expected one of [$end, ';']", + yyXError{321, -1}: "expected one of [$end, ';']", + yyXError{336, -1}: "expected one of [$end, ';']", + yyXError{347, -1}: "expected one of [$end, ';']", + yyXError{348, -1}: "expected one of [$end, ';']", + yyXError{354, -1}: "expected one of [$end, ';']", + yyXError{355, -1}: "expected one of [$end, ';']", + yyXError{358, -1}: "expected one of [$end, ';']", + yyXError{211, -1}: "expected one of ['!', '(', '*', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{105, -1}: "expected one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{106, -1}: "expected one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{110, -1}: "expected one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{111, -1}: "expected one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{320, -1}: "expected one of [')', ',']", + yyXError{178, -1}: "expected one of ['+', '-', '^', '|', AND]", + yyXError{183, -1}: "expected one of ['+', '-', '^', '|', AND]", + yyXError{213, -1}: "expected one of [',', FROM]", + yyXError{214, -1}: "expected one of [',', FROM]", + yyXError{271, -1}: "expected one of [',', FROM]", + yyXError{272, -1}: "expected one of [',', FROM]", + yyXError{274, -1}: "expected one of [',', FROM]", + yyXError{350, -1}: "expected one of [ADD, DROP]", + yyXError{158, -1}: "expected one of [BETWEEN, IN]", + yyXError{9, -1}: "expected one of [INDEX, TABLE]", + yyXError{225, -1}: "expected one of [JOIN, OUTER]", + yyXError{226, -1}: "expected one of [JOIN, OUTER]", + yyXError{227, -1}: "expected one of [JOIN, OUTER]", + yyXError{160, -1}: "expected one of [NOT, NULL]", + yyXError{280, -1}: "expected one of [SELECT, VALUES]", + yyXError{323, -1}: "expected optional DEFAULT clause or one of [$end, ')', ',', ';', DEFAULT]", + yyXError{322, -1}: "expected optional DEFAULT clause or optional column value constraint or one of [$end, '!', '(', ')', '+', ',', '-', ';', '^', DEFAULT, NOT, NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{228, -1}: "expected optional OUTER clause or one of [JOIN, OUTER]", + yyXError{122, -1}: "expected optional comma or one of [$end, ')', ',', ';', ASC, DESC, LIMIT, OFFSET]", + yyXError{253, -1}: "expected optional comma or one of [$end, ')', ',', ';', LIMIT, OFFSET, ORDER]", + yyXError{202, -1}: "expected optional comma or one of [$end, ',', ';', WHERE]", + yyXError{286, -1}: "expected optional comma or one of [$end, ',', ';']", + yyXError{317, -1}: "expected optional comma or one of [')', ',']", + yyXError{334, -1}: "expected optional comma or one of [')', ',']", + yyXError{159, -1}: "expected primary expression factor or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{161, -1}: "expected primary expression factor or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{162, -1}: "expected primary expression factor or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{163, -1}: "expected primary expression factor or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{164, -1}: "expected primary expression factor or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{165, -1}: "expected primary expression factor or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{166, -1}: "expected primary expression factor or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{167, -1}: "expected primary expression factor or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{179, -1}: "expected primary expression factor or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{182, -1}: "expected primary expression factor or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{184, -1}: "expected primary expression factor or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{90, -1}: "expected primary expression or one of ['(', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{91, -1}: "expected primary expression or one of ['(', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{92, -1}: "expected primary expression or one of ['(', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{93, -1}: "expected primary expression or one of ['(', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{149, -1}: "expected primary expression term or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{150, -1}: "expected primary expression term or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{151, -1}: "expected primary expression term or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{152, -1}: "expected primary expression term or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{218, -1}: "expected record set optional AS clause or one of [$end, ')', ',', ';', AS, FULL, GROUP, LEFT, LIMIT, OFFSET, ON, ORDER, RIGHT, WHERE]", + yyXError{223, -1}: "expected record set or one of [$end, '(', ')', ';', FULL, GROUP, LEFT, LIMIT, OFFSET, ORDER, RIGHT, WHERE, identifier]", + yyXError{259, -1}: "expected record set or one of ['(', identifier]", + yyXError{188, -1}: "expected semiOpt or one of [')', ';']", + yyXError{195, -1}: "expected semiOpt or one of [')', ';']", + yyXError{264, -1}: "expected semiOpt or one of [')', ';']", + yyXError{10, -1}: "expected statement or one of [$end, ';', ALTER, BEGIN, COMMIT, CREATE, DELETE, DROP, EXPLAIN, INSERT, ROLLBACK, SELECT, TRUNCATE, UPDATE]", + yyXError{357, -1}: "expected statement or one of [$end, ';', ALTER, BEGIN, COMMIT, CREATE, DELETE, DROP, EXPLAIN, INSERT, ROLLBACK, SELECT, TRUNCATE, UPDATE]", + yyXError{314, -1}: "expected table column definition or identifier", + yyXError{332, -1}: "expected table column definition or identifier", + yyXError{351, -1}: "expected table column definition or identifier", + yyXError{319, -1}: "expected table column definition or one of [')', identifier]", + yyXError{31, -1}: "expected table name or identifier", + yyXError{208, -1}: "expected table name or identifier", + yyXError{275, -1}: "expected table name or identifier", + yyXError{297, -1}: "expected table name or identifier", + yyXError{303, -1}: "expected table name or identifier", + yyXError{312, -1}: "expected table name or identifier", + yyXError{349, -1}: "expected table name or identifier", + yyXError{294, -1}: "expected table name or one of [IF, identifier]", + yyXError{308, -1}: "expected table name or one of [IF, identifier]", + yyXError{315, -1}: "expected type or one of [bigint, bigrat, blob, bool, byte, complex128, complex64, duration, float, float32, float64, int, int16, int32, int64, int8, rune, string, time, uint, uint16, uint32, uint64, uint8]", + yyXError{133, -1}: "expected unary expression or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{134, -1}: "expected unary expression or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{135, -1}: "expected unary expression or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{136, -1}: "expected unary expression or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{137, -1}: "expected unary expression or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{138, -1}: "expected unary expression or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + yyXError{139, -1}: "expected unary expression or one of ['!', '(', '+', '-', '^', NULL, QL parameter, bigint, bigrat, blob, bool, byte, complex128, complex64, duration, false, float, float32, float64, floating-point literal, identifier, imaginary literal, int, int16, int32, int64, int8, integer literal, rune, string, string literal, time, true, uint, uint16, uint32, uint64, uint8]", + } + + yyParseTab = [359][]uint16{ + // 0 + {172, 172, 96: 229, 101: 242, 104: 225, 114: 220, 231, 221, 232, 222, 233, 223, 234, 235, 236, 224, 237, 238, 230, 226, 239, 227, 240, 134: 228, 241, 137: 245, 246, 243, 247, 244, 179: 219, 190: 217, 218}, + {1: 216}, + {573, 215}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 572}, + {112: 565}, + // 5 + {192: 564}, + {197, 197}, + {110: 188, 112: 524, 161: 522, 193: 523}, + {51: 519}, + {110: 509, 112: 510}, + // 10 + {172, 172, 96: 229, 101: 242, 104: 225, 114: 220, 231, 221, 232, 222, 233, 223, 234, 235, 236, 224, 237, 238, 230, 226, 239, 227, 240, 134: 228, 241, 137: 508, 246, 243, 247, 244}, + {172: 491}, + {89, 89}, + {3: 75, 75, 75, 7: 75, 75, 14: 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 42: 75, 75, 47: 75, 75, 75, 75, 76: 75, 164: 427, 182: 426}, + {60, 60}, + // 15 + {59, 59}, + {58, 58}, + {57, 57}, + {56, 56}, + {55, 55}, + // 20 + {54, 54}, + {53, 53}, + {52, 52}, + {51, 51}, + {50, 50}, + // 25 + {49, 49}, + {48, 48}, + {47, 47}, + {46, 46}, + {45, 45}, + // 30 + {112: 424}, + {8: 248, 97: 249}, + {43, 43, 7: 43, 43, 13: 43, 96: 43, 104: 43, 113: 43, 144: 43, 151: 43}, + {8: 4, 151: 251, 189: 250}, + {8: 254, 92: 252, 145: 253, 153: 255}, + // 35 + {8: 3}, + {143: 422}, + {209, 209, 6: 209, 13: 209, 154: 418}, + {201, 201, 201, 6: 201, 9: 201, 201, 12: 201, 15: 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 143: 201}, + {12, 12, 13: 258, 142: 257, 194: 256}, + // 40 + {13, 13}, + {11, 11}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 261}, + {7: 415}, + {170, 170, 170, 6: 170, 9: 170, 170, 170, 170, 170, 41: 170, 45: 170, 170, 51: 170, 170, 170, 170, 170, 170, 327, 326, 150: 325}, + // 45 + {5, 5, 5, 9: 5, 5, 12: 5, 41: 5, 45: 322, 321, 91: 320}, + {163, 163, 163, 6: 163, 9: 163, 163, 163, 163, 163, 41: 163, 44: 374, 163, 163, 51: 163, 163, 163, 163, 163, 163, 163, 163, 60: 375, 373, 380, 378, 382, 377, 376, 379, 383, 381}, + {154, 154, 154, 368, 367, 365, 154, 9: 154, 154, 154, 154, 154, 41: 154, 44: 154, 154, 154, 51: 154, 154, 154, 154, 154, 154, 154, 154, 366, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154}, + {133, 133, 133, 133, 133, 133, 133, 133, 9: 133, 133, 133, 133, 133, 41: 133, 44: 133, 133, 133, 51: 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 76: 133, 78: 133, 133, 133, 133, 133, 133, 86: 133}, + {132, 132, 132, 132, 132, 132, 132, 132, 9: 132, 132, 132, 132, 132, 41: 132, 44: 132, 132, 132, 51: 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 76: 132, 78: 132, 132, 132, 132, 132, 132, 86: 132}, + // 50 + {131, 131, 131, 131, 131, 131, 131, 131, 9: 131, 131, 131, 131, 131, 41: 131, 44: 131, 131, 131, 51: 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 76: 131, 78: 131, 131, 131, 131, 131, 131, 86: 131}, + {130, 130, 130, 130, 130, 130, 130, 130, 9: 130, 130, 130, 130, 130, 41: 130, 44: 130, 130, 130, 51: 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 76: 130, 78: 130, 130, 130, 130, 130, 130, 86: 130}, + {129, 129, 129, 129, 129, 129, 129, 129, 9: 129, 129, 129, 129, 129, 41: 129, 44: 129, 129, 129, 51: 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 76: 129, 78: 129, 129, 129, 129, 129, 129, 86: 129}, + {128, 128, 128, 128, 128, 128, 128, 128, 9: 128, 128, 128, 128, 128, 41: 128, 44: 128, 128, 128, 51: 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 76: 128, 78: 128, 128, 128, 128, 128, 128, 86: 128}, + {127, 127, 127, 127, 127, 127, 127, 127, 9: 127, 127, 127, 127, 127, 41: 127, 44: 127, 127, 127, 51: 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 76: 127, 78: 127, 127, 127, 127, 127, 127, 86: 127}, + // 55 + {126, 126, 126, 126, 126, 126, 126, 126, 9: 126, 126, 126, 126, 126, 41: 126, 44: 126, 126, 126, 51: 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 76: 126, 78: 126, 126, 126, 126, 126, 126, 86: 126}, + {125, 125, 125, 125, 125, 125, 125, 125, 9: 125, 125, 125, 125, 125, 41: 125, 44: 125, 125, 125, 51: 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 76: 125, 78: 125, 125, 125, 125, 125, 125, 86: 125}, + {124, 124, 124, 124, 124, 124, 124, 124, 9: 124, 124, 124, 124, 124, 41: 124, 44: 124, 124, 124, 51: 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 76: 124, 78: 124, 124, 124, 124, 124, 124, 86: 124}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 363}, + {118, 118, 118, 118, 118, 118, 118, 118, 9: 118, 118, 118, 118, 118, 41: 118, 44: 118, 118, 118, 51: 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 76: 118, 78: 118, 118, 118, 118, 118, 118, 86: 118}, + // 60 + {117, 117, 117, 117, 117, 117, 117, 117, 9: 117, 117, 117, 117, 117, 41: 117, 44: 117, 117, 117, 51: 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 76: 117, 78: 117, 117, 117, 117, 117, 117, 86: 117}, + {10, 10, 10, 10, 10, 10, 10, 311, 9: 10, 10, 10, 10, 10, 41: 10, 44: 10, 10, 10, 51: 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 76: 10, 78: 10, 10, 10, 10, 10, 10, 86: 312, 103: 315, 105: 313, 314}, + {113, 113, 113, 113, 113, 113, 113, 9: 113, 113, 113, 113, 113, 41: 113, 44: 113, 113, 113, 51: 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 76: 355, 78: 353, 350, 354, 349, 351, 352}, + {108, 108, 108, 108, 108, 108, 108, 9: 108, 108, 108, 108, 108, 41: 108, 44: 108, 108, 108, 51: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 76: 108, 78: 108, 108, 108, 108, 108, 108}, + {100, 100, 100, 100, 100, 100, 100, 100, 9: 100, 100, 100, 100, 100, 41: 100, 44: 100, 100, 100, 51: 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 76: 100, 78: 100, 100, 100, 100, 100, 100, 86: 100, 152: 347}, + // 65 + {42, 42, 42, 6: 42, 9: 42, 42, 42, 42, 42, 41: 42, 45: 42, 42, 51: 42, 42, 42, 42, 42, 42, 42, 42}, + {37, 37, 37, 37, 37, 37, 37, 37, 37, 11: 37, 14: 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 42: 37, 37, 37, 47: 37, 37, 37, 37}, + {36, 36, 36, 36, 36, 36, 36, 36, 36, 11: 36, 14: 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 42: 36, 36, 36, 47: 36, 36, 36, 36}, + {35, 35, 35, 35, 35, 35, 35, 35, 35, 11: 35, 14: 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 42: 35, 35, 35, 47: 35, 35, 35, 35}, + {34, 34, 34, 34, 34, 34, 34, 34, 34, 11: 34, 14: 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 42: 34, 34, 34, 47: 34, 34, 34, 34}, + // 70 + {33, 33, 33, 33, 33, 33, 33, 33, 33, 11: 33, 14: 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 42: 33, 33, 33, 47: 33, 33, 33, 33}, + {32, 32, 32, 32, 32, 32, 32, 32, 32, 11: 32, 14: 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 42: 32, 32, 32, 47: 32, 32, 32, 32}, + {31, 31, 31, 31, 31, 31, 31, 31, 31, 11: 31, 14: 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 42: 31, 31, 31, 47: 31, 31, 31, 31}, + {30, 30, 30, 30, 30, 30, 30, 30, 30, 11: 30, 14: 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 42: 30, 30, 30, 47: 30, 30, 30, 30}, + {29, 29, 29, 29, 29, 29, 29, 29, 29, 11: 29, 14: 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 42: 29, 29, 29, 47: 29, 29, 29, 29}, + // 75 + {28, 28, 28, 28, 28, 28, 28, 28, 28, 11: 28, 14: 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 42: 28, 28, 28, 47: 28, 28, 28, 28}, + {27, 27, 27, 27, 27, 27, 27, 27, 27, 11: 27, 14: 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 42: 27, 27, 27, 47: 27, 27, 27, 27}, + {26, 26, 26, 26, 26, 26, 26, 26, 26, 11: 26, 14: 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 42: 26, 26, 26, 47: 26, 26, 26, 26}, + {25, 25, 25, 25, 25, 25, 25, 25, 25, 11: 25, 14: 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 42: 25, 25, 25, 47: 25, 25, 25, 25}, + {24, 24, 24, 24, 24, 24, 24, 24, 24, 11: 24, 14: 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 42: 24, 24, 24, 47: 24, 24, 24, 24}, + // 80 + {23, 23, 23, 23, 23, 23, 23, 23, 23, 11: 23, 14: 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 42: 23, 23, 23, 47: 23, 23, 23, 23}, + {22, 22, 22, 22, 22, 22, 22, 22, 22, 11: 22, 14: 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 42: 22, 22, 22, 47: 22, 22, 22, 22}, + {21, 21, 21, 21, 21, 21, 21, 21, 21, 11: 21, 14: 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 42: 21, 21, 21, 47: 21, 21, 21, 21}, + {20, 20, 20, 20, 20, 20, 20, 20, 20, 11: 20, 14: 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 42: 20, 20, 20, 47: 20, 20, 20, 20}, + {19, 19, 19, 19, 19, 19, 19, 19, 19, 11: 19, 14: 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 42: 19, 19, 19, 47: 19, 19, 19, 19}, + // 85 + {18, 18, 18, 18, 18, 18, 18, 18, 18, 11: 18, 14: 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 42: 18, 18, 18, 47: 18, 18, 18, 18}, + {17, 17, 17, 17, 17, 17, 17, 17, 17, 11: 17, 14: 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 42: 17, 17, 17, 47: 17, 17, 17, 17}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 11: 16, 14: 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 42: 16, 16, 16, 47: 16, 16, 16, 16}, + {15, 15, 15, 15, 15, 15, 15, 15, 15, 11: 15, 14: 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 42: 15, 15, 15, 47: 15, 15, 15, 15}, + {14, 14, 14, 14, 14, 14, 14, 14, 14, 11: 14, 14: 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 42: 14, 14, 14, 47: 14, 14, 14, 14}, + // 90 + {7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 70: 259, 276, 271, 275, 346, 273}, + {7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 70: 259, 276, 271, 275, 345, 273}, + {7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 70: 259, 276, 271, 275, 344, 273}, + {7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 70: 259, 276, 271, 275, 310, 273}, + {6, 6, 6, 6, 6, 6, 6, 311, 9: 6, 6, 6, 6, 6, 41: 6, 44: 6, 6, 6, 51: 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 76: 6, 78: 6, 6, 6, 6, 6, 6, 86: 312, 103: 315, 105: 313, 314}, + // 95 + {2: 204, 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 335, 279, 84: 278, 263, 87: 281, 262, 260, 337, 99: 336, 155: 334}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 56: 317, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 316}, + {116, 116, 116, 116, 116, 116, 116, 116, 9: 116, 116, 116, 116, 116, 41: 116, 44: 116, 116, 116, 51: 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 76: 116, 78: 116, 116, 116, 116, 116, 116, 86: 116}, + {115, 115, 115, 115, 115, 115, 115, 115, 9: 115, 115, 115, 115, 115, 41: 115, 44: 115, 115, 115, 51: 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 76: 115, 78: 115, 115, 115, 115, 115, 115, 86: 115}, + {114, 114, 114, 114, 114, 114, 114, 114, 9: 114, 114, 114, 114, 114, 41: 114, 44: 114, 114, 114, 51: 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 76: 114, 78: 114, 114, 114, 114, 114, 114, 86: 114}, + // 100 + {45: 322, 321, 54: 329, 56: 330, 91: 320}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 54: 319, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 318}, + {45: 322, 321, 54: 323, 91: 320}, + {64, 64, 64, 64, 64, 64, 64, 64, 9: 64, 64, 64, 64, 64, 41: 64, 44: 64, 64, 64, 51: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 76: 64, 78: 64, 64, 64, 64, 64, 64, 86: 64}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 324}, + // 105 + {3: 168, 168, 168, 7: 168, 168, 14: 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 42: 168, 168, 47: 168, 168, 168, 168}, + {3: 167, 167, 167, 7: 167, 167, 14: 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 42: 167, 167, 47: 167, 167, 167, 167}, + {63, 63, 63, 63, 63, 63, 63, 63, 9: 63, 63, 63, 63, 63, 41: 63, 44: 63, 63, 63, 51: 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 76: 63, 78: 63, 63, 63, 63, 63, 63, 86: 63}, + {169, 169, 169, 6: 169, 9: 169, 169, 169, 169, 169, 41: 169, 45: 169, 169, 51: 169, 169, 169, 169, 169, 169, 327, 326, 150: 325}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 328, 262}, + // 110 + {3: 40, 40, 40, 7: 40, 40, 14: 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 42: 40, 40, 47: 40, 40, 40, 40}, + {3: 39, 39, 39, 7: 39, 39, 14: 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 42: 39, 39, 47: 39, 39, 39, 39}, + {41, 41, 41, 6: 41, 9: 41, 41, 41, 41, 41, 41: 41, 45: 41, 41, 51: 41, 41, 41, 41, 41, 41, 41, 41}, + {140, 140, 140, 140, 140, 140, 140, 140, 9: 140, 140, 140, 140, 140, 41: 140, 44: 140, 140, 140, 51: 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 76: 140, 78: 140, 140, 140, 140, 140, 140, 86: 140}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 54: 332, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 331}, + // 115 + {45: 322, 321, 54: 333, 91: 320}, + {62, 62, 62, 62, 62, 62, 62, 62, 9: 62, 62, 62, 62, 62, 41: 62, 44: 62, 62, 62, 51: 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 76: 62, 78: 62, 62, 62, 62, 62, 62, 86: 62}, + {61, 61, 61, 61, 61, 61, 61, 61, 9: 61, 61, 61, 61, 61, 41: 61, 44: 61, 61, 61, 51: 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 76: 61, 78: 61, 61, 61, 61, 61, 61, 86: 61}, + {2: 343}, + {2: 342}, + // 120 + {2: 203}, + {165, 165, 165, 6: 165, 9: 165, 165, 45: 322, 321, 52: 165, 165, 91: 320, 166: 338}, + {2, 2, 2, 6: 340, 9: 2, 2, 52: 2, 2, 98: 339}, + {166, 166, 166, 9: 166, 166, 52: 166, 166}, + {1, 1, 1, 309, 308, 306, 7: 274, 280, 1, 1, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 52: 1, 1, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 341}, + // 125 + {164, 164, 164, 6: 164, 9: 164, 164, 45: 322, 321, 52: 164, 164, 91: 320}, + {205, 205, 205, 205, 205, 205, 205, 205, 9: 205, 205, 205, 205, 205, 41: 205, 44: 205, 205, 205, 51: 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 76: 205, 78: 205, 205, 205, 205, 205, 205, 86: 205}, + {206, 206, 206, 206, 206, 206, 206, 206, 9: 206, 206, 206, 206, 206, 41: 206, 44: 206, 206, 206, 51: 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 76: 206, 78: 206, 206, 206, 206, 206, 206, 86: 206}, + {7, 7, 7, 7, 7, 7, 7, 311, 9: 7, 7, 7, 7, 7, 41: 7, 44: 7, 7, 7, 51: 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 76: 7, 78: 7, 7, 7, 7, 7, 7, 86: 312, 103: 315, 105: 313, 314}, + {8, 8, 8, 8, 8, 8, 8, 311, 9: 8, 8, 8, 8, 8, 41: 8, 44: 8, 8, 8, 51: 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 76: 8, 78: 8, 8, 8, 8, 8, 8, 86: 312, 103: 315, 105: 313, 314}, + // 130 + {9, 9, 9, 9, 9, 9, 9, 311, 9: 9, 9, 9, 9, 9, 41: 9, 44: 9, 9, 9, 51: 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 76: 9, 78: 9, 9, 9, 9, 9, 9, 86: 312, 103: 315, 105: 313, 314}, + {8: 348}, + {99, 99, 99, 99, 99, 99, 99, 99, 9: 99, 99, 99, 99, 99, 41: 99, 44: 99, 99, 99, 51: 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 76: 99, 78: 99, 99, 99, 99, 99, 99, 86: 99}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 362}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 361}, + // 135 + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 360}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 359}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 358}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 357}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 356}, + // 140 + {101, 101, 101, 101, 101, 101, 101, 9: 101, 101, 101, 101, 101, 41: 101, 44: 101, 101, 101, 51: 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 76: 101, 78: 101, 101, 101, 101, 101, 101}, + {102, 102, 102, 102, 102, 102, 102, 9: 102, 102, 102, 102, 102, 41: 102, 44: 102, 102, 102, 51: 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 76: 102, 78: 102, 102, 102, 102, 102, 102}, + {103, 103, 103, 103, 103, 103, 103, 9: 103, 103, 103, 103, 103, 41: 103, 44: 103, 103, 103, 51: 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 76: 103, 78: 103, 103, 103, 103, 103, 103}, + {104, 104, 104, 104, 104, 104, 104, 9: 104, 104, 104, 104, 104, 41: 104, 44: 104, 104, 104, 51: 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 76: 104, 78: 104, 104, 104, 104, 104, 104}, + {105, 105, 105, 105, 105, 105, 105, 9: 105, 105, 105, 105, 105, 41: 105, 44: 105, 105, 105, 51: 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 76: 105, 78: 105, 105, 105, 105, 105, 105}, + // 145 + {106, 106, 106, 106, 106, 106, 106, 9: 106, 106, 106, 106, 106, 41: 106, 44: 106, 106, 106, 51: 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 76: 106, 78: 106, 106, 106, 106, 106, 106}, + {107, 107, 107, 107, 107, 107, 107, 9: 107, 107, 107, 107, 107, 41: 107, 44: 107, 107, 107, 51: 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 76: 107, 78: 107, 107, 107, 107, 107, 107}, + {2: 364, 45: 322, 321, 91: 320}, + {123, 123, 123, 123, 123, 123, 123, 123, 9: 123, 123, 123, 123, 123, 41: 123, 44: 123, 123, 123, 51: 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 76: 123, 78: 123, 123, 123, 123, 123, 123, 86: 123}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 372}, + // 150 + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 371}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 370}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 369}, + {109, 109, 109, 109, 109, 109, 109, 9: 109, 109, 109, 109, 109, 41: 109, 44: 109, 109, 109, 51: 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 76: 355, 78: 353, 350, 354, 349, 351, 352}, + {110, 110, 110, 110, 110, 110, 110, 9: 110, 110, 110, 110, 110, 41: 110, 44: 110, 110, 110, 51: 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 76: 355, 78: 353, 350, 354, 349, 351, 352}, + // 155 + {111, 111, 111, 111, 111, 111, 111, 9: 111, 111, 111, 111, 111, 41: 111, 44: 111, 111, 111, 51: 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 76: 355, 78: 353, 350, 354, 349, 351, 352}, + {112, 112, 112, 112, 112, 112, 112, 9: 112, 112, 112, 112, 112, 41: 112, 44: 112, 112, 112, 51: 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 76: 355, 78: 353, 350, 354, 349, 351, 352}, + {7: 409}, + {60: 398, 397}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 394}, + // 160 + {14: 391, 44: 392}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 390}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 389}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 388}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 387}, + // 165 + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 386}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 385}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 384}, + {147, 147, 147, 368, 367, 365, 147, 9: 147, 147, 147, 147, 147, 41: 147, 44: 147, 147, 147, 51: 147, 147, 147, 147, 147, 147, 147, 147, 366, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147}, + {148, 148, 148, 368, 367, 365, 148, 9: 148, 148, 148, 148, 148, 41: 148, 44: 148, 148, 148, 51: 148, 148, 148, 148, 148, 148, 148, 148, 366, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148}, + // 170 + {149, 149, 149, 368, 367, 365, 149, 9: 149, 149, 149, 149, 149, 41: 149, 44: 149, 149, 149, 51: 149, 149, 149, 149, 149, 149, 149, 149, 366, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149}, + {150, 150, 150, 368, 367, 365, 150, 9: 150, 150, 150, 150, 150, 41: 150, 44: 150, 150, 150, 51: 150, 150, 150, 150, 150, 150, 150, 150, 366, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150}, + {151, 151, 151, 368, 367, 365, 151, 9: 151, 151, 151, 151, 151, 41: 151, 44: 151, 151, 151, 51: 151, 151, 151, 151, 151, 151, 151, 151, 366, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151}, + {152, 152, 152, 368, 367, 365, 152, 9: 152, 152, 152, 152, 152, 41: 152, 44: 152, 152, 152, 51: 152, 152, 152, 152, 152, 152, 152, 152, 366, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152}, + {153, 153, 153, 368, 367, 365, 153, 9: 153, 153, 153, 153, 153, 41: 153, 44: 153, 153, 153, 51: 153, 153, 153, 153, 153, 153, 153, 153, 366, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153}, + // 175 + {156, 156, 156, 6: 156, 9: 156, 156, 156, 156, 156, 41: 156, 45: 156, 156, 51: 156, 156, 156, 156, 156, 156, 156, 156}, + {14: 393}, + {155, 155, 155, 6: 155, 9: 155, 155, 155, 155, 155, 41: 155, 45: 155, 155, 51: 155, 155, 155, 155, 155, 155, 155, 155}, + {3: 368, 367, 365, 57: 395, 59: 366}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 396}, + // 180 + {158, 158, 158, 368, 367, 365, 158, 9: 158, 158, 158, 158, 158, 41: 158, 45: 158, 158, 51: 158, 158, 158, 158, 158, 158, 158, 158, 366}, + {7: 402}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 399}, + {3: 368, 367, 365, 57: 400, 59: 366}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 401}, + // 185 + {157, 157, 157, 368, 367, 365, 157, 9: 157, 157, 157, 157, 157, 41: 157, 45: 157, 157, 51: 157, 157, 157, 157, 157, 157, 157, 157, 366}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 337, 96: 229, 99: 403, 101: 404}, + {2: 408}, + {406, 2: 95, 136: 405}, + {2: 407}, + // 190 + {2: 94}, + {159, 159, 159, 6: 159, 9: 159, 159, 159, 159, 159, 41: 159, 45: 159, 159, 51: 159, 159, 159, 159, 159, 159, 159, 159}, + {161, 161, 161, 6: 161, 9: 161, 161, 161, 161, 161, 41: 161, 45: 161, 161, 51: 161, 161, 161, 161, 161, 161, 161, 161}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 337, 96: 229, 99: 410, 101: 411}, + {2: 414}, + // 195 + {406, 2: 95, 136: 412}, + {2: 413}, + {160, 160, 160, 6: 160, 9: 160, 160, 160, 160, 160, 41: 160, 45: 160, 160, 51: 160, 160, 160, 160, 160, 160, 160, 160}, + {162, 162, 162, 6: 162, 9: 162, 162, 162, 162, 162, 41: 162, 45: 162, 162, 51: 162, 162, 162, 162, 162, 162, 162, 162}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 416}, + // 200 + {2: 417, 45: 322, 321, 91: 320}, + {192, 192, 192, 192, 192, 192, 192, 192, 9: 192, 192, 192, 192, 192, 41: 192, 44: 192, 192, 192, 51: 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 76: 192, 78: 192, 192, 192, 192, 192, 192, 86: 192}, + {2, 2, 6: 420, 13: 2, 98: 419}, + {210, 210, 13: 210}, + {1, 1, 8: 254, 13: 1, 92: 252, 145: 421}, + // 205 + {208, 208, 6: 208, 13: 208}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 423}, + {211, 211, 6: 211, 13: 211, 45: 322, 321, 91: 320}, + {8: 248, 97: 425}, + {38, 38}, + // 210 + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 432, 279, 84: 278, 263, 87: 281, 262, 260, 428, 149: 429, 168: 430, 183: 431}, + {3: 74, 74, 74, 7: 74, 74, 14: 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 42: 74, 74, 47: 74, 74, 74, 74, 76: 74}, + {6: 145, 45: 322, 321, 51: 145, 55: 489, 91: 320, 167: 488}, + {6: 143, 51: 143}, + {6: 486, 51: 72}, + // 215 + {51: 433}, + {51: 73}, + {7: 436, 435, 132: 437, 434, 181: 438}, + {93, 93, 93, 6: 93, 9: 93, 93, 12: 93, 93, 41: 93, 55: 484, 93: 93, 93, 93, 100: 93, 180: 483}, + {97, 97, 97, 6: 97, 9: 97, 97, 12: 97, 97, 41: 97, 55: 97, 93: 97, 97, 97, 100: 97}, + // 220 + {96: 229, 101: 480}, + {91, 91, 91, 6: 91, 9: 91, 91, 12: 91, 91, 41: 91, 93: 91, 91, 91}, + {2, 2, 2, 6: 439, 9: 2, 2, 12: 2, 2, 41: 2, 93: 2, 2, 2, 98: 440}, + {1, 1, 1, 7: 436, 435, 1, 1, 12: 1, 1, 41: 1, 93: 1, 1, 1, 132: 479, 434}, + {82, 82, 82, 9: 82, 82, 12: 82, 82, 41: 82, 93: 443, 441, 442, 173: 445, 446, 444}, + // 225 + {102: 88, 111: 88}, + {102: 87, 111: 87}, + {102: 86, 111: 86}, + {102: 85, 111: 473, 178: 474}, + {81, 81, 81, 9: 81, 81, 12: 81, 81, 41: 81}, + // 230 + {70, 70, 70, 9: 70, 70, 12: 70, 258, 41: 70, 142: 448, 188: 447}, + {68, 68, 68, 9: 68, 68, 12: 68, 41: 449, 169: 451, 184: 450}, + {69, 69, 69, 9: 69, 69, 12: 69, 41: 69}, + {146: 466}, + {66, 66, 66, 9: 66, 66, 12: 452, 176: 454, 187: 453}, + // 235 + {67, 67, 67, 9: 67, 67, 12: 67}, + {146: 461}, + {79, 79, 79, 9: 79, 456, 185: 455}, + {65, 65, 65, 9: 65, 65}, + {77, 77, 77, 9: 459, 186: 458}, + // 240 + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 457}, + {78, 78, 78, 9: 78, 45: 322, 321, 91: 320}, + {80, 80, 80}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 460}, + {76, 76, 76, 45: 322, 321, 91: 320}, + // 245 + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 337, 99: 462}, + {121, 121, 121, 9: 121, 121, 52: 464, 465, 177: 463}, + {122, 122, 122, 9: 122, 122}, + {120, 120, 120, 9: 120, 120}, + {119, 119, 119, 9: 119, 119}, + // 250 + {8: 254, 92: 467, 147: 468}, + {199, 199, 199, 6: 199, 9: 199, 199, 12: 199, 157: 469}, + {141, 141, 141, 9: 141, 141, 12: 141}, + {2, 2, 2, 6: 471, 9: 2, 2, 12: 2, 98: 470}, + {200, 200, 200, 9: 200, 200, 12: 200}, + // 255 + {1, 1, 1, 8: 254, 1, 1, 12: 1, 92: 472}, + {198, 198, 198, 6: 198, 9: 198, 198, 12: 198}, + {102: 84}, + {102: 475}, + {7: 436, 435, 132: 476, 434}, + // 260 + {100: 477}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 478}, + {83, 83, 83, 9: 83, 83, 12: 83, 83, 41: 83, 45: 322, 321, 91: 320}, + {90, 90, 90, 6: 90, 9: 90, 90, 12: 90, 90, 41: 90, 93: 90, 90, 90}, + {406, 2: 95, 136: 481}, + // 265 + {2: 482}, + {96, 96, 96, 6: 96, 9: 96, 96, 12: 96, 96, 41: 96, 55: 96, 93: 96, 96, 96, 100: 96}, + {98, 98, 98, 6: 98, 9: 98, 98, 12: 98, 98, 41: 98, 93: 98, 98, 98, 100: 98}, + {8: 485}, + {92, 92, 92, 6: 92, 9: 92, 92, 12: 92, 92, 41: 92, 93: 92, 92, 92, 100: 92}, + // 270 + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 71, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 428, 149: 487}, + {6: 142, 51: 142}, + {6: 146, 51: 146}, + {8: 490}, + {6: 144, 51: 144}, + // 275 + {8: 248, 97: 492}, + {7: 494, 96: 137, 113: 137, 170: 493}, + {96: 229, 101: 498, 113: 497}, + {8: 254, 92: 467, 147: 495}, + {2: 496}, + // 280 + {96: 136, 113: 136}, + {7: 499}, + {138, 138}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 337, 99: 500}, + {2: 501}, + // 285 + {135, 135, 6: 135, 171: 502}, + {2, 2, 6: 504, 98: 503}, + {139, 139}, + {1, 1, 7: 505}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 337, 99: 506}, + // 290 + {2: 507}, + {134, 134, 6: 134}, + {171, 171}, + {8: 176, 109: 516, 165: 515}, + {8: 248, 97: 511, 109: 512}, + // 295 + {174, 174}, + {108: 513}, + {8: 248, 97: 514}, + {173, 173}, + {8: 518}, + // 300 + {108: 517}, + {8: 175}, + {177, 177}, + {8: 248, 97: 520}, + {179, 179, 13: 258, 142: 521}, + // 305 + {178, 178}, + {110: 553}, + {110: 187}, + {8: 248, 97: 525, 109: 526}, + {7: 548}, + // 310 + {44: 527}, + {108: 528}, + {8: 248, 97: 529}, + {7: 530}, + {8: 254, 92: 531, 107: 532}, + // 315 + {15: 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 70: 538}, + {2: 184, 6: 184, 148: 533}, + {2: 2, 6: 535, 98: 534}, + {2: 537}, + {2: 1, 8: 254, 92: 531, 107: 536}, + // 320 + {2: 183, 6: 183}, + {185, 185}, + {194, 194, 194, 309, 308, 306, 194, 274, 280, 11: 194, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 540, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 541, 158: 542, 539}, + {181, 181, 181, 6: 181, 11: 545, 162: 546, 544}, + {14: 543}, + // 325 + {195, 195, 195, 6: 195, 11: 195, 45: 322, 321, 91: 320}, + {193, 193, 193, 6: 193, 11: 193}, + {196, 196, 196, 6: 196, 11: 196}, + {202, 202, 202, 6: 202}, + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 547}, + // 330 + {180, 180, 180, 6: 180}, + {182, 182, 182, 6: 182, 45: 322, 321, 91: 320}, + {8: 254, 92: 531, 107: 549}, + {2: 184, 6: 184, 148: 550}, + {2: 2, 6: 535, 98: 551}, + // 335 + {2: 552}, + {186, 186}, + {8: 190, 109: 555, 160: 554}, + {8: 558}, + {44: 556}, + // 340 + {108: 557}, + {8: 189}, + {100: 559}, + {8: 560}, + {7: 561}, + // 345 + {3: 309, 308, 306, 7: 274, 280, 14: 265, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 290, 294, 295, 296, 297, 293, 298, 299, 300, 302, 303, 304, 305, 301, 264, 267, 42: 268, 269, 47: 272, 270, 266, 307, 70: 259, 276, 271, 275, 277, 273, 77: 279, 84: 278, 263, 87: 281, 262, 260, 337, 99: 562}, + {2: 563}, + {191, 191}, + {207, 207}, + {8: 248, 97: 566}, + // 350 + {104: 568, 144: 567}, + {8: 254, 92: 531, 107: 571}, + {156: 569}, + {8: 254, 92: 570}, + {212, 212}, + // 355 + {213, 213}, + {1: 214, 45: 322, 321, 91: 320}, + {172, 172, 96: 229, 101: 242, 104: 225, 114: 220, 231, 221, 232, 222, 233, 223, 234, 235, 236, 224, 237, 238, 230, 226, 239, 227, 240, 134: 228, 241, 137: 574, 246, 243, 247, 244}, + {44, 44}, + } +) + +var yyDebug = 0 + +type yyLexer interface { + Lex(lval *yySymType) int + Error(s string) +} + +type yyLexerEx interface { + yyLexer + Reduced(rule, state int, lval *yySymType) bool +} + +func yySymName(c int) (s string) { + x, ok := yyXLAT[c] + if ok { + return yySymNames[x] + } + + if c < 0x7f { + return __yyfmt__.Sprintf("'%c'", c) + } + + return __yyfmt__.Sprintf("%d", c) +} + +func yylex1(yylex yyLexer, lval *yySymType) (n int) { + n = yylex.Lex(lval) + if n <= 0 { + n = yyEOFCode + } + if yyDebug >= 3 { + __yyfmt__.Printf("\nlex %s(%#x %d), lval: %+v\n", yySymName(n), n, n, lval) + } + return n +} + +func yyParse(yylex yyLexer) int { + const yyError = 196 + + yyEx, _ := yylex.(yyLexerEx) + var yyn int + var yylval yySymType + var yyVAL yySymType + yyS := make([]yySymType, 200) + + Nerrs := 0 /* number of errors */ + Errflag := 0 /* error recovery flag */ + yyerrok := func() { + if yyDebug >= 2 { + __yyfmt__.Printf("yyerrok()\n") + } + Errflag = 0 + } + _ = yyerrok + yystate := 0 + yychar := -1 + var yyxchar int + var yyshift int + yyp := -1 + goto yystack + +ret0: + return 0 + +ret1: + return 1 + +yystack: + /* put a state and value onto the stack */ + yyp++ + if yyp >= len(yyS) { + nyys := make([]yySymType, len(yyS)*2) + copy(nyys, yyS) + yyS = nyys + } + yyS[yyp] = yyVAL + yyS[yyp].yys = yystate + +yynewstate: + if yychar < 0 { + yychar = yylex1(yylex, &yylval) + var ok bool + if yyxchar, ok = yyXLAT[yychar]; !ok { + yyxchar = len(yySymNames) // > tab width + } + } + if yyDebug >= 4 { + var a []int + for _, v := range yyS[:yyp+1] { + a = append(a, v.yys) + } + __yyfmt__.Printf("state stack %v\n", a) + } + row := yyParseTab[yystate] + yyn = 0 + if yyxchar < len(row) { + if yyn = int(row[yyxchar]); yyn != 0 { + yyn += yyTabOfs + } + } + switch { + case yyn > 0: // shift + yychar = -1 + yyVAL = yylval + yystate = yyn + yyshift = yyn + if yyDebug >= 2 { + __yyfmt__.Printf("shift, and goto state %d\n", yystate) + } + if Errflag > 0 { + Errflag-- + } + goto yystack + case yyn < 0: // reduce + case yystate == 1: // accept + if yyDebug >= 2 { + __yyfmt__.Println("accept") + } + goto ret0 + } + + if yyn == 0 { + /* error ... attempt to resume parsing */ + switch Errflag { + case 0: /* brand new error */ + if yyDebug >= 1 { + __yyfmt__.Printf("no action for %s in state %d\n", yySymName(yychar), yystate) + } + msg, ok := yyXErrors[yyXError{yystate, yyxchar}] + if !ok { + msg, ok = yyXErrors[yyXError{yystate, -1}] + } + if !ok && yyshift != 0 { + msg, ok = yyXErrors[yyXError{yyshift, yyxchar}] + } + if !ok { + msg, ok = yyXErrors[yyXError{yyshift, -1}] + } + if yychar > 0 { + ls := yyTokenLiteralStrings[yychar] + if ls == "" { + ls = yySymName(yychar) + } + if ls != "" { + switch { + case msg == "": + msg = __yyfmt__.Sprintf("unexpected %s", ls) + default: + msg = __yyfmt__.Sprintf("unexpected %s, %s", ls, msg) + } + } + } + if msg == "" { + msg = "syntax error" + } + yylex.Error(msg) + Nerrs++ + fallthrough + + case 1, 2: /* incompletely recovered error ... try again */ + Errflag = 3 + + /* find a state where "error" is a legal shift action */ + for yyp >= 0 { + row := yyParseTab[yyS[yyp].yys] + if yyError < len(row) { + yyn = int(row[yyError]) + yyTabOfs + if yyn > 0 { // hit + if yyDebug >= 2 { + __yyfmt__.Printf("error recovery found error shift in state %d\n", yyS[yyp].yys) + } + yystate = yyn /* simulate a shift of "error" */ + goto yystack + } + } + + /* the current p has no shift on "error", pop stack */ + if yyDebug >= 2 { + __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys) + } + yyp-- + } + /* there is no state on the stack with an error shift ... abort */ + if yyDebug >= 2 { + __yyfmt__.Printf("error recovery failed\n") + } + goto ret1 + + case 3: /* no shift yet; clobber input char */ + if yyDebug >= 2 { + __yyfmt__.Printf("error recovery discards %s\n", yySymName(yychar)) + } + if yychar == yyEOFCode { + goto ret1 + } + + yychar = -1 + goto yynewstate /* try again in the same state */ + } + } + + r := -yyn + x0 := yyReductions[r] + x, n := x0.xsym, x0.components + yypt := yyp + _ = yypt // guard against "declared and not used" + + yyp -= n + if yyp+1 >= len(yyS) { + nyys := make([]yySymType, len(yyS)*2) + copy(nyys, yyS) + yyS = nyys + } + yyVAL = yyS[yyp+1] + + /* consult goto table to find next state */ + exState := yystate + yystate = int(yyParseTab[yyS[yyp].yys][x]) + yyTabOfs + /* reduction by production r */ + if yyDebug >= 2 { + __yyfmt__.Printf("reduce using rule %v (%s), and goto state %d\n", r, yySymNames[x], yystate) + } + + switch r { + case 2: + { + yylex.(*lexer).expr = expr(yyS[yypt-0].item) + } + case 3: + { + yyVAL.item = &alterTableAddStmt{tableName: yyS[yypt-2].item.(string), c: yyS[yypt-0].item.(*col)} + } + case 4: + { + yyVAL.item = &alterTableDropColumnStmt{tableName: yyS[yypt-3].item.(string), colName: yyS[yypt-0].item.(string)} + } + case 5: + { + yyVAL.item = assignment{colName: yyS[yypt-2].item.(string), expr: expr(yyS[yypt-0].item)} + } + case 6: + { + yyVAL.item = append([]assignment{yyS[yypt-2].item.(assignment)}, yyS[yypt-1].item.([]assignment)...) + } + case 7: + { + yyVAL.item = []assignment{} + } + case 8: + { + yyVAL.item = append(yyS[yypt-2].item.([]assignment), yyS[yypt-0].item.(assignment)) + } + case 9: + { + yyVAL.item = beginTransactionStmt{} + } + case 10: + { + yyVAL.item = yyS[yypt-1].item + } + case 11: + { + yyVAL.item = '*' + } + case 12: + { + yyVAL.item = []expression{} + } + case 14: + { + x := &col{name: yyS[yypt-3].item.(string), typ: yyS[yypt-2].item.(int), constraint: yyS[yypt-1].item.(*constraint)} + if yyS[yypt-0].item != nil { + x.dflt = expr(yyS[yypt-0].item) + } + yyVAL.item = x + } + case 16: + { + yyVAL.item = append([]string{yyS[yypt-2].item.(string)}, yyS[yypt-1].item.([]string)...) + } + case 17: + { + yyVAL.item = []string{} + } + case 18: + { + yyVAL.item = append(yyS[yypt-2].item.([]string), yyS[yypt-0].item.(string)) + } + case 19: + { + yyVAL.item = commitStmt{} + } + case 20: + { + yyVAL.item = &constraint{} + } + case 21: + { + yyVAL.item = &constraint{expr(yyS[yypt-0].item)} + } + case 22: + { + yyVAL.item = (*constraint)(nil) + } + case 24: + { + yyVAL.item = &conversion{typ: yyS[yypt-3].item.(int), val: expr(yyS[yypt-1].item)} + } + case 25: + { + indexName, tableName, exprList := yyS[yypt-5].item.(string), yyS[yypt-3].item.(string), yyS[yypt-1].item.([]expression) + simpleIndex := len(exprList) == 1 + var columnName string + if simpleIndex { + expr := exprList[0] + switch x := expr.(type) { + case *ident: + columnName = x.s + case *call: + if x.f == "id" && len(x.arg) == 0 { + columnName = "id()" + break + } + + simpleIndex = false + default: + simpleIndex = false + } + } + + if !simpleIndex { + columnName = "" + } + yyVAL.item = &createIndexStmt{unique: yyS[yypt-8].item.(bool), ifNotExists: yyS[yypt-6].item.(bool), indexName: indexName, tableName: tableName, colName: columnName, exprList: exprList} + + if indexName == tableName || indexName == columnName { + yylex.(*lexer).err("index name collision: %s", indexName) + return 1 + } + + if yylex.(*lexer).root { + break + } + + if isSystemName[indexName] || isSystemName[tableName] { + yylex.(*lexer).err("name is used for system tables: %s", indexName) + return 1 + } + } + case 26: + { + yyVAL.item = false + } + case 27: + { + yyVAL.item = true + } + case 28: + { + yyVAL.item = false + } + case 29: + { + yyVAL.item = true + } + case 30: + { + nm := yyS[yypt-5].item.(string) + yyVAL.item = &createTableStmt{tableName: nm, cols: append([]*col{yyS[yypt-3].item.(*col)}, yyS[yypt-2].item.([]*col)...)} + + if yylex.(*lexer).root { + break + } + + if isSystemName[nm] { + yylex.(*lexer).err("name is used for system tables: %s", nm) + return 1 + } + } + case 31: + { + nm := yyS[yypt-5].item.(string) + yyVAL.item = &createTableStmt{ifNotExists: true, tableName: nm, cols: append([]*col{yyS[yypt-3].item.(*col)}, yyS[yypt-2].item.([]*col)...)} + + if yylex.(*lexer).root { + break + } + + if isSystemName[nm] { + yylex.(*lexer).err("name is used for system tables: %s", nm) + return 1 + } + } + case 32: + { + yyVAL.item = []*col{} + } + case 33: + { + yyVAL.item = append(yyS[yypt-2].item.([]*col), yyS[yypt-0].item.(*col)) + } + case 34: + { + yyVAL.item = yyS[yypt-0].item + } + case 35: + { + yyVAL.item = nil + } + case 37: + { + yyVAL.item = &truncateTableStmt{yyS[yypt-0].item.(string)} + + if yylex.(*lexer).root { + break + } + + if isSystemName[yyS[yypt-0].item.(string)] { + yylex.(*lexer).err("name is used for system tables: %s", yyS[yypt-0].item.(string)) + return 1 + } + } + case 38: + { + yyVAL.item = &deleteStmt{tableName: yyS[yypt-1].item.(string), where: yyS[yypt-0].item.(*whereRset).expr} + + if yylex.(*lexer).root { + break + } + + if isSystemName[yyS[yypt-1].item.(string)] { + yylex.(*lexer).err("name is used for system tables: %s", yyS[yypt-1].item.(string)) + return 1 + } + } + case 39: + { + yyVAL.item = &dropIndexStmt{ifExists: yyS[yypt-1].item.(bool), indexName: yyS[yypt-0].item.(string)} + } + case 40: + { + yyVAL.item = false + } + case 41: + { + yyVAL.item = true + } + case 42: + { + nm := yyS[yypt-0].item.(string) + yyVAL.item = &dropTableStmt{tableName: nm} + + if yylex.(*lexer).root { + break + } + + if isSystemName[nm] { + yylex.(*lexer).err("name is used for system tables: %s", nm) + return 1 + } + } + case 43: + { + nm := yyS[yypt-0].item.(string) + yyVAL.item = &dropTableStmt{ifExists: true, tableName: nm} + + if yylex.(*lexer).root { + break + } + + if isSystemName[nm] { + yylex.(*lexer).err("name is used for system tables: %s", nm) + return 1 + } + } + case 44: + { + yyVAL.item = nil + } + case 45: + { + yyVAL.item = &explainStmt{yyS[yypt-0].item.(stmt)} + } + case 47: + { + var err error + if yyVAL.item, err = newBinaryOperation(oror, yyS[yypt-2].item, yyS[yypt-0].item); err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 50: + { + yyVAL.item = append([]expression{expr(yyS[yypt-2].item)}, yyS[yypt-1].item.([]expression)...) + } + case 51: + { + yyVAL.item = []expression(nil) + } + case 52: + { + yyVAL.item = append(yyS[yypt-2].item.([]expression), expr(yyS[yypt-0].item)) + } + case 54: + { + yyVAL.item = &pIn{expr: yyS[yypt-4].item.(expression), list: yyS[yypt-1].item.([]expression)} + } + case 55: + { + yyVAL.item = &pIn{expr: yyS[yypt-5].item.(expression), not: true, list: yyS[yypt-1].item.([]expression)} + } + case 56: + { + yyVAL.item = &pIn{expr: yyS[yypt-5].item.(expression), sel: yyS[yypt-2].item.(*selectStmt)} + } + case 57: + { + yyVAL.item = &pIn{expr: yyS[yypt-6].item.(expression), not: true, sel: yyS[yypt-2].item.(*selectStmt)} + } + case 58: + { + var err error + if yyVAL.item, err = newBetween(yyS[yypt-4].item, yyS[yypt-2].item, yyS[yypt-0].item, false); err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 59: + { + var err error + if yyVAL.item, err = newBetween(yyS[yypt-5].item, yyS[yypt-2].item, yyS[yypt-0].item, true); err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 60: + { + yyVAL.item = &isNull{expr: yyS[yypt-2].item.(expression)} + } + case 61: + { + yyVAL.item = &isNull{expr: yyS[yypt-3].item.(expression), not: true} + } + case 63: + { + var err error + if yyVAL.item, err = newBinaryOperation(ge, yyS[yypt-2].item, yyS[yypt-0].item); err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 64: + { + var err error + if yyVAL.item, err = newBinaryOperation('>', yyS[yypt-2].item, yyS[yypt-0].item); err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 65: + { + var err error + if yyVAL.item, err = newBinaryOperation(le, yyS[yypt-2].item, yyS[yypt-0].item); err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 66: + { + var err error + if yyVAL.item, err = newBinaryOperation('<', yyS[yypt-2].item, yyS[yypt-0].item); err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 67: + { + var err error + if yyVAL.item, err = newBinaryOperation(neq, yyS[yypt-2].item, yyS[yypt-0].item); err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 68: + { + var err error + if yyVAL.item, err = newBinaryOperation(eq, yyS[yypt-2].item, yyS[yypt-0].item); err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 69: + { + yyVAL.item = &pLike{expr: yyS[yypt-2].item.(expression), pattern: yyS[yypt-0].item.(expression)} + } + case 70: + { + expr, name := expr(yyS[yypt-1].item), yyS[yypt-0].item.(string) + if name == "" { + s, ok := expr.(*ident) + if ok { + name = s.s + } + } + yyVAL.item = &fld{expr: expr, name: name} + } + case 71: + { + yyVAL.item = "" + } + case 72: + { + yyVAL.item = yyS[yypt-0].item + } + case 73: + { + yyVAL.item = []*fld{yyS[yypt-0].item.(*fld)} + } + case 74: + { + l, f := yyS[yypt-2].item.([]*fld), yyS[yypt-0].item.(*fld) + if f.name != "" { + if f := findFld(l, f.name); f != nil { + yylex.(*lexer).err("duplicate field name %q", f.name) + return 1 + } + } + + yyVAL.item = append(yyS[yypt-2].item.([]*fld), yyS[yypt-0].item.(*fld)) + } + case 75: + { + yyVAL.item = &groupByRset{colNames: yyS[yypt-0].item.([]string)} + } + case 76: + { + yyVAL.item = yyS[yypt-1].item + } + case 77: + { + yyVAL.item = &insertIntoStmt{tableName: yyS[yypt-7].item.(string), colNames: yyS[yypt-6].item.([]string), lists: append([][]expression{yyS[yypt-3].item.([]expression)}, yyS[yypt-1].item.([][]expression)...)} + + if yylex.(*lexer).root { + break + } + + if isSystemName[yyS[yypt-7].item.(string)] { + yylex.(*lexer).err("name is used for system tables: %s", yyS[yypt-7].item.(string)) + return 1 + } + } + case 78: + { + yyVAL.item = &insertIntoStmt{tableName: yyS[yypt-2].item.(string), colNames: yyS[yypt-1].item.([]string), sel: yyS[yypt-0].item.(*selectStmt)} + } + case 79: + { + yyVAL.item = []string{} + } + case 80: + { + yyVAL.item = yyS[yypt-1].item + } + case 81: + { + yyVAL.item = [][]expression{} + } + case 82: + { + yyVAL.item = append(yyS[yypt-4].item.([][]expression), yyS[yypt-1].item.([]expression)) + } + case 90: + { + yyVAL.item = value{yyS[yypt-0].item} + } + case 91: + { + n := yyS[yypt-0].item.(int) + yyVAL.item = parameter{n} + l := yylex.(*lexer) + l.params = mathutil.Max(l.params, n) + if n == 0 { + l.err("parameter number must be non zero") + return 1 + } + } + case 92: + { + yyVAL.item = &ident{yyS[yypt-0].item.(string)} + } + case 93: + { + yyVAL.item = &pexpr{expr: expr(yyS[yypt-1].item)} + } + case 94: + { + yyVAL.item = &orderByRset{by: yyS[yypt-1].item.([]expression), asc: yyS[yypt-0].item.(bool)} + } + case 95: + { + yyVAL.item = true // ASC by default + } + case 96: + { + yyVAL.item = true + } + case 97: + { + yyVAL.item = false + } + case 100: + { + var err error + if yyVAL.item, err = newIndex(yyS[yypt-1].item.(expression), expr(yyS[yypt-0].item)); err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 101: + { + var err error + s := yyS[yypt-0].item.([2]*expression) + if yyVAL.item, err = newSlice(yyS[yypt-1].item.(expression), s[0], s[1]); err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 102: + { + x := yylex.(*lexer) + f, ok := yyS[yypt-1].item.(*ident) + if !ok { + x.err("expected identifier or qualified identifier") + return 1 + } + + if r, ok := yyS[yypt-0].item.(rune); ok { + if f.isQualified() || f.s != "count" || r != '*' { + x.err(fmt.Sprintf("invalid expression %s(%c)", f, r)) + return 1 + } + + yyS[yypt-0].item = []expression(nil) + } + + var err error + var agg bool + if yyVAL.item, agg, err = newCall(f.s, yyS[yypt-0].item.([]expression)); err != nil { + x.err("%v", err) + return 1 + } + if n := len(x.agg); n > 0 { + x.agg[n-1] = x.agg[n-1] || agg + } + } + case 104: + { + var err error + if yyVAL.item, err = newBinaryOperation('^', yyS[yypt-2].item, yyS[yypt-0].item); err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 105: + { + var err error + if yyVAL.item, err = newBinaryOperation('|', yyS[yypt-2].item, yyS[yypt-0].item); err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 106: + { + var err error + if yyVAL.item, err = newBinaryOperation('-', yyS[yypt-2].item, yyS[yypt-0].item); err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 107: + { + var err error + yyVAL.item, err = newBinaryOperation('+', yyS[yypt-2].item, yyS[yypt-0].item) + if err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 109: + { + var err error + yyVAL.item, err = newBinaryOperation(andnot, yyS[yypt-2].item, yyS[yypt-0].item) + if err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 110: + { + var err error + yyVAL.item, err = newBinaryOperation('&', yyS[yypt-2].item, yyS[yypt-0].item) + if err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 111: + { + var err error + yyVAL.item, err = newBinaryOperation(lsh, yyS[yypt-2].item, yyS[yypt-0].item) + if err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 112: + { + var err error + yyVAL.item, err = newBinaryOperation(rsh, yyS[yypt-2].item, yyS[yypt-0].item) + if err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 113: + { + var err error + yyVAL.item, err = newBinaryOperation('%', yyS[yypt-2].item, yyS[yypt-0].item) + if err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 114: + { + var err error + yyVAL.item, err = newBinaryOperation('/', yyS[yypt-2].item, yyS[yypt-0].item) + if err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 115: + { + var err error + yyVAL.item, err = newBinaryOperation('*', yyS[yypt-2].item, yyS[yypt-0].item) + if err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 117: + { + yyVAL.item = fmt.Sprintf("%s.%s", yyS[yypt-2].item.(string), yyS[yypt-0].item.(string)) + } + case 118: + { + yyVAL.item = []interface{}{yyS[yypt-1].item, yyS[yypt-0].item} + } + case 120: + { + yyVAL.item = yyS[yypt-2].item + } + case 123: + { + yyVAL.item = "" + } + case 124: + { + yyVAL.item = yyS[yypt-0].item + } + case 125: + { + yyVAL.list = []interface{}{yyS[yypt-0].item} + } + case 126: + { + yyVAL.list = append(yyS[yypt-2].list, yyS[yypt-0].item) + } + case 127: + { + yyVAL.item = rollbackStmt{} + } + case 128: + { + yyVAL.item = leftJoin + } + case 129: + { + yyVAL.item = rightJoin + } + case 130: + { + yyVAL.item = fullJoin + } + case 131: + { + yyVAL.item = nil + } + case 133: + { + yyVAL.item = []interface{}{yyS[yypt-5].item, yyS[yypt-2].item, yyS[yypt-0].item} + } + case 134: + { + yyVAL.item = nil + } + case 136: + { + x := yylex.(*lexer) + n := len(x.agg) + join := &joinRset{sources: yyS[yypt-7].list} + if o := yyS[yypt-5].item; o != nil { + o := o.([]interface{}) + join.typ = o[0].(int) + join.sources = append(join.sources, o[1].([]interface{})) + join.on = o[2].(expression) + } + yyVAL.item = &selectStmt{ + distinct: yyS[yypt-10].item.(bool), + flds: yyS[yypt-9].item.([]*fld), + from: join, + hasAggregates: x.agg[n-1], + where: yyS[yypt-4].item.(*whereRset), + group: yyS[yypt-3].item.(*groupByRset), + order: yyS[yypt-2].item.(*orderByRset), + limit: yyS[yypt-1].item.(*limitRset), + offset: yyS[yypt-0].item.(*offsetRset), + } + x.agg = x.agg[:n-1] + } + case 137: + { + yyVAL.item = (*limitRset)(nil) + } + case 138: + { + yyVAL.item = &limitRset{expr: expr(yyS[yypt-0].item)} + } + case 139: + { + yyVAL.item = (*offsetRset)(nil) + } + case 140: + { + yyVAL.item = &offsetRset{expr: expr(yyS[yypt-0].item)} + } + case 141: + { + yyVAL.item = false + } + case 142: + { + yyVAL.item = true + } + case 143: + { + yyVAL.item = []*fld{} + } + case 144: + { + yyVAL.item = yyS[yypt-0].item + } + case 145: + { + yyVAL.item = yyS[yypt-1].item + } + case 146: + { + yyVAL.item = (*whereRset)(nil) + } + case 148: + { + yyVAL.item = (*groupByRset)(nil) + } + case 150: + { + yyVAL.item = (*orderByRset)(nil) + } + case 152: + { + yyVAL.item = [2]*expression{nil, nil} + } + case 153: + { + hi := expr(yyS[yypt-1].item) + yyVAL.item = [2]*expression{nil, &hi} + } + case 154: + { + lo := expr(yyS[yypt-2].item) + yyVAL.item = [2]*expression{&lo, nil} + } + case 155: + { + lo := expr(yyS[yypt-3].item) + hi := expr(yyS[yypt-1].item) + yyVAL.item = [2]*expression{&lo, &hi} + } + case 171: + { + if yyS[yypt-0].item != nil { + yylex.(*lexer).list = []stmt{yyS[yypt-0].item.(stmt)} + } + } + case 172: + { + if yyS[yypt-0].item != nil { + yylex.(*lexer).list = append(yylex.(*lexer).list, yyS[yypt-0].item.(stmt)) + } + } + case 175: + { + var err error + if yyVAL.item, err = newBinaryOperation(andand, yyS[yypt-2].item, yyS[yypt-0].item); err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 178: + { + yyVAL.item = &truncateTableStmt{tableName: yyS[yypt-0].item.(string)} + } + case 203: + { + var expr expression + if w := yyS[yypt-0].item; w != nil { + expr = w.(*whereRset).expr + } + yyVAL.item = &updateStmt{tableName: yyS[yypt-3].item.(string), list: yyS[yypt-1].item.([]assignment), where: expr} + + if yylex.(*lexer).root { + break + } + + if isSystemName[yyS[yypt-3].item.(string)] { + yylex.(*lexer).err("name is used for system tables: %s", yyS[yypt-3].item.(string)) + return 1 + } + } + case 204: + { + yyVAL.item = nil + } + case 207: + { + var err error + yyVAL.item, err = newUnaryOperation('^', yyS[yypt-0].item) + if err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 208: + { + var err error + yyVAL.item, err = newUnaryOperation('!', yyS[yypt-0].item) + if err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 209: + { + var err error + yyVAL.item, err = newUnaryOperation('-', yyS[yypt-0].item) + if err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 210: + { + var err error + yyVAL.item, err = newUnaryOperation('+', yyS[yypt-0].item) + if err != nil { + yylex.(*lexer).err("%v", err) + return 1 + } + } + case 211: + { + yyVAL.item = &whereRset{expr: expr(yyS[yypt-0].item)} + } + + } + + if yyEx != nil && yyEx.Reduced(r, exState, &yyVAL) { + return -1 + } + goto yystack /* stack new state and value */ +} + +func expr(v interface{}) expression { + e := v.(expression) + for { + x, ok := e.(*pexpr) + if !ok { + return e + } + e = x.expr + } +} diff --git a/vendor/github.com/cznic/ql/plan.go b/vendor/github.com/cznic/ql/plan.go new file mode 100644 index 00000000..be52b72c --- /dev/null +++ b/vendor/github.com/cznic/ql/plan.go @@ -0,0 +1,2800 @@ +// Copyright 2015 The ql 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 ql + +import ( + "bytes" + "fmt" + "strings" + + "github.com/cznic/b" + "github.com/cznic/strutil" +) + +const ( + _ = iota + indexEq // [L] + indexFalse // [false] + indexGe // [L, ...) + indexGt // (L, ...) + indexIsNotNull // (NULL, ...) + indexIsNull // [NULL] + indexIntervalCC // [L, H] + indexIntervalCO // [L, H) + indexIntervalOC // (L, H] + indexIntervalOO // (L, H) + indexLe // (..., H] + indexLt // (..., H) + indexNe // (L) + indexTrue // [true] +) + +// Note: All plans must have a pointer receiver. Enables planA == planB operation. +var ( + _ plan = (*crossJoinDefaultPlan)(nil) + _ plan = (*distinctDefaultPlan)(nil) + _ plan = (*explainDefaultPlan)(nil) + _ plan = (*filterDefaultPlan)(nil) + _ plan = (*fullJoinDefaultPlan)(nil) + _ plan = (*groupByDefaultPlan)(nil) + _ plan = (*indexPlan)(nil) + _ plan = (*leftJoinDefaultPlan)(nil) + _ plan = (*limitDefaultPlan)(nil) + _ plan = (*nullPlan)(nil) + _ plan = (*offsetDefaultPlan)(nil) + _ plan = (*orderByDefaultPlan)(nil) + _ plan = (*rightJoinDefaultPlan)(nil) + _ plan = (*selectFieldsDefaultPlan)(nil) + _ plan = (*selectFieldsGroupPlan)(nil) + _ plan = (*selectIndexDefaultPlan)(nil) + _ plan = (*sysColumnDefaultPlan)(nil) + _ plan = (*sysIndexDefaultPlan)(nil) + _ plan = (*sysTableDefaultPlan)(nil) + _ plan = (*tableDefaultPlan)(nil) + _ plan = (*tableNilPlan)(nil) +) + +type plan interface { + do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) error + explain(w strutil.Formatter) + fieldNames() []string + filter(expr expression) (p plan, indicesSought []string, err error) + hasID() bool +} + +func isTableOrIndex(p plan) bool { + switch p.(type) { + case + *indexPlan, + *sysColumnDefaultPlan, + *sysIndexDefaultPlan, + *sysTableDefaultPlan, + *tableDefaultPlan: + return true + default: + return false + } +} + +// Invariants +// - All interval plans produce rows in ascending index value collating order. +// - L <= H +type indexPlan struct { + src *table + cname string + xname string + x btreeIndex + kind int // See interval* consts. + lval interface{} // L, H: Ordered and comparable (lldb perspective). + hval interface{} +} + +func (r *indexPlan) doGe(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error { + // nil, nil, ..., L-1, L-1, L, L, L+1, L+1, ... + // --- --- --- --- --- + + +++ +++ +++ + t := r.src + it, _, err := r.x.Seek([]interface{}{r.lval}) + if err != nil { + return noEOF(err) + } + + for { + _, h, err := it.Next() + if err != nil { + return noEOF(err) + } + + id, data, err := t.row(ctx, h) + if err != nil { + return err + } + + if more, err := f(id, data); err != nil || !more { + return err + } + } +} + +func (r *indexPlan) doGt(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error { + // nil, nil, ..., L-1, L-1, L, L, L+1, L+1, ... + // --- --- --- --- --- - - +++ +++ +++ + t := r.src + it, _, err := r.x.Seek([]interface{}{r.lval}) + if err != nil { + return noEOF(err) + } + + var ok bool + for { + k, h, err := it.Next() + if err != nil { + return noEOF(err) + } + + if !ok { + val, err := expand1(k[0], nil) + if err != nil { + return err + } + + if collate1(val, r.lval) == 0 { + continue + } + + ok = true + } + + id, data, err := t.row(ctx, h) + if err != nil { + return err + } + + if more, err := f(id, data); err != nil || !more { + return err + } + } +} + +func (r *indexPlan) doInterval00(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error { + // nil, nil, ..., L-1, L-1, L, L, L+1, L+1, ..., H-1, H-1, H, H, H+1, H+1, ... + // --- --- --- --- --- - - +++ +++ +++ +++ +++ - - --- --- --- + t := r.src + it, _, err := r.x.Seek([]interface{}{r.lval}) + if err != nil { + return noEOF(err) + } + + var ok bool + for { + k, h, err := it.Next() + if err != nil { + return noEOF(err) + } + + if !ok { + val, err := expand1(k[0], nil) + if err != nil { + return err + } + + if collate1(val, r.lval) == 0 { + continue + } + + ok = true + } + + val, err := expand1(k[0], nil) + if err != nil { + return err + } + + if collate1(val, r.hval) == 0 { + return nil + } + + id, data, err := t.row(ctx, h) + if err != nil { + return err + } + + if more, err := f(id, data); err != nil || !more { + return err + } + } +} + +func (r *indexPlan) doIntervalOC(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error { + // nil, nil, ..., L-1, L-1, L, L, L+1, L+1, ..., H-1, H-1, H, H, H+1, H+1, ... + // --- --- --- --- --- - - +++ +++ +++ +++ +++ + + --- --- --- + t := r.src + it, _, err := r.x.Seek([]interface{}{r.lval}) + if err != nil { + return noEOF(err) + } + + var ok bool + for { + k, h, err := it.Next() + if err != nil { + return noEOF(err) + } + + if !ok { + val, err := expand1(k[0], nil) + if err != nil { + return err + } + + if collate1(val, r.lval) == 0 { + continue + } + + ok = true + } + + val, err := expand1(k[0], nil) + if err != nil { + return err + } + + if collate1(val, r.hval) > 0 { + return nil + } + + id, data, err := t.row(ctx, h) + if err != nil { + return err + } + + if more, err := f(id, data); err != nil || !more { + return err + } + } +} + +func (r *indexPlan) doIntervalCC(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error { + // nil, nil, ..., L-1, L-1, L, L, L+1, L+1, ..., H-1, H-1, H, H, H+1, H+1, ... + // --- --- --- --- --- + + +++ +++ +++ +++ +++ + + --- --- --- + t := r.src + it, _, err := r.x.Seek([]interface{}{r.lval}) + if err != nil { + return noEOF(err) + } + + for { + k, h, err := it.Next() + if err != nil { + return noEOF(err) + } + + val, err := expand1(k[0], nil) + if err != nil { + return err + } + + if collate1(val, r.hval) > 0 { + return nil + } + + id, data, err := t.row(ctx, h) + if err != nil { + return err + } + + if more, err := f(id, data); err != nil || !more { + return err + } + } +} + +func (r *indexPlan) doIntervalCO(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error { + // nil, nil, ..., L-1, L-1, L, L, L+1, L+1, ..., H-1, H-1, H, H, H+1, H+1, ... + // --- --- --- --- --- + + +++ +++ +++ +++ +++ - - --- --- --- + t := r.src + it, _, err := r.x.Seek([]interface{}{r.lval}) + if err != nil { + return noEOF(err) + } + + for { + k, h, err := it.Next() + if err != nil { + return noEOF(err) + } + + val, err := expand1(k[0], nil) + if err != nil { + return err + } + + if collate1(val, r.hval) >= 0 { + return nil + } + + id, data, err := t.row(ctx, h) + if err != nil { + return err + } + + if more, err := f(id, data); err != nil || !more { + return err + } + } +} + +func (r *indexPlan) doLe(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error { + // nil, nil, ..., H-1, H-1, H, H, H+1, H+1, ... + // --- --- +++ +++ +++ + + --- --- + t := r.src + it, err := r.x.SeekFirst() + if err != nil { + return noEOF(err) + } + + for { + k, h, err := it.Next() + if err != nil { + return noEOF(err) + } + + if k == nil || k[0] == nil { + continue + } + + val, err := expand1(k[0], nil) + if err != nil { + return err + } + + if collate1(val, r.hval) > 0 { + return nil + } + + id, data, err := t.row(ctx, h) + if err != nil { + return err + } + + if more, err := f(id, data); err != nil || !more { + return err + } + } +} + +func (r *indexPlan) doLt(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error { + // nil, nil, ..., H-1, H-1, H, H, H+1, H+1, ... + // --- --- +++ +++ +++ - - --- --- + t := r.src + it, err := r.x.SeekFirst() + if err != nil { + return noEOF(err) + } + + for { + k, h, err := it.Next() + if err != nil { + return noEOF(err) + } + + if k == nil || k[0] == nil { + continue + } + + val, err := expand1(k[0], nil) + if err != nil { + return err + } + + if collate1(val, r.hval) >= 0 { + return nil + } + + id, data, err := t.row(ctx, h) + if err != nil { + return err + } + + if more, err := f(id, data); err != nil || !more { + return err + } + } +} + +func (r *indexPlan) doEq(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error { + // nil, nil, ..., L-1, L-1, L, L, L+1, L+1, ... + // --- --- --- --- --- + + --- --- --- + t := r.src + it, _, err := r.x.Seek([]interface{}{r.lval}) + if err != nil { + return noEOF(err) + } + + for { + k, h, err := it.Next() + if err != nil { + return noEOF(err) + } + + val, err := expand1(k[0], nil) + if err != nil { + return err + } + + if collate1(val, r.lval) != 0 { + return nil + } + + id, data, err := t.row(ctx, h) + if err != nil { + return err + } + + if more, err := f(id, data); err != nil || !more { + return err + } + } +} + +func (r *indexPlan) doNe(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error { + // nil, nil, ..., L-1, L-1, L, L, L+1, L+1, ... + // --- --- +++ +++ +++ - - +++ +++ +++ + t := r.src + it, err := r.x.SeekFirst() + if err != nil { + return noEOF(err) + } + + for { + k, h, err := it.Next() + if err != nil { + return noEOF(err) + } + + if k == nil || k[0] == nil { + continue + } + + val, err := expand1(k[0], nil) + if err != nil { + return err + } + + if collate1(val, r.hval) == 0 { + continue + } + + id, data, err := t.row(ctx, h) + if err != nil { + return err + } + + if more, err := f(id, data); err != nil || !more { + return err + } + } +} + +func (r *indexPlan) doIsNull(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error { + // nil, nil, ... + // +++ +++ --- + t := r.src + it, err := r.x.SeekFirst() + if err != nil { + return noEOF(err) + } + + for { + k, h, err := it.Next() + if err != nil { + return noEOF(err) + } + + if k != nil && k[0] != nil { + return nil + } + + id, data, err := t.row(ctx, h) + if err != nil { + return err + } + + if more, err := f(id, data); err != nil || !more { + return err + } + } +} + +func (r *indexPlan) doIsNotNull(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error { + // nil, nil, ... + // --- --- +++ + t := r.src + it, _, err := r.x.Seek([]interface{}{false}) // lldb collates false right after NULL. + if err != nil { + return noEOF(err) + } + + for { + _, h, err := it.Next() + if err != nil { + return noEOF(err) + } + + id, data, err := t.row(ctx, h) + if err != nil { + return err + } + + if more, err := f(id, data); err != nil || !more { + return err + } + } +} + +func (r *indexPlan) doFalse(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error { + t := r.src + it, _, err := r.x.Seek([]interface{}{false}) + if err != nil { + return noEOF(err) + } + + for { + k, h, err := it.Next() + if err != nil { + return noEOF(err) + } + + b, ok := k[0].(bool) + if !ok || b { + return nil + } + + id, data, err := t.row(ctx, h) + if err != nil { + return err + } + + if more, err := f(id, data); err != nil || !more { + return err + } + } +} + +func (r *indexPlan) doTrue(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error { + t := r.src + it, _, err := r.x.Seek([]interface{}{true}) + if err != nil { + return noEOF(err) + } + + for { + k, h, err := it.Next() + if err != nil { + return noEOF(err) + } + + if _, ok := k[0].(bool); !ok { + return nil + } + + id, data, err := t.row(ctx, h) + if err != nil { + return err + } + + if more, err := f(id, data); err != nil || !more { + return err + } + } +} + +func (r *indexPlan) do(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error { + switch r.kind { + case indexEq: + return r.doEq(ctx, f) + case indexGe: + return r.doGe(ctx, f) + case indexGt: + return r.doGt(ctx, f) + case indexLe: + return r.doLe(ctx, f) + case indexLt: + return r.doLt(ctx, f) + case indexNe: + return r.doNe(ctx, f) + case indexIsNull: + return r.doIsNull(ctx, f) + case indexIsNotNull: + return r.doIsNotNull(ctx, f) + case indexFalse: + return r.doFalse(ctx, f) + case indexTrue: + return r.doTrue(ctx, f) + case indexIntervalOO: + return r.doInterval00(ctx, f) + case indexIntervalCC: + return r.doIntervalCC(ctx, f) + case indexIntervalOC: + return r.doIntervalOC(ctx, f) + case indexIntervalCO: + return r.doIntervalCO(ctx, f) + default: + //dbg("", r.kind) + panic("internal error 072") + } +} + +func (r *indexPlan) explain(w strutil.Formatter) { + s := "" + if r.kind == indexFalse { + s = "!" + } + w.Format("┌Iterate all rows of table %q using index %q where %s%s", r.src.name, r.xname, s, r.cname) + switch r.kind { + case indexEq: + w.Format(" == %v", value{r.lval}) + case indexGe: + w.Format(" >= %v", value{r.lval}) + case indexGt: + w.Format(" > %v", value{r.lval}) + case indexLe: + w.Format(" <= %v", value{r.hval}) + case indexLt: + w.Format(" < %v", value{r.hval}) + case indexNe: + w.Format(" != %v", value{r.lval}) + case indexIsNull: + w.Format(" IS NULL") + case indexIsNotNull: + w.Format(" IS NOT NULL") + case indexFalse, indexTrue: + // nop + case indexIntervalOO: + w.Format(" > %v && %s < %v", value{r.lval}, r.cname, value{r.hval}) + case indexIntervalCC: + w.Format(" >= %v && %s <= %v", value{r.lval}, r.cname, value{r.hval}) + case indexIntervalCO: + w.Format(" >= %v && %s < %v", value{r.lval}, r.cname, value{r.hval}) + case indexIntervalOC: + w.Format(" > %v && %s <= %v", value{r.lval}, r.cname, value{r.hval}) + default: + //dbg("", r.kind) + panic("internal error 073") + } + w.Format("\n└Output field names %v\n", qnames(r.fieldNames())) +} + +func (r *indexPlan) fieldNames() []string { return r.src.fieldNames() } + +func (r *indexPlan) filterEq(binOp2 int, val interface{}) (plan, []string, error) { + switch binOp2 { + case eq: + if collate1(r.lval, val) == 0 { + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case ge: + if collate1(r.lval, val) >= 0 { + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case '>': + if collate1(r.lval, val) > 0 { + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case le: + if collate1(r.lval, val) <= 0 { + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case '<': + if collate1(r.lval, val) < 0 { + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case neq: + if collate1(r.lval, val) != 0 { + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + } + return nil, nil, nil +} + +func (r *indexPlan) filterGe(binOp2 int, val interface{}) (plan, []string, error) { + switch binOp2 { + case eq: + if collate1(r.lval, val) <= 0 { + r.lval = val + r.kind = indexEq + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case ge: + if collate1(r.lval, val) < 0 { + r.lval = val + } + return r, nil, nil + case '>': + if collate1(r.lval, val) <= 0 { + r.lval = val + r.kind = indexGt + } + return r, nil, nil + case le: + switch c := collate1(r.lval, val); { + case c < 0: + r.hval = val + r.kind = indexIntervalCC + return r, nil, nil + case c == 0: + r.kind = indexEq + return r, nil, nil + default: // c > 0 + return &nullPlan{r.fieldNames()}, nil, nil + } + case '<': + if collate1(r.lval, val) < 0 { + r.hval = val + r.kind = indexIntervalCO + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case neq: + switch c := collate1(r.lval, val); { + case c < 0: + //MAYBE ORed intervals + case c == 0: + r.kind = indexGt + return r, nil, nil + default: // c > 0 + return r, nil, nil + } + } + return nil, nil, nil +} + +func (r *indexPlan) filterGt(binOp2 int, val interface{}) (plan, []string, error) { + switch binOp2 { + case eq: + if collate1(r.lval, val) < 0 { + r.lval = val + r.kind = indexEq + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case ge: + if collate1(r.lval, val) < 0 { + r.lval = val + r.kind = indexGe + } + return r, nil, nil + case '>': + if collate1(r.lval, val) < 0 { + r.lval = val + } + return r, nil, nil + case le: + if collate1(r.lval, val) < 0 { + r.hval = val + r.kind = indexIntervalOC + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case '<': + if collate1(r.lval, val) < 0 { + r.hval = val + r.kind = indexIntervalOO + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case neq: + if collate1(r.lval, val) >= 0 { + return r, nil, nil + } + } + return nil, nil, nil +} + +func (r *indexPlan) filterLe(binOp2 int, val interface{}) (plan, []string, error) { + switch binOp2 { + case eq: + if collate1(r.hval, val) >= 0 { + r.lval = val + r.kind = indexEq + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case ge: + switch c := collate1(r.hval, val); { + case c < 0: + return &nullPlan{r.fieldNames()}, nil, nil + case c == 0: + r.lval = val + r.kind = indexEq + return r, nil, nil + default: // c > 0 + r.lval = val + r.kind = indexIntervalCC + return r, nil, nil + } + case '>': + if collate1(r.hval, val) > 0 { + r.lval = val + r.kind = indexIntervalOC + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case le: + if collate1(r.hval, val) > 0 { + r.hval = val + } + return r, nil, nil + case '<': + if collate1(r.hval, val) >= 0 { + r.hval = val + r.kind = indexLt + } + return r, nil, nil + case neq: + switch c := collate1(r.hval, val); { + case c < 0: + return r, nil, nil + case c == 0: + r.kind = indexLt + return r, nil, nil + default: // c > 0 + //bop + } + } + return nil, nil, nil +} + +func (r *indexPlan) filterLt(binOp2 int, val interface{}) (plan, []string, error) { + switch binOp2 { + case eq: + if collate1(r.hval, val) > 0 { + r.lval = val + r.kind = indexEq + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case ge: + if collate1(r.hval, val) > 0 { + r.lval = val + r.kind = indexIntervalCO + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case '>': + if collate1(r.hval, val) > 0 { + r.lval = val + r.kind = indexIntervalOO + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case le: + if collate1(r.hval, val) > 0 { + r.hval = val + r.kind = indexLe + } + return r, nil, nil + case '<': + if collate1(r.hval, val) > 0 { + r.hval = val + } + return r, nil, nil + case neq: + if collate1(r.hval, val) > 0 { + return nil, nil, nil + } + + return r, nil, nil + } + return nil, nil, nil +} + +func (r *indexPlan) filterCC(binOp2 int, val interface{}) (plan, []string, error) { + switch binOp2 { + case eq: + if collate1(val, r.lval) < 0 || collate1(val, r.hval) > 0 { + return &nullPlan{r.fieldNames()}, nil, nil + } + + r.lval = val + r.kind = indexEq + return r, nil, nil + case ge: + if collate1(val, r.lval) <= 0 { + return r, nil, nil + } + + switch c := collate1(val, r.hval); { + case c < 0: + r.lval = val + return r, nil, nil + case c == 0: + r.lval = val + r.kind = indexEq + return r, nil, nil + default: + return &nullPlan{r.fieldNames()}, nil, nil + } + case '>': + switch c := collate1(val, r.lval); { + case c < 0: + return r, nil, nil + case c == 0: + r.kind = indexIntervalOC + return r, nil, nil + default: + if collate1(val, r.hval) < 0 { + r.lval = val + r.kind = indexIntervalOC + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + } + case le: + switch c := collate1(val, r.lval); { + case c < 0: + return &nullPlan{r.fieldNames()}, nil, nil + case c == 0: + r.kind = indexEq + return r, nil, nil + default: + if collate1(val, r.hval) < 0 { + r.hval = val + } + return r, nil, nil + } + case '<': + if collate1(val, r.lval) <= 0 { + return &nullPlan{r.fieldNames()}, nil, nil + } + + if collate1(val, r.hval) <= 0 { + r.hval = val + r.kind = indexIntervalCO + } + return r, nil, nil + case neq: + switch c := collate1(val, r.lval); { + case c < 0: + return r, nil, nil + case c == 0: + r.kind = indexIntervalOC + return r, nil, nil + default: + switch c := collate1(val, r.hval); { + case c == 0: + r.kind = indexIntervalCO + return r, nil, nil + case c > 0: + return r, nil, nil + default: + return nil, nil, nil + } + } + } + return nil, nil, nil +} + +func (r *indexPlan) filterOC(binOp2 int, val interface{}) (plan, []string, error) { + switch binOp2 { + case eq: + if collate1(val, r.lval) <= 0 || collate1(val, r.hval) > 0 { + return &nullPlan{r.fieldNames()}, nil, nil + } + + r.lval = val + r.kind = indexEq + return r, nil, nil + case ge: + if collate1(val, r.lval) <= 0 { + return r, nil, nil + } + + switch c := collate1(val, r.hval); { + case c < 0: + r.lval = val + r.kind = indexIntervalCC + return r, nil, nil + case c == 0: + r.lval = val + r.kind = indexEq + return r, nil, nil + default: + return &nullPlan{r.fieldNames()}, nil, nil + } + case '>': + if collate1(val, r.lval) <= 0 { + return r, nil, nil + } + + if collate1(val, r.hval) < 0 { + r.lval = val + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case le: + if collate1(val, r.lval) <= 0 { + return &nullPlan{r.fieldNames()}, nil, nil + } + + if collate1(val, r.hval) < 0 { + r.hval = val + } + return r, nil, nil + case '<': + if collate1(val, r.lval) <= 0 { + return &nullPlan{r.fieldNames()}, nil, nil + } + + switch c := collate1(val, r.hval); { + case c < 0: + r.hval = val + r.kind = indexIntervalOO + case c == 0: + r.kind = indexIntervalOO + } + return r, nil, nil + case neq: + if collate1(val, r.lval) <= 0 { + return r, nil, nil + } + + switch c := collate1(val, r.hval); { + case c < 0: + return nil, nil, nil + case c == 0: + r.kind = indexIntervalOO + return r, nil, nil + default: + return r, nil, nil + } + } + return nil, nil, nil +} + +func (r *indexPlan) filterOO(binOp2 int, val interface{}) (plan, []string, error) { + switch binOp2 { + case eq: + if collate1(val, r.lval) <= 0 || collate1(val, r.hval) >= 0 { + return &nullPlan{r.fieldNames()}, nil, nil + } + + r.lval = val + r.kind = indexEq + return r, nil, nil + case ge: + if collate1(val, r.lval) <= 0 { + return r, nil, nil + } + + if collate1(val, r.hval) < 0 { + r.lval = val + r.kind = indexIntervalCO + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case '>': + if collate1(val, r.lval) <= 0 { + return r, nil, nil + } + + if collate1(val, r.hval) < 0 { + r.lval = val + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case le: + if collate1(val, r.lval) <= 0 { + return &nullPlan{r.fieldNames()}, nil, nil + } + + if collate1(val, r.hval) < 0 { + r.hval = val + r.kind = indexIntervalOC + } + return r, nil, nil + case '<': + if collate1(val, r.lval) <= 0 { + return &nullPlan{r.fieldNames()}, nil, nil + } + + if collate1(val, r.hval) < 0 { + r.hval = val + } + return r, nil, nil + case neq: + if collate1(val, r.lval) <= 0 || collate1(val, r.hval) >= 0 { + return r, nil, nil + } + + return nil, nil, nil + } + return nil, nil, nil +} + +func (r *indexPlan) filterCO(binOp2 int, val interface{}) (plan, []string, error) { + switch binOp2 { + case eq: + if collate1(val, r.lval) < 0 || collate1(val, r.hval) >= 0 { + return &nullPlan{r.fieldNames()}, nil, nil + } + + r.lval = val + r.kind = indexEq + return r, nil, nil + case ge: + if collate1(val, r.lval) <= 0 { + return r, nil, nil + } + + if collate1(val, r.hval) < 0 { + r.lval = val + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case '>': + switch c := collate1(val, r.lval); { + case c < 0: + return r, nil, nil + case c == 0: + r.kind = indexIntervalOO + return r, nil, nil + default: + if collate1(val, r.hval) < 0 { + r.lval = val + r.kind = indexIntervalOO + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + } + case le: + switch c := collate1(val, r.lval); { + case c < 0: + return &nullPlan{r.fieldNames()}, nil, nil + case c == 0: + r.kind = indexEq + return r, nil, nil + default: + if collate1(val, r.hval) < 0 { + r.hval = val + r.kind = indexIntervalCC + } + return r, nil, nil + } + case '<': + if collate1(val, r.lval) <= 0 { + return &nullPlan{r.fieldNames()}, nil, nil + } + + if collate1(val, r.hval) < 0 { + r.hval = val + } + return r, nil, nil + case neq: + switch c := collate1(val, r.lval); { + case c < 0: + return r, nil, nil + case c == 0: + r.kind = indexIntervalOO + return r, nil, nil + default: + if collate1(val, r.hval) < 0 { + return nil, nil, nil + } + + return r, nil, nil + } + } + return nil, nil, nil +} + +func (r *indexPlan) filterNe(binOp2 int, val interface{}) (plan, []string, error) { + switch binOp2 { + case eq: + if collate1(val, r.lval) != 0 { + r.lval = val + r.kind = indexEq + return r, nil, nil + } + + return &nullPlan{r.fieldNames()}, nil, nil + case ge: + switch c := collate1(val, r.lval); { + case c < 0: + return nil, nil, nil //TODO + case c == 0: + r.kind = indexGt + return r, nil, nil + default: + r.lval = val + r.kind = indexGe + return r, nil, nil + } + case '>': + if collate1(val, r.lval) < 0 { + return nil, nil, nil //TODO + } + + r.lval = val + r.kind = indexGt + return r, nil, nil + case le: + switch c := collate1(val, r.lval); { + case c < 0: + r.hval = val + r.kind = indexLe + return r, nil, nil + case c == 0: + r.kind = indexLt + return r, nil, nil + default: + return nil, nil, nil //TODO + } + case '<': + if collate1(val, r.lval) <= 0 { + r.hval = val + r.kind = indexLt + return r, nil, nil + } + + return nil, nil, nil //TODO + case neq: + if collate1(val, r.lval) == 0 { + return r, nil, nil + } + + return nil, nil, nil + } + return nil, nil, nil +} + +func (r *indexPlan) filter(expr expression) (plan, []string, error) { + switch x := expr.(type) { + case *binaryOperation: + ok, cname, val, err := x.isIdentRelOpVal() + if err != nil { + return nil, nil, err + } + + if !ok || r.cname != cname { + break + } + + if val, err = typeCheck1(val, findCol(r.src.cols, cname)); err != nil { + return nil, nil, err + } + + switch r.kind { + case indexEq: // [L] + return r.filterEq(x.op, val) + case indexGe: // [L, ...) + return r.filterGe(x.op, val) + case indexGt: // (L, ...) + return r.filterGt(x.op, val) + case indexIntervalCC: // [L, H] + return r.filterCC(x.op, val) + case indexIntervalCO: // [L, H) + return r.filterCO(x.op, val) + case indexIntervalOC: // (L, H] + return r.filterOC(x.op, val) + case indexIntervalOO: // (L, H) + return r.filterOO(x.op, val) + case indexLe: // (..., H] + return r.filterLe(x.op, val) + case indexLt: // (..., H) + return r.filterLt(x.op, val) + case indexNe: // (L) + return r.filterNe(x.op, val) + } + case *ident: + cname := x.s + if r.cname != cname { + break + } + + switch r.kind { + case indexFalse: // [false] + return &nullPlan{r.fieldNames()}, nil, nil + case indexTrue: // [true] + return r, nil, nil + } + case *unaryOperation: + if x.op != '!' { + break + } + + operand, ok := x.v.(*ident) + if !ok { + break + } + + cname := operand.s + if r.cname != cname { + break + } + + switch r.kind { + case indexFalse: // [false] + return r, nil, nil + case indexTrue: // [true] + return &nullPlan{r.fieldNames()}, nil, nil + } + } + + return nil, nil, nil +} + +func (r *indexPlan) hasID() bool { return true } + +type explainDefaultPlan struct { + s stmt +} + +func (r *explainDefaultPlan) hasID() bool { return false } + +func (r *explainDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) error { + var buf bytes.Buffer + switch x := r.s.(type) { + default: + w := strutil.IndentFormatter(&buf, "│ ") + x.explain(ctx, w) + } + + a := bytes.Split(buf.Bytes(), []byte{'\n'}) + for _, v := range a[:len(a)-1] { + if more, err := f(nil, []interface{}{string(v)}); !more || err != nil { + return err + } + } + return nil +} + +func (r *explainDefaultPlan) explain(w strutil.Formatter) { + return +} + +func (r *explainDefaultPlan) fieldNames() []string { + return []string{""} +} + +func (r *explainDefaultPlan) filter(expr expression) (plan, []string, error) { + return nil, nil, nil +} + +type filterDefaultPlan struct { + plan + expr expression + is []string +} + +func (r *filterDefaultPlan) hasID() bool { return r.plan.hasID() } + +func (r *filterDefaultPlan) explain(w strutil.Formatter) { + r.plan.explain(w) + w.Format("┌Filter on %v\n", r.expr) + if len(r.is) != 0 { + w.Format("│Possibly useful indices\n") + m := map[string]bool{} + for _, v := range r.is { + if !m[v] { + m[v] = true + n := "" + for _, r := range v { + if r >= '0' && r <= '9' || r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' || r == '_' { + n += string(r) + continue + } + + n += "_" + } + for strings.Contains(n, "__") { + n = strings.Replace(n, "__", "_", -1) + } + for strings.HasSuffix(n, "_") { + n = n[:len(n)-1] + } + w.Format("│CREATE INDEX x%s ON %s;\n", n, v) + } + } + } + w.Format("└Output field names %v\n", qnames(r.plan.fieldNames())) +} + +func (r *filterDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) { + m := map[interface{}]interface{}{} + fields := r.plan.fieldNames() + return r.plan.do(ctx, func(rid interface{}, data []interface{}) (bool, error) { + for i, v := range fields { + m[v] = data[i] + } + m["$id"] = rid + val, err := r.expr.eval(ctx, m) + if err != nil { + return false, err + } + + if val == nil { + return true, nil + } + + x, ok := val.(bool) + if !ok { + return false, fmt.Errorf("invalid boolean expression %s (value of type %T)", val, val) + } + + if !x { + return true, nil + } + + return f(rid, data) + }) +} + +type crossJoinDefaultPlan struct { + rsets []plan + names []string + fields []string +} + +func (r *crossJoinDefaultPlan) hasID() bool { return false } + +func (r *crossJoinDefaultPlan) explain(w strutil.Formatter) { + w.Format("┌Compute Cartesian product of%i\n") + for i, v := range r.rsets { + sel := !isTableOrIndex(v) + if sel { + w.Format("┌Iterate all rows of virtual table %q%i\n", r.names[i]) + } + v.explain(w) + if sel { + w.Format("%u└Output field names %v\n", qnames(v.fieldNames())) + } + } + w.Format("%u└Output field names %v\n", qnames(r.fields)) +} + +func (r *crossJoinDefaultPlan) filter(expr expression) (plan, []string, error) { + var is []string + for i, v := range r.names { + e2, err := expr.clone(nil, v) + if err != nil { + return nil, nil, err + } + + p2, is2, err := r.rsets[i].filter(e2) + is = append(is, is2...) + if err != nil { + return nil, nil, err + } + + if p2 != nil { + r.rsets[i] = p2 + return r, is, nil + } + } + return nil, is, nil +} + +func (r *crossJoinDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error { + if len(r.rsets) == 1 { + return r.rsets[0].do(ctx, f) + } + + ids := map[string]interface{}{} + var g func([]interface{}, []plan, int) error + g = func(prefix []interface{}, rsets []plan, x int) (err error) { + return rsets[0].do(ctx, func(id interface{}, in []interface{}) (bool, error) { + ids[r.names[x]] = id + if len(rsets) > 1 { + return true, g(append(prefix, in...), rsets[1:], x+1) + } + + return f(ids, append(prefix, in...)) + }) + } + return g(nil, r.rsets, 0) +} + +func (r *crossJoinDefaultPlan) fieldNames() []string { return r.fields } + +type distinctDefaultPlan struct { + src plan + fields []string +} + +func (r *distinctDefaultPlan) hasID() bool { return false } + +func (r *distinctDefaultPlan) explain(w strutil.Formatter) { + r.src.explain(w) + w.Format("┌Compute distinct rows\n└Output field names %v\n", r.fields) +} + +func (r *distinctDefaultPlan) filter(expr expression) (plan, []string, error) { + return nil, nil, nil +} + +func (r *distinctDefaultPlan) fieldNames() []string { return r.fields } + +func (r *distinctDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) { + t, err := ctx.db.store.CreateTemp(true) + if err != nil { + return + } + + defer func() { + if derr := t.Drop(); derr != nil && err == nil { + err = derr + } + }() + + if err = r.src.do(ctx, func(id interface{}, in []interface{}) (bool, error) { + if err = t.Set(in, nil); err != nil { + return false, err + } + + return true, nil + }); err != nil { + return + } + + var data []interface{} + more := true + it, err := t.SeekFirst() + for more && err == nil { + data, _, err = it.Next() + if err != nil { + break + } + + more, err = f(nil, data) + } + return noEOF(err) +} + +type groupByDefaultPlan struct { + colNames []string + src plan + fields []string +} + +func (r *groupByDefaultPlan) hasID() bool { return false } + +func (r *groupByDefaultPlan) explain(w strutil.Formatter) { + r.src.explain(w) + switch { + case len(r.colNames) == 0: //TODO this case should not exist for this plan, should become tableDefaultPlan + w.Format("┌Group by distinct rows") + default: + w.Format("┌Group by") + for _, v := range r.colNames { + w.Format(" %s,", v) + } + } + w.Format("\n└Output field names %v\n", qnames(r.fields)) +} + +func (r *groupByDefaultPlan) filter(expr expression) (plan, []string, error) { + return nil, nil, nil +} + +func (r *groupByDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) { + t, err := ctx.db.store.CreateTemp(true) + if err != nil { + return + } + + defer func() { + if derr := t.Drop(); derr != nil && err == nil { + err = derr + } + }() + + var gcols []*col + var cols []*col + m := map[string]int{} + for i, v := range r.src.fieldNames() { + m[v] = i + } + for _, c := range r.colNames { + i, ok := m[c] + if !ok { + return fmt.Errorf("unknown field %s", c) + } + + gcols = append(gcols, &col{name: c, index: i}) + } + k := make([]interface{}, len(r.colNames)) //TODO optimize when len(r.cols) == 0, should become tableDefaultPlan + if err = r.src.do(ctx, func(rid interface{}, in []interface{}) (more bool, err error) { + infer(in, &cols) + for i, c := range gcols { + k[i] = in[c.index] + } + h0, err := t.Get(k) + if err != nil { + return false, err + } + + var h int64 + if len(h0) != 0 { + h, _ = h0[0].(int64) + } + nh, err := t.Create(append([]interface{}{h, nil}, in...)...) + if err != nil { + return false, err + } + + for i, c := range gcols { + k[i] = in[c.index] + } + err = t.Set(k, []interface{}{nh}) + if err != nil { + return false, err + } + + return true, nil + }); err != nil { + return + } + + for i, v := range r.src.fieldNames()[:len(cols)] { + cols[i].name = v + cols[i].index = i + } + if more, err := f(nil, []interface{}{t, cols}); !more || err != nil { + return err + } + + it, err := t.SeekFirst() + more := true + var data []interface{} + for more && err == nil { + if _, data, err = it.Next(); err != nil { + break + } + + more, err = f(nil, data) + } + return noEOF(err) +} + +func (r *groupByDefaultPlan) fieldNames() []string { return r.fields } + +type selectIndexDefaultPlan struct { + nm string + x interface{} +} + +func (r *selectIndexDefaultPlan) hasID() bool { return false } + +func (r *selectIndexDefaultPlan) explain(w strutil.Formatter) { + w.Format("┌Iterate all values of index %q\n└Output field names N/A\n", r.nm) +} + +func (r *selectIndexDefaultPlan) filter(expr expression) (plan, []string, error) { + return nil, nil, nil +} + +func (r *selectIndexDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) { + var x btreeIndex + switch ix := r.x.(type) { + case *indexedCol: + x = ix.x + case *index2: + x = ix.x + default: + panic("internal error 007") + } + + en, err := x.SeekFirst() + if err != nil { + return noEOF(err) + } + + var id int64 + for { + k, _, err := en.Next() + if err != nil { + return noEOF(err) + } + + id++ + if more, err := f(id, k); !more || err != nil { + return err + } + } +} + +func (r *selectIndexDefaultPlan) fieldNames() []string { + return []string{r.nm} +} + +type limitDefaultPlan struct { + expr expression + src plan + fields []string +} + +func (r *limitDefaultPlan) hasID() bool { return r.src.hasID() } + +func (r *limitDefaultPlan) explain(w strutil.Formatter) { + r.src.explain(w) + w.Format("┌Pass first %v records\n└Output field names %v\n", r.expr, r.fields) +} + +func (r *limitDefaultPlan) filter(expr expression) (plan, []string, error) { + return nil, nil, nil +} + +func (r *limitDefaultPlan) fieldNames() []string { return r.fields } + +func (r *limitDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) (err error) { + m := map[interface{}]interface{}{} + var eval bool + var lim uint64 + return r.src.do(ctx, func(rid interface{}, in []interface{}) (more bool, err error) { + if !eval { + for i, fld := range r.fields { + if fld != "" { + m[fld] = in[i] + } + } + m["$id"] = rid + val, err := r.expr.eval(ctx, m) + if err != nil { + return false, err + } + + if val == nil { + return true, nil + } + + if lim, err = limOffExpr(val); err != nil { + return false, err + } + + eval = true + } + switch lim { + case 0: + return false, nil + default: + lim-- + return f(rid, in) + } + }) +} + +type offsetDefaultPlan struct { + expr expression + src plan + fields []string +} + +func (r *offsetDefaultPlan) hasID() bool { return r.src.hasID() } + +func (r *offsetDefaultPlan) explain(w strutil.Formatter) { + r.src.explain(w) + w.Format("┌Skip first %v records\n└Output field names %v\n", r.expr, qnames(r.fields)) +} + +func (r *offsetDefaultPlan) filter(expr expression) (plan, []string, error) { + return nil, nil, nil +} + +func (r *offsetDefaultPlan) fieldNames() []string { return r.fields } + +func (r *offsetDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error { + m := map[interface{}]interface{}{} + var eval bool + var off uint64 + return r.src.do(ctx, func(rid interface{}, in []interface{}) (bool, error) { + if !eval { + for i, fld := range r.fields { + if fld != "" { + m[fld] = in[i] + } + } + m["$id"] = rid + val, err := r.expr.eval(ctx, m) + if err != nil { + return false, err + } + + if val == nil { + return true, nil + } + + if off, err = limOffExpr(val); err != nil { + return false, err + } + + eval = true + } + if off > 0 { + off-- + return true, nil + } + + return f(rid, in) + }) +} + +type orderByDefaultPlan struct { + asc bool + by []expression + src plan + fields []string +} + +func (r *orderByDefaultPlan) hasID() bool { return r.src.hasID() } + +func (r *orderByDefaultPlan) explain(w strutil.Formatter) { + r.src.explain(w) + w.Format("┌Order%s by", map[bool]string{false: " descending"}[r.asc]) + for _, v := range r.by { + w.Format(" %s,", v) + } + w.Format("\n└Output field names %v\n", qnames(r.fields)) +} + +func (r *orderByDefaultPlan) filter(expr expression) (plan, []string, error) { + return nil, nil, nil +} + +func (r *orderByDefaultPlan) fieldNames() []string { return r.fields } + +func (r *orderByDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) { + t, err := ctx.db.store.CreateTemp(r.asc) + if err != nil { + return + } + + defer func() { + if derr := t.Drop(); derr != nil && err == nil { + err = derr + } + }() + + m := map[interface{}]interface{}{} + flds := r.fields + k := make([]interface{}, len(r.by)+1) + id := int64(-1) + if err = r.src.do(ctx, func(rid interface{}, in []interface{}) (bool, error) { + id++ + for i, fld := range flds { + if fld != "" { + m[fld] = in[i] + } + } + m["$id"] = rid + for i, expr := range r.by { + val, err := expr.eval(ctx, m) + if err != nil { + return false, err + } + + if val != nil { + val, ordered, err := isOrderedType(val) + if err != nil { + return false, err + } + + if !ordered { + return false, fmt.Errorf("cannot order by %v (type %T)", val, val) + + } + } + + k[i] = val + } + k[len(r.by)] = id + if err = t.Set(k, in); err != nil { + return false, err + } + + return true, nil + }); err != nil { + return + } + + it, err := t.SeekFirst() + if err != nil { + return noEOF(err) + } + + var data []interface{} + more := true + for more && err == nil { + if _, data, err = it.Next(); err != nil { + break + } + + more, err = f(nil, data) + } + return noEOF(err) +} + +type selectFieldsDefaultPlan struct { + flds []*fld + src plan + fields []string +} + +func (r *selectFieldsDefaultPlan) hasID() bool { return r.src.hasID() } + +func (r *selectFieldsDefaultPlan) explain(w strutil.Formatter) { + //TODO check for non existing fields + r.src.explain(w) + w.Format("┌Evaluate") + for _, v := range r.flds { + w.Format(" %s as %s,", v.expr, fmt.Sprintf("%q", v.name)) + } + w.Format("\n└Output field names %v\n", qnames(r.fields)) +} + +func (r *selectFieldsDefaultPlan) filter(expr expression) (plan, []string, error) { + return nil, nil, nil +} + +func (r *selectFieldsDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error { + fields := r.src.fieldNames() + m := map[interface{}]interface{}{} + return r.src.do(ctx, func(rid interface{}, in []interface{}) (bool, error) { + for i, nm := range fields { + if nm != "" { + m[nm] = in[i] + } + } + m["$id"] = rid + out := make([]interface{}, len(r.flds)) + for i, fld := range r.flds { + var err error + if out[i], err = fld.expr.eval(ctx, m); err != nil { + return false, err + } + } + return f(rid, out) + }) +} + +func (r *selectFieldsDefaultPlan) fieldNames() []string { return r.fields } + +type selectFieldsGroupPlan struct { + flds []*fld + src *groupByDefaultPlan + fields []string +} + +func (r *selectFieldsGroupPlan) hasID() bool { return false } + +func (r *selectFieldsGroupPlan) explain(w strutil.Formatter) { + //TODO check for non existing fields + r.src.explain(w) + w.Format("┌Evaluate") + for _, v := range r.flds { + w.Format(" %s as %s,", v.expr, fmt.Sprintf("%q", v.name)) + } + w.Format("\n└Output field names %v\n", qnames(r.fields)) +} + +func (r *selectFieldsGroupPlan) fieldNames() []string { return r.fields } + +func (r *selectFieldsGroupPlan) filter(expr expression) (plan, []string, error) { + return nil, nil, nil +} + +func (r *selectFieldsGroupPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error { + var t temp + var cols []*col + var err error + out := make([]interface{}, len(r.flds)) + ok := false + rows := false + if err = r.src.do(ctx, func(rid interface{}, in []interface{}) (bool, error) { + if ok { + h := in[0].(int64) + m := map[interface{}]interface{}{} + for h != 0 { + in, err = t.Read(nil, h, cols...) + if err != nil { + return false, err + } + + rec := in[2:] + for i, c := range cols { + if nm := c.name; nm != "" { + m[nm] = rec[i] + } + } + m["$id"] = rid + for _, fld := range r.flds { + if _, err = fld.expr.eval(ctx, m); err != nil { + return false, err + } + } + + h = in[0].(int64) + } + m["$agg"] = true + for i, fld := range r.flds { + if out[i], err = fld.expr.eval(ctx, m); err != nil { + return false, err + } + } + rows = true + return f(nil, out) + } + + ok = true + t = in[0].(temp) + cols = in[1].([]*col) + if len(r.flds) == 0 { // SELECT * + r.flds = make([]*fld, len(cols)) + for i, v := range cols { + r.flds[i] = &fld{expr: &ident{v.name}, name: v.name} + } + out = make([]interface{}, len(r.flds)) + } + return true, nil + }); err != nil { + return err + } + + if rows { + return nil + } + + m := map[interface{}]interface{}{"$agg0": true} // aggregate empty record set + for i, fld := range r.flds { + if out[i], err = fld.expr.eval(ctx, m); err != nil { + return err + } + } + _, err = f(nil, out) + + return err +} + +type sysColumnDefaultPlan struct{} + +func (r *sysColumnDefaultPlan) hasID() bool { return false } + +func (r *sysColumnDefaultPlan) explain(w strutil.Formatter) { + w.Format("┌Iterate all rows of table \"__Column\"\n└Output field names %v\n", qnames(r.fieldNames())) +} + +func (r *sysColumnDefaultPlan) filter(expr expression) (plan, []string, error) { + return nil, nil, nil +} + +func (r *sysColumnDefaultPlan) fieldNames() []string { + return []string{"TableName", "Ordinal", "Name", "Type"} +} + +func (r *sysColumnDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error { + rec := make([]interface{}, 4) + di, err := ctx.db.info() + if err != nil { + return err + } + + var id int64 + for _, ti := range di.Tables { + rec[0] = ti.Name + var ix int64 + for _, ci := range ti.Columns { + ix++ + rec[1] = ix + rec[2] = ci.Name + rec[3] = ci.Type.String() + id++ + if more, err := f(id, rec); !more || err != nil { + return err + } + } + } + return nil +} + +type sysIndexDefaultPlan struct{} + +func (r *sysIndexDefaultPlan) hasID() bool { return false } + +func (r *sysIndexDefaultPlan) explain(w strutil.Formatter) { + w.Format("┌Iterate all rows of table \"__Index\"\n└Output field names %v\n", qnames(r.fieldNames())) +} + +func (r *sysIndexDefaultPlan) filter(expr expression) (plan, []string, error) { + return nil, nil, nil +} + +func (r *sysIndexDefaultPlan) fieldNames() []string { + return []string{"TableName", "ColumnName", "Name", "IsUnique"} +} + +func (r *sysIndexDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error { + rec := make([]interface{}, 4) + di, err := ctx.db.info() + if err != nil { + return err + } + + var id int64 + for _, xi := range di.Indices { + rec[0] = xi.Table + rec[1] = xi.Column + rec[2] = xi.Name + rec[3] = xi.Unique + id++ + if more, err := f(id, rec); !more || err != nil { + return err + } + } + return nil +} + +type sysTableDefaultPlan struct{} + +func (r *sysTableDefaultPlan) hasID() bool { return false } + +func (r *sysTableDefaultPlan) explain(w strutil.Formatter) { + w.Format("┌Iterate all rows of table \"__Table\"\n└Output field names %v\n", qnames(r.fieldNames())) +} + +func (r *sysTableDefaultPlan) filter(expr expression) (plan, []string, error) { + return nil, nil, nil +} + +func (r *sysTableDefaultPlan) fieldNames() []string { return []string{"Name", "Schema"} } + +func (r *sysTableDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error { + rec := make([]interface{}, 2) + di, err := ctx.db.info() + if err != nil { + return err + } + + var id int64 + for _, ti := range di.Tables { + rec[0] = ti.Name + a := []string{} + for _, ci := range ti.Columns { + s := "" + if ci.NotNull { + s += " NOT NULL" + } + if c := ci.Constraint; c != "" { + s += " " + c + } + if d := ci.Default; d != "" { + s += " DEFAULT " + d + } + a = append(a, fmt.Sprintf("%s %s%s", ci.Name, ci.Type, s)) + } + rec[1] = fmt.Sprintf("CREATE TABLE %s (%s);", ti.Name, strings.Join(a, ", ")) + id++ + if more, err := f(id, rec); !more || err != nil { + return err + } + } + return nil +} + +type tableNilPlan struct { + t *table +} + +func (r *tableNilPlan) hasID() bool { return true } + +func (r *tableNilPlan) explain(w strutil.Formatter) { + w.Format("┌Iterate all rows of table %q\n└Output field names %v\n", r.t.name, qnames(r.fieldNames())) +} + +func (r *tableNilPlan) fieldNames() []string { return []string{} } + +func (r *tableNilPlan) filter(expr expression) (plan, []string, error) { + return nil, nil, nil +} + +func (r *tableNilPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) { + t := r.t + h := t.head + cols := t.cols + for h > 0 { + rec, err := t.store.Read(nil, h, cols...) // 0:next, 1:id, 2...: data + if err != nil { + return err + } + + if m, err := f(rec[1], nil); !m || err != nil { + return err + } + + h = rec[0].(int64) // next + } + return nil +} + +type tableDefaultPlan struct { + t *table + fields []string +} + +func (r *tableDefaultPlan) hasID() bool { return true } + +func (r *tableDefaultPlan) explain(w strutil.Formatter) { + w.Format("┌Iterate all rows of table %q\n└Output field names %v\n", r.t.name, qnames(r.fields)) +} + +func (r *tableDefaultPlan) filterBinOp(x *binaryOperation) (plan, []string, error) { + ok, cn, rval, err := x.isIdentRelOpVal() + if err != nil { + return nil, nil, err + } + + if !ok { + return nil, nil, nil + } + + t := r.t + c, ix := t.findIndexByColName(cn) + if ix == nil { // Column cn has no index. + return nil, []string{fmt.Sprintf("%s(%s)", t.name, cn)}, nil + } + + if rval, err = typeCheck1(rval, c); err != nil { + return nil, nil, err + } + + switch x.op { + case eq: + return &indexPlan{t, cn, ix.name, ix.x, indexEq, rval, rval}, nil, nil + case '<': + return &indexPlan{t, cn, ix.name, ix.x, indexLt, nil, rval}, nil, nil + case le: + return &indexPlan{t, cn, ix.name, ix.x, indexLe, nil, rval}, nil, nil + case ge: + return &indexPlan{t, cn, ix.name, ix.x, indexGe, rval, nil}, nil, nil + case '>': + return &indexPlan{t, cn, ix.name, ix.x, indexGt, rval, nil}, nil, nil + case neq: + return &indexPlan{t, cn, ix.name, ix.x, indexNe, rval, rval}, nil, nil + default: + panic("internal error 069") + } +} + +func (r *tableDefaultPlan) filterIdent(x *ident, trueValue bool) (plan, []string, error) { + cn := x.s + t := r.t + for _, v := range t.cols { + if v.name != cn { + continue + } + + if v.typ != qBool { + return nil, nil, nil + } + + xi := v.index + 1 // 0: id() + if xi >= len(t.indices) { + return nil, nil, nil + } + + ix := t.indices[xi] + if ix == nil { // Column cn has no index. + return nil, []string{fmt.Sprintf("%s(%s)", t.name, cn)}, nil + } + + kind := indexFalse + if trueValue { + kind = indexTrue + } + return &indexPlan{t, cn, ix.name, ix.x, kind, nil, nil}, nil, nil + } + return nil, nil, nil +} + +func (r *tableDefaultPlan) filterIsNull(x *isNull) (plan, []string, error) { + ok, cn := isColumnExpression(x.expr) + if !ok { + return nil, nil, nil + } + + t := r.t + _, ix := t.findIndexByColName(cn) + if ix == nil { // Column cn has no index. + return nil, []string{fmt.Sprintf("%s(%s)", t.name, cn)}, nil + } + + switch { + case x.not: + return &indexPlan{t, cn, ix.name, ix.x, indexIsNotNull, nil, nil}, nil, nil + default: + return &indexPlan{t, cn, ix.name, ix.x, indexIsNull, nil, nil}, nil, nil + } +} + +func (r *tableDefaultPlan) filter(expr expression) (plan, []string, error) { + cols := mentionedColumns(expr) + for _, v := range r.fields { + delete(cols, v) + } + for k := range cols { + return nil, nil, fmt.Errorf("unknown field %s", k) + } + + var is []string + + //TODO var sexpr string + //TODO for _, ix := range t.indices2 { + //TODO if len(ix.exprList) != 1 { + //TODO continue + //TODO } + + //TODO if sexpr == "" { + //TODO sexpr = expr.String() + //TODO } + //TODO if ix.sources[0] != sexpr { + //TODO continue + //TODO } + + //TODO } + + switch x := expr.(type) { + case *binaryOperation: + return r.filterBinOp(x) + case *ident: + return r.filterIdent(x, true) + case *isNull: + return r.filterIsNull(x) + case *unaryOperation: + if x.op != '!' { + break + } + + if operand, ok := x.v.(*ident); ok { + return r.filterIdent(operand, false) + } + default: + //dbg("", expr) + return nil, is, nil //TODO + } + + return nil, is, nil +} + +func (r *tableDefaultPlan) do(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) (err error) { + t := r.t + cols := t.cols + h := t.head + for h > 0 { + rec, err := t.row0(ctx, h) + if err != nil { + return err + } + + h = rec[0].(int64) + id := rec[1].(int64) + for i, c := range cols { + rec[i] = rec[c.index+2] + } + if m, err := f(id, rec[:len(cols)]); !m || err != nil { + return err + } + } + return nil +} + +func (r *tableDefaultPlan) fieldNames() []string { return r.fields } + +type nullPlan struct { + fields []string +} + +func (r *nullPlan) hasID() bool { return false } + +func (r *nullPlan) fieldNames() []string { return r.fields } + +func (r *nullPlan) explain(w strutil.Formatter) { + w.Format("┌Iterate no rows\n└Output field names %v\n", qnames(r.fields)) +} + +func (r *nullPlan) do(*execCtx, func(interface{}, []interface{}) (bool, error)) error { + return nil +} + +func (r *nullPlan) filter(expr expression) (plan, []string, error) { + return r, nil, nil +} + +type leftJoinDefaultPlan struct { + on expression + rsets []plan + names []string + right int + fields []string +} + +func (r *leftJoinDefaultPlan) hasID() bool { return false } + +func (r *leftJoinDefaultPlan) explain(w strutil.Formatter) { + w.Format("┌Compute Cartesian product of%i\n") + for i, v := range r.rsets { + sel := !isTableOrIndex(v) + if sel { + w.Format("┌Iterate all rows of virtual table %q%i\n", r.names[i]) + } + v.explain(w) + if sel { + w.Format("%u└Output field names %v\n", qnames(v.fieldNames())) + } + } + w.Format("Extend the product with all NULL rows of %q when no match for %v%u\n", r.names[len(r.names)-1], r.on) + w.Format("└Output field names %v\n", qnames(r.fields)) +} + +func (r *leftJoinDefaultPlan) filter(expr expression) (plan, []string, error) { + var is []string + for i, v := range r.names { + e2, err := expr.clone(nil, v) + if err != nil { + return nil, nil, err + } + + p2, is2, err := r.rsets[i].filter(e2) + is = append(is, is2...) + if err != nil { + return nil, nil, err + } + + if p2 != nil { + r.rsets[i] = p2 + return r, is, nil + } + } + return nil, is, nil +} + +type rightJoinDefaultPlan struct { + leftJoinDefaultPlan +} + +func (r *rightJoinDefaultPlan) hasID() bool { return false } + +func (r *rightJoinDefaultPlan) explain(w strutil.Formatter) { + w.Format("┌Compute Cartesian product of%i\n") + for i, v := range r.rsets { + sel := !isTableOrIndex(v) + if sel { + w.Format("┌Iterate all rows of virtual table %q%i\n", r.names[i]) + } + v.explain(w) + if sel { + w.Format("%u└Output field names %v\n", qnames(v.fieldNames())) + } + } + w.Format("Extend the product with all NULL rows of all but %q when no match for %v%u\n", r.names[len(r.names)-1], r.on) + w.Format("└Output field names %v\n", qnames(r.fields)) +} + +func (r *rightJoinDefaultPlan) filter(expr expression) (plan, []string, error) { + var is []string + for i, v := range r.names { + e2, err := expr.clone(nil, v) + if err != nil { + return nil, nil, err + } + + p2, is2, err := r.rsets[i].filter(e2) + is = append(is, is2...) + if err != nil { + return nil, nil, err + } + + if p2 != nil { + r.rsets[i] = p2 + return r, is, nil + } + } + return nil, is, nil +} + +type fullJoinDefaultPlan struct { + leftJoinDefaultPlan +} + +func (r *fullJoinDefaultPlan) hasID() bool { return false } + +func (r *fullJoinDefaultPlan) explain(w strutil.Formatter) { + w.Format("┌Compute Cartesian product of%i\n") + for i, v := range r.rsets { + sel := !isTableOrIndex(v) + if sel { + w.Format("┌Iterate all rows of virtual table %q%i\n", r.names[i]) + } + v.explain(w) + if sel { + w.Format("%u└Output field names %v\n", qnames(v.fieldNames())) + } + } + w.Format("Extend the product with all NULL rows of %q when no match for %v\n", r.names[len(r.names)-1], r.on) + w.Format("Extend the product with all NULL rows of all but %q when no match for %v%u\n", r.names[len(r.names)-1], r.on) + w.Format("└Output field names %v\n", qnames(r.fields)) +} + +func (r *fullJoinDefaultPlan) filter(expr expression) (plan, []string, error) { + var is []string + for i, v := range r.names { + e2, err := expr.clone(nil, v) + if err != nil { + return nil, nil, err + } + + p2, is2, err := r.rsets[i].filter(e2) + is = append(is, is2...) + if err != nil { + return nil, nil, err + } + + if p2 != nil { + r.rsets[i] = p2 + return r, is, nil + } + } + return nil, is, nil +} + +func (r *leftJoinDefaultPlan) fieldNames() []string { return r.fields } + +func (r *leftJoinDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) error { + m := map[interface{}]interface{}{} + ids := map[string]interface{}{} + var g func([]interface{}, []plan, int) error + var match bool + g = func(prefix []interface{}, rsets []plan, x int) (err error) { + return rsets[0].do(ctx, func(id interface{}, in []interface{}) (bool, error) { + ids[r.names[x]] = id + row := append(prefix, in...) + if len(rsets) > 1 { + if len(rsets) == 2 { + match = false + } + if err = g(row, rsets[1:], x+1); err != nil { + return false, err + } + + if len(rsets) != 2 || match { + return true, nil + } + + ids[r.names[x+1]] = nil + return f(ids, append(row, make([]interface{}, r.right)...)) + } + + for i, fld := range r.fields { + if fld != "" { + m[fld] = row[i] + } + } + + val, err := r.on.eval(ctx, m) + if err != nil { + return false, err + } + + if val == nil { + return true, nil + } + + x, ok := val.(bool) + if !ok { + return false, fmt.Errorf("invalid ON expression %s (value of type %T)", val, val) + } + + if !x { + return true, nil + } + + match = true + return f(ids, row) + }) + } + return g(nil, r.rsets, 0) +} + +func (r *rightJoinDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) error { + right := r.right + left := len(r.fields) - right + n := len(r.rsets) + m := map[interface{}]interface{}{} + ids := map[string]interface{}{} + var g func([]interface{}, []plan, int) error + var match bool + nf := len(r.fields) + fields := append(append([]string(nil), r.fields[nf-right:]...), r.fields[:nf-right]...) + g = func(prefix []interface{}, rsets []plan, x int) (err error) { + return rsets[0].do(ctx, func(id interface{}, in []interface{}) (bool, error) { + ids[r.names[x]] = id + row := append(prefix, in...) + if len(rsets) > 1 { + if len(rsets) == n { + match = false + } + if err = g(row, rsets[1:], x+1); err != nil { + return false, err + } + + if len(rsets) != n || match { + return true, nil + } + + for i := 0; i < n-1; i++ { + ids[r.names[i]] = nil + } + + // rigth, left -> left, right + return f(ids, append(make([]interface{}, left), row[:right]...)) + } + + for i, fld := range fields { + if fld != "" { + m[fld] = row[i] + } + } + + val, err := r.on.eval(ctx, m) + if err != nil { + return false, err + } + + if val == nil { + return true, nil + } + + x, ok := val.(bool) + if !ok { + return false, fmt.Errorf("invalid ON expression %s (value of type %T)", val, val) + } + + if !x { + return true, nil + } + + match = true + // rigth, left -> left, right + return f(ids, append(append([]interface{}(nil), row[right:]...), row[:right]...)) + }) + } + return g(nil, append([]plan{r.rsets[n-1]}, r.rsets[:n-1]...), 0) +} + +func (r *fullJoinDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) error { + b3 := b.TreeNew(func(a, b interface{}) int { + x := a.(int64) + y := b.(int64) + if x < y { + return -1 + } + + if x == y { + return 0 + } + + return 1 + }) + m := map[interface{}]interface{}{} + ids := map[string]interface{}{} + var g func([]interface{}, []plan, int) error + var match bool + var rid int64 + firstR := true + g = func(prefix []interface{}, rsets []plan, x int) (err error) { + return rsets[0].do(ctx, func(id interface{}, in []interface{}) (bool, error) { + ids[r.names[x]] = id + row := append(prefix, in...) + if len(rsets) > 1 { + if len(rsets) == 2 { + match = false + rid = 0 + } + if err = g(row, rsets[1:], x+1); err != nil { + return false, err + } + + if len(rsets) == 2 { + firstR = false + } + if len(rsets) != 2 || match { + return true, nil + } + + ids[r.names[x+1]] = nil + return f(ids, append(row, make([]interface{}, r.right)...)) + } + + rid++ + if firstR { + b3.Set(rid, in) + } + for i, fld := range r.fields { + if fld != "" { + m[fld] = row[i] + } + } + + val, err := r.on.eval(ctx, m) + if err != nil { + return false, err + } + + if val == nil { + return true, nil + } + + x, ok := val.(bool) + if !ok { + return false, fmt.Errorf("invalid ON expression %s (value of type %T)", val, val) + } + + if !x { + return true, nil + } + + match = true + b3.Delete(rid) + return f(ids, row) + }) + } + if err := g(nil, r.rsets, 0); err != nil { + return err + } + + it, err := b3.SeekFirst() + if err != nil { + return noEOF(err) + } + + pref := make([]interface{}, len(r.fields)-r.right) + for { + _, v, err := it.Next() + if err != nil { + return noEOF(err) + } + + more, err := f(nil, append(pref, v.([]interface{})...)) + if err != nil || !more { + return err + } + } +} diff --git a/vendor/github.com/cznic/ql/ql.go b/vendor/github.com/cznic/ql/ql.go new file mode 100644 index 00000000..3a70b86d --- /dev/null +++ b/vendor/github.com/cznic/ql/ql.go @@ -0,0 +1,1729 @@ +// Copyright 2014 The ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//LATER profile mem +//LATER profile cpu +//LATER coverage + +package ql + +import ( + "bytes" + "errors" + "fmt" + "math/big" + "strconv" + "strings" + "sync" + "time" + + "github.com/cznic/strutil" +) + +const ( + crossJoin = iota + leftJoin + rightJoin + fullJoin +) + +// NOTE: all rset implementations must be safe for concurrent use by multiple +// goroutines. If the do method requires any execution domain local data, they +// must be held out of the implementing instance. +var ( + _ rset = (*distinctRset)(nil) + _ rset = (*groupByRset)(nil) + _ rset = (*joinRset)(nil) + _ rset = (*limitRset)(nil) + _ rset = (*offsetRset)(nil) + _ rset = (*orderByRset)(nil) + _ rset = (*selectRset)(nil) + _ rset = (*selectStmt)(nil) + _ rset = (*tableRset)(nil) + _ rset = (*whereRset)(nil) + + isTesting bool // enables test hook: select from an index +) + +type rset interface { + plan(ctx *execCtx) (plan, error) +} + +type recordset struct { + ctx *execCtx + plan + tx *TCtx +} + +func (r recordset) fieldNames() []interface{} { + f := r.plan.fieldNames() + a := make([]interface{}, len(f)) + for i, v := range f { + a[i] = v + } + return a +} + +// Do implements Recordset. +func (r recordset) Do(names bool, f func(data []interface{}) (bool, error)) error { + if names { + if more, err := f(r.fieldNames()); err != nil || !more { + return err + } + } + return r.ctx.db.do(r, f) +} + +// Fields implements Recordset. +func (r recordset) Fields() (names []string, err error) { + return r.plan.fieldNames(), nil +} + +// FirstRow implements Recordset. +func (r recordset) FirstRow() (row []interface{}, err error) { + rows, err := r.Rows(1, 0) + if err != nil { + return nil, err + } + + if len(rows) != 0 { + return rows[0], nil + } + + return nil, nil +} + +// Rows implements Recordset. +func (r recordset) Rows(limit, offset int) ([][]interface{}, error) { + var rows [][]interface{} + if err := r.Do(false, func(row []interface{}) (bool, error) { + if offset > 0 { + offset-- + return true, nil + } + + switch { + case limit < 0: + rows = append(rows, row) + return true, nil + case limit == 0: + return false, nil + default: // limit > 0 + rows = append(rows, row) + limit-- + return limit > 0, nil + } + }); err != nil { + return nil, err + } + + return rows, nil +} + +// List represents a group of compiled statements. +type List struct { + l []stmt + params int +} + +// String implements fmt.Stringer +func (l List) String() string { + var b bytes.Buffer + f := strutil.IndentFormatter(&b, "\t") + for _, s := range l.l { + switch s.(type) { + case beginTransactionStmt: + f.Format("%s\n%i", s) + case commitStmt, rollbackStmt: + f.Format("%u%s\n", s) + default: + f.Format("%s\n", s) + } + } + return b.String() +} + +// IsExplainStmt reports whether l is a single EXPLAIN statment or a single EXPLAIN +// statment enclosed in a transaction. +func (l List) IsExplainStmt() bool { + switch len(l.l) { + case 1: + _, ok := l.l[0].(*explainStmt) + return ok + case 3: + if _, ok := l.l[0].(beginTransactionStmt); !ok { + return false + } + if _, ok := l.l[1].(*explainStmt); !ok { + return false + } + _, ok := l.l[2].(commitStmt) + return ok + default: + return false + } +} + +type groupByRset struct { + colNames []string + src plan +} + +func (r *groupByRset) plan(ctx *execCtx) (plan, error) { + fields := r.src.fieldNames() + for _, v := range r.colNames { + found := false + for _, v2 := range fields { + if v == v2 { + found = true + break + } + } + if !found { + return nil, fmt.Errorf("unknown field %s", v) + } + } + return &groupByDefaultPlan{colNames: r.colNames, src: r.src, fields: fields}, nil +} + +// TCtx represents transaction context. It enables to execute multiple +// statement lists in the same context. The same context guarantees the state +// of the DB cannot change in between the separated executions. +// +// LastInsertID +// +// LastInsertID is updated by INSERT INTO statements. The value considers +// performed ROLLBACK statements, if any, even though roll backed IDs are not +// reused. QL clients should treat the field as read only. +// +// RowsAffected +// +// RowsAffected is updated by INSERT INTO, DELETE FROM and UPDATE statements. +// The value does not (yet) consider any ROLLBACK statements involved. QL +// clients should treat the field as read only. +type TCtx struct { + LastInsertID int64 + RowsAffected int64 +} + +// NewRWCtx returns a new read/write transaction context. NewRWCtx is safe for +// concurrent use by multiple goroutines, every one of them will get a new, +// unique conext. +func NewRWCtx() *TCtx { return &TCtx{} } + +// Recordset is a result of a select statment. It can call a user function for +// every row (record) in the set using the Do method. +// +// Recordsets can be safely reused. Evaluation of the rows is performed lazily. +// Every invocation of Do will see the current, potentially actualized data. +// +// Do +// +// Do will call f for every row (record) in the Recordset. +// +// If f returns more == false or err != nil then f will not be called for any +// remaining rows in the set and the err value is returned from Do. +// +// If names == true then f is firstly called with a virtual row +// consisting of field (column) names of the RecordSet. +// +// Do is executed in a read only context and performs a RLock of the +// database. +// +// Do is safe for concurrent use by multiple goroutines. +// +// Fields +// +// Fields return a slice of field names of the recordset. The result is computed +// without actually computing the recordset rows. +// +// FirstRow +// +// FirstRow will return the first row of the RecordSet or an error, if any. If +// the Recordset has no rows the result is (nil, nil). +// +// Rows +// +// Rows will return rows in Recordset or an error, if any. The semantics of +// limit and offset are the same as of the LIMIT and OFFSET clauses of the +// SELECT statement. To get all rows pass limit < 0. If there are no rows to +// return the result is (nil, nil). +type Recordset interface { + Do(names bool, f func(data []interface{}) (more bool, err error)) error + Fields() (names []string, err error) + FirstRow() (row []interface{}, err error) + Rows(limit, offset int) (rows [][]interface{}, err error) +} + +type assignment struct { + colName string + expr expression +} + +func (a *assignment) String() string { + return fmt.Sprintf("%s=%s", a.colName, a.expr) +} + +type distinctRset struct { + src plan +} + +func (r *distinctRset) plan(ctx *execCtx) (plan, error) { + return &distinctDefaultPlan{src: r.src, fields: r.src.fieldNames()}, nil +} + +type orderByRset struct { + asc bool + by []expression + src plan +} + +func (r *orderByRset) String() string { + a := make([]string, len(r.by)) + for i, v := range r.by { + a[i] = v.String() + } + s := strings.Join(a, ", ") + if !r.asc { + s += " DESC" + } + return s +} + +func (r *orderByRset) plan(ctx *execCtx) (plan, error) { + if _, ok := r.src.(*nullPlan); ok { + return r.src, nil + } + + var by []expression + fields := r.src.fieldNames() + for _, e := range r.by { + cols := mentionedColumns(e) + for k := range cols { + found := false + for _, v := range fields { + if k == v { + found = true + break + } + } + if !found { + return nil, fmt.Errorf("unknown field %s", k) + } + } + if len(cols) == 0 { + v, err := e.eval(ctx, nil) + if err != nil { + by = append(by, e) + continue + } + + if isConstValue(v) != nil { + continue + } + } + + by = append(by, e) + } + return &orderByDefaultPlan{asc: r.asc, by: by, src: r.src, fields: fields}, nil +} + +type whereRset struct { + expr expression + src plan +} + +func (r *whereRset) planBinOp(x *binaryOperation) (plan, error) { + p := r.src + ok, cn := isColumnExpression(x.l) + if ok && cn == "id()" { + if v := isConstValue(x.r); v != nil { + v, err := typeCheck1(v, idCol) + if err != nil { + return nil, err + } + + rv := v.(int64) + switch { + case p.hasID(): + switch x.op { + case '<': + if rv <= 1 { + return &nullPlan{p.fieldNames()}, nil + } + case '>': + if rv <= 0 { + return p, nil + } + case ge: + if rv >= 1 { + return p, nil + } + case neq: + if rv <= 0 { + return p, nil + } + case eq: + if rv <= 0 { + return &nullPlan{p.fieldNames()}, nil + } + case le: + if rv <= 0 { + return &nullPlan{p.fieldNames()}, nil + } + } + } + } + } + + var err error + var p2 plan + var is []string + switch x.op { + case eq, ge, '>', le, '<', neq: + if p2, is, err = p.filter(x); err != nil { + return nil, err + } + + if p2 != nil { + return p2, nil + } + case andand: + var in []expression + var f func(expression) + f = func(e expression) { + b, ok := e.(*binaryOperation) + if !ok || b.op != andand { + in = append(in, e) + return + } + + f(b.l) + f(b.r) + } + f(x) + out := []expression{} + p := r.src + isNewPlan := false + for _, e := range in { + p2, is2, err := p.filter(e) + if err != nil { + return nil, err + } + + if p2 == nil { + is = append(is, is2...) + out = append(out, e) + continue + } + + p = p2 + isNewPlan = true + } + + if !isNewPlan { + break + } + + if len(out) == 0 { + return p, nil + } + + for len(out) > 1 { + n := len(out) + e, err := newBinaryOperation(andand, out[n-2], out[n-1]) + if err != nil { + return nil, err + } + + out = out[:n-1] + out[n-2] = e + } + + return &filterDefaultPlan{p, out[0], is}, nil + } + + return &filterDefaultPlan{p, x, is}, nil +} + +func (r *whereRset) planIdent(x *ident) (plan, error) { + p := r.src + p2, is, err := p.filter(x) + if err != nil { + return nil, err + } + + if p2 != nil { + return p2, nil + } + + return &filterDefaultPlan{p, x, is}, nil +} + +func (r *whereRset) planIsNull(x *isNull) (plan, error) { + p := r.src + ok, cn := isColumnExpression(x.expr) + if !ok { + return &filterDefaultPlan{p, x, nil}, nil + } + + if cn == "id()" { + switch { + case p.hasID(): + switch { + case x.not: // IS NOT NULL + return p, nil + default: // IS NULL + return &nullPlan{p.fieldNames()}, nil + } + default: + switch { + case x.not: // IS NOT NULL + return &nullPlan{p.fieldNames()}, nil + default: // IS NULL + return p, nil + } + } + } + + p2, is, err := p.filter(x) + if err != nil { + return nil, err + } + + if p2 != nil { + return p2, nil + } + + return &filterDefaultPlan{p, x, is}, nil +} + +func (r *whereRset) planUnaryOp(x *unaryOperation) (plan, error) { + p := r.src + p2, is, err := p.filter(x) + if err != nil { + return nil, err + } + + if p2 != nil { + return p2, nil + } + + return &filterDefaultPlan{p, x, is}, nil +} + +func (r *whereRset) plan(ctx *execCtx) (plan, error) { + expr, err := r.expr.clone(ctx.arg) + if err != nil { + return nil, err + } + + switch r.src.(type) { + case *leftJoinDefaultPlan, *rightJoinDefaultPlan, *fullJoinDefaultPlan: + return &filterDefaultPlan{r.src, expr, nil}, nil + } + + switch x := expr.(type) { + case *binaryOperation: + return r.planBinOp(x) + case *ident: + return r.planIdent(x) + case *isNull: + return r.planIsNull(x) + case *pIn: + //TODO optimize + //TODO show plan + case *pLike: + //TODO optimize + case *unaryOperation: + return r.planUnaryOp(x) + } + + return &filterDefaultPlan{r.src, expr, nil}, nil +} + +type offsetRset struct { + expr expression + src plan +} + +func (r *offsetRset) plan(ctx *execCtx) (plan, error) { + return &offsetDefaultPlan{expr: r.expr, src: r.src, fields: r.src.fieldNames()}, nil +} + +type limitRset struct { + expr expression + src plan +} + +func (r *limitRset) plan(ctx *execCtx) (plan, error) { + return &limitDefaultPlan{expr: r.expr, src: r.src, fields: r.src.fieldNames()}, nil +} + +type selectRset struct { + flds []*fld + src plan +} + +func (r *selectRset) plan(ctx *execCtx) (plan, error) { + var flds2 []*fld + if len(r.flds) != 0 { + m := map[string]struct{}{} + for _, v := range r.flds { + mentionedColumns0(v.expr, true, true, m) + } + for _, v := range r.src.fieldNames() { + delete(m, v) + } + for k := range m { + return nil, fmt.Errorf("unknown field %s", k) + } + + flds2 = append(flds2, r.flds...) + } + + if x, ok := r.src.(*groupByDefaultPlan); ok { + if len(r.flds) == 0 { + fields := x.fieldNames() + flds := make([]*fld, len(fields)) + for i, v := range fields { + flds[i] = &fld{&ident{v}, v} + } + return &selectFieldsGroupPlan{flds: flds, src: x, fields: fields}, nil + } + + p := &selectFieldsGroupPlan{flds: flds2, src: x} + for _, v := range r.flds { + p.fields = append(p.fields, v.name) + } + return p, nil + } + + if len(r.flds) == 0 { + return r.src, nil + } + + f0 := r.src.fieldNames() + if len(f0) == len(flds2) { + match := true + for i, v := range flds2 { + if x, ok := v.expr.(*ident); ok && x.s == f0[i] && v.name == f0[i] { + continue + } + + match = false + break + } + + if match { + return r.src, nil + } + } + + src := r.src + if x, ok := src.(*tableDefaultPlan); ok { + isconst := true + for _, v := range flds2 { + if isConstValue(v.expr) == nil { + isconst = false + break + } + } + if isconst { // #250 + src = &tableNilPlan{x.t} + } + } + + p := &selectFieldsDefaultPlan{flds: flds2, src: src} + for _, v := range r.flds { + p.fields = append(p.fields, v.name) + } + return p, nil +} + +type tableRset string + +func (r tableRset) plan(ctx *execCtx) (plan, error) { + switch r { + case "__Table": + return &sysTableDefaultPlan{}, nil + case "__Column": + return &sysColumnDefaultPlan{}, nil + case "__Index": + return &sysIndexDefaultPlan{}, nil + } + + t, ok := ctx.db.root.tables[string(r)] + if !ok && isTesting { + if _, x0 := ctx.db.root.findIndexByName(string(r)); x0 != nil { + return &selectIndexDefaultPlan{nm: string(r), x: x0}, nil + } + } + + if !ok { + return nil, fmt.Errorf("table %s does not exist", r) + } + + rs := &tableDefaultPlan{t: t} + for _, col := range t.cols { + rs.fields = append(rs.fields, col.name) + } + return rs, nil +} + +func findFldIndex(fields []*fld, name string) int { + for i, f := range fields { + if f.name == name { + return i + } + } + + return -1 +} + +func findFld(fields []*fld, name string) (f *fld) { + for _, f = range fields { + if f.name == name { + return + } + } + + return nil +} + +type col struct { + index int + name string + typ int + constraint *constraint + dflt expression +} + +var idCol = &col{name: "id()", typ: qInt64} + +func findCol(cols []*col, name string) (c *col) { + for _, c = range cols { + if c.name == name { + return + } + } + + return nil +} + +func (f *col) clone() *col { + var r col + r = *f + r.constraint = f.constraint.clone() + if f.dflt != nil { + r.dflt, _ = r.dflt.clone(nil) + } + return &r +} + +func (f *col) typeCheck(x interface{}) (ok bool) { //NTYPE + switch x.(type) { + case nil: + return true + case bool: + return f.typ == qBool + case complex64: + return f.typ == qComplex64 + case complex128: + return f.typ == qComplex128 + case float32: + return f.typ == qFloat32 + case float64: + return f.typ == qFloat64 + case int8: + return f.typ == qInt8 + case int16: + return f.typ == qInt16 + case int32: + return f.typ == qInt32 + case int64: + return f.typ == qInt64 + case string: + return f.typ == qString + case uint8: + return f.typ == qUint8 + case uint16: + return f.typ == qUint16 + case uint32: + return f.typ == qUint32 + case uint64: + return f.typ == qUint64 + case []byte: + return f.typ == qBlob + case *big.Int: + return f.typ == qBigInt + case *big.Rat: + return f.typ == qBigRat + case time.Time: + return f.typ == qTime + case time.Duration: + return f.typ == qDuration + case chunk: + return true // was checked earlier + } + return +} + +func cols2meta(f []*col) (s string) { + a := []string{} + for _, f := range f { + a = append(a, string(f.typ)+f.name) + } + return strings.Join(a, "|") +} + +// DB represent the database capable of executing QL statements. +type DB struct { + cc *TCtx // Current transaction context + isMem bool + mu sync.Mutex + root *root + rw bool // DB FSM + rwmu sync.RWMutex + store storage + tnl int // Transaction nesting level + exprCache map[string]expression + exprCacheMu sync.Mutex + hasIndex2 int // 0: nope, 1: in progress, 2: yes. +} + +var selIndex2Expr = MustCompile("select Expr from __Index2_Expr where Index2_ID == $1") + +func newDB(store storage) (db *DB, err error) { + db0 := &DB{ + exprCache: map[string]expression{}, + store: store, + } + if db0.root, err = newRoot(store); err != nil { + return + } + + ctx := &execCtx{db: db0} + for _, t := range db0.root.tables { + if err := t.constraintsAndDefaults(ctx); err != nil { + return nil, err + } + } + + if !db0.hasAllIndex2() { + return db0, nil + } + + db0.hasIndex2 = 2 + rss, _, err := db0.Run(nil, "select id(), TableName, IndexName, IsUnique, Root from __Index2 where !IsSimple") + if err != nil { + return nil, err + } + + rows, err := rss[0].Rows(-1, 0) + if err != nil { + return nil, err + } + + for _, row := range rows { + defer func() { + if e := recover(); e != nil { + err = fmt.Errorf("error loading DB indices: %v", e) + } + }() + + id := row[0].(int64) + tn := row[1].(string) + xn := row[2].(string) + unique := row[3].(bool) + xroot := row[4].(int64) + + t := db0.root.tables[tn] + if t == nil { + return nil, fmt.Errorf("DB index refers to nonexistent table: %s", tn) + } + + x, err := store.OpenIndex(unique, xroot) + if err != nil { + return nil, err + } + + if v := t.indices2[xn]; v != nil { + return nil, fmt.Errorf("duplicate DB index: %s", xn) + } + + ix := &index2{ + unique: unique, + x: x, + xroot: xroot, + } + + rss, _, err := db0.Execute(nil, selIndex2Expr, id) + if err != nil { + return nil, err + } + + rows, err := rss[0].Rows(-1, 0) + if err != nil { + return nil, err + } + + if len(rows) == 0 { + return nil, fmt.Errorf("index has no expression: %s", xn) + } + + var sources []string + var list []expression + for _, row := range rows { + src, ok := row[0].(string) + if !ok { + return nil, fmt.Errorf("index %s: expression of type %T", xn, row[0]) + } + + expr, err := db0.str2expr(src) + if err != nil { + return nil, fmt.Errorf("index %s: expression error: %v", xn, err) + } + + sources = append(sources, src) + list = append(list, expr) + } + + ix.sources = sources + ix.exprList = list + if t.indices2 == nil { + t.indices2 = map[string]*index2{} + } + t.indices2[xn] = ix + } + return db0, nil +} + +func (db *DB) deleteIndex2ByIndexName(nm string) error { + for _, s := range deleteIndex2ByIndexName.l { + if _, err := s.exec(&execCtx{db: db, arg: []interface{}{nm}}); err != nil { + return err + } + } + return nil +} + +func (db *DB) deleteIndex2ByTableName(nm string) error { + for _, s := range deleteIndex2ByTableName.l { + if _, err := s.exec(&execCtx{db: db, arg: []interface{}{nm}}); err != nil { + return err + } + } + return nil +} + +func (db *DB) createIndex2() error { + if db.hasIndex2 != 0 { + return nil + } + + db.hasIndex2 = 1 + ctx := execCtx{db: db} + for _, s := range createIndex2.l { + if _, err := s.exec(&ctx); err != nil { + db.hasIndex2 = 0 + return err + } + } + + for t := db.root.thead; t != nil; t = t.tnext { + for i, index := range t.indices { + if index == nil { + continue + } + + expr := "id()" + if i != 0 { + expr = t.cols[i-1].name + } + + if err := db.insertIndex2(t.name, index.name, []string{expr}, index.unique, true, index.xroot); err != nil { + db.hasIndex2 = 0 + return err + } + } + } + + db.hasIndex2 = 2 + return nil +} + +func (db *DB) insertIndex2(tableName, indexName string, expr []string, unique, isSimple bool, h int64) error { + ctx := execCtx{db: db} + ctx.arg = []interface{}{ + tableName, + indexName, + unique, + isSimple, + h, + } + if _, err := insertIndex2.l[0].exec(&ctx); err != nil { + return err + } + + id := db.root.lastInsertID + for _, e := range expr { + ctx.arg = []interface{}{id, e} + if _, err := insertIndex2Expr.l[0].exec(&ctx); err != nil { + return err + } + } + return nil +} + +func (db *DB) hasAllIndex2() bool { + t := db.root.tables + if _, ok := t["__Index2"]; !ok { + return false + } + + _, ok := t["__Index2_Expr"] + return ok +} + +func (db *DB) str2expr(expr string) (expression, error) { + db.exprCacheMu.Lock() + e := db.exprCache[expr] + db.exprCacheMu.Unlock() + if e != nil { + return e, nil + } + + e, err := compileExpr(expr) + if err != nil { + return nil, err + } + + db.exprCacheMu.Lock() + for k := range db.exprCache { + if len(db.exprCache) < 1000 { + break + } + + delete(db.exprCache, k) + } + db.exprCache[expr] = e + db.exprCacheMu.Unlock() + return e, nil +} + +// Name returns the name of the DB. +func (db *DB) Name() string { return db.store.Name() } + +// Run compiles and executes a statement list. It returns, if applicable, a +// RecordSet slice and/or an index and error. +// +// For more details please see DB.Execute +// +// Run is safe for concurrent use by multiple goroutines. +func (db *DB) Run(ctx *TCtx, ql string, arg ...interface{}) (rs []Recordset, index int, err error) { + l, err := Compile(ql) + if err != nil { + return nil, -1, err + } + + return db.Execute(ctx, l, arg...) +} + +func (db *DB) run(ctx *TCtx, ql string, arg ...interface{}) (rs []Recordset, index int, err error) { + l, err := compile(ql) + if err != nil { + return nil, -1, err + } + + return db.Execute(ctx, l, arg...) +} + +// Compile parses the ql statements from src and returns a compiled list for +// DB.Execute or an error if any. +// +// Compile is safe for concurrent use by multiple goroutines. +func Compile(src string) (List, error) { + l := newLexer(src) + if yyParse(l) != 0 { + return List{}, l.errs[0] + } + + return List{l.list, l.params}, nil +} + +func compileExpr(src string) (expression, error) { + l := newLexer(src) + l.inj = parseExpression + if yyParse(l) != 0 { + return nil, l.errs[0] + } + + return l.expr, nil +} + +func compile(src string) (List, error) { + l := newLexer(src) + l.root = true + if yyParse(l) != 0 { + return List{}, l.errs[0] + } + + return List{l.list, l.params}, nil +} + +// MustCompile is like Compile but panics if the ql statements in src cannot be +// compiled. It simplifies safe initialization of global variables holding +// compiled statement lists for DB.Execute. +// +// MustCompile is safe for concurrent use by multiple goroutines. +func MustCompile(src string) List { + list, err := Compile(src) + if err != nil { + panic("ql: Compile(" + strconv.Quote(src) + "): " + err.Error()) // panic ok here + } + + return list +} + +func mustCompile(src string) List { + list, err := compile(src) + if err != nil { + panic("ql: compile(" + strconv.Quote(src) + "): " + err.Error()) // panic ok here + } + + return list +} + +// Execute executes statements in a list while substituting QL paramaters from +// arg. +// +// The resulting []Recordset corresponds to the SELECT FROM statements in the +// list. +// +// If err != nil then index is the zero based index of the failed QL statement. +// Empty statements do not count. +// +// The FSM STT describing the relations between DB states, statements and the +// ctx parameter. +// +// +-----------+---------------------+------------------+------------------+------------------+ +// |\ Event | | | | | +// | \-------\ | BEGIN | | | Other | +// | State \| TRANSACTION | COMMIT | ROLLBACK | statement | +// +-----------+---------------------+------------------+------------------+------------------+ +// | RD | if PC == nil | return error | return error | DB.RLock | +// | | return error | | | Execute(1) | +// | CC == nil | | | | DB.RUnlock | +// | TNL == 0 | DB.Lock | | | | +// | | CC = PC | | | | +// | | TNL++ | | | | +// | | DB.BeginTransaction | | | | +// | | State = WR | | | | +// +-----------+---------------------+------------------+------------------+------------------+ +// | WR | if PC == nil | if PC != CC | if PC != CC | if PC == nil | +// | | return error | return error | return error | DB.Rlock | +// | CC != nil | | | | Execute(1) | +// | TNL != 0 | if PC != CC | DB.Commit | DB.Rollback | RUnlock | +// | | DB.Lock | TNL-- | TNL-- | else if PC != CC | +// | | CC = PC | if TNL == 0 | if TNL == 0 | return error | +// | | | CC = nil | CC = nil | else | +// | | TNL++ | State = RD | State = RD | Execute(2) | +// | | DB.BeginTransaction | DB.Unlock | DB.Unlock | | +// +-----------+---------------------+------------------+------------------+------------------+ +// CC: Curent transaction context +// PC: Passed transaction context +// TNL: Transaction nesting level +// +// Lock, Unlock, RLock, RUnlock semantics above are the same as in +// sync.RWMutex. +// +// (1): Statement list is executed outside of a transaction. Attempts to update +// the DB will fail, the execution context is read-only. Other statements with +// read only context will execute concurrently. If any statement fails, the +// execution of the statement list is aborted. +// +// Note that the RLock/RUnlock surrounds every single "other" statement when it +// is executed outside of a transaction. If read consistency is required by a +// list of more than one statement then an explicit BEGIN TRANSACTION / COMMIT +// or ROLLBACK wrapper must be provided. Otherwise the state of the DB may +// change in between executing any two out-of-transaction statements. +// +// (2): Statement list is executed inside an isolated transaction. Execution of +// statements can update the DB, the execution context is read-write. If any +// statement fails, the execution of the statement list is aborted and the DB +// is automatically rolled back to the TNL which was active before the start of +// execution of the statement list. +// +// Execute is safe for concurrent use by multiple goroutines, but one must +// consider the blocking issues as discussed above. +// +// ACID +// +// Atomicity: Transactions are atomic. Transactions can be nested. Commit or +// rollbacks work on the current transaction level. Transactions are made +// persistent only on the top level commit. Reads made from within an open +// transaction are dirty reads. +// +// Consistency: Transactions bring the DB from one structurally consistent +// state to other structurally consistent state. +// +// Isolation: Transactions are isolated. Isolation is implemented by +// serialization. +// +// Durability: Transactions are durable. A two phase commit protocol and a +// write ahead log is used. Database is recovered after a crash from the write +// ahead log automatically on open. +func (db *DB) Execute(ctx *TCtx, l List, arg ...interface{}) (rs []Recordset, index int, err error) { + // Sanitize args + for i, v := range arg { + switch x := v.(type) { + case nil, bool, complex64, complex128, float32, float64, string, + int8, int16, int32, int64, int, + uint8, uint16, uint32, uint64, uint, + *big.Int, *big.Rat, []byte, time.Duration, time.Time: + case big.Int: + arg[i] = &x + case big.Rat: + arg[i] = &x + default: + return nil, 0, fmt.Errorf("cannot use arg[%d] (type %T):unsupported type", i, v) + } + } + + tnl0 := -1 + if ctx != nil { + ctx.LastInsertID, ctx.RowsAffected = 0, 0 + } + + list := l.l + for _, s := range list { + r, tnla, tnl, err := db.run1(ctx, s, arg...) + if tnl0 < 0 { + tnl0 = tnla + } + if err != nil { + for tnl > tnl0 { + var e2 error + if _, _, tnl, e2 = db.run1(ctx, rollbackStmt{}); e2 != nil { + err = e2 + } + } + return rs, index, err + } + + if r != nil { + if x, ok := r.(recordset); ok { + x.tx = ctx + r = x + } + rs = append(rs, r) + } + } + return +} + +func (db *DB) run1(pc *TCtx, s stmt, arg ...interface{}) (rs Recordset, tnla, tnlb int, err error) { + db.mu.Lock() + tnla = db.tnl + tnlb = db.tnl + switch db.rw { + case false: + switch s.(type) { + case beginTransactionStmt: + defer db.mu.Unlock() + if pc == nil { + return nil, tnla, tnlb, errors.New("BEGIN TRANSACTION: cannot start a transaction in nil TransactionCtx") + } + + if err = db.store.BeginTransaction(); err != nil { + return + } + + db.rwmu.Lock() + db.beginTransaction() + db.cc = pc + db.tnl++ + tnlb = db.tnl + db.rw = true + return + case commitStmt: + defer db.mu.Unlock() + return nil, tnla, tnlb, errCommitNotInTransaction + case rollbackStmt: + defer db.mu.Unlock() + return nil, tnla, tnlb, errRollbackNotInTransaction + default: + if s.isUpdating() { + db.mu.Unlock() + return nil, tnla, tnlb, fmt.Errorf("attempt to update the DB outside of a transaction") + } + + db.rwmu.RLock() // can safely grab before Unlock + db.mu.Unlock() + defer db.rwmu.RUnlock() + rs, err = s.exec(&execCtx{db, arg}) // R/O tctx + return rs, tnla, tnlb, err + } + default: // case true: + switch s.(type) { + case beginTransactionStmt: + defer db.mu.Unlock() + + if pc == nil { + return nil, tnla, tnlb, errBeginTransNoCtx + } + + if pc != db.cc { + for db.rw == true { + db.mu.Unlock() // Transaction isolation + db.mu.Lock() + } + + db.rw = true + db.rwmu.Lock() + } + + if err = db.store.BeginTransaction(); err != nil { + return + } + + db.beginTransaction() + db.cc = pc + db.tnl++ + tnlb = db.tnl + return + case commitStmt: + defer db.mu.Unlock() + if pc != db.cc { + return nil, tnla, tnlb, fmt.Errorf("invalid passed transaction context") + } + + db.commit() + err = db.store.Commit() + db.tnl-- + tnlb = db.tnl + if db.tnl != 0 { + return + } + + db.cc = nil + db.rw = false + db.rwmu.Unlock() + return + case rollbackStmt: + defer db.mu.Unlock() + defer func() { pc.LastInsertID = db.root.lastInsertID }() + if pc != db.cc { + return nil, tnla, tnlb, fmt.Errorf("invalid passed transaction context") + } + + db.rollback() + err = db.store.Rollback() + db.tnl-- + tnlb = db.tnl + if db.tnl != 0 { + return + } + + db.cc = nil + db.rw = false + db.rwmu.Unlock() + return + default: + if pc == nil { + if s.isUpdating() { + db.mu.Unlock() + return nil, tnla, tnlb, fmt.Errorf("attempt to update the DB outside of a transaction") + } + + db.mu.Unlock() // must Unlock before RLock + db.rwmu.RLock() + defer db.rwmu.RUnlock() + rs, err = s.exec(&execCtx{db, arg}) + return rs, tnla, tnlb, err + } + + defer db.mu.Unlock() + defer func() { pc.LastInsertID = db.root.lastInsertID }() + if pc != db.cc { + return nil, tnla, tnlb, fmt.Errorf("invalid passed transaction context") + } + + rs, err = s.exec(&execCtx{db, arg}) + return rs, tnla, tnlb, err + } + } +} + +// Flush ends the transaction collecting window, if applicable. IOW, if the DB +// is dirty, it schedules a 2PC (WAL + DB file) commit on the next outer most +// DB.Commit or performs it synchronously if there's currently no open +// transaction. +// +// The collecting window is an implementation detail and future versions of +// Flush may become a no operation while keeping the operation semantics. +func (db *DB) Flush() (err error) { + return nil +} + +// Close will close the DB. Successful Close is idempotent. +func (db *DB) Close() error { + db.mu.Lock() + defer db.mu.Unlock() + if db.store == nil { + return nil + } + + if db.tnl != 0 { + return fmt.Errorf("cannot close DB while open transaction exist") + } + + err := db.store.Close() + db.root, db.store = nil, nil + return err +} + +func (db *DB) do(r recordset, f func(data []interface{}) (bool, error)) (err error) { + db.mu.Lock() + switch db.rw { + case false: + db.rwmu.RLock() // can safely grab before Unlock + db.mu.Unlock() + defer db.rwmu.RUnlock() + default: // case true: + if r.tx == nil { + db.mu.Unlock() // must Unlock before RLock + db.rwmu.RLock() + defer db.rwmu.RUnlock() + break + } + + defer db.mu.Unlock() + if r.tx != db.cc { + return fmt.Errorf("invalid passed transaction context") + } + } + + return r.do(r.ctx, func(id interface{}, data []interface{}) (bool, error) { + if err = expand(data); err != nil { + return false, err + } + + return f(data) + }) +} + +func (db *DB) beginTransaction() { //TODO Rewrite, must use much smaller undo info! + root := *db.root + root.parent = db.root + root.tables = make(map[string]*table, len(db.root.tables)) + var tprev *table + for t := db.root.thead; t != nil; t = t.tnext { + t2 := t.clone() + root.tables[t2.name] = t2 + t2.tprev = tprev + switch { + case tprev == nil: + root.thead = t2 + default: + tprev.tnext = t2 + } + tprev = t2 + } + db.root = &root +} + +func (db *DB) rollback() { + db.root = db.root.parent +} + +func (db *DB) commit() { + db.root.parent = db.root.parent.parent +} + +// Type represents a QL type (bigint, int, string, ...) +type Type int + +// Values of ColumnInfo.Type. +const ( + BigInt Type = qBigInt + BigRat = qBigRat + Blob = qBlob + Bool = qBool + Complex128 = qComplex128 + Complex64 = qComplex64 + Duration = qDuration + Float32 = qFloat32 + Float64 = qFloat64 + Int16 = qInt16 + Int32 = qInt32 + Int64 = qInt64 + Int8 = qInt8 + String = qString + Time = qTime + Uint16 = qUint16 + Uint32 = qUint32 + Uint64 = qUint64 + Uint8 = qUint8 +) + +// String implements fmt.Stringer. +func (t Type) String() string { + return typeStr(int(t)) +} + +// ColumnInfo provides meta data describing a table column. +type ColumnInfo struct { + Name string // Column name. + Type Type // Column type (BigInt, BigRat, ...). + NotNull bool // Column cannot be NULL. + Constraint string // Constraint expression, if any. + Default string // Default expression, if any. +} + +// TableInfo provides meta data describing a DB table. +type TableInfo struct { + // Table name. + Name string + + // Table schema. Columns are listed in the order in which they appear + // in the schema. + Columns []ColumnInfo +} + +// IndexInfo provides meta data describing a DB index. It corresponds to the +// statement +// +// CREATE INDEX Name ON Table (Column); +type IndexInfo struct { + Name string // Index name + Table string // Table name. + Column string // Column name. + Unique bool // Wheter the index is unique. + ExpressionList []string // Index expression list. +} + +// DbInfo provides meta data describing a DB. +type DbInfo struct { + Name string // DB name. + Tables []TableInfo // Tables in the DB. + Indices []IndexInfo // Indices in the DB. +} + +func (db *DB) info() (r *DbInfo, err error) { + _, hasColumn2 := db.root.tables["__Column2"] + r = &DbInfo{Name: db.Name()} + for nm, t := range db.root.tables { + ti := TableInfo{Name: nm} + m := map[string]*ColumnInfo{} + if hasColumn2 { + rs, err := selectColumn2.l[0].exec(&execCtx{db: db, arg: []interface{}{nm}}) + if err != nil { + return nil, err + } + + if err := rs.(recordset).do( + &execCtx{db: db, arg: []interface{}{nm}}, + func(id interface{}, data []interface{}) (bool, error) { + ci := &ColumnInfo{NotNull: data[1].(bool), Constraint: data[2].(string), Default: data[3].(string)} + m[data[0].(string)] = ci + return true, nil + }, + ); err != nil { + return nil, err + } + } + for _, c := range t.cols { + ci := ColumnInfo{Name: c.name, Type: Type(c.typ)} + if c2 := m[c.name]; c2 != nil { + ci.NotNull = c2.NotNull + ci.Constraint = c2.Constraint + ci.Default = c2.Default + } + ti.Columns = append(ti.Columns, ci) + } + r.Tables = append(r.Tables, ti) + for i, x := range t.indices { + if x == nil { + continue + } + + var cn string + switch { + case i == 0: + cn = "id()" + default: + cn = t.cols0[i-1].name + } + r.Indices = append(r.Indices, IndexInfo{x.name, nm, cn, x.unique, []string{cn}}) + } + var a []string + for k := range t.indices2 { + a = append(a, k) + } + for _, k := range a { + x := t.indices2[k] + a = a[:0] + for _, e := range x.exprList { + a = append(a, e.String()) + } + r.Indices = append(r.Indices, IndexInfo{k, nm, "", x.unique, a}) + } + } + return +} + +// Info provides meta data describing a DB or an error if any. It locks the DB +// to obtain the result. +func (db *DB) Info() (r *DbInfo, err error) { + db.mu.Lock() + defer db.mu.Unlock() + return db.info() +} + +type constraint struct { + expr expression // If expr == nil: constraint is 'NOT NULL' +} + +func (c *constraint) clone() *constraint { + if c == nil { + return nil + } + + var e expression + if c.expr != nil { + e, _ = c.expr.clone(nil) + } + return &constraint{e} +} + +type joinRset struct { + sources []interface{} + typ int + on expression +} + +func (r *joinRset) String() string { + a := make([]string, len(r.sources)) + for i, pair0 := range r.sources { + pair := pair0.([]interface{}) + altName := pair[1].(string) + switch x := pair[0].(type) { + case string: // table name + switch { + case altName == "": + a[i] = x + default: + a[i] = fmt.Sprintf("%s AS %s", x, altName) + } + case *selectStmt: + switch { + case altName == "": + a[i] = fmt.Sprintf("(%s)", x) + default: + a[i] = fmt.Sprintf("(%s) AS %s", x, altName) + } + default: + panic("internal error 054") + } + } + n := len(a) + a2 := a[:n-1] + j := a[n-1] + var s string + switch r.typ { + case crossJoin: + return strings.Join(a, ", ") + case leftJoin: + s = strings.Join(a2, ",") + " LEFT" + case rightJoin: + s = strings.Join(a2, ",") + " RIGHT" + case fullJoin: + s = strings.Join(a2, ",") + " FULL" + } + s += " OUTER JOIN " + j + " ON " + r.on.String() + return s +} + +func (r *joinRset) plan(ctx *execCtx) (plan, error) { + rsets := make([]plan, len(r.sources)) + names := make([]string, len(r.sources)) + var err error + m := map[string]bool{} + var fields []string + for i, v := range r.sources { + pair := v.([]interface{}) + src := pair[0] + nm := pair[1].(string) + if s, ok := src.(string); ok { + src = tableRset(s) + if nm == "" { + nm = s + } + } + if m[nm] { + return nil, fmt.Errorf("%s: duplicate name %s", r.String(), nm) + } + + if nm != "" { + m[nm] = true + } + names[i] = nm + var q plan + switch x := src.(type) { + case rset: + if q, err = x.plan(ctx); err != nil { + return nil, err + } + case plan: + q = x + default: + panic("internal error 008") + } + + switch { + case len(r.sources) == 1: + fields = q.fieldNames() + default: + for _, f := range q.fieldNames() { + if strings.Contains(f, ".") { + return nil, fmt.Errorf("cannot join on recordset with already qualified field names (use the AS clause): %s", f) + } + + if f != "" && nm != "" { + f = fmt.Sprintf("%s.%s", nm, f) + } + if nm == "" { + f = "" + } + fields = append(fields, f) + } + } + rsets[i] = q + } + + if len(rsets) == 1 { + return rsets[0], nil + } + + right := len(rsets[len(rsets)-1].fieldNames()) + switch r.typ { + case crossJoin: + return &crossJoinDefaultPlan{rsets: rsets, names: names, fields: fields}, nil + case leftJoin: + return &leftJoinDefaultPlan{rsets: rsets, names: names, fields: fields, on: r.on, right: right}, nil + case rightJoin: + return &rightJoinDefaultPlan{leftJoinDefaultPlan{rsets: rsets, names: names, fields: fields, on: r.on, right: right}}, nil + case fullJoin: + return &fullJoinDefaultPlan{leftJoinDefaultPlan{rsets: rsets, names: names, fields: fields, on: r.on, right: right}}, nil + default: + panic("internal error 010") + } +} + +type fld struct { + expr expression + name string +} diff --git a/vendor/github.com/cznic/ql/ql/main.go b/vendor/github.com/cznic/ql/ql/main.go new file mode 100644 index 00000000..568fd706 --- /dev/null +++ b/vendor/github.com/cznic/ql/ql/main.go @@ -0,0 +1,219 @@ +// Copyright 2014 The ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Command ql is a utility to explore a database, prototype a schema or test +// drive a query, etc. +// +// Installation: +// +// $ go get github.com/cznic/ql/ql +// +// Usage: +// +// ql [-db name] [-schema regexp] [-tables regexp] [-fld] statement_list +// +// Options: +// +// -db name Name of the database to use. Defaults to "ql.db". +// If the DB file does not exists it is created automatically. +// +// -schema re If re != "" show the CREATE statements of matching tables and exit. +// +// -tables re If re != "" show the matching table names and exit. +// +// -fld First row of a query result set will show field names. +// +// statement_list QL statements to execute. +// If no non flag arguments are present, ql reads from stdin. +// The list is wrapped into an automatic transaction. +// +// -t Report and measure time to execute, including creating/opening and closing the DB. +// +// Example: +// +// $ ql 'create table t (i int, s string)' +// $ ql << EOF +// > insert into t values +// > (1, "a"), +// > (2, "b"), +// > (3, "c"), +// > EOF +// $ ql 'select * from t' +// 3, "c" +// 2, "b" +// 1, "a" +// $ ql -fld 'select * from t where i != 2 order by s' +// "i", "s" +// 1, "a" +// 3, "c" +// $ +package main + +import ( + "bufio" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "regexp" + "sort" + "strings" + "time" + + "github.com/cznic/ql" +) + +func str(data []interface{}) string { + a := make([]string, len(data)) + for i, v := range data { + switch x := v.(type) { + case string: + a[i] = fmt.Sprintf("%q", x) + default: + a[i] = fmt.Sprint(x) + } + } + return strings.Join(a, ", ") +} + +func main() { + if err := do(); err != nil { + log.Fatal(err) + } +} + +func do() (err error) { + oDB := flag.String("db", "ql.db", "The DB file to open. It'll be created if missing.") + oFlds := flag.Bool("fld", false, "Show recordset's field names.") + oSchema := flag.String("schema", "", "If non empty, show the CREATE statements of matching tables and exit.") + oTables := flag.String("tables", "", "If non empty, list matching table names and exit.") + oTime := flag.Bool("t", false, "Measure and report time to execute the statement(s) including DB create/open/close.") + flag.Parse() + + t0 := time.Now() + if *oTime { + defer func() { + fmt.Fprintf(os.Stderr, "%s\n", time.Since(t0)) + }() + } + + db, err := ql.OpenFile(*oDB, &ql.Options{CanCreate: true}) + if err != nil { + return err + } + + defer func() { + ec := db.Close() + switch { + case ec != nil && err != nil: + log.Println(ec) + case ec != nil: + err = ec + } + }() + + if pat := *oSchema; pat != "" { + re, err := regexp.Compile(pat) + if err != nil { + return err + } + + nfo, err := db.Info() + if err != nil { + return err + } + + r := []string{} + for _, ti := range nfo.Tables { + if !re.MatchString(ti.Name) { + continue + } + + a := []string{} + for _, ci := range ti.Columns { + a = append(a, fmt.Sprintf("%s %s", ci.Name, ci.Type)) + } + r = append(r, fmt.Sprintf("CREATE TABLE %s (%s);", ti.Name, strings.Join(a, ", "))) + } + sort.Strings(r) + if len(r) != 0 { + fmt.Println(strings.Join(r, "\n")) + } + return nil + } + + if pat := *oTables; pat != "" { + re, err := regexp.Compile(pat) + if err != nil { + return err + } + + nfo, err := db.Info() + if err != nil { + return err + } + + r := []string{} + for _, ti := range nfo.Tables { + if !re.MatchString(ti.Name) { + continue + } + + r = append(r, ti.Name) + } + sort.Strings(r) + if len(r) != 0 { + fmt.Println(strings.Join(r, "\n")) + } + return nil + } + + var src string + switch n := flag.NArg(); n { + case 0: + b, err := ioutil.ReadAll(bufio.NewReader(os.Stdin)) + if err != nil { + return err + } + + src = string(b) + default: + a := make([]string, n) + for i := range a { + a[i] = flag.Arg(i) + } + src = strings.Join(a, " ") + } + + src = "BEGIN TRANSACTION; " + src + "; COMMIT;" + l, err := ql.Compile(src) + if err != nil { + log.Println(src) + return err + } + + rs, i, err := db.Execute(ql.NewRWCtx(), l) + if err != nil { + a := strings.Split(strings.TrimSpace(fmt.Sprint(l)), "\n") + return fmt.Errorf("%v: %s", err, a[i]) + } + + if len(rs) == 0 { + return + } + + switch { + case l.IsExplainStmt(): + return rs[len(rs)-1].Do(*oFlds, func(data []interface{}) (bool, error) { + fmt.Println(data[0]) + return true, nil + }) + default: + return rs[len(rs)-1].Do(*oFlds, func(data []interface{}) (bool, error) { + fmt.Println(str(data)) + return true, nil + }) + } +} diff --git a/vendor/github.com/cznic/ql/scanner.go b/vendor/github.com/cznic/ql/scanner.go new file mode 100644 index 00000000..aafa3cf8 --- /dev/null +++ b/vendor/github.com/cznic/ql/scanner.go @@ -0,0 +1,4129 @@ +// CAUTION: Generated file - DO NOT EDIT. + +/* +Copyright (c) 2014 The ql 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 ql + +import ( + "fmt" + "math" + "strconv" + "unicode" +) + +type lexer struct { + agg []bool + c int + col int + errs []error + expr expression + i int + inj int + lcol int + line int + list []stmt + ncol int + nline int + params int + sc int + src string + val []byte + root bool +} + +func newLexer(src string) (l *lexer) { + l = &lexer{ + src: src, + nline: 1, + ncol: 0, + } + l.next() + return +} + +func (l *lexer) next() int { + if l.c != 0 { + l.val = append(l.val, byte(l.c)) + } + l.c = 0 + if l.i < len(l.src) { + l.c = int(l.src[l.i]) + l.i++ + } + switch l.c { + case '\n': + l.lcol = l.ncol + l.nline++ + l.ncol = 0 + default: + l.ncol++ + } + return l.c +} + +func (l *lexer) err0(ln, c int, s string, arg ...interface{}) { + err := fmt.Errorf(fmt.Sprintf("%d:%d ", ln, c)+s, arg...) + l.errs = append(l.errs, err) +} + +func (l *lexer) err(s string, arg ...interface{}) { + l.err0(l.line, l.col, s, arg...) +} + +func (l *lexer) Error(s string) { + l.err(s) +} + +func (l *lexer) Lex(lval *yySymType) (r int) { + //defer func() { dbg("Lex -> %d(%#x)", r, r) }() + defer func() { + lval.line, lval.col = l.line, l.col + }() + const ( + INITIAL = iota + S1 + S2 + ) + + if n := l.inj; n != 0 { + l.inj = 0 + return n + } + + c0, c := 0, l.c + +yystate0: + + l.val = l.val[:0] + c0, l.line, l.col = l.c, l.nline, l.ncol + + switch yyt := l.sc; yyt { + default: + panic(fmt.Errorf(`invalid start condition %d`, yyt)) + case 0: // start condition: INITIAL + goto yystart1 + case 1: // start condition: S1 + goto yystart319 + case 2: // start condition: S2 + goto yystart324 + } + + goto yystate0 // silence unused label error + goto yystate1 // silence unused label error +yystate1: + c = l.next() +yystart1: + switch { + default: + goto yystate3 // c >= '\x01' && c <= '\b' || c == '\v' || c == '\f' || c >= '\x0e' && c <= '\x1f' || c == '#' || c == '%%' || c >= '(' && c <= ',' || c == ':' || c == ';' || c == '@' || c >= '[' && c <= '^' || c == '{' || c >= '}' && c <= 'ÿ' + case c == '!': + goto yystate6 + case c == '"': + goto yystate8 + case c == '$' || c == '?': + goto yystate9 + case c == '&': + goto yystate11 + case c == '-': + goto yystate19 + case c == '.': + goto yystate21 + case c == '/': + goto yystate27 + case c == '0': + goto yystate32 + case c == '<': + goto yystate40 + case c == '=': + goto yystate43 + case c == '>': + goto yystate45 + case c == 'A' || c == 'a': + goto yystate48 + case c == 'B' || c == 'b': + goto yystate60 + case c == 'C' || c == 'c': + goto yystate87 + case c == 'D' || c == 'd': + goto yystate111 + case c == 'E' || c == 'e': + goto yystate141 + case c == 'F' || c == 'f': + goto yystate152 + case c == 'G' || c == 'g': + goto yystate171 + case c == 'H' || c == 'K' || c == 'M' || c == 'P' || c == 'Q' || c >= 'X' && c <= 'Z' || c == '_' || c == 'h' || c == 'k' || c == 'm' || c == 'p' || c == 'q' || c >= 'x' && c <= 'z': + goto yystate176 + case c == 'I' || c == 'i': + goto yystate177 + case c == 'J' || c == 'j': + goto yystate197 + case c == 'L' || c == 'l': + goto yystate201 + case c == 'N' || c == 'n': + goto yystate211 + case c == 'O' || c == 'o': + goto yystate217 + case c == 'R' || c == 'r': + goto yystate232 + case c == 'S' || c == 's': + goto yystate247 + case c == 'T' || c == 't': + goto yystate259 + case c == 'U' || c == 'u': + goto yystate284 + case c == 'V' || c == 'v': + goto yystate305 + case c == 'W' || c == 'w': + goto yystate311 + case c == '\'': + goto yystate14 + case c == '\n': + goto yystate5 + case c == '\t' || c == '\r' || c == ' ': + goto yystate4 + case c == '\x00': + goto yystate2 + case c == '`': + goto yystate316 + case c == '|': + goto yystate317 + case c >= '1' && c <= '9': + goto yystate38 + } + +yystate2: + c = l.next() + goto yyrule1 + +yystate3: + c = l.next() + goto yyrule101 + +yystate4: + c = l.next() + switch { + default: + goto yyrule2 + case c == '\t' || c == '\n' || c == '\r' || c == ' ': + goto yystate5 + } + +yystate5: + c = l.next() + switch { + default: + goto yyrule2 + case c == '\t' || c == '\n' || c == '\r' || c == ' ': + goto yystate5 + } + +yystate6: + c = l.next() + switch { + default: + goto yyrule101 + case c == '=': + goto yystate7 + } + +yystate7: + c = l.next() + goto yyrule21 + +yystate8: + c = l.next() + goto yyrule10 + +yystate9: + c = l.next() + switch { + default: + goto yyrule101 + case c >= '0' && c <= '9': + goto yystate10 + } + +yystate10: + c = l.next() + switch { + default: + goto yyrule100 + case c >= '0' && c <= '9': + goto yystate10 + } + +yystate11: + c = l.next() + switch { + default: + goto yyrule101 + case c == '&': + goto yystate12 + case c == '^': + goto yystate13 + } + +yystate12: + c = l.next() + goto yyrule15 + +yystate13: + c = l.next() + goto yyrule16 + +yystate14: + c = l.next() + switch { + default: + goto yyrule101 + case c == '\'': + goto yystate16 + case c == '\\': + goto yystate17 + case c >= '\x01' && c <= '&' || c >= '(' && c <= '[' || c >= ']' && c <= 'ÿ': + goto yystate15 + } + +yystate15: + c = l.next() + switch { + default: + goto yyabort + case c == '\'': + goto yystate16 + case c == '\\': + goto yystate17 + case c >= '\x01' && c <= '&' || c >= '(' && c <= '[' || c >= ']' && c <= 'ÿ': + goto yystate15 + } + +yystate16: + c = l.next() + goto yyrule12 + +yystate17: + c = l.next() + switch { + default: + goto yyabort + case c == '\'': + goto yystate18 + case c == '\\': + goto yystate17 + case c >= '\x01' && c <= '&' || c >= '(' && c <= '[' || c >= ']' && c <= 'ÿ': + goto yystate15 + } + +yystate18: + c = l.next() + switch { + default: + goto yyrule12 + case c == '\'': + goto yystate16 + case c == '\\': + goto yystate17 + case c >= '\x01' && c <= '&' || c >= '(' && c <= '[' || c >= ']' && c <= 'ÿ': + goto yystate15 + } + +yystate19: + c = l.next() + switch { + default: + goto yyrule101 + case c == '-': + goto yystate20 + } + +yystate20: + c = l.next() + switch { + default: + goto yyrule3 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ': + goto yystate20 + } + +yystate21: + c = l.next() + switch { + default: + goto yyrule101 + case c >= '0' && c <= '9': + goto yystate22 + } + +yystate22: + c = l.next() + switch { + default: + goto yyrule9 + case c == 'E' || c == 'e': + goto yystate23 + case c == 'i': + goto yystate26 + case c >= '0' && c <= '9': + goto yystate22 + } + +yystate23: + c = l.next() + switch { + default: + goto yyabort + case c == '+' || c == '-': + goto yystate24 + case c >= '0' && c <= '9': + goto yystate25 + } + +yystate24: + c = l.next() + switch { + default: + goto yyabort + case c >= '0' && c <= '9': + goto yystate25 + } + +yystate25: + c = l.next() + switch { + default: + goto yyrule9 + case c == 'i': + goto yystate26 + case c >= '0' && c <= '9': + goto yystate25 + } + +yystate26: + c = l.next() + goto yyrule7 + +yystate27: + c = l.next() + switch { + default: + goto yyrule101 + case c == '*': + goto yystate28 + case c == '/': + goto yystate31 + } + +yystate28: + c = l.next() + switch { + default: + goto yyabort + case c == '*': + goto yystate29 + case c >= '\x01' && c <= ')' || c >= '+' && c <= 'ÿ': + goto yystate28 + } + +yystate29: + c = l.next() + switch { + default: + goto yyabort + case c == '*': + goto yystate29 + case c == '/': + goto yystate30 + case c >= '\x01' && c <= ')' || c >= '+' && c <= '.' || c >= '0' && c <= 'ÿ': + goto yystate28 + } + +yystate30: + c = l.next() + goto yyrule5 + +yystate31: + c = l.next() + switch { + default: + goto yyrule4 + case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ': + goto yystate31 + } + +yystate32: + c = l.next() + switch { + default: + goto yyrule8 + case c == '.': + goto yystate22 + case c == '8' || c == '9': + goto yystate34 + case c == 'E' || c == 'e': + goto yystate23 + case c == 'X' || c == 'x': + goto yystate36 + case c == 'i': + goto yystate35 + case c >= '0' && c <= '7': + goto yystate33 + } + +yystate33: + c = l.next() + switch { + default: + goto yyrule8 + case c == '.': + goto yystate22 + case c == '8' || c == '9': + goto yystate34 + case c == 'E' || c == 'e': + goto yystate23 + case c == 'i': + goto yystate35 + case c >= '0' && c <= '7': + goto yystate33 + } + +yystate34: + c = l.next() + switch { + default: + goto yyabort + case c == '.': + goto yystate22 + case c == 'E' || c == 'e': + goto yystate23 + case c == 'i': + goto yystate35 + case c >= '0' && c <= '9': + goto yystate34 + } + +yystate35: + c = l.next() + goto yyrule6 + +yystate36: + c = l.next() + switch { + default: + goto yyabort + case c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f': + goto yystate37 + } + +yystate37: + c = l.next() + switch { + default: + goto yyrule8 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f': + goto yystate37 + } + +yystate38: + c = l.next() + switch { + default: + goto yyrule8 + case c == '.': + goto yystate22 + case c == 'E' || c == 'e': + goto yystate23 + case c == 'i': + goto yystate35 + case c >= '0' && c <= '9': + goto yystate39 + } + +yystate39: + c = l.next() + switch { + default: + goto yyrule8 + case c == '.': + goto yystate22 + case c == 'E' || c == 'e': + goto yystate23 + case c == 'i': + goto yystate35 + case c >= '0' && c <= '9': + goto yystate39 + } + +yystate40: + c = l.next() + switch { + default: + goto yyrule101 + case c == '<': + goto yystate41 + case c == '=': + goto yystate42 + } + +yystate41: + c = l.next() + goto yyrule17 + +yystate42: + c = l.next() + goto yyrule18 + +yystate43: + c = l.next() + switch { + default: + goto yyrule101 + case c == '=': + goto yystate44 + } + +yystate44: + c = l.next() + goto yyrule19 + +yystate45: + c = l.next() + switch { + default: + goto yyrule101 + case c == '=': + goto yystate46 + case c == '>': + goto yystate47 + } + +yystate46: + c = l.next() + goto yyrule20 + +yystate47: + c = l.next() + goto yyrule23 + +yystate48: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'D' || c == 'd': + goto yystate50 + case c == 'L' || c == 'l': + goto yystate52 + case c == 'N' || c == 'n': + goto yystate56 + case c == 'S' || c == 's': + goto yystate58 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'C' || c >= 'E' && c <= 'K' || c == 'M' || c >= 'O' && c <= 'R' || c >= 'T' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'c' || c >= 'e' && c <= 'k' || c == 'm' || c >= 'o' && c <= 'r' || c >= 't' && c <= 'z': + goto yystate49 + } + +yystate49: + c = l.next() + switch { + default: + goto yyrule99 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate50: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'D' || c == 'd': + goto yystate51 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'C' || c >= 'E' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'c' || c >= 'e' && c <= 'z': + goto yystate49 + } + +yystate51: + c = l.next() + switch { + default: + goto yyrule24 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate52: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate53 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate53: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate54 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate54: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'R' || c == 'r': + goto yystate55 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + goto yystate49 + } + +yystate55: + c = l.next() + switch { + default: + goto yyrule25 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate56: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'D' || c == 'd': + goto yystate57 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'C' || c >= 'E' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'c' || c >= 'e' && c <= 'z': + goto yystate49 + } + +yystate57: + c = l.next() + switch { + default: + goto yyrule26 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate58: + c = l.next() + switch { + default: + goto yyrule28 + case c == 'C' || c == 'c': + goto yystate59 + case c >= '0' && c <= '9' || c == 'A' || c == 'B' || c >= 'D' && c <= 'Z' || c == '_' || c == 'a' || c == 'b' || c >= 'd' && c <= 'z': + goto yystate49 + } + +yystate59: + c = l.next() + switch { + default: + goto yyrule27 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate60: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate61 + case c == 'I' || c == 'i': + goto yystate70 + case c == 'L' || c == 'l': + goto yystate78 + case c == 'O' || c == 'o': + goto yystate81 + case c == 'Y' || c == 'y': + goto yystate84 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'H' || c == 'J' || c == 'K' || c == 'M' || c == 'N' || c >= 'P' && c <= 'X' || c == 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'h' || c == 'j' || c == 'k' || c == 'm' || c == 'n' || c >= 'p' && c <= 'x' || c == 'z': + goto yystate49 + } + +yystate61: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'G' || c == 'g': + goto yystate62 + case c == 'T' || c == 't': + goto yystate65 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'H' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'f' || c >= 'h' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate62: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'I' || c == 'i': + goto yystate63 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': + goto yystate49 + } + +yystate63: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'N' || c == 'n': + goto yystate64 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate49 + } + +yystate64: + c = l.next() + switch { + default: + goto yyrule29 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate65: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'W' || c == 'w': + goto yystate66 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'V' || c >= 'X' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'v' || c >= 'x' && c <= 'z': + goto yystate49 + } + +yystate66: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate67 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate67: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate68 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate68: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'N' || c == 'n': + goto yystate69 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate49 + } + +yystate69: + c = l.next() + switch { + default: + goto yyrule30 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate70: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'G' || c == 'g': + goto yystate71 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'H' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'f' || c >= 'h' && c <= 'z': + goto yystate49 + } + +yystate71: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'I' || c == 'i': + goto yystate72 + case c == 'R' || c == 'r': + goto yystate75 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'q' || c >= 's' && c <= 'z': + goto yystate49 + } + +yystate72: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'N' || c == 'n': + goto yystate73 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate49 + } + +yystate73: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate74 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate74: + c = l.next() + switch { + default: + goto yyrule75 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate75: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'A' || c == 'a': + goto yystate76 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + goto yystate49 + } + +yystate76: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate77 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate77: + c = l.next() + switch { + default: + goto yyrule76 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate78: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'O' || c == 'o': + goto yystate79 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'N' || c >= 'P' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': + goto yystate49 + } + +yystate79: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'B' || c == 'b': + goto yystate80 + case c >= '0' && c <= '9' || c == 'A' || c >= 'C' && c <= 'Z' || c == '_' || c == 'a' || c >= 'c' && c <= 'z': + goto yystate49 + } + +yystate80: + c = l.next() + switch { + default: + goto yyrule77 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate81: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'O' || c == 'o': + goto yystate82 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'N' || c >= 'P' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': + goto yystate49 + } + +yystate82: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'L' || c == 'l': + goto yystate83 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'K' || c >= 'M' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'm' && c <= 'z': + goto yystate49 + } + +yystate83: + c = l.next() + switch { + default: + goto yyrule78 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate84: + c = l.next() + switch { + default: + goto yyrule31 + case c == 'T' || c == 't': + goto yystate85 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate85: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate86 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate86: + c = l.next() + switch { + default: + goto yyrule79 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate87: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'O' || c == 'o': + goto yystate88 + case c == 'R' || c == 'r': + goto yystate106 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'N' || c == 'P' || c == 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c == 'p' || c == 'q' || c >= 's' && c <= 'z': + goto yystate49 + } + +yystate88: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'L' || c == 'l': + goto yystate89 + case c == 'M' || c == 'm': + goto yystate93 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'K' || c >= 'N' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'n' && c <= 'z': + goto yystate49 + } + +yystate89: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'U' || c == 'u': + goto yystate90 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'a' && c <= 't' || c >= 'v' && c <= 'z': + goto yystate49 + } + +yystate90: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'M' || c == 'm': + goto yystate91 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'L' || c >= 'N' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'l' || c >= 'n' && c <= 'z': + goto yystate49 + } + +yystate91: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'N' || c == 'n': + goto yystate92 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate49 + } + +yystate92: + c = l.next() + switch { + default: + goto yyrule32 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate93: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'M' || c == 'm': + goto yystate94 + case c == 'P' || c == 'p': + goto yystate97 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'L' || c == 'N' || c == 'O' || c >= 'Q' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'l' || c == 'n' || c == 'o' || c >= 'q' && c <= 'z': + goto yystate49 + } + +yystate94: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'I' || c == 'i': + goto yystate95 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': + goto yystate49 + } + +yystate95: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate96 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate96: + c = l.next() + switch { + default: + goto yyrule33 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate97: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'L' || c == 'l': + goto yystate98 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'K' || c >= 'M' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'm' && c <= 'z': + goto yystate49 + } + +yystate98: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate99 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate99: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'X' || c == 'x': + goto yystate100 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'W' || c == 'Y' || c == 'Z' || c == '_' || c >= 'a' && c <= 'w' || c == 'y' || c == 'z': + goto yystate49 + } + +yystate100: + c = l.next() + switch { + default: + goto yyrule99 + case c == '0' || c >= '2' && c <= '5' || c >= '7' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + case c == '1': + goto yystate101 + case c == '6': + goto yystate104 + } + +yystate101: + c = l.next() + switch { + default: + goto yyrule99 + case c == '0' || c == '1' || c >= '3' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + case c == '2': + goto yystate102 + } + +yystate102: + c = l.next() + switch { + default: + goto yyrule99 + case c == '8': + goto yystate103 + case c >= '0' && c <= '7' || c == '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate103: + c = l.next() + switch { + default: + goto yyrule80 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate104: + c = l.next() + switch { + default: + goto yyrule99 + case c == '4': + goto yystate105 + case c >= '0' && c <= '3' || c >= '5' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate105: + c = l.next() + switch { + default: + goto yyrule81 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate106: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate107 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate107: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'A' || c == 'a': + goto yystate108 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + goto yystate49 + } + +yystate108: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate109 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate109: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate110 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate110: + c = l.next() + switch { + default: + goto yyrule34 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate111: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate112 + case c == 'I' || c == 'i': + goto yystate124 + case c == 'R' || c == 'r': + goto yystate131 + case c == 'U' || c == 'u': + goto yystate134 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'H' || c >= 'J' && c <= 'Q' || c == 'S' || c == 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'h' || c >= 'j' && c <= 'q' || c == 's' || c == 't' || c >= 'v' && c <= 'z': + goto yystate49 + } + +yystate112: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'F' || c == 'f': + goto yystate113 + case c == 'L' || c == 'l': + goto yystate118 + case c == 'S' || c == 's': + goto yystate122 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'E' || c >= 'G' && c <= 'K' || c >= 'M' && c <= 'R' || c >= 'T' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'k' || c >= 'm' && c <= 'r' || c >= 't' && c <= 'z': + goto yystate49 + } + +yystate113: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'A' || c == 'a': + goto yystate114 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + goto yystate49 + } + +yystate114: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'U' || c == 'u': + goto yystate115 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'a' && c <= 't' || c >= 'v' && c <= 'z': + goto yystate49 + } + +yystate115: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'L' || c == 'l': + goto yystate116 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'K' || c >= 'M' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'm' && c <= 'z': + goto yystate49 + } + +yystate116: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate117 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate117: + c = l.next() + switch { + default: + goto yyrule35 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate118: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate119 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate119: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate120 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate120: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate121 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate121: + c = l.next() + switch { + default: + goto yyrule36 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate122: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'C' || c == 'c': + goto yystate123 + case c >= '0' && c <= '9' || c == 'A' || c == 'B' || c >= 'D' && c <= 'Z' || c == '_' || c == 'a' || c == 'b' || c >= 'd' && c <= 'z': + goto yystate49 + } + +yystate123: + c = l.next() + switch { + default: + goto yyrule37 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate124: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'S' || c == 's': + goto yystate125 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'R' || c >= 'T' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'r' || c >= 't' && c <= 'z': + goto yystate49 + } + +yystate125: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate126 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate126: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'I' || c == 'i': + goto yystate127 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': + goto yystate49 + } + +yystate127: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'N' || c == 'n': + goto yystate128 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate49 + } + +yystate128: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'C' || c == 'c': + goto yystate129 + case c >= '0' && c <= '9' || c == 'A' || c == 'B' || c >= 'D' && c <= 'Z' || c == '_' || c == 'a' || c == 'b' || c >= 'd' && c <= 'z': + goto yystate49 + } + +yystate129: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate130 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate130: + c = l.next() + switch { + default: + goto yyrule38 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate131: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'O' || c == 'o': + goto yystate132 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'N' || c >= 'P' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': + goto yystate49 + } + +yystate132: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'P' || c == 'p': + goto yystate133 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'O' || c >= 'Q' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'o' || c >= 'q' && c <= 'z': + goto yystate49 + } + +yystate133: + c = l.next() + switch { + default: + goto yyrule39 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate134: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'R' || c == 'r': + goto yystate135 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + goto yystate49 + } + +yystate135: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'A' || c == 'a': + goto yystate136 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + goto yystate49 + } + +yystate136: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate137 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate137: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'I' || c == 'i': + goto yystate138 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': + goto yystate49 + } + +yystate138: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'O' || c == 'o': + goto yystate139 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'N' || c >= 'P' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': + goto yystate49 + } + +yystate139: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'N' || c == 'n': + goto yystate140 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate49 + } + +yystate140: + c = l.next() + switch { + default: + goto yyrule82 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate141: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'X' || c == 'x': + goto yystate142 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'W' || c == 'Y' || c == 'Z' || c == '_' || c >= 'a' && c <= 'w' || c == 'y' || c == 'z': + goto yystate49 + } + +yystate142: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'I' || c == 'i': + goto yystate143 + case c == 'P' || c == 'p': + goto yystate147 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'O' || c >= 'Q' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'o' || c >= 'q' && c <= 'z': + goto yystate49 + } + +yystate143: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'S' || c == 's': + goto yystate144 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'R' || c >= 'T' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'r' || c >= 't' && c <= 'z': + goto yystate49 + } + +yystate144: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate145 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate145: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'S' || c == 's': + goto yystate146 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'R' || c >= 'T' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'r' || c >= 't' && c <= 'z': + goto yystate49 + } + +yystate146: + c = l.next() + switch { + default: + goto yyrule40 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate147: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'L' || c == 'l': + goto yystate148 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'K' || c >= 'M' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'm' && c <= 'z': + goto yystate49 + } + +yystate148: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'A' || c == 'a': + goto yystate149 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + goto yystate49 + } + +yystate149: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'I' || c == 'i': + goto yystate150 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': + goto yystate49 + } + +yystate150: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'N' || c == 'n': + goto yystate151 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate49 + } + +yystate151: + c = l.next() + switch { + default: + goto yyrule41 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate152: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'A' || c == 'a': + goto yystate153 + case c == 'L' || c == 'l': + goto yystate157 + case c == 'R' || c == 'r': + goto yystate165 + case c == 'U' || c == 'u': + goto yystate168 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'K' || c >= 'M' && c <= 'Q' || c == 'S' || c == 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'k' || c >= 'm' && c <= 'q' || c == 's' || c == 't' || c >= 'v' && c <= 'z': + goto yystate49 + } + +yystate153: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'L' || c == 'l': + goto yystate154 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'K' || c >= 'M' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'm' && c <= 'z': + goto yystate49 + } + +yystate154: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'S' || c == 's': + goto yystate155 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'R' || c >= 'T' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'r' || c >= 't' && c <= 'z': + goto yystate49 + } + +yystate155: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate156 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate156: + c = l.next() + switch { + default: + goto yyrule73 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate157: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'O' || c == 'o': + goto yystate158 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'N' || c >= 'P' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': + goto yystate49 + } + +yystate158: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'A' || c == 'a': + goto yystate159 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + goto yystate49 + } + +yystate159: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate160 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate160: + c = l.next() + switch { + default: + goto yyrule83 + case c == '3': + goto yystate161 + case c == '6': + goto yystate163 + case c >= '0' && c <= '2' || c == '4' || c == '5' || c >= '7' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate161: + c = l.next() + switch { + default: + goto yyrule99 + case c == '0' || c == '1' || c >= '3' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + case c == '2': + goto yystate162 + } + +yystate162: + c = l.next() + switch { + default: + goto yyrule84 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate163: + c = l.next() + switch { + default: + goto yyrule99 + case c == '4': + goto yystate164 + case c >= '0' && c <= '3' || c >= '5' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate164: + c = l.next() + switch { + default: + goto yyrule85 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate165: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'O' || c == 'o': + goto yystate166 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'N' || c >= 'P' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': + goto yystate49 + } + +yystate166: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'M' || c == 'm': + goto yystate167 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'L' || c >= 'N' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'l' || c >= 'n' && c <= 'z': + goto yystate49 + } + +yystate167: + c = l.next() + switch { + default: + goto yyrule42 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate168: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'L' || c == 'l': + goto yystate169 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'K' || c >= 'M' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'm' && c <= 'z': + goto yystate49 + } + +yystate169: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'L' || c == 'l': + goto yystate170 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'K' || c >= 'M' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'm' && c <= 'z': + goto yystate49 + } + +yystate170: + c = l.next() + switch { + default: + goto yyrule43 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate171: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'R' || c == 'r': + goto yystate172 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + goto yystate49 + } + +yystate172: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'O' || c == 'o': + goto yystate173 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'N' || c >= 'P' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': + goto yystate49 + } + +yystate173: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'U' || c == 'u': + goto yystate174 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'a' && c <= 't' || c >= 'v' && c <= 'z': + goto yystate49 + } + +yystate174: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'P' || c == 'p': + goto yystate175 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'O' || c >= 'Q' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'o' || c >= 'q' && c <= 'z': + goto yystate49 + } + +yystate175: + c = l.next() + switch { + default: + goto yyrule44 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate176: + c = l.next() + switch { + default: + goto yyrule99 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate177: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'F' || c == 'f': + goto yystate178 + case c == 'N' || c == 'n': + goto yystate179 + case c == 'S' || c == 's': + goto yystate196 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'E' || c >= 'G' && c <= 'M' || c >= 'O' && c <= 'R' || c >= 'T' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'm' || c >= 'o' && c <= 'r' || c >= 't' && c <= 'z': + goto yystate49 + } + +yystate178: + c = l.next() + switch { + default: + goto yyrule45 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate179: + c = l.next() + switch { + default: + goto yyrule49 + case c == 'D' || c == 'd': + goto yystate180 + case c == 'S' || c == 's': + goto yystate183 + case c == 'T' || c == 't': + goto yystate187 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'C' || c >= 'E' && c <= 'R' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'c' || c >= 'e' && c <= 'r' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate180: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate181 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate181: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'X' || c == 'x': + goto yystate182 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'W' || c == 'Y' || c == 'Z' || c == '_' || c >= 'a' && c <= 'w' || c == 'y' || c == 'z': + goto yystate49 + } + +yystate182: + c = l.next() + switch { + default: + goto yyrule46 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate183: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate184 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate184: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'R' || c == 'r': + goto yystate185 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + goto yystate49 + } + +yystate185: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate186 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate186: + c = l.next() + switch { + default: + goto yyrule47 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate187: + c = l.next() + switch { + default: + goto yyrule86 + case c == '0' || c == '2' || c == '4' || c == '5' || c == '7' || c == '9' || c >= 'A' && c <= 'N' || c >= 'P' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': + goto yystate49 + case c == '1': + goto yystate188 + case c == '3': + goto yystate190 + case c == '6': + goto yystate192 + case c == '8': + goto yystate194 + case c == 'O' || c == 'o': + goto yystate195 + } + +yystate188: + c = l.next() + switch { + default: + goto yyrule99 + case c == '6': + goto yystate189 + case c >= '0' && c <= '5' || c >= '7' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate189: + c = l.next() + switch { + default: + goto yyrule87 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate190: + c = l.next() + switch { + default: + goto yyrule99 + case c == '0' || c == '1' || c >= '3' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + case c == '2': + goto yystate191 + } + +yystate191: + c = l.next() + switch { + default: + goto yyrule88 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate192: + c = l.next() + switch { + default: + goto yyrule99 + case c == '4': + goto yystate193 + case c >= '0' && c <= '3' || c >= '5' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate193: + c = l.next() + switch { + default: + goto yyrule89 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate194: + c = l.next() + switch { + default: + goto yyrule90 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate195: + c = l.next() + switch { + default: + goto yyrule48 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate196: + c = l.next() + switch { + default: + goto yyrule50 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate197: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'O' || c == 'o': + goto yystate198 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'N' || c >= 'P' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': + goto yystate49 + } + +yystate198: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'I' || c == 'i': + goto yystate199 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': + goto yystate49 + } + +yystate199: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'N' || c == 'n': + goto yystate200 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate49 + } + +yystate200: + c = l.next() + switch { + default: + goto yyrule51 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate201: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate202 + case c == 'I' || c == 'i': + goto yystate205 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'h' || c >= 'j' && c <= 'z': + goto yystate49 + } + +yystate202: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'F' || c == 'f': + goto yystate203 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'E' || c >= 'G' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'z': + goto yystate49 + } + +yystate203: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate204 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate204: + c = l.next() + switch { + default: + goto yyrule52 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate205: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'K' || c == 'k': + goto yystate206 + case c == 'M' || c == 'm': + goto yystate208 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'J' || c == 'L' || c >= 'N' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'j' || c == 'l' || c >= 'n' && c <= 'z': + goto yystate49 + } + +yystate206: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate207 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate207: + c = l.next() + switch { + default: + goto yyrule53 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate208: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'I' || c == 'i': + goto yystate209 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': + goto yystate49 + } + +yystate209: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate210 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate210: + c = l.next() + switch { + default: + goto yyrule54 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate211: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'O' || c == 'o': + goto yystate212 + case c == 'U' || c == 'u': + goto yystate214 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'N' || c >= 'P' && c <= 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 't' || c >= 'v' && c <= 'z': + goto yystate49 + } + +yystate212: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate213 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate213: + c = l.next() + switch { + default: + goto yyrule55 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate214: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'L' || c == 'l': + goto yystate215 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'K' || c >= 'M' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'm' && c <= 'z': + goto yystate49 + } + +yystate215: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'L' || c == 'l': + goto yystate216 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'K' || c >= 'M' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'm' && c <= 'z': + goto yystate49 + } + +yystate216: + c = l.next() + switch { + default: + goto yyrule72 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate217: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'F' || c == 'f': + goto yystate218 + case c == 'N' || c == 'n': + goto yystate223 + case c == 'R' || c == 'r': + goto yystate224 + case c == 'U' || c == 'u': + goto yystate228 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'E' || c >= 'G' && c <= 'M' || c >= 'O' && c <= 'Q' || c == 'S' || c == 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'm' || c >= 'o' && c <= 'q' || c == 's' || c == 't' || c >= 'v' && c <= 'z': + goto yystate49 + } + +yystate218: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'F' || c == 'f': + goto yystate219 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'E' || c >= 'G' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'z': + goto yystate49 + } + +yystate219: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'S' || c == 's': + goto yystate220 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'R' || c >= 'T' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'r' || c >= 't' && c <= 'z': + goto yystate49 + } + +yystate220: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate221 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate221: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate222 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate222: + c = l.next() + switch { + default: + goto yyrule56 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate223: + c = l.next() + switch { + default: + goto yyrule57 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate224: + c = l.next() + switch { + default: + goto yyrule59 + case c == 'D' || c == 'd': + goto yystate225 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'C' || c >= 'E' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'c' || c >= 'e' && c <= 'z': + goto yystate49 + } + +yystate225: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate226 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate226: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'R' || c == 'r': + goto yystate227 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + goto yystate49 + } + +yystate227: + c = l.next() + switch { + default: + goto yyrule58 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate228: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate229 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate229: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate230 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate230: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'R' || c == 'r': + goto yystate231 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + goto yystate49 + } + +yystate231: + c = l.next() + switch { + default: + goto yyrule60 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate232: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'I' || c == 'i': + goto yystate233 + case c == 'O' || c == 'o': + goto yystate237 + case c == 'U' || c == 'u': + goto yystate244 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'N' || c >= 'P' && c <= 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'n' || c >= 'p' && c <= 't' || c >= 'v' && c <= 'z': + goto yystate49 + } + +yystate233: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'G' || c == 'g': + goto yystate234 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'H' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'f' || c >= 'h' && c <= 'z': + goto yystate49 + } + +yystate234: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'H' || c == 'h': + goto yystate235 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'G' || c >= 'I' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'g' || c >= 'i' && c <= 'z': + goto yystate49 + } + +yystate235: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate236 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate236: + c = l.next() + switch { + default: + goto yyrule61 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate237: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'L' || c == 'l': + goto yystate238 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'K' || c >= 'M' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'm' && c <= 'z': + goto yystate49 + } + +yystate238: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'L' || c == 'l': + goto yystate239 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'K' || c >= 'M' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'm' && c <= 'z': + goto yystate49 + } + +yystate239: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'B' || c == 'b': + goto yystate240 + case c >= '0' && c <= '9' || c == 'A' || c >= 'C' && c <= 'Z' || c == '_' || c == 'a' || c >= 'c' && c <= 'z': + goto yystate49 + } + +yystate240: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'A' || c == 'a': + goto yystate241 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + goto yystate49 + } + +yystate241: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'C' || c == 'c': + goto yystate242 + case c >= '0' && c <= '9' || c == 'A' || c == 'B' || c >= 'D' && c <= 'Z' || c == '_' || c == 'a' || c == 'b' || c >= 'd' && c <= 'z': + goto yystate49 + } + +yystate242: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'K' || c == 'k': + goto yystate243 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'J' || c >= 'L' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'j' || c >= 'l' && c <= 'z': + goto yystate49 + } + +yystate243: + c = l.next() + switch { + default: + goto yyrule62 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate244: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'N' || c == 'n': + goto yystate245 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate49 + } + +yystate245: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate246 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate246: + c = l.next() + switch { + default: + goto yyrule91 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate247: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate248 + case c == 'T' || c == 't': + goto yystate254 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate248: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'L' || c == 'l': + goto yystate249 + case c == 'T' || c == 't': + goto yystate253 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'K' || c >= 'M' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'm' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate249: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate250 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate250: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'C' || c == 'c': + goto yystate251 + case c >= '0' && c <= '9' || c == 'A' || c == 'B' || c >= 'D' && c <= 'Z' || c == '_' || c == 'a' || c == 'b' || c >= 'd' && c <= 'z': + goto yystate49 + } + +yystate251: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate252 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate252: + c = l.next() + switch { + default: + goto yyrule63 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate253: + c = l.next() + switch { + default: + goto yyrule64 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate254: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'R' || c == 'r': + goto yystate255 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + goto yystate49 + } + +yystate255: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'I' || c == 'i': + goto yystate256 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': + goto yystate49 + } + +yystate256: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'N' || c == 'n': + goto yystate257 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate49 + } + +yystate257: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'G' || c == 'g': + goto yystate258 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'H' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'f' || c >= 'h' && c <= 'z': + goto yystate49 + } + +yystate258: + c = l.next() + switch { + default: + goto yyrule92 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate259: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'A' || c == 'a': + goto yystate260 + case c == 'I' || c == 'i': + goto yystate264 + case c == 'R' || c == 'r': + goto yystate267 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'H' || c >= 'J' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'h' || c >= 'j' && c <= 'q' || c >= 's' && c <= 'z': + goto yystate49 + } + +yystate260: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'B' || c == 'b': + goto yystate261 + case c >= '0' && c <= '9' || c == 'A' || c >= 'C' && c <= 'Z' || c == '_' || c == 'a' || c >= 'c' && c <= 'z': + goto yystate49 + } + +yystate261: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'L' || c == 'l': + goto yystate262 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'K' || c >= 'M' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'm' && c <= 'z': + goto yystate49 + } + +yystate262: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate263 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate263: + c = l.next() + switch { + default: + goto yyrule65 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate264: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'M' || c == 'm': + goto yystate265 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'L' || c >= 'N' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'l' || c >= 'n' && c <= 'z': + goto yystate49 + } + +yystate265: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate266 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate266: + c = l.next() + switch { + default: + goto yyrule93 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate267: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'A' || c == 'a': + goto yystate268 + case c == 'U' || c == 'u': + goto yystate277 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'b' && c <= 't' || c >= 'v' && c <= 'z': + goto yystate49 + } + +yystate268: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'N' || c == 'n': + goto yystate269 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate49 + } + +yystate269: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'S' || c == 's': + goto yystate270 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'R' || c >= 'T' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'r' || c >= 't' && c <= 'z': + goto yystate49 + } + +yystate270: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'A' || c == 'a': + goto yystate271 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + goto yystate49 + } + +yystate271: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'C' || c == 'c': + goto yystate272 + case c >= '0' && c <= '9' || c == 'A' || c == 'B' || c >= 'D' && c <= 'Z' || c == '_' || c == 'a' || c == 'b' || c >= 'd' && c <= 'z': + goto yystate49 + } + +yystate272: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate273 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate273: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'I' || c == 'i': + goto yystate274 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': + goto yystate49 + } + +yystate274: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'O' || c == 'o': + goto yystate275 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'N' || c >= 'P' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': + goto yystate49 + } + +yystate275: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'N' || c == 'n': + goto yystate276 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate49 + } + +yystate276: + c = l.next() + switch { + default: + goto yyrule66 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate277: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate278 + case c == 'N' || c == 'n': + goto yystate279 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate49 + } + +yystate278: + c = l.next() + switch { + default: + goto yyrule74 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate279: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'C' || c == 'c': + goto yystate280 + case c >= '0' && c <= '9' || c == 'A' || c == 'B' || c >= 'D' && c <= 'Z' || c == '_' || c == 'a' || c == 'b' || c >= 'd' && c <= 'z': + goto yystate49 + } + +yystate280: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'A' || c == 'a': + goto yystate281 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + goto yystate49 + } + +yystate281: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate282 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate282: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate283 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate283: + c = l.next() + switch { + default: + goto yyrule67 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate284: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'I' || c == 'i': + goto yystate285 + case c == 'N' || c == 'n': + goto yystate295 + case c == 'P' || c == 'p': + goto yystate300 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'M' || c == 'O' || c >= 'Q' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'm' || c == 'o' || c >= 'q' && c <= 'z': + goto yystate49 + } + +yystate285: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'N' || c == 'n': + goto yystate286 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': + goto yystate49 + } + +yystate286: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate287 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate287: + c = l.next() + switch { + default: + goto yyrule94 + case c == '0' || c == '2' || c == '4' || c == '5' || c == '7' || c == '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + case c == '1': + goto yystate288 + case c == '3': + goto yystate290 + case c == '6': + goto yystate292 + case c == '8': + goto yystate294 + } + +yystate288: + c = l.next() + switch { + default: + goto yyrule99 + case c == '6': + goto yystate289 + case c >= '0' && c <= '5' || c >= '7' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate289: + c = l.next() + switch { + default: + goto yyrule95 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate290: + c = l.next() + switch { + default: + goto yyrule99 + case c == '0' || c == '1' || c >= '3' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + case c == '2': + goto yystate291 + } + +yystate291: + c = l.next() + switch { + default: + goto yyrule96 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate292: + c = l.next() + switch { + default: + goto yyrule99 + case c == '4': + goto yystate293 + case c >= '0' && c <= '3' || c >= '5' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate293: + c = l.next() + switch { + default: + goto yyrule97 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate294: + c = l.next() + switch { + default: + goto yyrule98 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate295: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'I' || c == 'i': + goto yystate296 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': + goto yystate49 + } + +yystate296: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'Q' || c == 'q': + goto yystate297 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'P' || c >= 'R' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'p' || c >= 'r' && c <= 'z': + goto yystate49 + } + +yystate297: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'U' || c == 'u': + goto yystate298 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'a' && c <= 't' || c >= 'v' && c <= 'z': + goto yystate49 + } + +yystate298: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate299 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate299: + c = l.next() + switch { + default: + goto yyrule69 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate300: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'D' || c == 'd': + goto yystate301 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'C' || c >= 'E' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'c' || c >= 'e' && c <= 'z': + goto yystate49 + } + +yystate301: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'A' || c == 'a': + goto yystate302 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + goto yystate49 + } + +yystate302: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'T' || c == 't': + goto yystate303 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': + goto yystate49 + } + +yystate303: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate304 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate304: + c = l.next() + switch { + default: + goto yyrule68 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate305: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'A' || c == 'a': + goto yystate306 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + goto yystate49 + } + +yystate306: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'L' || c == 'l': + goto yystate307 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'K' || c >= 'M' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'm' && c <= 'z': + goto yystate49 + } + +yystate307: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'U' || c == 'u': + goto yystate308 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'a' && c <= 't' || c >= 'v' && c <= 'z': + goto yystate49 + } + +yystate308: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate309 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate309: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'S' || c == 's': + goto yystate310 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'R' || c >= 'T' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'r' || c >= 't' && c <= 'z': + goto yystate49 + } + +yystate310: + c = l.next() + switch { + default: + goto yyrule70 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate311: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'H' || c == 'h': + goto yystate312 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'G' || c >= 'I' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'g' || c >= 'i' && c <= 'z': + goto yystate49 + } + +yystate312: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate313 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate313: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'R' || c == 'r': + goto yystate314 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + goto yystate49 + } + +yystate314: + c = l.next() + switch { + default: + goto yyrule99 + case c == 'E' || c == 'e': + goto yystate315 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate49 + } + +yystate315: + c = l.next() + switch { + default: + goto yyrule71 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate49 + } + +yystate316: + c = l.next() + goto yyrule11 + +yystate317: + c = l.next() + switch { + default: + goto yyrule101 + case c == '|': + goto yystate318 + } + +yystate318: + c = l.next() + goto yyrule22 + + goto yystate319 // silence unused label error +yystate319: + c = l.next() +yystart319: + switch { + default: + goto yystate320 // c >= '\x01' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ' + case c == '"': + goto yystate321 + case c == '\\': + goto yystate322 + case c == '\x00': + goto yystate2 + } + +yystate320: + c = l.next() + switch { + default: + goto yyabort + case c == '"': + goto yystate321 + case c == '\\': + goto yystate322 + case c >= '\x01' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ': + goto yystate320 + } + +yystate321: + c = l.next() + goto yyrule13 + +yystate322: + c = l.next() + switch { + default: + goto yyabort + case c == '"': + goto yystate323 + case c == '\\': + goto yystate322 + case c >= '\x01' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ': + goto yystate320 + } + +yystate323: + c = l.next() + switch { + default: + goto yyrule13 + case c == '"': + goto yystate321 + case c == '\\': + goto yystate322 + case c >= '\x01' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ': + goto yystate320 + } + + goto yystate324 // silence unused label error +yystate324: + c = l.next() +yystart324: + switch { + default: + goto yystate325 // c >= '\x01' && c <= '_' || c >= 'a' && c <= 'ÿ' + case c == '\x00': + goto yystate2 + case c == '`': + goto yystate326 + } + +yystate325: + c = l.next() + switch { + default: + goto yyabort + case c == '`': + goto yystate326 + case c >= '\x01' && c <= '_' || c >= 'a' && c <= 'ÿ': + goto yystate325 + } + +yystate326: + c = l.next() + goto yyrule14 + +yyrule1: // \0 + { + return 0 + } +yyrule2: // [ \t\n\r]+ + + goto yystate0 +yyrule3: // --.* + + goto yystate0 +yyrule4: // \/\/.* + + goto yystate0 +yyrule5: // \/\*([^*]|\*+[^*/])*\*+\/ + + goto yystate0 +yyrule6: // {imaginary_ilit} + { + return l.int(lval, true) + } +yyrule7: // {imaginary_lit} + { + return l.float(lval, true) + } +yyrule8: // {int_lit} + { + return l.int(lval, false) + } +yyrule9: // {float_lit} + { + return l.float(lval, false) + } +yyrule10: // \" + { + l.sc = S1 + goto yystate0 + } +yyrule11: // ` + { + l.sc = S2 + goto yystate0 + } +yyrule12: // '(\\.|[^'])*' + { + if ret := l.str(lval, ""); ret != stringLit { + return ret + } + lval.item = idealRune(lval.item.(string)[0]) + return intLit + } +yyrule13: // (\\.|[^\"])*\" + { + return l.str(lval, "\"") + } +yyrule14: // ([^`]|\n)*` + { + return l.str(lval, "`") + } +yyrule15: // "&&" + { + return andand + } +yyrule16: // "&^" + { + return andnot + } +yyrule17: // "<<" + { + return lsh + } +yyrule18: // "<=" + { + return le + } +yyrule19: // "==" + { + return eq + } +yyrule20: // ">=" + { + return ge + } +yyrule21: // "!=" + { + return neq + } +yyrule22: // "||" + { + return oror + } +yyrule23: // ">>" + { + return rsh + } +yyrule24: // {add} + { + return add + } +yyrule25: // {alter} + { + return alter + } +yyrule26: // {and} + { + return and + } +yyrule27: // {asc} + { + return asc + } +yyrule28: // {as} + { + return as + } +yyrule29: // {begin} + { + return begin + } +yyrule30: // {between} + { + return between + } +yyrule31: // {by} + { + return by + } +yyrule32: // {column} + { + return column + } +yyrule33: // {commit} + { + return commit + } +yyrule34: // {create} + { + return create + } +yyrule35: // {default} + { + return defaultKwd + } +yyrule36: // {delete} + { + return deleteKwd + } +yyrule37: // {desc} + { + return desc + } +yyrule38: // {distinct} + { + return distinct + } +yyrule39: // {drop} + { + return drop + } +yyrule40: // {exists} + { + return exists + } +yyrule41: // {explain} + { + return explain + } +yyrule42: // {from} + { + return from + } +yyrule43: // {full} + { + return full + } +yyrule44: // {group} + { + return group + } +yyrule45: // {if} + { + return ifKwd + } +yyrule46: // {index} + { + return index + } +yyrule47: // {insert} + { + return insert + } +yyrule48: // {into} + { + return into + } +yyrule49: // {in} + { + return in + } +yyrule50: // {is} + { + return is + } +yyrule51: // {join} + { + return join + } +yyrule52: // {left} + { + return left + } +yyrule53: // {like} + { + return like + } +yyrule54: // {limit} + { + return limit + } +yyrule55: // {not} + { + return not + } +yyrule56: // {offset} + { + return offset + } +yyrule57: // {on} + { + return on + } +yyrule58: // {order} + { + return order + } +yyrule59: // {or} + { + return or + } +yyrule60: // {outer} + { + return outer + } +yyrule61: // {right} + { + return right + } +yyrule62: // {rollback} + { + return rollback + } +yyrule63: // {select} + { + l.agg = append(l.agg, false) + return selectKwd + } +yyrule64: // {set} + { + return set + } +yyrule65: // {table} + { + return tableKwd + } +yyrule66: // {transaction} + { + return transaction + } +yyrule67: // {truncate} + { + return truncate + } +yyrule68: // {update} + { + return update + } +yyrule69: // {unique} + { + return unique + } +yyrule70: // {values} + { + return values + } +yyrule71: // {where} + { + return where + } +yyrule72: // {null} + { + lval.item = nil + return null + } +yyrule73: // {false} + { + lval.item = false + return falseKwd + } +yyrule74: // {true} + { + lval.item = true + return trueKwd + } +yyrule75: // {bigint} + { + lval.item = qBigInt + return bigIntType + } +yyrule76: // {bigrat} + { + lval.item = qBigRat + return bigRatType + } +yyrule77: // {blob} + { + lval.item = qBlob + return blobType + } +yyrule78: // {bool} + { + lval.item = qBool + return boolType + } +yyrule79: // {byte} + { + lval.item = qUint8 + return byteType + } +yyrule80: // {complex}128 + { + lval.item = qComplex128 + return complex128Type + } +yyrule81: // {complex}64 + { + lval.item = qComplex64 + return complex64Type + } +yyrule82: // {duration} + { + lval.item = qDuration + return durationType + } +yyrule83: // {float} + { + lval.item = qFloat64 + return floatType + } +yyrule84: // {float}32 + { + lval.item = qFloat32 + return float32Type + } +yyrule85: // {float}64 + { + lval.item = qFloat64 + return float64Type + } +yyrule86: // {int} + { + lval.item = qInt64 + return intType + } +yyrule87: // {int}16 + { + lval.item = qInt16 + return int16Type + } +yyrule88: // {int}32 + { + lval.item = qInt32 + return int32Type + } +yyrule89: // {int}64 + { + lval.item = qInt64 + return int64Type + } +yyrule90: // {int}8 + { + lval.item = qInt8 + return int8Type + } +yyrule91: // {rune} + { + lval.item = qInt32 + return runeType + } +yyrule92: // {string} + { + lval.item = qString + return stringType + } +yyrule93: // {time} + { + lval.item = qTime + return timeType + } +yyrule94: // {uint} + { + lval.item = qUint64 + return uintType + } +yyrule95: // {uint}16 + { + lval.item = qUint16 + return uint16Type + } +yyrule96: // {uint}32 + { + lval.item = qUint32 + return uint32Type + } +yyrule97: // {uint}64 + { + lval.item = qUint64 + return uint64Type + } +yyrule98: // {uint}8 + { + lval.item = qUint8 + return uint8Type + } +yyrule99: // {ident} + { + lval.item = string(l.val) + return identifier + } +yyrule100: // ($|\?){D} + { + lval.item, _ = strconv.Atoi(string(l.val[1:])) + return qlParam + } +yyrule101: // . + { + return c0 + } + panic("unreachable") + + goto yyabort // silence unused label error + +yyabort: // no lexem recognized + return int(unicode.ReplacementChar) +} + +func (l *lexer) npos() (line, col int) { + if line, col = l.nline, l.ncol; col == 0 { + line-- + col = l.lcol + 1 + } + return +} + +func (l *lexer) str(lval *yySymType, pref string) int { + l.sc = 0 + s := pref + string(l.val) + s, err := strconv.Unquote(s) + if err != nil { + l.err("string literal: %v", err) + return int(unicode.ReplacementChar) + } + + lval.item = s + return stringLit +} + +func (l *lexer) int(lval *yySymType, im bool) int { + if im { + l.val = l.val[:len(l.val)-1] + } + n, err := strconv.ParseUint(string(l.val), 0, 64) + if err != nil { + l.err("integer literal: %v", err) + return int(unicode.ReplacementChar) + } + + if im { + lval.item = idealComplex(complex(0, float64(n))) + return imaginaryLit + } + + switch { + case n < math.MaxInt64: + lval.item = idealInt(n) + default: + lval.item = idealUint(n) + } + return intLit +} + +func (l *lexer) float(lval *yySymType, im bool) int { + if im { + l.val = l.val[:len(l.val)-1] + } + n, err := strconv.ParseFloat(string(l.val), 64) + if err != nil { + l.err("float literal: %v", err) + return int(unicode.ReplacementChar) + } + + if im { + lval.item = idealComplex(complex(0, n)) + return imaginaryLit + } + + lval.item = idealFloat(n) + return floatLit +} diff --git a/vendor/github.com/cznic/ql/stmt.go b/vendor/github.com/cznic/ql/stmt.go new file mode 100644 index 00000000..8de367d4 --- /dev/null +++ b/vendor/github.com/cznic/ql/stmt.go @@ -0,0 +1,1268 @@ +// Copyright (c) 2014 ql 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 ql + +import ( + "bytes" + "fmt" + "strings" + "sync" + + "github.com/cznic/strutil" +) + +// NOTE: all stmt implementations must be safe for concurrent use by multiple +// goroutines. If the exec method requires any execution domain local data, +// they must be held out of the implementing instance. +var ( + _ stmt = (*alterTableAddStmt)(nil) + _ stmt = (*alterTableDropColumnStmt)(nil) + _ stmt = (*createIndexStmt)(nil) + _ stmt = (*createTableStmt)(nil) + _ stmt = (*deleteStmt)(nil) //TODO optimizer plan + _ stmt = (*dropIndexStmt)(nil) + _ stmt = (*dropTableStmt)(nil) + _ stmt = (*explainStmt)(nil) + _ stmt = (*insertIntoStmt)(nil) + _ stmt = (*selectStmt)(nil) + _ stmt = (*truncateTableStmt)(nil) + _ stmt = (*updateStmt)(nil) //TODO optimizer plan + _ stmt = beginTransactionStmt{} + _ stmt = commitStmt{} + _ stmt = rollbackStmt{} +) + +var ( + createColumn2 = mustCompile(` + create table if not exists __Column2 ( + TableName string, + Name string, + NotNull bool, + ConstraintExpr string, + DefaultExpr string, + ); + create index if not exists __Column2TableName on __Column2(TableName); + `) + + insertColumn2 = mustCompile(`insert into __Column2 values($1, $2, $3, $4, $5)`) + + selectColumn2 = MustCompile(` + select Name, NotNull, ConstraintExpr, DefaultExpr + from __Column2 + where TableName == $1 + `) + + deleteColumn2 = mustCompile(` + delete from __Column2 + where TableName == $1 && Name == $2 + `) + + createIndex2 = mustCompile(` + // Index register 2. + create table if not exists __Index2( + TableName string, + IndexName string, + IsUnique bool, + IsSimple bool, // Just a column name or id(). + Root int64, // BTree handle + ); + + // Expressions for given index. Compared in order of id(__Index2_Expr). + create table if not exists __Index2_Expr( + Index2_ID int, + Expr string, + ); + + create index if not exists __xIndex2_TableName on __Index2(TableName); + create unique index if not exists __xIndex2_IndexName on __Index2(IndexName); + create index if not exists __xIndex2_ID on __Index2(id()); + create index if not exists __xIndex2_Expr_Index2_ID on __Index2_Expr(Index2_ID); +`) + + insertIndex2 = mustCompile("insert into __Index2 values($1, $2, $3, $4, $5)") + insertIndex2Expr = mustCompile("insert into __Index2_Expr values($1, $2)") + + deleteIndex2ByIndexName = mustCompile(` + delete from __Index2_Expr + where Index2_ID in ( + select id() from __Index2 where IndexName == $1; + ); + + delete from __Index2 + where IndexName == $1; +`) + deleteIndex2ByTableName = mustCompile(` + delete from __Index2_Expr + where Index2_ID in ( + select id() from __Index2 where TableName == $1; + ); + + delete from __Index2 + where TableName == $1; +`) +) + +type stmt interface { + // never invoked for + // - beginTransactionStmt + // - commitStmt + // - rollbackStmt + exec(ctx *execCtx) (Recordset, error) + + explain(ctx *execCtx, w strutil.Formatter) + + // return value ignored for + // - beginTransactionStmt + // - commitStmt + // - rollbackStmt + isUpdating() bool + String() string +} + +type execCtx struct { //LATER +shared temp + db *DB + arg []interface{} +} + +type explainStmt struct { + s stmt +} + +func (s *explainStmt) explain(ctx *execCtx, w strutil.Formatter) { + for { + x, ok := s.s.(*explainStmt) + if !ok { + s.s.explain(ctx, w) + return + } + + s = x + } +} + +func (s *explainStmt) String() string { + return "EXPLAIN " + s.s.String() +} + +func (*explainStmt) isUpdating() bool { return false } + +func (s *explainStmt) exec(ctx *execCtx) (_ Recordset, err error) { + return recordset{ctx, &explainDefaultPlan{s.s}, ctx.db.cc}, nil +} + +type updateStmt struct { + tableName string + list []assignment + where expression +} + +func (s *updateStmt) explain(ctx *execCtx, w strutil.Formatter) { + w.Format("%s\n", s) +} + +func (s *updateStmt) String() string { + u := fmt.Sprintf("UPDATE %s", s.tableName) + a := make([]string, len(s.list)) + for i, v := range s.list { + a[i] = v.String() + } + w := "" + if s.where != nil { + w = fmt.Sprintf(" WHERE %s", s.where) + } + return fmt.Sprintf("%s %s%s;", u, strings.Join(a, ", "), w) +} + +func (s *updateStmt) exec(ctx *execCtx) (_ Recordset, err error) { + t, ok := ctx.db.root.tables[s.tableName] + if !ok { + return nil, fmt.Errorf("UPDATE: table %s does not exist", s.tableName) + } + + tcols := make([]*col, len(s.list)) + for i, asgn := range s.list { + col := findCol(t.cols, asgn.colName) + if col == nil { + return nil, fmt.Errorf("UPDATE: unknown column %s", asgn.colName) + } + tcols[i] = col + } + + m := map[interface{}]interface{}{} + var nh int64 + expr := s.where + blobCols := t.blobCols() + cc := ctx.db.cc + var old []interface{} + var touched []bool + if t.hasIndices() { + old = make([]interface{}, len(t.cols0)) + touched = make([]bool, len(t.cols0)) + } + for h := t.head; h != 0; h = nh { + // Read can return lazily expanded chunks + data, err := t.store.Read(nil, h, t.cols...) + if err != nil { + return nil, err + } + + nh = data[0].(int64) + for _, col := range t.cols { + m[col.name] = data[2+col.index] + } + id := data[1].(int64) + m["$id"] = id + if expr != nil { + val, err := s.where.eval(ctx, m) + if err != nil { + return nil, err + } + + if val == nil { + continue + } + + x, ok := val.(bool) + if !ok { + return nil, fmt.Errorf("invalid WHERE expression %s (value of type %T)", val, val) + } + + if !x { + continue + } + } + + // hit + for _, ix := range t.indices2 { + vlist, err := ix.eval(ctx, t.cols, id, data[2:]) + if err != nil { + return nil, err + } + + if err := ix.x.Delete(vlist, h); err != nil { + return nil, err + } + } + for i, asgn := range s.list { + val, err := asgn.expr.eval(ctx, m) + if err != nil { + return nil, err + } + + colIndex := tcols[i].index + if t.hasIndices() { + old[colIndex] = data[2+colIndex] + touched[colIndex] = true + } + data[2+colIndex] = val + } + if err = typeCheck(data[2:], t.cols); err != nil { + return nil, err + } + + if err = t.checkConstraintsAndDefaults(ctx, data[2:], m); err != nil { + return nil, err + } + + for i, v := range t.indices { + if i == 0 { // id() N/A + continue + } + + if v == nil || !touched[i-1] { + continue + } + + if err = v.x.Delete([]interface{}{old[i-1]}, h); err != nil { + return nil, err + } + } + + if err = t.store.UpdateRow(h, blobCols, data...); err != nil { //LATER detect which blobs are actually affected + return nil, err + } + + for i, v := range t.indices { + if i == 0 { // id() N/A + continue + } + + if v == nil || !touched[i-1] { + continue + } + + if err = v.x.Create([]interface{}{data[2+i-1]}, h); err != nil { + return nil, err + } + } + for _, ix := range t.indices2 { + vlist, err := ix.eval(ctx, t.cols, id, data[2:]) + if err != nil { + return nil, err + } + + if err := ix.x.Create(vlist, h); err != nil { + return nil, err + } + } + + cc.RowsAffected++ + } + return +} + +func (s *updateStmt) isUpdating() bool { return true } + +type deleteStmt struct { + tableName string + where expression +} + +func (s *deleteStmt) explain(ctx *execCtx, w strutil.Formatter) { + w.Format("%s\n", s) +} + +func (s *deleteStmt) String() string { + switch { + case s.where == nil: + return fmt.Sprintf("DELETE FROM %s;", s.tableName) + default: + return fmt.Sprintf("DELETE FROM %s WHERE %s;", s.tableName, s.where) + } +} + +func (s *deleteStmt) exec(ctx *execCtx) (_ Recordset, err error) { + t, ok := ctx.db.root.tables[s.tableName] + if !ok { + return nil, fmt.Errorf("DELETE FROM: table %s does not exist", s.tableName) + } + + m := map[interface{}]interface{}{} + var ph, h, nh int64 + var data []interface{} + blobCols := t.blobCols() + cc := ctx.db.cc + for h = t.head; h != 0; ph, h = h, nh { + for i, v := range data { + c, ok := v.(chunk) + if !ok { + continue + } + + data[i] = c.b + } + // Read can return lazily expanded chunks + data, err = t.store.Read(nil, h, t.cols...) + if err != nil { + return nil, err + } + + nh = data[0].(int64) + for _, col := range t.cols { + m[col.name] = data[2+col.index] + } + id := data[1].(int64) + m["$id"] = id + val, err := s.where.eval(ctx, m) + if err != nil { + return nil, err + } + + if val == nil { + continue + } + + x, ok := val.(bool) + if !ok { + return nil, fmt.Errorf("invalid WHERE expression %s (value of type %T)", val, val) + } + + if !x { + continue + } + + // hit + for i, v := range t.indices { + if v == nil { + continue + } + + // overflow chunks left in place + if err = v.x.Delete([]interface{}{data[i+1]}, h); err != nil { + return nil, err + } + } + for _, ix := range t.indices2 { + vlist, err := ix.eval(ctx, t.cols, id, data[2:]) + if err != nil { + return nil, err + } + + if err := ix.x.Delete(vlist, h); err != nil { + return nil, err + } + } + + // overflow chunks freed here + if err = t.store.Delete(h, blobCols...); err != nil { + return nil, err + } + + cc.RowsAffected++ + switch { + case ph == 0 && nh == 0: // "only" + fallthrough + case ph == 0 && nh != 0: // "first" + if err = t.store.Update(t.hhead, nh); err != nil { + return nil, err + } + + t.head, h = nh, 0 + case ph != 0 && nh == 0: // "last" + fallthrough + case ph != 0 && nh != 0: // "inner" + pdata, err := t.store.Read(nil, ph, t.cols...) + if err != nil { + return nil, err + } + + for i, v := range pdata { + if x, ok := v.(chunk); ok { + pdata[i] = x.b + } + } + pdata[0] = nh + if err = t.store.Update(ph, pdata...); err != nil { + return nil, err + } + + h = ph + } + } + + return +} + +func (s *deleteStmt) isUpdating() bool { return true } + +type truncateTableStmt struct { + tableName string +} + +func (s *truncateTableStmt) explain(ctx *execCtx, w strutil.Formatter) { + w.Format("%s\n", s) +} + +func (s *truncateTableStmt) String() string { return fmt.Sprintf("TRUNCATE TABLE %s;", s.tableName) } + +func (s *truncateTableStmt) exec(ctx *execCtx) (Recordset, error) { + t, ok := ctx.db.root.tables[s.tableName] + if !ok { + return nil, fmt.Errorf("TRUNCATE TABLE: table %s does not exist", s.tableName) + } + + return nil, t.truncate() +} + +func (s *truncateTableStmt) isUpdating() bool { return true } + +type dropIndexStmt struct { + ifExists bool + indexName string +} + +func (s *dropIndexStmt) explain(ctx *execCtx, w strutil.Formatter) { + w.Format("%s\n", s) +} + +func (s *dropIndexStmt) String() string { return fmt.Sprintf("DROP INDEX %s;", s.indexName) } + +func (s *dropIndexStmt) exec(ctx *execCtx) (Recordset, error) { + t, x := ctx.db.root.findIndexByName(s.indexName) + if x == nil { + if s.ifExists { + return nil, nil + } + + return nil, fmt.Errorf("DROP INDEX: index %s does not exist", s.indexName) + } + + if ctx.db.hasAllIndex2() { + if err := ctx.db.deleteIndex2ByIndexName(s.indexName); err != nil { + return nil, err + } + } + + switch ix := x.(type) { + case *indexedCol: + for i, v := range t.indices { + if v == nil || v.name != s.indexName { + continue + } + + return nil, t.dropIndex(i) + } + case *index2: + delete(t.indices2, s.indexName) + return nil, ix.x.Drop() + } + + panic("internal error 058") +} + +func (s *dropIndexStmt) isUpdating() bool { return true } + +type dropTableStmt struct { + ifExists bool + tableName string +} + +func (s *dropTableStmt) explain(ctx *execCtx, w strutil.Formatter) { + w.Format("%s\n", s) +} + +func (s *dropTableStmt) String() string { return fmt.Sprintf("DROP TABLE %s;", s.tableName) } + +func (s *dropTableStmt) exec(ctx *execCtx) (Recordset, error) { + t, ok := ctx.db.root.tables[s.tableName] + if !ok { + if s.ifExists { + return nil, nil + } + + return nil, fmt.Errorf("DROP TABLE: table %s does not exist", s.tableName) + } + + if ctx.db.hasAllIndex2() { + if err := ctx.db.deleteIndex2ByTableName(s.tableName); err != nil { + return nil, err + } + } + + return nil, ctx.db.root.dropTable(t) +} + +func (s *dropTableStmt) isUpdating() bool { return true } + +type alterTableDropColumnStmt struct { + tableName, colName string +} + +func (s *alterTableDropColumnStmt) explain(ctx *execCtx, w strutil.Formatter) { + w.Format("%s\n", s) +} + +func (s *alterTableDropColumnStmt) String() string { + return fmt.Sprintf("ALTER TABLE %s DROP COLUMN %s;", s.tableName, s.colName) +} + +func (s *alterTableDropColumnStmt) exec(ctx *execCtx) (Recordset, error) { + t, ok := ctx.db.root.tables[s.tableName] + if !ok { + return nil, fmt.Errorf("ALTER TABLE: table %s does not exist", s.tableName) + } + + cols := t.cols + for _, c := range cols { + if c.name == s.colName { + if len(cols) == 1 { + return nil, fmt.Errorf("ALTER TABLE %s DROP COLUMN: cannot drop the only column: %s", s.tableName, s.colName) + } + + if _, ok := ctx.db.root.tables["__Column2"]; ok { + if _, err := deleteColumn2.l[0].exec(&execCtx{db: ctx.db, arg: []interface{}{s.tableName, c.name}}); err != nil { + return nil, err + } + } + + c.name = "" + t.cols0[c.index].name = "" + if t.hasIndices() { + if len(t.indices) != 0 { + if v := t.indices[c.index+1]; v != nil { + if err := t.dropIndex(c.index + 1); err != nil { + return nil, err + } + + if ctx.db.hasAllIndex2() { + if err := ctx.db.deleteIndex2ByIndexName(v.name); err != nil { + return nil, err + } + } + } + } + + for nm, ix := range t.indices2 { + for _, e := range ix.exprList { + m := mentionedColumns(e) + if _, ok := m[s.colName]; ok { + if err := ctx.db.deleteIndex2ByIndexName(nm); err != nil { + return nil, err + } + + if err := ix.x.Drop(); err != nil { + return nil, err + } + + delete(t.indices2, nm) + break + } + } + } + } + if err := t.constraintsAndDefaults(ctx); err != nil { + return nil, err + } + + return nil, t.updated() + } + } + + return nil, fmt.Errorf("ALTER TABLE %s DROP COLUMN: column %s does not exist", s.tableName, s.colName) +} + +func (s *alterTableDropColumnStmt) isUpdating() bool { return true } + +type alterTableAddStmt struct { + tableName string + c *col +} + +func (s *alterTableAddStmt) explain(ctx *execCtx, w strutil.Formatter) { + w.Format("%s\n", s) +} + +func (s *alterTableAddStmt) String() string { + r := fmt.Sprintf("ALTER TABLE %s ADD %s %s", s.tableName, s.c.name, typeStr(s.c.typ)) + c := s.c + if x := c.constraint; x != nil { //TODO add (*col).String() + switch e := x.expr; { + case e != nil: + r += " " + e.String() + default: + r += " NOT NULL" + } + } + if x := c.dflt; x != nil { + r += " DEFAULT " + x.String() + } + return r + ";" +} + +func (s *alterTableAddStmt) exec(ctx *execCtx) (Recordset, error) { + t, ok := ctx.db.root.tables[s.tableName] + if !ok { + return nil, fmt.Errorf("ALTER TABLE: table %s does not exist", s.tableName) + } + + hasRecords := t.head != 0 + c := s.c + if c.constraint != nil && hasRecords { + return nil, fmt.Errorf("ALTER TABLE %s ADD %s: cannot add constrained column to table with existing data", s.tableName, c.name) + } + + cols := t.cols + for _, c := range cols { + nm := c.name + if nm == s.c.name { + return nil, fmt.Errorf("ALTER TABLE %s ADD: column %s exists", s.tableName, nm) + } + } + + if len(t.indices) != 0 { + t.indices = append(t.indices, nil) + t.xroots = append(t.xroots, 0) + if err := t.store.Update(t.hxroots, t.xroots...); err != nil { + return nil, err + } + } + + if c.constraint != nil || c.dflt != nil { + for _, s := range createColumn2.l { + _, err := s.exec(&execCtx{db: ctx.db}) + if err != nil { + return nil, err + } + } + notNull := c.constraint != nil && c.constraint.expr == nil + var co, d string + if c.constraint != nil && c.constraint.expr != nil { + co = c.constraint.expr.String() + } + if e := c.dflt; e != nil { + d = e.String() + } + if _, err := insertColumn2.l[0].exec(&execCtx{db: ctx.db, arg: []interface{}{s.tableName, c.name, notNull, co, d}}); err != nil { + return nil, err + } + } + + t.cols0 = append(t.cols0, s.c) + if err := t.constraintsAndDefaults(ctx); err != nil { + return nil, err + } + + return nil, t.updated() +} + +func (s *alterTableAddStmt) isUpdating() bool { return true } + +type selectStmt struct { + distinct bool + flds []*fld + from *joinRset + group *groupByRset + hasAggregates bool + limit *limitRset + mu sync.Mutex + offset *offsetRset + order *orderByRset + where *whereRset +} + +func (s *selectStmt) explain(ctx *execCtx, w strutil.Formatter) { + p, err := s.plan(ctx) + if err != nil { + w.Format("ERROR: %v\n", err) + return + } + + p.explain(w) +} + +func (s *selectStmt) String() string { + var b bytes.Buffer + b.WriteString("SELECT") + if s.distinct { + b.WriteString(" DISTINCT") + } + switch { + case len(s.flds) == 0: + b.WriteString(" *") + default: + a := make([]string, len(s.flds)) + for i, v := range s.flds { + s := v.expr.String() + if v.name != "" && v.name != s { + s += " AS " + v.name + } + a[i] = s + } + b.WriteString(" " + strings.Join(a, ", ")) + } + b.WriteString(" FROM ") + b.WriteString(s.from.String()) + if s.where != nil { + b.WriteString(" WHERE ") + b.WriteString(s.where.expr.String()) + } + if s.group != nil { + b.WriteString(" GROUP BY ") + b.WriteString(strings.Join(s.group.colNames, ", ")) + } + if s.order != nil { + b.WriteString(" ORDER BY ") + b.WriteString(s.order.String()) + } + if s.limit != nil { + b.WriteString(" LIMIT ") + b.WriteString(s.limit.expr.String()) + } + if s.offset != nil { + b.WriteString(" OFFSET ") + b.WriteString(s.offset.expr.String()) + } + b.WriteRune(';') + return b.String() +} + +func (s *selectStmt) plan(ctx *execCtx) (plan, error) { //LATER overlapping goroutines/pipelines + r, err := s.from.plan(ctx) + if err != nil { + return nil, err + } + + if w := s.where; w != nil { + if r, err = (&whereRset{expr: w.expr, src: r}).plan(ctx); err != nil { + return nil, err + } + } + switch { + case !s.hasAggregates && s.group == nil: // nop + case !s.hasAggregates && s.group != nil: + if r, err = (&groupByRset{colNames: s.group.colNames, src: r}).plan(ctx); err != nil { + return nil, err + } + case s.hasAggregates && s.group == nil: + if r, err = (&groupByRset{src: r}).plan(ctx); err != nil { + return nil, err + } + case s.hasAggregates && s.group != nil: + if r, err = (&groupByRset{colNames: s.group.colNames, src: r}).plan(ctx); err != nil { + return nil, err + } + } + if r, err = (&selectRset{flds: s.flds, src: r}).plan(ctx); err != nil { + return nil, err + } + + if s.distinct { + if r, err = (&distinctRset{src: r}).plan(ctx); err != nil { + return nil, err + } + } + if s := s.order; s != nil { + if r, err = (&orderByRset{asc: s.asc, by: s.by, src: r}).plan(ctx); err != nil { + return nil, err + } + } + if s := s.offset; s != nil { + if r, err = (&offsetRset{s.expr, r}).plan(ctx); err != nil { + return nil, err + } + } + if s := s.limit; s != nil { + if r, err = (&limitRset{s.expr, r}).plan(ctx); err != nil { + return nil, err + } + } + return r, nil +} + +func (s *selectStmt) exec(ctx *execCtx) (rs Recordset, err error) { + r, err := s.plan(ctx) + if err != nil { + return nil, err + } + + return recordset{ctx, r, nil}, nil +} + +func (s *selectStmt) isUpdating() bool { return false } + +type insertIntoStmt struct { + colNames []string + lists [][]expression + sel *selectStmt + tableName string +} + +func (s *insertIntoStmt) explain(ctx *execCtx, w strutil.Formatter) { + w.Format("%s\n", s) +} + +func (s *insertIntoStmt) String() string { + cn := "" + if len(s.colNames) != 0 { + cn = fmt.Sprintf(" (%s)", strings.Join(s.colNames, ", ")) + } + switch { + case s.sel != nil: + return fmt.Sprintf("INSERT INTO %s%s %s;", s.tableName, cn, s.sel) + default: + a := make([]string, len(s.lists)) + for i, v := range s.lists { + b := make([]string, len(v)) + for i, v := range v { + b[i] = v.String() + } + a[i] = fmt.Sprintf("(%s)", strings.Join(b, ", ")) + } + return fmt.Sprintf("INSERT INTO %s%s VALUES %s;", s.tableName, cn, strings.Join(a, ", ")) + } +} + +func (s *insertIntoStmt) execSelect(t *table, cols []*col, ctx *execCtx) (_ Recordset, err error) { + //TODO missing rs column number eq check + r, err := s.sel.plan(ctx) + if err != nil { + return nil, err + } + + h := t.head + data0 := make([]interface{}, len(t.cols0)+2) + cc := ctx.db.cc + m := map[interface{}]interface{}{} + if err = r.do(ctx, func(_ interface{}, data []interface{}) (more bool, err error) { + for i, d := range data { + data0[cols[i].index+2] = d + } + if err = typeCheck(data0[2:], cols); err != nil { + return + } + + if err = t.checkConstraintsAndDefaults(ctx, data0[2:], m); err != nil { + return false, err + } + + id, err := t.store.ID() + if err != nil { + return false, err + } + + data0[0] = h + data0[1] = id + + // Any overflow chunks are written here. + if h, err = t.store.Create(data0...); err != nil { + return false, err + } + + for i, v := range t.indices { + if v == nil { + continue + } + + // Any overflow chunks are shared with the BTree key + if err = v.x.Create([]interface{}{data0[i+1]}, h); err != nil { + return false, err + } + } + for _, ix := range t.indices2 { + vlist, err := ix.eval(ctx, t.cols, id, data0[2:]) + if err != nil { + return false, err + } + + if err := ix.x.Create(vlist, h); err != nil { + return false, err + } + } + + cc.RowsAffected++ + ctx.db.root.lastInsertID = id + return true, nil + }); err != nil { + return nil, err + } + + t.head = h + return nil, t.store.Update(t.hhead, h) +} + +func (s *insertIntoStmt) exec(ctx *execCtx) (_ Recordset, err error) { + root := ctx.db.root + t, ok := root.tables[s.tableName] + if !ok { + return nil, fmt.Errorf("INSERT INTO %s: table does not exist", s.tableName) + } + + var cols []*col + switch len(s.colNames) { + case 0: + cols = t.cols + default: + for _, colName := range s.colNames { + if col := findCol(t.cols, colName); col != nil { + cols = append(cols, col) + continue + } + + return nil, fmt.Errorf("INSERT INTO %s: unknown column %s", s.tableName, colName) + } + } + + if s.sel != nil { + return s.execSelect(t, cols, ctx) + } + + for _, list := range s.lists { + if g, e := len(list), len(cols); g != e { + return nil, fmt.Errorf("INSERT INTO %s: expected %d value(s), have %d", s.tableName, e, g) + } + } + + cc := ctx.db.cc + r := make([]interface{}, len(t.cols0)) + m := map[interface{}]interface{}{} + for _, list := range s.lists { + for i, expr := range list { + val, err := expr.eval(ctx, m) + if err != nil { + return nil, err + } + + r[cols[i].index] = val + } + if err = typeCheck(r, cols); err != nil { + return nil, err + } + + if err = t.checkConstraintsAndDefaults(ctx, r, m); err != nil { + return nil, err + } + + id, err := t.addRecord(ctx, r) + if err != nil { + return nil, err + } + + cc.RowsAffected++ + root.lastInsertID = id + } + return nil, nil +} + +func (s *insertIntoStmt) isUpdating() bool { return true } + +type beginTransactionStmt struct{} + +func (s beginTransactionStmt) explain(ctx *execCtx, w strutil.Formatter) { + w.Format("%s\n", s) +} + +func (beginTransactionStmt) String() string { return "BEGIN TRANSACTION;" } +func (beginTransactionStmt) exec(*execCtx) (Recordset, error) { + panic("internal error 059") +} +func (beginTransactionStmt) isUpdating() bool { + panic("internal error 060") +} + +type commitStmt struct{} + +func (s commitStmt) explain(ctx *execCtx, w strutil.Formatter) { + w.Format("%s\n", s) +} + +func (commitStmt) String() string { return "COMMIT;" } +func (commitStmt) exec(*execCtx) (Recordset, error) { + panic("internal error 061") +} +func (commitStmt) isUpdating() bool { + panic("internal error 062") +} + +type rollbackStmt struct{} + +func (s rollbackStmt) explain(ctx *execCtx, w strutil.Formatter) { + w.Format("%s\n", s) +} + +func (rollbackStmt) String() string { return "ROLLBACK;" } +func (rollbackStmt) exec(*execCtx) (Recordset, error) { + panic("internal error 063") +} +func (rollbackStmt) isUpdating() bool { + panic("internal error 064") +} + +type createIndexStmt struct { + colName string // alt. "id()" for simple index on id() + ifNotExists bool + indexName string + tableName string + unique bool + exprList []expression +} + +func (s *createIndexStmt) explain(ctx *execCtx, w strutil.Formatter) { + w.Format("%s\n", s) +} + +func (s *createIndexStmt) isSimpleIndex() bool { return s.colName != "" } + +func (s *createIndexStmt) String() string { + u := "" + if s.unique { + u = "UNIQUE " + } + e := "" + if s.ifNotExists { + e = "IF NOT EXISTS " + } + expr := s.colName + if !s.isSimpleIndex() { + var a []string + for _, v := range s.exprList { + a = append(a, v.String()) + } + expr = strings.Join(a, ", ") + } + return fmt.Sprintf("CREATE %sINDEX %s%s ON %s (%s);", u, e, s.indexName, s.tableName, expr) +} + +func (s *createIndexStmt) exec(ctx *execCtx) (Recordset, error) { + root := ctx.db.root + if t, i := root.findIndexByName(s.indexName); i != nil { + if s.ifNotExists { + return nil, nil + } + + return nil, fmt.Errorf("CREATE INDEX: table %s already has an index named %s", t.name, s.indexName) + } + + if root.tables[s.indexName] != nil { + return nil, fmt.Errorf("CREATE INDEX: index name collision with existing table: %s", s.indexName) + } + + t, ok := root.tables[s.tableName] + if !ok { + return nil, fmt.Errorf("CREATE INDEX: table does not exist %s", s.tableName) + } + + if findCol(t.cols, s.indexName) != nil { + return nil, fmt.Errorf("CREATE INDEX: index name collision with existing column: %s", s.indexName) + } + + var h int64 + var err error + switch { + case s.isSimpleIndex(): + colIndex := -1 + if s.colName != "id()" { + c := findCol(t.cols, s.colName) + if c == nil { + return nil, fmt.Errorf("CREATE INDEX: column does not exist: %s", s.colName) + } + + colIndex = c.index + } + + if h, err = t.addIndex(s.unique, s.indexName, colIndex); err != nil { + return nil, fmt.Errorf("CREATE INDEX: %v", err) + } + + if err = t.updated(); err != nil { + return nil, err + } + default: + for _, e := range s.exprList { + m := mentionedColumns(e) + for colName := range m { + c := findCol(t.cols, colName) + if c == nil { + return nil, fmt.Errorf("CREATE INDEX: column does not exist: %s", colName) + } + } + } + if h, err = t.addIndex2(ctx, s.unique, s.indexName, s.exprList); err != nil { + return nil, fmt.Errorf("CREATE INDEX: %v", err) + } + } + + switch ctx.db.hasIndex2 { + case 0: + if err := ctx.db.createIndex2(); err != nil { + return nil, err + } + + if s.isSimpleIndex() { + return nil, nil + } + case 1: + return nil, nil + case 2: + if s.isSimpleIndex() { + return nil, ctx.db.insertIndex2(s.tableName, s.indexName, []string{s.colName}, s.unique, true, h) + } + default: + panic("internal error 011") + } + + exprList := make([]string, 0, len(s.exprList)) + for _, e := range s.exprList { + exprList = append(exprList, e.String()) + } + return nil, ctx.db.insertIndex2(s.tableName, s.indexName, exprList, s.unique, false, h) +} + +func (s *createIndexStmt) isUpdating() bool { return true } + +type createTableStmt struct { + ifNotExists bool + tableName string + cols []*col +} + +func (s *createTableStmt) explain(ctx *execCtx, w strutil.Formatter) { + w.Format("%s\n", s) +} + +func (s *createTableStmt) String() string { + a := make([]string, len(s.cols)) + for i, v := range s.cols { + var c, d string + if x := v.constraint; x != nil { + switch e := x.expr; { + case e != nil: + c = " " + e.String() + default: + c = " NOT NULL" + } + } + if x := v.dflt; x != nil { + d = " DEFAULT " + x.String() + } + a[i] = fmt.Sprintf("%s %s%s%s", v.name, typeStr(v.typ), c, d) + } + e := "" + if s.ifNotExists { + e = "IF NOT EXISTS " + } + return fmt.Sprintf("CREATE TABLE %s%s (%s);", e, s.tableName, strings.Join(a, ", ")) +} + +func (s *createTableStmt) exec(ctx *execCtx) (_ Recordset, err error) { + var cols []*col + for _, v := range s.cols { + cols = append(cols, v.clone()) + } + root := ctx.db.root + if _, ok := root.tables[s.tableName]; ok { + if s.ifNotExists { + return nil, nil + } + + return nil, fmt.Errorf("CREATE TABLE: table exists %s", s.tableName) + } + + if t, x := root.findIndexByName(s.tableName); x != nil { + return nil, fmt.Errorf("CREATE TABLE: table %s has index %s", t.name, s.tableName) + } + + m := map[string]bool{} + mustCreateColumn2 := true + for i, c := range cols { + nm := c.name + if m[nm] { + return nil, fmt.Errorf("CREATE TABLE: duplicate column %s", nm) + } + + m[nm] = true + c.index = i + if c.constraint != nil || c.dflt != nil { + if mustCreateColumn2 { + for _, stmt := range createColumn2.l { + _, err := stmt.exec(&execCtx{db: ctx.db}) + if err != nil { + return nil, err + } + } + } + + mustCreateColumn2 = false + notNull := c.constraint != nil && c.constraint.expr == nil + var co, d string + if c.constraint != nil && c.constraint.expr != nil { + co = c.constraint.expr.String() + } + if e := c.dflt; e != nil { + d = e.String() + } + if _, err := insertColumn2.l[0].exec(&execCtx{db: ctx.db, arg: []interface{}{s.tableName, c.name, notNull, co, d}}); err != nil { + return nil, err + } + } + } + t, err := root.createTable(s.tableName, cols) + if err != nil { + return nil, err + } + + return nil, t.constraintsAndDefaults(ctx) +} + +func (s *createTableStmt) isUpdating() bool { return true } diff --git a/vendor/github.com/cznic/ql/storage.go b/vendor/github.com/cznic/ql/storage.go new file mode 100644 index 00000000..fa7a4bf0 --- /dev/null +++ b/vendor/github.com/cznic/ql/storage.go @@ -0,0 +1,991 @@ +// Copyright (c) 2014 ql 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 ql + +import ( + "fmt" + "strings" +) + +type storage interface { + Acid() bool + BeginTransaction() error + Close() error + Commit() error + Create(data ...interface{}) (h int64, err error) + CreateIndex(unique bool) (handle int64, x btreeIndex, err error) + CreateTemp(asc bool) (bt temp, err error) + Delete(h int64, blobCols ...*col) error //LATER split the nil blobCols case + ID() (id int64, err error) + Name() string + OpenIndex(unique bool, handle int64) (btreeIndex, error) // Never called on the memory backend. + Read(dst []interface{}, h int64, cols ...*col) (data []interface{}, err error) + ResetID() (err error) + Rollback() error + Update(h int64, data ...interface{}) error + UpdateRow(h int64, blobCols []*col, data ...interface{}) error + Verify() (allocs int64, err error) +} + +type btreeIterator interface { + Next() (k, v []interface{}, err error) +} + +type temp interface { + BeginTransaction() error + Create(data ...interface{}) (h int64, err error) + Drop() (err error) + Get(k []interface{}) (v []interface{}, err error) + Read(dst []interface{}, h int64, cols ...*col) (data []interface{}, err error) + SeekFirst() (e btreeIterator, err error) + Set(k, v []interface{}) (err error) +} + +type indexIterator interface { + Next() (k []interface{}, h int64, err error) + Prev() (k []interface{}, h int64, err error) +} + +type btreeIndex interface { + Clear() error // supports truncate table statement + Create(indexedValues []interface{}, h int64) error // supports insert into statement + Delete(indexedValues []interface{}, h int64) error // supports delete from statement + Drop() error // supports drop table, drop index statements + Seek(indexedValues []interface{}) (iter indexIterator, hit bool, err error) // supports where clause + SeekFirst() (iter indexIterator, err error) // supports aggregate min / ascending order by + SeekLast() (iter indexIterator, err error) // supports aggregate max / descending order by +} + +type indexedCol struct { // Column name or id() index. + name string + unique bool + x btreeIndex + xroot int64 +} + +type index2 struct { // Expression list index. + unique bool + x btreeIndex + xroot int64 + sources []string + exprList []expression +} + +func (x *index2) eval(ctx *execCtx, cols []*col, id int64, r []interface{}) ([]interface{}, error) { + f, isFile := ctx.db.store.(*file) + vlist := make([]interface{}, len(x.exprList)) + m := map[interface{}]interface{}{"$id": id} + for _, col := range cols { + ci := col.index + v := interface{}(nil) + if ci < len(r) { + v = r[ci] + } + if b, ok := v.([]byte); ok && isFile { + var err error + if v, err = expand1(chunk{f: f, b: b}, nil); err != nil { + return nil, err + } + } + m[col.name] = v + } + for i, e := range x.exprList { + v, err := e.eval(ctx, m) + if err != nil { + return nil, err + } + + if ok, typ := isBlobType(v); ok { + return nil, fmt.Errorf("value of a complex index cannot be of blob-like type: %v", typ) + } + + vlist[i] = v + } + return vlist, nil +} + +type indexKey struct { + value []interface{} + h int64 +} + +// storage fields +// 0: next int64 +// 1: scols string +// 2: hhead int64 +// 3: name string +// 4: indices string - optional +// 5: hxroots int64 - optional +type table struct { + cols []*col // logical + cols0 []*col // physical + h int64 // + head int64 // head of the single linked record list + hhead int64 // handle of the head of the single linked record list + hxroots int64 + indices []*indexedCol + indices2 map[string]*index2 + name string + next int64 // single linked table list + store storage + tnext *table + tprev *table + xroots []interface{} + constraints []*constraint + defaults []expression +} + +func (t *table) hasIndices() bool { return len(t.indices) != 0 || len(t.indices2) != 0 } +func (t *table) hasIndices2() bool { return len(t.indices2) != 0 } + +func (t *table) constraintsAndDefaults(ctx *execCtx) error { + if isSystemName[t.name] { + return nil + } + + _, ok := ctx.db.root.tables["__Column2"] + if !ok { + return nil + } + + cols := t.cols + constraints := make([]*constraint, len(cols)) + defaults := make([]expression, len(cols)) + arg := []interface{}{t.name} + rs, err := selectColumn2.l[0].exec(&execCtx{db: ctx.db, arg: arg}) + if err != nil { + return err + } + + var rows [][]interface{} + ok = false + if err := rs.(recordset).do( + &execCtx{db: ctx.db, arg: arg}, + func(id interface{}, data []interface{}) (more bool, err error) { + rows = append(rows, data) + return true, nil + }, + ); err != nil { + return err + } + + for _, row := range rows { + nm := row[0].(string) + nonNull := row[1].(bool) + cexpr := row[2].(string) + dexpr := row[3].(string) + for i, c := range cols { + if c.name == nm { + var co *constraint + if nonNull || cexpr != "" { + co = &constraint{} + constraints[i] = co + if cexpr != "" { + if co.expr, err = ctx.db.str2expr(cexpr); err != nil { + return fmt.Errorf("constraint %q: %v", cexpr, err) + } + } + + t.constraints = constraints + } + if dexpr != "" { + if defaults[i], err = ctx.db.str2expr(dexpr); err != nil { + return fmt.Errorf("constraint %q: %v", dexpr, err) + } + + t.defaults = defaults + } + } + } + } + return nil +} + +func (t *table) checkConstraintsAndDefaults(ctx *execCtx, row []interface{}, m map[interface{}]interface{}) error { + cols := t.cols + + if len(t.defaults) != 0 { + // 1. + for _, c := range cols { + m[c.name] = row[c.index] + } + + // 2. + for i, c := range cols { + val := row[c.index] + expr := t.defaults[i] + if val != nil || expr == nil { + continue + } + + dval, err := expr.eval(ctx, m) + if err != nil { + return err + } + + row[c.index] = dval + if err = typeCheck(row, []*col{c}); err != nil { + return err + } + } + } + + if len(t.constraints) != 0 { + // 3. + for _, c := range cols { + m[c.name] = row[c.index] + } + + // 4. + for i, c := range cols { + constraint := t.constraints[i] + if constraint == nil { + continue + } + + val := row[c.index] + expr := constraint.expr + if expr == nil { // Constraint: NOT NULL + if val == nil { + return fmt.Errorf("column %s: constraint violation: NOT NULL", c.name) + } + + continue + } + + // Constraint is an expression + cval, err := expr.eval(ctx, m) + if err != nil { + return err + } + + if cval == nil { + return fmt.Errorf("column %s: constraint violation: %s", c.name, expr) + } + + bval, ok := cval.(bool) + if !ok { + return fmt.Errorf("column %s: non bool constraint expression: %s", c.name, expr) + } + + if !bval { + return fmt.Errorf("column %s: constraint violation: %s", c.name, expr) + } + } + } + + return nil +} + +func (t *table) clone() *table { + r := &table{} + *r = *t + r.constraints = append([]*constraint(nil), t.constraints...) + r.defaults = append([]expression(nil), t.defaults...) + r.indices2 = nil + if n := len(t.indices2); n != 0 { + r.indices2 = make(map[string]*index2, n) + for k, v := range t.indices2 { + r.indices2[k] = v + } + } + r.cols = make([]*col, len(t.cols)) + for i, v := range t.cols { + c := &col{} + *c = *v + r.cols[i] = c + } + r.cols0 = make([]*col, len(t.cols0)) + for i, v := range t.cols0 { + c := &col{} + *c = *v + r.cols0[i] = c + } + r.indices = make([]*indexedCol, len(t.indices)) + for i, v := range t.indices { + if v != nil { + c := &indexedCol{} + *c = *v + r.indices[i] = c + } + } + r.xroots = make([]interface{}, len(t.xroots)) + copy(r.xroots, t.xroots) + r.tnext, r.tprev = nil, nil + return r +} + +func (t *table) findIndexByColName(name string) (*col, *indexedCol) { + for i, v := range t.indices { + if v == nil { + continue + } + + if i == 0 { + if name == "id()" { + return idCol, v + } + + continue + } + + if c := t.cols[i-1]; c.name == name { + return c, v + } + } + + return nil, nil +} + +func (t *table) findIndexByName(name string) interface{} { + for _, v := range t.indices { + if v != nil && v.name == name { + return v + } + } + for k, v := range t.indices2 { + if k == name { + return v + } + } + return nil +} + +func (t *table) load() (err error) { + data, err := t.store.Read(nil, t.h) + if err != nil { + return + } + + var hasIndices bool + switch n := len(data); n { + case 4: + case 6: + hasIndices = true + default: + return fmt.Errorf("corrupted DB: table data len %d", n) + } + + var ok bool + if t.next, ok = data[0].(int64); !ok { + return fmt.Errorf("corrupted DB: table data[0] of type %T", data[0]) + } + + scols, ok := data[1].(string) + if !ok { + return fmt.Errorf("corrupted DB: table data[1] of type %T", data[1]) + } + + if t.hhead, ok = data[2].(int64); !ok { + return fmt.Errorf("corrupted DB: table data[2] of type %T", data[2]) + } + + if t.name, ok = data[3].(string); !ok { + return fmt.Errorf("corrupted DB: table data[3] of type %T", data[3]) + } + + var head []interface{} + if head, err = t.store.Read(nil, t.hhead); err != nil { + return err + } + + if len(head) != 1 { + return fmt.Errorf("corrupted DB: table head data len %d", len(head)) + } + + if t.head, ok = head[0].(int64); !ok { + return fmt.Errorf("corrupted DB: table head data[0] of type %T", head[0]) + } + + a := strings.Split(scols, "|") + t.cols0 = make([]*col, len(a)) + for i, v := range a { + if len(v) < 1 { + return fmt.Errorf("corrupted DB: field info %q", v) + } + + col := &col{name: v[1:], typ: int(v[0]), index: i} + t.cols0[i] = col + if col.name != "" { + t.cols = append(t.cols, col) + } + } + + if !hasIndices { + return + } + + if t.hxroots, ok = data[5].(int64); !ok { + return fmt.Errorf("corrupted DB: table data[5] of type %T", data[5]) + } + + xroots, err := t.store.Read(nil, t.hxroots) + if err != nil { + return err + } + + if g, e := len(xroots), len(t.cols0)+1; g != e { + return fmt.Errorf("corrupted DB: got %d index roots, expected %d", g, e) + } + + indices, ok := data[4].(string) + if !ok { + return fmt.Errorf("corrupted DB: table data[4] of type %T", data[4]) + } + + a = strings.Split(indices, "|") + if g, e := len(a), len(t.cols0)+1; g != e { + return fmt.Errorf("corrupted DB: got %d index definitions, expected %d", g, e) + } + + t.indices = make([]*indexedCol, len(a)) + for i, v := range a { + if v == "" { + continue + } + + if len(v) < 2 { + return fmt.Errorf("corrupted DB: invalid index definition %q", v) + } + + nm := v[1:] + h, ok := xroots[i].(int64) + if !ok { + return fmt.Errorf("corrupted DB: table index root of type %T", xroots[i]) + } + + if h == 0 { + return fmt.Errorf("corrupted DB: missing root for index %s", nm) + } + + unique := v[0] == 'u' + x, err := t.store.OpenIndex(unique, h) + if err != nil { + return err + } + + t.indices[i] = &indexedCol{nm, unique, x, h} + } + t.xroots = xroots + + return +} + +func newTable(store storage, name string, next int64, cols []*col, tprev, tnext *table) (t *table, err error) { + hhead, err := store.Create(int64(0)) + if err != nil { + return + } + + scols := cols2meta(cols) + h, err := store.Create(next, scols, hhead, name) + if err != nil { + return + } + + t = &table{ + cols0: cols, + h: h, + hhead: hhead, + name: name, + next: next, + store: store, + tnext: tnext, + tprev: tprev, + } + return t.updateCols(), nil +} + +func (t *table) blobCols() (r []*col) { + for _, c := range t.cols0 { + switch c.typ { + case qBlob, qBigInt, qBigRat, qTime, qDuration: + r = append(r, c) + } + } + return +} + +func (t *table) truncate() (err error) { + h := t.head + var rec []interface{} + blobCols := t.blobCols() + for h != 0 { + rec, err := t.store.Read(rec, h) + if err != nil { + return err + } + nh := rec[0].(int64) + + if err = t.store.Delete(h, blobCols...); err != nil { //LATER remove double read for len(blobCols) != 0 + return err + } + + h = nh + } + if err = t.store.Update(t.hhead, 0); err != nil { + return + } + + for _, v := range t.indices { + if v == nil { + continue + } + + if err := v.x.Clear(); err != nil { + return err + } + } + for _, ix := range t.indices2 { + if err := ix.x.Clear(); err != nil { + return err + } + } + t.head = 0 + return t.updated() +} + +func (t *table) addIndex0(unique bool, indexName string, colIndex int) (int64, btreeIndex, error) { + switch len(t.indices) { + case 0: + indices := make([]*indexedCol, len(t.cols0)+1) + h, x, err := t.store.CreateIndex(unique) + if err != nil { + return -1, nil, err + } + + indices[colIndex+1] = &indexedCol{indexName, unique, x, h} + xroots := make([]interface{}, len(indices)) + xroots[colIndex+1] = h + hx, err := t.store.Create(xroots...) + if err != nil { + return -1, nil, err + } + + t.hxroots, t.xroots, t.indices = hx, xroots, indices + return h, x, t.updated() + default: + ex := t.indices[colIndex+1] + if ex != nil && ex.name != "" { + colName := "id()" + if colIndex >= 0 { + colName = t.cols0[colIndex].name + } + return -1, nil, fmt.Errorf("column %s already has an index: %s", colName, ex.name) + } + + h, x, err := t.store.CreateIndex(unique) + if err != nil { + return -1, nil, err + } + + t.xroots[colIndex+1] = h + if err := t.store.Update(t.hxroots, t.xroots...); err != nil { + return -1, nil, err + } + + t.indices[colIndex+1] = &indexedCol{indexName, unique, x, h} + return h, x, t.updated() + } +} + +func (t *table) addIndex(unique bool, indexName string, colIndex int) (int64, error) { + hx, x, err := t.addIndex0(unique, indexName, colIndex) + if err != nil { + return -1, err + } + + // Must fill the new index. + ncols := len(t.cols0) + h, store := t.head, t.store + for h != 0 { + rec, err := store.Read(nil, h, t.cols...) + if err != nil { + return -1, err + } + + if n := ncols + 2 - len(rec); n > 0 { + rec = append(rec, make([]interface{}, n)...) + } + + if err = x.Create([]interface{}{rec[colIndex+2]}, h); err != nil { + return -1, err + } + + h = rec[0].(int64) + } + return hx, nil +} + +func (t *table) addIndex2(execCtx *execCtx, unique bool, indexName string, exprList []expression) (int64, error) { + if _, ok := t.indices2[indexName]; ok { + panic("internal error 009") + } + + hx, x, err := t.store.CreateIndex(unique) + if err != nil { + return -1, err + } + var a []string + for _, v := range exprList { + a = append(a, v.String()) + } + x2 := &index2{unique, x, hx, a, exprList} + if t.indices2 == nil { + t.indices2 = map[string]*index2{} + } + t.indices2[indexName] = x2 + + // Must fill the new index. + m := map[interface{}]interface{}{} + h, store := t.head, t.store + for h != 0 { + rec, err := store.Read(nil, h, t.cols...) + if err != nil { + return -1, err + } + + for _, col := range t.cols { + ci := col.index + v := interface{}(nil) + if ci < len(rec) { + v = rec[ci+2] + } + m[col.name] = v + } + + id := rec[1].(int64) + vlist, err := x2.eval(execCtx, t.cols, id, rec[2:]) + if err != nil { + return -1, err + } + + if err := x2.x.Create(vlist, h); err != nil { + return -1, err + } + + h = rec[0].(int64) + } + return hx, nil +} + +func (t *table) dropIndex(xIndex int) error { + t.xroots[xIndex] = 0 + if err := t.indices[xIndex].x.Drop(); err != nil { + return err + } + + t.indices[xIndex] = nil + return t.updated() +} + +func (t *table) updated() (err error) { + switch { + case len(t.indices) != 0: + a := []string{} + for _, v := range t.indices { + if v == nil { + a = append(a, "") + continue + } + + s := "n" + if v.unique { + s = "u" + } + a = append(a, s+v.name) + } + return t.store.Update(t.h, t.next, cols2meta(t.updateCols().cols0), t.hhead, t.name, strings.Join(a, "|"), t.hxroots) + default: + return t.store.Update(t.h, t.next, cols2meta(t.updateCols().cols0), t.hhead, t.name) + } +} + +// storage fields +// 0: next record handle int64 +// 1: record id int64 +// 2...: data row +func (t *table) addRecord(execCtx *execCtx, r []interface{}) (id int64, err error) { + if id, err = t.store.ID(); err != nil { + return + } + + r = append([]interface{}{t.head, id}, r...) + h, err := t.store.Create(r...) + if err != nil { + return + } + + for i, v := range t.indices { + if v == nil { + continue + } + + if err = v.x.Create([]interface{}{r[i+1]}, h); err != nil { + return + } + } + + for _, ix := range t.indices2 { + vlist, err := ix.eval(execCtx, t.cols, id, r[2:]) + if err != nil { + return -1, err + } + + if err := ix.x.Create(vlist, h); err != nil { + return -1, err + } + } + + if err = t.store.Update(t.hhead, h); err != nil { + return + } + + t.head = h + return +} + +func (t *table) flds() (r []*fld) { + r = make([]*fld, len(t.cols)) + for i, v := range t.cols { + r[i] = &fld{expr: &ident{v.name}, name: v.name} + } + return +} + +func (t *table) fieldNames() []string { + r := make([]string, len(t.cols)) + for i, v := range t.cols { + r[i] = v.name + } + return r +} + +func (t *table) updateCols() *table { + t.cols = t.cols[:0] + for i, c := range t.cols0 { + if c.name != "" { + c.index = i + t.cols = append(t.cols, c) + } + } + return t +} + +func (t *table) row0(ctx *execCtx, h int64) ([]interface{}, error) { + rec, err := ctx.db.store.Read(nil, h, t.cols...) + if err != nil { + return nil, err + } + + if d := len(t.cols) - (len(rec) - 2); d > 0 { + rec = append(rec, make([]interface{}, d)...) + } + + return rec, nil +} + +func (t *table) row(ctx *execCtx, h int64) (int64, []interface{}, error) { + rec, err := t.row0(ctx, h) + if err != nil { + return -1, nil, err + } + + return rec[1].(int64), rec[2:], nil +} + +// storage fields +// 0: handle of first table in DB int64 +type root struct { + head int64 // Single linked table list + lastInsertID int64 + parent *root + rowsAffected int64 //LATER implement + store storage + tables map[string]*table + thead *table +} + +func newRoot(store storage) (r *root, err error) { + data, err := store.Read(nil, 1) + if err != nil { + return + } + + switch len(data) { + case 0: // new empty DB, create empty table list + if err = store.BeginTransaction(); err != nil { + return + } + + if err = store.Update(1, int64(0)); err != nil { + store.Rollback() + return + } + + if err = store.Commit(); err != nil { + return + } + + return &root{ + store: store, + tables: map[string]*table{}, + }, nil + case 1: // existing DB, load tables + if len(data) != 1 { + return nil, fmt.Errorf("corrupted DB: root is an %d-scalar", len(data)) + } + + p, ok := data[0].(int64) + if !ok { + return nil, fmt.Errorf("corrupted DB: root head has type %T", data[0]) + } + + r := &root{ + head: p, + store: store, + tables: map[string]*table{}, + } + + var tprev *table + for p != 0 { + t := &table{ + h: p, + store: store, + tprev: tprev, + } + + if r.thead == nil { + r.thead = t + } + if tprev != nil { + tprev.tnext = t + } + tprev = t + + if err = t.load(); err != nil { + return nil, err + } + + if r.tables[t.name] != nil { // duplicate + return nil, fmt.Errorf("corrupted DB: duplicate table metadata for table %s", t.name) + } + + r.tables[t.name] = t + p = t.next + } + return r, nil + default: + return nil, errIncompatibleDBFormat + } +} + +func (r *root) findIndexByName(name string) (*table, interface{}) { + for _, t := range r.tables { + if i := t.findIndexByName(name); i != nil { + return t, i + } + } + + return nil, nil +} + +func (r *root) updated() (err error) { + return r.store.Update(1, r.head) +} + +func (r *root) createTable(name string, cols []*col) (t *table, err error) { + if _, ok := r.tables[name]; ok { + panic("internal error 065") + } + + if t, err = newTable(r.store, name, r.head, cols, nil, r.thead); err != nil { + return nil, err + } + + if err = r.store.Update(1, t.h); err != nil { + return nil, err + } + + if p := r.thead; p != nil { + p.tprev = t + } + r.tables[name], r.head, r.thead = t, t.h, t + return +} + +func (r *root) dropTable(t *table) (err error) { + defer func() { + if err != nil { + return + } + + delete(r.tables, t.name) + }() + + if err = t.truncate(); err != nil { + return + } + + if err = t.store.Delete(t.hhead); err != nil { + return + } + + if err = t.store.Delete(t.h); err != nil { + return + } + + for _, v := range t.indices { + if v != nil && v.x != nil { + if err = v.x.Drop(); err != nil { + return + } + } + } + for _, v := range t.indices2 { + if err = v.x.Drop(); err != nil { + return + } + } + + if h := t.hxroots; h != 0 { + if err = t.store.Delete(h); err != nil { + return + } + } + + switch { + case t.tprev == nil && t.tnext == nil: + r.head = 0 + r.thead = nil + err = r.updated() + return errSet(&err, r.store.ResetID()) + case t.tprev == nil && t.tnext != nil: + next := t.tnext + next.tprev = nil + r.head = next.h + r.thead = next + if err = r.updated(); err != nil { + return + } + + return next.updated() + case t.tprev != nil && t.tnext == nil: // last in list + prev := t.tprev + prev.next = 0 + prev.tnext = nil + return prev.updated() + default: //case t.tprev != nil && t.tnext != nil: + prev, next := t.tprev, t.tnext + prev.next = next.h + prev.tnext = next + next.tprev = prev + if err = prev.updated(); err != nil { + return + } + + return next.updated() + } +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock.go b/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock.go new file mode 100644 index 00000000..a9fb802d --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock.go @@ -0,0 +1,186 @@ +/* +Copyright 2013 The Go Authors + +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 lock is a file locking library. +package lock + +import ( + "encoding/json" + "fmt" + "io" + "os" + "path/filepath" + "sync" +) + +// Lock locks the given file, creating the file if necessary. If the +// file already exists, it must have zero size or an error is returned. +// The lock is an exclusive lock (a write lock), but locked files +// should neither be read from nor written to. Such files should have +// zero size and only exist to co-ordinate ownership across processes. +// +// A nil Closer is returned if an error occurred. Otherwise, close that +// Closer to release the lock. +// +// On Linux, FreeBSD and OSX, a lock has the same semantics as fcntl(2)'s +// advisory locks. In particular, closing any other file descriptor for the +// same file will release the lock prematurely. +// +// Attempting to lock a file that is already locked by the current process +// has undefined behavior. +// +// On other operating systems, lock will fallback to using the presence and +// content of a file named name + '.lock' to implement locking behavior. +func Lock(name string) (io.Closer, error) { + abs, err := filepath.Abs(name) + if err != nil { + return nil, err + } + lockmu.Lock() + defer lockmu.Unlock() + if locked[abs] { + return nil, fmt.Errorf("file %q already locked", abs) + } + + c, err := lockFn(abs) + if err != nil { + return nil, fmt.Errorf("cannot acquire lock: %v", err) + } + locked[abs] = true + return c, nil +} + +var lockFn = lockPortable + +// lockPortable is a portable version not using fcntl. Doesn't handle crashes as gracefully, +// since it can leave stale lock files. +func lockPortable(name string) (io.Closer, error) { + fi, err := os.Stat(name) + if err == nil && fi.Size() > 0 { + st := portableLockStatus(name) + switch st { + case statusLocked: + return nil, fmt.Errorf("file %q already locked", name) + case statusStale: + os.Remove(name) + case statusInvalid: + return nil, fmt.Errorf("can't Lock file %q: has invalid contents", name) + } + } + f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_EXCL, 0666) + if err != nil { + return nil, fmt.Errorf("failed to create lock file %s %v", name, err) + } + if err := json.NewEncoder(f).Encode(&pidLockMeta{OwnerPID: os.Getpid()}); err != nil { + return nil, fmt.Errorf("cannot write owner pid: %v", err) + } + return &unlocker{ + f: f, + abs: name, + portable: true, + }, nil +} + +type lockStatus int + +const ( + statusInvalid lockStatus = iota + statusLocked + statusUnlocked + statusStale +) + +type pidLockMeta struct { + OwnerPID int +} + +func portableLockStatus(path string) lockStatus { + f, err := os.Open(path) + if err != nil { + return statusUnlocked + } + defer f.Close() + var meta pidLockMeta + if json.NewDecoder(f).Decode(&meta) != nil { + return statusInvalid + } + if meta.OwnerPID == 0 { + return statusInvalid + } + p, err := os.FindProcess(meta.OwnerPID) + if err != nil { + // e.g. on Windows + return statusStale + } + // On unix, os.FindProcess always is true, so we have to send + // it a signal to see if it's alive. + if signalZero != nil { + if p.Signal(signalZero) != nil { + return statusStale + } + } + return statusLocked +} + +var signalZero os.Signal // nil or set by lock_sigzero.go + +var ( + lockmu sync.Mutex + locked = map[string]bool{} // abs path -> true +) + +type unlocker struct { + portable bool + f *os.File + abs string + // once guards the close method call. + once sync.Once + // err holds the error returned by Close. + err error +} + +func (u *unlocker) Close() error { + u.once.Do(u.close) + return u.err +} + +func (u *unlocker) close() { + lockmu.Lock() + defer lockmu.Unlock() + delete(locked, u.abs) + + if u.portable { + // In the portable lock implementation, it's + // important to close before removing because + // Windows won't allow us to remove an open + // file. + if err := u.f.Close(); err != nil { + u.err = err + } + if err := os.Remove(u.abs); err != nil { + // Note that if both Close and Remove fail, + // we care more about the latter than the former + // so we'll return that error. + u.err = err + } + return + } + // In other implementatioons, it's nice for us to clean up. + // If we do do this, though, it needs to be before the + // u.f.Close below. + os.Remove(u.abs) + u.err = u.f.Close() +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_appengine.go b/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_appengine.go new file mode 100644 index 00000000..ab4cad6a --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_appengine.go @@ -0,0 +1,32 @@ +// +build appengine + +/* +Copyright 2013 The Go Authors + +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 lock + +import ( + "errors" + "io" +) + +func init() { + lockFn = lockAppEngine +} + +func lockAppEngine(name string) (io.Closer, error) { + return nil, errors.New("Lock not available on App Engine") +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_darwin_amd64.go b/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_darwin_amd64.go new file mode 100644 index 00000000..35f5787b --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_darwin_amd64.go @@ -0,0 +1,67 @@ +// +build darwin,amd64 +// +build !appengine + +/* +Copyright 2013 The Go Authors + +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 lock + +import ( + "fmt" + "io" + "os" + "syscall" + "unsafe" +) + +func init() { + lockFn = lockFcntl +} + +func lockFcntl(name string) (io.Closer, error) { + fi, err := os.Stat(name) + if err == nil && fi.Size() > 0 { + return nil, fmt.Errorf("can't Lock file %q: has non-zero size", name) + } + + f, err := os.Create(name) + if err != nil { + return nil, fmt.Errorf("Lock Create of %s failed: %v", name, err) + } + + // This type matches C's "struct flock" defined in /usr/include/sys/fcntl.h. + // TODO: move this into the standard syscall package. + k := struct { + Start uint64 // sizeof(off_t): 8 + Len uint64 // sizeof(off_t): 8 + Pid uint32 // sizeof(pid_t): 4 + Type uint16 // sizeof(short): 2 + Whence uint16 // sizeof(short): 2 + }{ + Type: syscall.F_WRLCK, + Whence: uint16(os.SEEK_SET), + Start: 0, + Len: 0, // 0 means to lock the entire file. + Pid: uint32(os.Getpid()), + } + + _, _, errno := syscall.Syscall(syscall.SYS_FCNTL, f.Fd(), uintptr(syscall.F_SETLK), uintptr(unsafe.Pointer(&k))) + if errno != 0 { + f.Close() + return nil, errno + } + return &unlocker{f: f, abs: name}, nil +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_freebsd.go b/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_freebsd.go new file mode 100644 index 00000000..ee2767a0 --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_freebsd.go @@ -0,0 +1,66 @@ +/* +Copyright 2013 The Go Authors + +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 lock + +import ( + "fmt" + "io" + "os" + "syscall" + "unsafe" +) + +func init() { + lockFn = lockFcntl +} + +func lockFcntl(name string) (io.Closer, error) { + fi, err := os.Stat(name) + if err == nil && fi.Size() > 0 { + return nil, fmt.Errorf("can't Lock file %q: has non-zero size", name) + } + + f, err := os.Create(name) + if err != nil { + return nil, err + } + + // This type matches C's "struct flock" defined in /usr/include/fcntl.h. + // TODO: move this into the standard syscall package. + k := struct { + Start int64 /* off_t starting offset */ + Len int64 /* off_t len = 0 means until end of file */ + Pid int32 /* pid_t lock owner */ + Type int16 /* short lock type: read/write, etc. */ + Whence int16 /* short type of l_start */ + Sysid int32 /* int remote system id or zero for local */ + }{ + Start: 0, + Len: 0, // 0 means to lock the entire file. + Pid: int32(os.Getpid()), + Type: syscall.F_WRLCK, + Whence: int16(os.SEEK_SET), + Sysid: 0, + } + + _, _, errno := syscall.Syscall(syscall.SYS_FCNTL, f.Fd(), uintptr(syscall.F_SETLK), uintptr(unsafe.Pointer(&k))) + if errno != 0 { + f.Close() + return nil, errno + } + return &unlocker{f: f, abs: name}, nil +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_linux_amd64.go b/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_linux_amd64.go new file mode 100644 index 00000000..08b3aae9 --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_linux_amd64.go @@ -0,0 +1,67 @@ +// +build linux,amd64 +// +build !appengine + +/* +Copyright 2013 The Go Authors + +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 lock + +import ( + "fmt" + "io" + "os" + "syscall" + "unsafe" +) + +func init() { + lockFn = lockFcntl +} + +func lockFcntl(name string) (io.Closer, error) { + fi, err := os.Stat(name) + if err == nil && fi.Size() > 0 { + return nil, fmt.Errorf("can't Lock file %q: has non-zero size", name) + } + + f, err := os.Create(name) + if err != nil { + return nil, err + } + + // This type matches C's "struct flock" defined in /usr/include/bits/fcntl.h. + // TODO: move this into the standard syscall package. + k := struct { + Type uint32 + Whence uint32 + Start uint64 + Len uint64 + Pid uint32 + }{ + Type: syscall.F_WRLCK, + Whence: uint32(os.SEEK_SET), + Start: 0, + Len: 0, // 0 means to lock the entire file. + Pid: uint32(os.Getpid()), + } + + _, _, errno := syscall.Syscall(syscall.SYS_FCNTL, f.Fd(), uintptr(syscall.F_SETLK), uintptr(unsafe.Pointer(&k))) + if errno != 0 { + f.Close() + return nil, errno + } + return &unlocker{f: f, abs: name}, nil +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_linux_arm.go b/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_linux_arm.go new file mode 100644 index 00000000..ebf87bd3 --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_linux_arm.go @@ -0,0 +1,68 @@ +// +build linux,arm +// +build !appengine + +/* +Copyright 2013 The Go Authors + +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 lock + +import ( + "fmt" + "io" + "os" + "syscall" + "unsafe" +) + +func init() { + lockFn = lockFcntl +} + +func lockFcntl(name string) (io.Closer, error) { + fi, err := os.Stat(name) + if err == nil && fi.Size() > 0 { + return nil, fmt.Errorf("can't Lock file %q: has non-zero size", name) + } + + f, err := os.Create(name) + if err != nil { + return nil, err + } + + // This type matches C's "struct flock" defined in /usr/include/bits/fcntl.h. + // TODO: move this into the standard syscall package. + k := struct { + Type uint16 + Whence uint16 + Start uint32 + Len uint32 + Pid uint32 + }{ + Type: syscall.F_WRLCK, + Whence: uint16(os.SEEK_SET), + Start: 0, + Len: 0, // 0 means to lock the entire file. + Pid: uint32(os.Getpid()), + } + + const F_SETLK = 6 // actual value. syscall package is wrong: golang.org/issue/7059 + _, _, errno := syscall.Syscall(syscall.SYS_FCNTL, f.Fd(), uintptr(F_SETLK), uintptr(unsafe.Pointer(&k))) + if errno != 0 { + f.Close() + return nil, errno + } + return &unlocker{f: f, abs: name}, nil +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_plan9.go b/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_plan9.go new file mode 100644 index 00000000..d841c27d --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_plan9.go @@ -0,0 +1,41 @@ +/* +Copyright 2013 The Go Authors + +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 lock + +import ( + "fmt" + "io" + "os" +) + +func init() { + lockFn = lockPlan9 +} + +func lockPlan9(name string) (io.Closer, error) { + fi, err := os.Stat(name) + if err == nil && fi.Size() > 0 { + return nil, fmt.Errorf("can't Lock file %q: has non-zero size", name) + } + + f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE, os.ModeExclusive|0644) + if err != nil { + return nil, fmt.Errorf("Lock Create of %s failed: %v", name, err) + } + + return &unlocker{f: f, abs: name}, nil +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_sigzero.go b/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_sigzero.go new file mode 100644 index 00000000..fd3ba2db --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/camlistore/go4/lock/lock_sigzero.go @@ -0,0 +1,26 @@ +// +build !appengine +// +build linux darwin freebsd openbsd netbsd dragonfly + +/* +Copyright 2013 The Go Authors + +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 lock + +import "syscall" + +func init() { + signalZero = syscall.Signal(0) +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/2pc.go b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/2pc.go new file mode 100644 index 00000000..887604de --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/2pc.go @@ -0,0 +1,324 @@ +// Copyright 2014 The lldb Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Two Phase Commit & Structural ACID + +package lldb + +import ( + "bufio" + "encoding/binary" + "fmt" + "io" + "os" + + "github.com/cznic/fileutil" + "github.com/cznic/mathutil" +) + +var _ Filer = &ACIDFiler0{} // Ensure ACIDFiler0 is a Filer + +type acidWrite struct { + b []byte + off int64 +} + +type acidWriter0 ACIDFiler0 + +func (a *acidWriter0) WriteAt(b []byte, off int64) (n int, err error) { + f := (*ACIDFiler0)(a) + if f.bwal == nil { // new epoch + f.data = f.data[:0] + f.bwal = bufio.NewWriter(f.wal) + if err = a.writePacket([]interface{}{wpt00Header, walTypeACIDFiler0, ""}); err != nil { + return + } + } + + if err = a.writePacket([]interface{}{wpt00WriteData, b, off}); err != nil { + return + } + + f.data = append(f.data, acidWrite{b, off}) + return len(b), nil +} + +func (a *acidWriter0) writePacket(items []interface{}) (err error) { + f := (*ACIDFiler0)(a) + b, err := EncodeScalars(items...) + if err != nil { + return + } + + var b4 [4]byte + binary.BigEndian.PutUint32(b4[:], uint32(len(b))) + if _, err = f.bwal.Write(b4[:]); err != nil { + return + } + + if _, err = f.bwal.Write(b); err != nil { + return + } + + if m := (4 + len(b)) % 16; m != 0 { + var pad [15]byte + _, err = f.bwal.Write(pad[:16-m]) + } + return +} + +// WAL Packet Tags +const ( + wpt00Header = iota + wpt00WriteData + wpt00Checkpoint +) + +const ( + walTypeACIDFiler0 = iota +) + +// ACIDFiler0 is a very simple, synchronous implementation of 2PC. It uses a +// single write ahead log file to provide the structural atomicity +// (BeginUpdate/EndUpdate/Rollback) and durability (DB can be recovered from +// WAL if a crash occurred). +// +// ACIDFiler0 is a Filer. +// +// NOTE: Durable synchronous 2PC involves three fsyncs in this implementation +// (WAL, DB, zero truncated WAL). Where possible, it's recommended to collect +// transactions for, say one second before performing the two phase commit as +// the typical performance for rotational hard disks is about few tens of +// fsyncs per second atmost. For an example of such collective transaction +// approach please see the colecting FSM STT in Dbm's documentation[1]. +// +// [1]: http://godoc.org/github.com/cznic/exp/dbm +type ACIDFiler0 struct { + *RollbackFiler + wal *os.File + bwal *bufio.Writer + data []acidWrite + testHook bool // keeps WAL untruncated (once) + peakWal int64 // tracks WAL maximum used size + peakBitFilerPages int // track maximum transaction memory +} + +// NewACIDFiler0 returns a newly created ACIDFiler0 with WAL in wal. +// +// If the WAL is zero sized then a previous clean shutdown of db is taken for +// granted and no recovery procedure is taken. +// +// If the WAL is of non zero size then it is checked for having a +// commited/fully finished transaction not yet been reflected in db. If such +// transaction exists it's committed to db. If the recovery process finishes +// successfully, the WAL is truncated to zero size and fsync'ed prior to return +// from NewACIDFiler0. +func NewACIDFiler(db Filer, wal *os.File) (r *ACIDFiler0, err error) { + fi, err := wal.Stat() + if err != nil { + return + } + + r = &ACIDFiler0{wal: wal} + + if fi.Size() != 0 { + if err = r.recoverDb(db); err != nil { + return + } + } + + acidWriter := (*acidWriter0)(r) + + if r.RollbackFiler, err = NewRollbackFiler( + db, + func(sz int64) (err error) { + // Checkpoint + if err = acidWriter.writePacket([]interface{}{wpt00Checkpoint, sz}); err != nil { + return + } + + if err = r.bwal.Flush(); err != nil { + return + } + + r.bwal = nil + + if err = r.wal.Sync(); err != nil { + return + } + + wfi, err := r.wal.Stat() + switch err != nil { + case true: + // unexpected, but ignored + case false: + r.peakWal = mathutil.MaxInt64(wfi.Size(), r.peakWal) + } + + // Phase 1 commit complete + + for _, v := range r.data { + if _, err := db.WriteAt(v.b, v.off); err != nil { + return err + } + } + + if err = db.Truncate(sz); err != nil { + return + } + + if err = db.Sync(); err != nil { + return + } + + // Phase 2 commit complete + + if !r.testHook { + if err = r.wal.Truncate(0); err != nil { + return + } + + if _, err = r.wal.Seek(0, 0); err != nil { + return + } + } + + r.testHook = false + return r.wal.Sync() + + }, + acidWriter, + ); err != nil { + return + } + + return r, nil +} + +// PeakWALSize reports the maximum size WAL has ever used. +func (a ACIDFiler0) PeakWALSize() int64 { + return a.peakWal +} + +func (a *ACIDFiler0) readPacket(f *bufio.Reader) (items []interface{}, err error) { + var b4 [4]byte + n, err := io.ReadAtLeast(f, b4[:], 4) + if n != 4 { + return + } + + ln := int(binary.BigEndian.Uint32(b4[:])) + m := (4 + ln) % 16 + padd := (16 - m) % 16 + b := make([]byte, ln+padd) + if n, err = io.ReadAtLeast(f, b, len(b)); n != len(b) { + return + } + + return DecodeScalars(b[:ln]) +} + +func (a *ACIDFiler0) recoverDb(db Filer) (err error) { + fi, err := a.wal.Stat() + if err != nil { + return &ErrILSEQ{Type: ErrInvalidWAL, Name: a.wal.Name(), More: err} + } + + if sz := fi.Size(); sz%16 != 0 { + return &ErrILSEQ{Type: ErrFileSize, Name: a.wal.Name(), Arg: sz} + } + + f := bufio.NewReader(a.wal) + items, err := a.readPacket(f) + if err != nil { + return + } + + if len(items) != 3 || items[0] != int64(wpt00Header) || items[1] != int64(walTypeACIDFiler0) { + return &ErrILSEQ{Type: ErrInvalidWAL, Name: a.wal.Name(), More: fmt.Sprintf("invalid packet items %#v", items)} + } + + tr := NewBTree(nil) + + for { + items, err = a.readPacket(f) + if err != nil { + return + } + + if len(items) < 2 { + return &ErrILSEQ{Type: ErrInvalidWAL, Name: a.wal.Name(), More: fmt.Sprintf("too few packet items %#v", items)} + } + + switch items[0] { + case int64(wpt00WriteData): + if len(items) != 3 { + return &ErrILSEQ{Type: ErrInvalidWAL, Name: a.wal.Name(), More: fmt.Sprintf("invalid data packet items %#v", items)} + } + + b, off := items[1].([]byte), items[2].(int64) + var key [8]byte + binary.BigEndian.PutUint64(key[:], uint64(off)) + if err = tr.Set(key[:], b); err != nil { + return + } + case int64(wpt00Checkpoint): + var b1 [1]byte + if n, err := f.Read(b1[:]); n != 0 || err == nil { + return &ErrILSEQ{Type: ErrInvalidWAL, Name: a.wal.Name(), More: fmt.Sprintf("checkpoint n %d, err %v", n, err)} + } + + if len(items) != 2 { + return &ErrILSEQ{Type: ErrInvalidWAL, Name: a.wal.Name(), More: fmt.Sprintf("checkpoint packet invalid items %#v", items)} + } + + sz := items[1].(int64) + enum, err := tr.seekFirst() + if err != nil { + return err + } + + for { + k, v, err := enum.current() + if err != nil { + if fileutil.IsEOF(err) { + break + } + + return err + } + + if _, err = db.WriteAt(v, int64(binary.BigEndian.Uint64(k))); err != nil { + return err + } + + if err = enum.next(); err != nil { + if fileutil.IsEOF(err) { + break + } + + return err + } + } + + if err = db.Truncate(sz); err != nil { + return err + } + + if err = db.Sync(); err != nil { + return err + } + + // Recovery complete + + if err = a.wal.Truncate(0); err != nil { + return err + } + + return a.wal.Sync() + default: + return &ErrILSEQ{Type: ErrInvalidWAL, Name: a.wal.Name(), More: fmt.Sprintf("packet tag %v", items[0])} + } + } +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/2pc_docs.go b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/2pc_docs.go new file mode 100644 index 00000000..02c993b8 --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/2pc_docs.go @@ -0,0 +1,44 @@ +// Copyright 2014 The lldb Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + +Anatomy of a WAL file + +WAL file + A sequence of packets + +WAL packet, parts in slice notation + [0:4], 4 bytes: N uint32 // network byte order + [4:4+N], N bytes: payload []byte // gb encoded scalars + +Packets, including the 4 byte 'size' prefix, MUST BE padded to size == 0 (mod +16). The values of the padding bytes MUST BE zero. + +Encoded scalars first item is a packet type number (packet tag). The meaning of +any other item(s) of the payload depends on the packet tag. + +Packet definitions + + {wpt00Header int, typ int, s string} + typ: Must be zero (ACIDFiler0 file). + s: Any comment string, empty string is okay. + + This packet must be present only once - as the first packet of + a WAL file. + + {wpt00WriteData int, b []byte, off int64} + Write data (WriteAt(b, off)). + + {wpt00Checkpoint int, sz int64} + Checkpoint (Truncate(sz)). + + This packet must be present only once - as the last packet of + a WAL file. + +*/ + +package lldb + +//TODO optimize bitfiler/wal/2pc data above final size diff --git a/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/btree.go b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/btree.go new file mode 100644 index 00000000..8e58a925 --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/btree.go @@ -0,0 +1,2320 @@ +// Copyright 2014 The lldb 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 lldb + +import ( + "bytes" + "errors" + "fmt" + "io" + "sort" + "strings" + + "github.com/cznic/bufs" + "github.com/cznic/fileutil" + "github.com/cznic/sortutil" +) + +const ( + kData = 256 // [1, 512] + kIndex = 256 // [2, 2048] + kKV = 19 // Size of the key/value field in btreeDataPage + kSz = kKV - 1 - 7 // Content prefix size + kH = kKV - 7 // Content field offset for handle + tagBTreeDataPage = 1 + tagBTreeIndexPage = 0 +) + +// BTree is a B+tree[1][2], i.e. a variant which speeds up +// enumeration/iteration of the BTree. According to its origin it can be +// volatile (backed only by memory) or non-volatile (backed by a non-volatile +// Allocator). +// +// The specific implementation of BTrees in this package are B+trees with +// delayed split/concatenation (discussed in e.g. [3]). +// +// Note: No BTree methods returns io.EOF for physical Filer reads/writes. The +// io.EOF is returned only by bTreeEnumerator methods to indicate "no more K-V +// pair". +// +// [1]: http://en.wikipedia.org/wiki/B+tree +// [2]: http://zgking.com:8080/home/donghui/publications/books/dshandbook_BTree.pdf +// [3]: http://people.cs.aau.dk/~simas/aalg06/UbiquitBtree.pdf +type BTree struct { + store btreeStore + root btree + collate func(a, b []byte) int + serial uint64 +} + +// NewBTree returns a new, memory-only BTree. +func NewBTree(collate func(a, b []byte) int) *BTree { + store := newMemBTreeStore() + root, err := newBTree(store) + if err != nil { // should not happen + panic(err.Error()) + } + + return &BTree{store, root, collate, 0} +} + +// IsMem reports if t is a memory only BTree. +func (t *BTree) IsMem() (r bool) { + _, r = t.store.(*memBTreeStore) + return +} + +// Clear empties the tree. +func (t *BTree) Clear() (err error) { + if t == nil { + err = errors.New("BTree method invoked on nil receiver") + return + } + + t.serial++ + return t.root.clear(t.store) +} + +// Delete deletes key and its associated value from the tree. +func (t *BTree) Delete(key []byte) (err error) { + if t == nil { + err = errors.New("BTree method invoked on nil receiver") + return + } + + t.serial++ + _, err = t.root.extract(t.store, nil, t.collate, key) + return +} + +// DeleteAny deletes one key and its associated value from the tree. If the +// tree is empty on return then empty is true. +func (t *BTree) DeleteAny() (empty bool, err error) { + if t == nil { + err = errors.New("BTree method invoked on nil receiver") + return + } + + t.serial++ + return t.root.deleteAny(t.store) +} + +func elem(v interface{}) string { + switch x := v.(type) { + default: + panic("internal error") + case nil: + return "nil" + case bool: + if x { + return "true" + } + + return "false" + case int64: + return fmt.Sprint(x) + case uint64: + return fmt.Sprint(x) + case float64: + s := fmt.Sprintf("%g", x) + if !strings.Contains(s, ".") { + s += "." + } + return s + case complex128: + s := fmt.Sprint(x) + return s[1 : len(s)-1] + case []byte: + return fmt.Sprintf("[]byte{% 02x}", x) + case string: + return fmt.Sprintf("%q", x) + } +} + +// Dump outputs a human readable dump of t to w. It is usable iff t keys and +// values are encoded scalars (see EncodeScalars). Intended use is only for +// examples or debugging. Some type information is lost in the rendering, for +// example a float value '17.' and an integer value '17' may both output as +// '17'. +func (t *BTree) Dump(w io.Writer) (err error) { + enum, err := t.seekFirst() + if err != nil { + return + } + + for { + bkey, bval, err := enum.current() + if err != nil { + return err + } + + key, err := DecodeScalars(bkey) + if err != nil { + return err + } + + val, err := DecodeScalars(bval) + if err != nil { + return err + } + + kk := []string{} + if key == nil { + kk = []string{"null"} + } + for _, v := range key { + kk = append(kk, elem(v)) + } + vv := []string{} + if val == nil { + vv = []string{"null"} + } + for _, v := range val { + vv = append(vv, elem(v)) + } + skey := strings.Join(kk, ", ") + sval := strings.Join(vv, ", ") + if len(vv) > 1 { + sval = fmt.Sprintf("[]interface{%s}", sval) + } + if _, err = fmt.Fprintf(w, "%s → %s\n", skey, sval); err != nil { + return err + } + + err = enum.next() + if err != nil { + if fileutil.IsEOF(err) { + err = nil + break + } + + return err + } + } + return +} + +// Extract is a combination of Get and Delete. If the key exists in the tree, +// it is returned (like Get) and also deleted from a tree in a more efficient +// way which doesn't walk it twice. The returned slice may be a sub-slice of +// buf if buf was large enough to hold the entire content. Otherwise, a newly +// allocated slice will be returned. It is valid to pass a nil buf. +func (t *BTree) Extract(buf, key []byte) (value []byte, err error) { + if t == nil { + err = errors.New("BTree method invoked on nil receiver") + return + } + + t.serial++ + return t.root.extract(t.store, buf, t.collate, key) +} + +// First returns the first KV pair of the tree, if it exists. Otherwise key == nil +// and value == nil. +func (t *BTree) First() (key, value []byte, err error) { + if t == nil { + err = errors.New("BTree method invoked on nil receiver") + return + } + + var p btreeDataPage + if _, p, err = t.root.first(t.store); err != nil || p == nil { + return + } + + if key, err = p.key(t.store, 0); err != nil { + return + } + + value, err = p.value(t.store, 0) + return +} + +// Get returns the value associated with key, or nil if no such value exists. +// The returned slice may be a sub-slice of buf if buf was large enough to hold +// the entire content. Otherwise, a newly allocated slice will be returned. +// It is valid to pass a nil buf. +// +// Get is safe for concurrent access by multiple goroutines iff no other +// goroutine mutates the tree. +func (t *BTree) Get(buf, key []byte) (value []byte, err error) { + if t == nil { + err = errors.New("BTree method invoked on nil receiver") + return + } + + buffer := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(buffer) + if buffer, err = t.root.get(t.store, buffer, t.collate, key); buffer == nil || err != nil { + return + } + + if len(buffer) != 0 { + // The buffer cache returns nil for empty buffers, bypass it + value = need(len(buffer), buf) + } else { + value = []byte{} + } + copy(value, buffer) + return +} + +// Handle reports t's handle. +func (t *BTree) Handle() int64 { + return int64(t.root) +} + +// Last returns the last KV pair of the tree, if it exists. Otherwise key == nil +// and value == nil. +func (t *BTree) Last() (key, value []byte, err error) { + if t == nil { + err = errors.New("BTree method invoked on nil receiver") + return + } + + var p btreeDataPage + if _, p, err = t.root.last(t.store); err != nil || p == nil { + return + } + + index := p.len() - 1 + if key, err = p.key(t.store, index); err != nil { + return + } + + value, err = p.value(t.store, index) + return +} + +// Put combines Get and Set in a more efficient way where the tree is walked +// only once. The upd(ater) receives the current (key, old-value), if that +// exists or (key, nil) otherwise. It can then return a (new-value, true, nil) +// to create or overwrite the existing value in the KV pair, or (whatever, +// false, nil) if it decides not to create or not to update the value of the KV +// pair. +// +// tree.Set(k, v) +// +// conceptually equals +// +// tree.Put(k, func(k, v []byte){ return v, true }([]byte, bool)) +// +// modulo the differing return values. +// +// The returned slice may be a sub-slice of buf if buf was large enough to hold +// the entire content. Otherwise, a newly allocated slice will be returned. +// It is valid to pass a nil buf. +func (t *BTree) Put(buf, key []byte, upd func(key, old []byte) (new []byte, write bool, err error)) (old []byte, written bool, err error) { + if t == nil { + err = errors.New("BTree method invoked on nil receiver") + return + } + + t.serial++ + return t.root.put2(buf, t.store, t.collate, key, upd) +} + +// Seek returns an Enumerator with "position" or an error of any. Normally the +// position is on a KV pair such that key >= KV.key. Then hit is key == KV.key. +// The position is possibly "after" the last KV pair, but that is not an error. +// +// Seek is safe for concurrent access by multiple goroutines iff no other +// goroutine mutates the tree. +func (t *BTree) Seek(key []byte) (enum *BTreeEnumerator, hit bool, err error) { + enum0, hit, err := t.seek(key) + if err != nil { + return + } + + enum = &BTreeEnumerator{ + enum: enum0, + firstHit: hit, + key: append([]byte(nil), key...), + } + return +} + +func (t *BTree) seek(key []byte) (enum *bTreeEnumerator, hit bool, err error) { + if t == nil { + err = errors.New("BTree method invoked on nil receiver") + return + } + + r := &bTreeEnumerator{t: t, collate: t.collate, serial: t.serial} + if r.p, r.index, hit, err = t.root.seek(t.store, r.collate, key); err != nil { + return + } + + enum = r + return +} + +// IndexSeek returns an Enumerator with "position" or an error of any. Normally +// the position is on a KV pair such that key >= KV.key. Then hit is key == +// KV.key. The position is possibly "after" the last KV pair, but that is not +// an error. The collate function originally passed to CreateBTree is used for +// enumerating the tree but a custom collate function c is used for IndexSeek. +// +// IndexSeek is safe for concurrent access by multiple goroutines iff no other +// goroutine mutates the tree. +func (t *BTree) IndexSeek(key []byte, c func(a, b []byte) int) (enum *BTreeEnumerator, hit bool, err error) { //TODO +test + enum0, hit, err := t.indexSeek(key, c) + if err != nil { + return + } + + enum = &BTreeEnumerator{ + enum: enum0, + firstHit: hit, + key: append([]byte(nil), key...), + } + return +} + +func (t *BTree) indexSeek(key []byte, c func(a, b []byte) int) (enum *bTreeEnumerator, hit bool, err error) { + if t == nil { + err = errors.New("BTree method invoked on nil receiver") + return + } + + r := &bTreeEnumerator{t: t, collate: t.collate, serial: t.serial} + if r.p, r.index, hit, err = t.root.seek(t.store, c, key); err != nil { + return + } + + enum = r + return +} + +// seekFirst returns an enumerator positioned on the first KV pair in the tree, +// if any. For an empty tree, err == io.EOF is returend. +// +// SeekFirst is safe for concurrent access by multiple goroutines iff no other +// goroutine mutates the tree. +func (t *BTree) SeekFirst() (enum *BTreeEnumerator, err error) { + enum0, err := t.seekFirst() + if err != nil { + return + } + + var key []byte + if key, _, err = enum0.current(); err != nil { + return + } + + enum = &BTreeEnumerator{ + enum: enum0, + firstHit: true, + key: append([]byte(nil), key...), + } + return +} + +func (t *BTree) seekFirst() (enum *bTreeEnumerator, err error) { + if t == nil { + err = errors.New("BTree method invoked on nil receiver") + return + } + + var p btreeDataPage + if _, p, err = t.root.first(t.store); err == nil && p == nil { + err = io.EOF + } + if err != nil { + return + } + + return &bTreeEnumerator{t: t, collate: t.collate, p: p, index: 0, serial: t.serial}, nil +} + +// seekLast returns an enumerator positioned on the last KV pair in the tree, +// if any. For an empty tree, err == io.EOF is returend. +// +// SeekLast is safe for concurrent access by multiple goroutines iff no other +// goroutine mutates the tree. +func (t *BTree) SeekLast() (enum *BTreeEnumerator, err error) { + enum0, err := t.seekLast() + if err != nil { + return + } + + var key []byte + if key, _, err = enum0.current(); err != nil { + return + } + + enum = &BTreeEnumerator{ + enum: enum0, + firstHit: true, + key: append([]byte(nil), key...), + } + return +} + +func (t *BTree) seekLast() (enum *bTreeEnumerator, err error) { + if t == nil { + err = errors.New("BTree method invoked on nil receiver") + return + } + + var p btreeDataPage + if _, p, err = t.root.last(t.store); err == nil && p == nil { + err = io.EOF + } + if err != nil { + return + } + + return &bTreeEnumerator{t: t, collate: t.collate, p: p, index: p.len() - 1, serial: t.serial}, nil +} + +// Set sets the value associated with key. Any previous value, if existed, is +// overwritten by the new one. +func (t *BTree) Set(key, value []byte) (err error) { + if t == nil { + err = errors.New("BTree method invoked on nil receiver") + return + } + + t.serial++ + dst := bufs.GCache.Get(maxBuf) + _, err = t.root.put(dst, t.store, t.collate, key, value, true) + bufs.GCache.Put(dst) + return +} + +// bTreeEnumerator is a closure of a BTree and a position. It is returned from +// BTree.seek. +// +// NOTE: bTreeEnumerator cannot be used after its BTree was mutated after the +// bTreeEnumerator was acquired from any of the seek, seekFirst, seekLast +// methods. +type bTreeEnumerator struct { + t *BTree + collate func(a, b []byte) int + p btreeDataPage + index int + serial uint64 +} + +// Current returns the KV pair the enumerator is currently positioned on. If +// the position is before the first KV pair in the tree or after the last KV +// pair in the tree then err == io.EOF is returned. +// +// If the enumerator has been invalidated by updating the tree, ErrINVAL is +// returned. +func (e *bTreeEnumerator) current() (key, value []byte, err error) { + if e == nil { + err = errors.New("bTreeEnumerator method invoked on nil receiver") + return + } + + if e.serial != e.t.serial { + err = &ErrINVAL{Src: "bTreeEnumerator invalidated by updating the tree"} + return + } + + if e.p == nil || e.index == e.p.len() { + return nil, nil, io.EOF + } + + if key, err = e.p.key(e.t.store, e.index); err != nil { + return + } + + value, err = e.p.value(e.t.store, e.index) + return +} + +// Next attempts to position the enumerator onto the next KV pair wrt the +// current position. If there is no "next" KV pair, io.EOF is returned. +// +// If the enumerator has been invalidated by updating the tree, ErrINVAL is +// returned. +func (e *bTreeEnumerator) next() (err error) { + if e == nil { + err = errors.New("bTreeEnumerator method invoked on nil receiver") + return + } + + if e.serial != e.t.serial { + err = &ErrINVAL{Src: "bTreeEnumerator invalidated by updating the tree"} + return + } + + if e.p == nil { + return io.EOF + } + + switch { + case e.index < e.p.len()-1: + e.index++ + default: + ph := e.p.next() + if ph == 0 { + err = io.EOF + break + } + + if e.p, err = e.t.store.Get(e.p, ph); err != nil { + e.p = nil + return + } + e.index = 0 + } + return +} + +// Prev attempts to position the enumerator onto the previous KV pair wrt the +// current position. If there is no "previous" KV pair, io.EOF is returned. +// +// If the enumerator has been invalidated by updating the tree, ErrINVAL is +// returned. +func (e *bTreeEnumerator) prev() (err error) { + if e == nil { + err = errors.New("bTreeEnumerator method invoked on nil receiver") + return + } + + if e.serial != e.t.serial { + err = &ErrINVAL{Src: "bTreeEnumerator invalidated by updating the tree"} + return + } + + if e.p == nil { + return io.EOF + } + + switch { + case e.index > 0: + e.index-- + default: + ph := e.p.prev() + if ph == 0 { + err = io.EOF + break + } + + if e.p, err = e.t.store.Get(e.p, ph); err != nil { + e.p = nil + return + } + e.index = e.p.len() - 1 + } + return +} + +// BTreeEnumerator captures the state of enumerating a tree. It is returned +// from the Seek* methods. The enumerator is aware of any mutations made to +// the tree in the process of enumerating it and automatically resumes the +// enumeration. +type BTreeEnumerator struct { + enum *bTreeEnumerator + err error + key []byte + firstHit bool +} + +// Next returns the currently enumerated KV pair, if it exists and moves to the +// next KV in the key collation order. If there is no KV pair to return, err == +// io.EOF is returned. +// +// Next is safe for concurrent access by multiple goroutines iff no other +// goroutine mutates the tree. +func (e *BTreeEnumerator) Next() (key, value []byte, err error) { + if err = e.err; err != nil { + return + } + + canRetry := true +retry: + if e.enum.p == nil { + e.err = io.EOF + return nil, nil, e.err + } + + if e.enum.index == e.enum.p.len() && e.enum.serial == e.enum.t.serial { + if err := e.enum.next(); err != nil { + e.err = err + return nil, nil, e.err + } + } + + if key, value, err = e.enum.current(); err != nil { + if _, ok := err.(*ErrINVAL); !ok || !canRetry { + e.err = err + return + } + + canRetry = false + var hit bool + if e.enum, hit, err = e.enum.t.seek(e.key); err != nil { + e.err = err + return + } + + if !e.firstHit && hit { + err = e.enum.next() + if err != nil { + e.err = err + return + } + } + + goto retry + } + + e.firstHit = false + e.key = append([]byte(nil), key...) + e.err = e.enum.next() + return +} + +// Prev returns the currently enumerated KV pair, if it exists and moves to the +// previous KV in the key collation order. If there is no KV pair to return, +// err == io.EOF is returned. +// +// Prev is safe for concurrent access by multiple goroutines iff no other +// goroutine mutates the tree. +func (e *BTreeEnumerator) Prev() (key, value []byte, err error) { + if err = e.err; err != nil { + return + } + + canRetry := true +retry: + if key, value, err = e.enum.current(); err != nil { + if _, ok := err.(*ErrINVAL); !ok || !canRetry { + e.err = err + return + } + + canRetry = false + var hit bool + if e.enum, hit, err = e.enum.t.seek(e.key); err != nil { + e.err = err + return + } + + if !e.firstHit && hit { + err = e.enum.prev() + if err != nil { + e.err = err + return + } + } + + goto retry + } + + e.firstHit = false + e.key = append([]byte(nil), key...) + e.err = e.enum.prev() + return +} + +// CreateBTree creates a new BTree in store. It returns the tree, its (freshly +// assigned) handle (for OpenBTree or RemoveBTree) or an error, if any. +func CreateBTree(store *Allocator, collate func(a, b []byte) int) (bt *BTree, handle int64, err error) { + r := &BTree{store: store, collate: collate} + if r.root, err = newBTree(store); err != nil { + return + } + + return r, int64(r.root), nil +} + +// OpenBTree opens a store's BTree using handle. It returns the tree or an +// error, if any. The same tree may be opened more than once, but operations on +// the separate instances should not ever overlap or void the other instances. +// However, the intended API usage is to open the same tree handle only once +// (handled by some upper layer "dispatcher"). +func OpenBTree(store *Allocator, collate func(a, b []byte) int, handle int64) (bt *BTree, err error) { + r := &BTree{store: store, root: btree(handle), collate: collate} + b := bufs.GCache.Get(7) + defer bufs.GCache.Put(b) + if b, err = store.Get(b, handle); err != nil { + return + } + + if len(b) != 7 { + return nil, &ErrILSEQ{Off: h2off(handle), More: "btree.go:671"} + } + + return r, nil +} + +// RemoveBTree removes tree, represented by handle from store. Empty trees are +// cheap, each uses only few bytes of the store. If there's a chance that a +// tree will eventually get reused (non empty again), it's recommended to +// not/never remove it. One advantage of such approach is a stable handle of +// such tree. +func RemoveBTree(store *Allocator, handle int64) (err error) { + tree, err := OpenBTree(store, nil, handle) + if err != nil { + return + } + + if err = tree.Clear(); err != nil { + return + } + + return store.Free(handle) +} + +type btreeStore interface { + Alloc(b []byte) (handle int64, err error) + Free(handle int64) (err error) + Get(dst []byte, handle int64) (b []byte, err error) + Realloc(handle int64, b []byte) (err error) +} + +// Read only zero bytes +var zeros [2 * kKV]byte + +func init() { + if kData < 1 || kData > 512 { + panic(fmt.Errorf("kData %d: out of limits", kData)) + } + + if kIndex < 2 || kIndex > 2048 { + panic(fmt.Errorf("kIndex %d: out of limits", kIndex)) + } + + if kKV < 8 || kKV > 23 { + panic(fmt.Errorf("kKV %d: out of limits", kKV)) + } + + if n := len(zeros); n < 15 { + panic(fmt.Errorf("not enough zeros: %d", n)) + } +} + +type memBTreeStore struct { + h int64 + m map[int64][]byte +} + +func newMemBTreeStore() *memBTreeStore { + return &memBTreeStore{h: 0, m: map[int64][]byte{}} +} + +func (s *memBTreeStore) String() string { + var a sortutil.Int64Slice + for k := range s.m { + a = append(a, k) + } + sort.Sort(a) + var sa []string + for _, k := range a { + sa = append(sa, fmt.Sprintf("%#x:|% x|", k, s.m[k])) + } + return strings.Join(sa, "\n") +} + +func (s *memBTreeStore) Alloc(b []byte) (handle int64, err error) { + s.h++ + handle = s.h + s.m[handle] = bpack(b) + return +} + +func (s *memBTreeStore) Free(handle int64) (err error) { + if _, ok := s.m[handle]; !ok { + return &ErrILSEQ{Type: ErrOther, Off: h2off(handle), More: "btree.go:754"} + } + + delete(s.m, handle) + return +} + +func (s *memBTreeStore) Get(dst []byte, handle int64) (b []byte, err error) { + r, ok := s.m[handle] + if !ok { + return nil, &ErrILSEQ{Type: ErrOther, Off: h2off(handle), More: "btree.go:764"} + } + + b = need(len(r), dst) + copy(b, r) + return +} + +func (s *memBTreeStore) Realloc(handle int64, b []byte) (err error) { + if _, ok := s.m[handle]; !ok { + return &ErrILSEQ{Type: ErrOther, Off: h2off(handle), More: "btree.go:774"} + } + + s.m[handle] = bpack(b) + return +} + +/* + +0...0 (1 bytes): +Flag + + 0 + +---+ + | 0 | + +---+ + +0 indicates an index page + +1...count*14-1 +"array" of items, 14 bytes each. Count of items in kIndex-1..2*kIndex+2 + + Count = (len(raw) - 8) / 14 + + 0..6 7..13 + +-------+----------+ + | Child | DataPage | + +-------+----------+ + + Child == handle of a child index page + DataPage == handle of a data page + +Offsets into the raw []byte: +Child[X] == 1+14*X +DataPage[X] == 8+14*X + +*/ +type btreeIndexPage []byte + +func newBTreeIndexPage(leftmostChild int64) (p btreeIndexPage) { + p = bufs.GCache.Get(1 + (kIndex+1)*2*7)[:8] + p[0] = tagBTreeIndexPage + h2b(p[1:], leftmostChild) + return +} + +func (p btreeIndexPage) len() int { + return (len(p) - 8) / 14 +} + +func (p btreeIndexPage) child(index int) int64 { + return b2h(p[1+14*index:]) +} + +func (p btreeIndexPage) setChild(index int, dp int64) { + h2b(p[1+14*index:], dp) +} + +func (p btreeIndexPage) dataPage(index int) int64 { + return b2h(p[8+14*index:]) +} + +func (p btreeIndexPage) setDataPage(index int, dp int64) { + h2b(p[8+14*index:], dp) +} + +func (q btreeIndexPage) insert(index int) btreeIndexPage { + switch len0 := q.len(); { + case index < len0: + has := len(q) + need := has + 14 + switch { + case cap(q) >= need: + q = q[:need] + default: + q = append(q, zeros[:14]...) + } + copy(q[8+14*(index+1):8+14*(index+1)+2*(len0-index)*7], q[8+14*index:]) + case index == len0: + has := len(q) + need := has + 14 + switch { + case cap(q) >= need: + q = q[:need] + default: + q = append(q, zeros[:14]...) + } + } + return q +} + +func (p btreeIndexPage) insert3(index int, dataPage, child int64) btreeIndexPage { + p = p.insert(index) + p.setDataPage(index, dataPage) + p.setChild(index+1, child) + return p +} + +func (p btreeIndexPage) cmp(a btreeStore, c func(a, b []byte) int, keyA []byte, keyBIndex int) (int, error) { + b := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(b) + dp, err := a.Get(b, p.dataPage(keyBIndex)) + if err != nil { + return 0, err + } + + return btreeDataPage(dp).cmp(a, c, keyA, 0) +} + +func (q btreeIndexPage) setLen(n int) btreeIndexPage { + q = q[:cap(q)] + need := 8 + 14*n + if need < len(q) { + return q[:need] + } + return append(q, make([]byte, need-len(q))...) +} + +func (p btreeIndexPage) split(a btreeStore, root btree, ph *int64, parent int64, parentIndex int, index *int) (btreeIndexPage, error) { + right := newBTreeIndexPage(0) + canRecycle := true + defer func() { + if canRecycle { + bufs.GCache.Put(right) + } + }() + right = right.setLen(kIndex) + copy(right[1:1+(2*kIndex+1)*7], p[1+14*(kIndex+1):]) + p = p.setLen(kIndex) + if err := a.Realloc(*ph, p); err != nil { + return nil, err + } + + rh, err := a.Alloc(right) + if err != nil { + return nil, err + } + + if parentIndex >= 0 { + var pp btreeIndexPage = bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(pp) + if pp, err = a.Get(pp, parent); err != nil { + return nil, err + } + pp = pp.insert3(parentIndex, p.dataPage(kIndex), rh) + if err = a.Realloc(parent, pp); err != nil { + return nil, err + } + + } else { + nr := newBTreeIndexPage(*ph) + defer bufs.GCache.Put(nr) + nr = nr.insert3(0, p.dataPage(kIndex), rh) + nrh, err := a.Alloc(nr) + if err != nil { + return nil, err + } + + if err = a.Realloc(int64(root), h2b(make([]byte, 7), nrh)); err != nil { + return nil, err + } + } + if *index > kIndex { + p = right + canRecycle = false + *ph = rh + *index -= kIndex + 1 + } + return p, nil +} + +// p is dirty on return +func (p btreeIndexPage) extract(index int) btreeIndexPage { + n := p.len() - 1 + if index < n { + sz := (n-index)*14 + 7 + copy(p[1+14*index:1+14*index+sz], p[1+14*(index+1):]) + } + return p.setLen(n) +} + +// must persist all changes made +func (p btreeIndexPage) underflow(a btreeStore, root, iroot, parent int64, ph *int64, parentIndex int, index *int) (btreeIndexPage, error) { + lh, rh, err := checkSiblings(a, parent, parentIndex) + if err != nil { + return nil, err + } + + var left btreeIndexPage = bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(left) + + if lh != 0 { + if left, err = a.Get(left, lh); err != nil { + return nil, err + } + + if lc := btreeIndexPage(left).len(); lc > kIndex { + var pp = bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(pp) + if pp, err = a.Get(pp, parent); err != nil { + return nil, err + } + + pc := p.len() + p = p.setLen(pc + 1) + di, si, sz := 1+1*14, 1+0*14, (2*pc+1)*7 + copy(p[di:di+sz], p[si:]) + p.setChild(0, btreeIndexPage(left).child(lc)) + p.setDataPage(0, btreeIndexPage(pp).dataPage(parentIndex-1)) + *index++ + btreeIndexPage(pp).setDataPage(parentIndex-1, btreeIndexPage(left).dataPage(lc-1)) + left = left.setLen(lc - 1) + if err = a.Realloc(parent, pp); err != nil { + return nil, err + } + + if err = a.Realloc(*ph, p); err != nil { + return nil, err + } + + return p, a.Realloc(lh, left) + } + } + + if rh != 0 { + right := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(right) + if right, err = a.Get(right, rh); err != nil { + return nil, err + } + + if rc := btreeIndexPage(right).len(); rc > kIndex { + pp := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(pp) + if pp, err = a.Get(pp, parent); err != nil { + return nil, err + } + + pc := p.len() + p = p.setLen(pc + 1) + p.setDataPage(pc, btreeIndexPage(pp).dataPage(parentIndex)) + pc++ + p.setChild(pc, btreeIndexPage(right).child(0)) + btreeIndexPage(pp).setDataPage(parentIndex, btreeIndexPage(right).dataPage(0)) + di, si, sz := 1+0*14, 1+1*14, (2*rc+1)*7 + copy(right[di:di+sz], right[si:]) + right = btreeIndexPage(right).setLen(rc - 1) + if err = a.Realloc(parent, pp); err != nil { + return nil, err + } + + if err = a.Realloc(*ph, p); err != nil { + return nil, err + } + + return p, a.Realloc(rh, right) + } + } + + if lh != 0 { + *index += left.len() + 1 + if left, err = left.concat(a, root, iroot, parent, lh, *ph, parentIndex-1); err != nil { + return p, err + } + + p, *ph = left, lh + return p, nil + } + + return p.concat(a, root, iroot, parent, *ph, rh, parentIndex) +} + +// must persist all changes made +func (p btreeIndexPage) concat(a btreeStore, root, iroot, parent, ph, rh int64, parentIndex int) (btreeIndexPage, error) { + pp := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(pp) + pp, err := a.Get(pp, parent) + if err != nil { + return nil, err + } + + right := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(right) + if right, err = a.Get(right, rh); err != nil { + return nil, err + } + + pc := p.len() + rc := btreeIndexPage(right).len() + p = p.setLen(pc + rc + 1) + p.setDataPage(pc, btreeIndexPage(pp).dataPage(parentIndex)) + di, si, sz := 1+14*(pc+1), 1+0*14, (2*rc+1)*7 + copy(p[di:di+sz], right[si:]) + if err := a.Realloc(ph, p); err != nil { + return nil, err + } + + if err := a.Free(rh); err != nil { + return nil, err + } + + if pc := btreeIndexPage(pp).len(); pc > 1 { + if parentIndex < pc-1 { + di, si, sz := 8+parentIndex*14, 8+(parentIndex+1)*14, 2*(pc-1-parentIndex)*7 + copy(pp[di:si+sz], pp[si:]) + } + pp = btreeIndexPage(pp).setLen(pc - 1) + return p, a.Realloc(parent, pp) + } + + if err := a.Free(iroot); err != nil { + return nil, err + } + + b7 := bufs.GCache.Get(7) + defer bufs.GCache.Put(b7) + return p, a.Realloc(root, h2b(b7[:7], ph)) +} + +/* + +0...0 (1 bytes): +Flag + + 0 + +---+ + | 1 | + +---+ + +1 indicates a data page + +1...14 (14 bytes) + + 1..7 8..14 + +------+------+ + | Prev | Next | + +------+------+ + + Prev, Next == Handles of the data pages doubly linked list + + Count = (len(raw) - 15) / (2*kKV) + +15...count*2*kKV-1 +"array" of items, 2*kKV bytes each. Count of items in kData-1..2*kData + +Item + 0..kKV-1 kKV..2*kKV-1 + +----------+--------------+ + | Key | Value | + +----------+--------------+ + +Key/Value encoding + +Length 0...kKV-1 + + 0 1...N N+1...kKV-1 + +---+---------+-------------+ + | N | Data | Padding | + +---+---------+-------------+ + + N == content length + Data == Key or Value content + Padding == MUST be zero bytes + +Length >= kKV + + 0 1...kkV-8 kKV-7...kkV-1 + +------+-----------+--------------+ + | 0xFF | Data | H | + +------+-----------+--------------+ + + Data == Key or Value content, first kKV-7 bytes + H == Handle to THE REST of the content, w/o the first bytes in Data. + +Offsets into the raw []byte: +Key[X] == 15+2*kKV*X +Value[X] == 15+kKV+2*kKV*X +*/ +type btreeDataPage []byte + +func newBTreeDataPage() (p btreeDataPage) { + p = bufs.GCache.Cget(1 + 2*7 + (kData+1)*2*kKV)[:1+2*7] + p[0] = tagBTreeDataPage + return +} + +func newBTreeDataPageAlloc(a btreeStore) (p btreeDataPage, h int64, err error) { + p = newBTreeDataPage() + h, err = a.Alloc(p) + return +} + +func (p btreeDataPage) len() int { + return (len(p) - 15) / (2 * kKV) +} + +func (q btreeDataPage) setLen(n int) btreeDataPage { + q = q[:cap(q)] + need := 15 + 2*kKV*n + if need < len(q) { + return q[:need] + } + return append(q, make([]byte, need-len(q))...) +} + +func (p btreeDataPage) prev() int64 { + return b2h(p[1:]) +} + +func (p btreeDataPage) next() int64 { + return b2h(p[8:]) +} + +func (p btreeDataPage) setPrev(h int64) { + h2b(p[1:], h) +} + +func (p btreeDataPage) setNext(h int64) { + h2b(p[8:], h) +} + +func (q btreeDataPage) insert(index int) btreeDataPage { + switch len0 := q.len(); { + case index < len0: + has := len(q) + need := has + 2*kKV + switch { + case cap(q) >= need: + q = q[:need] + default: + q = append(q, zeros[:2*kKV]...) + } + q.copy(q, index+1, index, len0-index) + return q + case index == len0: + has := len(q) + need := has + 2*kKV + switch { + case cap(q) >= need: + return q[:need] + default: + return append(q, zeros[:2*kKV]...) + } + } + panic("internal error") +} + +func (p btreeDataPage) contentField(off int) (b []byte, h int64) { + p = p[off:] + switch n := int(p[0]); { + case n >= kKV: // content has a handle + b = append([]byte(nil), p[1:1+kSz]...) + h = b2h(p[kH:]) + default: // content is embedded + b, h = append([]byte(nil), p[1:1+n]...), 0 + } + return +} + +func (p btreeDataPage) content(a btreeStore, off int) (b []byte, err error) { + b, h := p.contentField(off) + if h == 0 { + return + } + + // content has a handle + b2, err := a.Get(nil, h) //TODO buffers: Later, not a public API + if err != nil { + return nil, err + } + + return append(b, b2...), nil +} + +func (p btreeDataPage) setContent(a btreeStore, off int, b []byte) (err error) { + p = p[off:] + switch { + case p[0] >= kKV: // existing content has a handle + switch n := len(b); { + case n < kKV: + p[0] = byte(n) + if err = a.Free(b2h(p[kH:])); err != nil { + return + } + copy(p[1:], b) + default: + // reuse handle + copy(p[1:1+kSz], b) + return a.Realloc(b2h(p[kH:]), b[kSz:]) + } + default: // existing content is embedded + switch n := len(b); { + case n < kKV: + p[0] = byte(n) + copy(p[1:], b) + default: + p[0] = 0xff + copy(p[1:1+kSz], b) + h, err := a.Alloc(b[kSz:]) + if err != nil { + return err + } + + h2b(p[kH:], h) + } + } + return +} + +func (p btreeDataPage) keyField(index int) (b []byte, h int64) { + return p.contentField(15 + 2*kKV*index) +} + +func (p btreeDataPage) key(a btreeStore, index int) (b []byte, err error) { + return p.content(a, 15+2*kKV*index) +} + +func (p btreeDataPage) valueField(index int) (b []byte, h int64) { + return p.contentField(15 + kKV + 2*kKV*index) +} + +func (p btreeDataPage) value(a btreeStore, index int) (b []byte, err error) { + value, err := p.content(a, 15+kKV+2*kKV*index) + if err == nil && value == nil { + // We have a valid page, no fetch error, the key is valid so return + // non-nil data + return []byte{}, nil + } + return value, err +} + +func (p btreeDataPage) valueCopy(a btreeStore, index int) (b []byte, err error) { + if b, err = p.content(a, 15+kKV+2*kKV*index); err != nil { + return + } + + return append([]byte(nil), b...), nil +} + +func (p btreeDataPage) setKey(a btreeStore, index int, key []byte) (err error) { + return p.setContent(a, 15+2*kKV*index, key) +} + +func (p btreeDataPage) setValue(a btreeStore, index int, value []byte) (err error) { + return p.setContent(a, 15+kKV+2*kKV*index, value) +} + +func (p btreeDataPage) cmp(a btreeStore, c func(a, b []byte) int, keyA []byte, keyBIndex int) (y int, err error) { + var keyB []byte + if keyB, err = p.content(a, 15+2*kKV*keyBIndex); err != nil { + return + } + + return c(keyA, keyB), nil +} + +func (p btreeDataPage) copy(src btreeDataPage, di, si, n int) { + do, so := 15+2*kKV*di, 15+2*kKV*si + copy(p[do:do+2*kKV*n], src[so:]) +} + +// {p,left} dirty on exit +func (p btreeDataPage) moveLeft(left btreeDataPage, n int) (btreeDataPage, btreeDataPage) { + nl, np := left.len(), p.len() + left = left.setLen(nl + n) + left.copy(p, nl, 0, n) + p.copy(p, 0, n, np-n) + return p.setLen(np - n), left +} + +func (p btreeDataPage) moveRight(right btreeDataPage, n int) (btreeDataPage, btreeDataPage) { + nr, np := right.len(), p.len() + right = right.setLen(nr + n) + right.copy(right, n, 0, nr) + right.copy(p, 0, np-n, n) + return p.setLen(np - n), right +} + +func (p btreeDataPage) insertItem(a btreeStore, index int, key, value []byte) (btreeDataPage, error) { + p = p.insert(index) + di, sz := 15+2*kKV*index, 2*kKV + copy(p[di:di+sz], zeros[:sz]) + if err := p.setKey(a, index, key); err != nil { + return nil, err + } + return p, p.setValue(a, index, value) +} + +func (p btreeDataPage) split(a btreeStore, root, ph, parent int64, parentIndex, index int, key, value []byte) (btreeDataPage, error) { + right, rh, err := newBTreeDataPageAlloc(a) + // fails defer bufs.GCache.Put(right) + if err != nil { + return nil, err + } + + if next := p.next(); next != 0 { + right.setNext(p.next()) + nxh := right.next() + nx := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(nx) + if nx, err = a.Get(nx, nxh); err != nil { + return nil, err + } + + btreeDataPage(nx).setPrev(rh) + if err = a.Realloc(nxh, nx); err != nil { + return nil, err + } + } + + p.setNext(rh) + right.setPrev(ph) + right = right.setLen(kData) + right.copy(p, 0, kData, kData) + p = p.setLen(kData) + + if parentIndex >= 0 { + var pp btreeIndexPage = bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(pp) + if pp, err = a.Get(pp, parent); err != nil { + return nil, err + } + + pp = pp.insert3(parentIndex, rh, rh) + if err = a.Realloc(parent, pp); err != nil { + return nil, err + } + + } else { + nr := newBTreeIndexPage(ph) + defer bufs.GCache.Put(nr) + nr = nr.insert3(0, rh, rh) + nrh, err := a.Alloc(nr) + if err != nil { + return nil, err + } + + if err = a.Realloc(root, h2b(make([]byte, 7), nrh)); err != nil { + return nil, err + } + + } + if index > kData { + if right, err = right.insertItem(a, index-kData, key, value); err != nil { + return nil, err + } + } else { + if p, err = p.insertItem(a, index, key, value); err != nil { + return nil, err + } + } + if err = a.Realloc(ph, p); err != nil { + return nil, err + } + + return p, a.Realloc(rh, right) +} + +func (p btreeDataPage) overflow(a btreeStore, root, ph, parent int64, parentIndex, index int, key, value []byte) (btreeDataPage, error) { + leftH, rightH, err := checkSiblings(a, parent, parentIndex) + if err != nil { + return nil, err + } + + if leftH != 0 { + left := btreeDataPage(bufs.GCache.Get(maxBuf)) + defer bufs.GCache.Put(left) + if left, err = a.Get(left, leftH); err != nil { + return nil, err + } + + if left.len() < 2*kData && index > 0 { + + p, left = p.moveLeft(left, 1) + if err = a.Realloc(leftH, left); err != nil { + return nil, err + } + + if p, err = p.insertItem(a, index-1, key, value); err != nil { + return nil, err + } + + return p, a.Realloc(ph, p) + } + } + + if rightH != 0 { + right := btreeDataPage(bufs.GCache.Get(maxBuf)) + defer bufs.GCache.Put(right) + if right, err = a.Get(right, rightH); err != nil { + return nil, err + } + + if right.len() < 2*kData { + if index < 2*kData { + p, right = p.moveRight(right, 1) + if err = a.Realloc(rightH, right); err != nil { + return nil, err + } + + if p, err = p.insertItem(a, index, key, value); err != nil { + return nil, err + } + + return p, a.Realloc(ph, p) + } else { + if right, err = right.insertItem(a, 0, key, value); err != nil { + return nil, err + } + + return p, a.Realloc(rightH, right) + } + } + } + return p.split(a, root, ph, parent, parentIndex, index, key, value) +} + +func (p btreeDataPage) swap(a btreeStore, di int, value []byte, canOverwrite bool) (oldValue []byte, err error) { + if oldValue, err = p.value(a, di); err != nil { + return + } + + if !canOverwrite { + return + } + + oldValue = append([]byte(nil), oldValue...) + err = p.setValue(a, di, value) + return +} + +type btreePage []byte + +func (p btreePage) isIndex() bool { + return p[0] == tagBTreeIndexPage +} + +func (p btreePage) len() int { + if p.isIndex() { + return btreeIndexPage(p).len() + } + + return btreeDataPage(p).len() +} + +func (p btreePage) find(a btreeStore, c func(a, b []byte) int, key []byte) (index int, ok bool, err error) { + l := 0 + h := p.len() - 1 + isIndex := p.isIndex() + if c == nil { + c = bytes.Compare + } + for l <= h { + index = (l + h) >> 1 + var cmp int + if isIndex { + if cmp, err = btreeIndexPage(p).cmp(a, c, key, index); err != nil { + return + } + } else { + if cmp, err = btreeDataPage(p).cmp(a, c, key, index); err != nil { + return + } + } + switch ok = cmp == 0; { + case cmp > 0: + l = index + 1 + case ok: + return + default: + h = index - 1 + } + } + return l, false, nil +} + +// p is dirty after extract! +func (p btreeDataPage) extract(a btreeStore, index int) (btreeDataPage, []byte, error) { + value, err := p.valueCopy(a, index) + if err != nil { + return nil, nil, err + } + + if _, h := p.keyField(index); h != 0 { + if err = a.Free(h); err != nil { + return nil, nil, err + } + } + + if _, h := p.valueField(index); h != 0 { + if err = a.Free(h); err != nil { + return nil, nil, err + } + } + + n := p.len() - 1 + if index < n { + p.copy(p, index, index+1, n-index) + } + return p.setLen(n), value, nil +} + +func checkSiblings(a btreeStore, parent int64, parentIndex int) (left, right int64, err error) { + if parentIndex >= 0 { + var p btreeIndexPage = bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(p) + if p, err = a.Get(p, parent); err != nil { + return + } + + if parentIndex > 0 { + left = p.child(parentIndex - 1) + } + if parentIndex < p.len() { + right = p.child(parentIndex + 1) + } + } + return +} + +// underflow must persist all changes made. +func (p btreeDataPage) underflow(a btreeStore, root, iroot, parent, ph int64, parentIndex int) (err error) { + lh, rh, err := checkSiblings(a, parent, parentIndex) + if err != nil { + return err + } + + if lh != 0 { + left := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(left) + if left, err = a.Get(left, lh); err != nil { + return err + } + + if btreeDataPage(left).len()+p.len() >= 2*kData { + left, p = btreeDataPage(left).moveRight(p, 1) + if err = a.Realloc(lh, left); err != nil { + return err + } + + return a.Realloc(ph, p) + } + } + + if rh != 0 { + right := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(right) + if right, err = a.Get(right, rh); err != nil { + return err + } + + if p.len()+btreeDataPage(right).len() > 2*kData { + right, p = btreeDataPage(right).moveLeft(p, 1) + if err = a.Realloc(rh, right); err != nil { + return err + } + + return a.Realloc(ph, p) + } + } + + if lh != 0 { + left := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(left) + if left, err = a.Get(left, lh); err != nil { + return err + } + + if err = a.Realloc(ph, p); err != nil { + return err + } + + return btreeDataPage(left).concat(a, root, iroot, parent, lh, ph, parentIndex-1) + } + + return p.concat(a, root, iroot, parent, ph, rh, parentIndex) +} + +// concat must persist all changes made. +func (p btreeDataPage) concat(a btreeStore, root, iroot, parent, ph, rh int64, parentIndex int) (err error) { + right := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(right) + if right, err = a.Get(right, rh); err != nil { + return err + } + + right, p = btreeDataPage(right).moveLeft(p, btreeDataPage(right).len()) + nxh := btreeDataPage(right).next() + if nxh != 0 { + nx := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(nx) + if nx, err = a.Get(nx, nxh); err != nil { + return err + } + + btreeDataPage(nx).setPrev(ph) + if err = a.Realloc(nxh, nx); err != nil { + return err + } + } + p.setNext(nxh) + if err = a.Free(rh); err != nil { + return err + } + + pp := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(pp) + if pp, err = a.Get(pp, parent); err != nil { + return err + } + + if btreeIndexPage(pp).len() > 1 { + pp = btreeIndexPage(pp).extract(parentIndex) + btreeIndexPage(pp).setChild(parentIndex, ph) + if err = a.Realloc(parent, pp); err != nil { + return err + } + + return a.Realloc(ph, p) + } + + if err = a.Free(iroot); err != nil { + return err + } + + if err = a.Realloc(ph, p); err != nil { + return err + } + + var b7 [7]byte + return a.Realloc(root, h2b(b7[:], ph)) +} + +// external "root" is stable and contains the real root. +type btree int64 + +func newBTree(a btreeStore) (btree, error) { + r, err := a.Alloc(zeros[:7]) + return btree(r), err +} + +func (root btree) String(a btreeStore) string { + r := bufs.GCache.Get(16) + defer bufs.GCache.Put(r) + r, err := a.Get(r, int64(root)) + if err != nil { + panic(err) + } + + iroot := b2h(r) + m := map[int64]bool{int64(root): true} + + s := []string{fmt.Sprintf("tree %#x -> %#x\n====", root, iroot)} + if iroot == 0 { + return s[0] + } + + var f func(int64, string) + f = func(h int64, ind string) { + if m[h] { + return + } + + m[h] = true + var b btreePage = bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(b) + var err error + if b, err = a.Get(b, h); err != nil { + panic(err) + } + + s = append(s, fmt.Sprintf("%s@%#x", ind, h)) + switch b.isIndex() { + case true: + da := []int64{} + b := btreeIndexPage(b) + for i := 0; i < b.len(); i++ { + c, d := b.child(i), b.dataPage(i) + s = append(s, fmt.Sprintf("%schild[%d] %#x dataPage[%d] %#x", ind, i, c, i, d)) + da = append(da, c) + da = append(da, d) + } + i := b.len() + c := b.child(i) + s = append(s, fmt.Sprintf("%schild[%d] %#x", ind, i, c)) + for _, c := range da { + f(c, ind+" ") + } + f(c, ind+" ") + case false: + b := btreeDataPage(b) + s = append(s, fmt.Sprintf("%sprev %#x next %#x", ind, b.prev(), b.next())) + for i := 0; i < b.len(); i++ { + k, err := b.key(a, i) + if err != nil { + panic(err) + } + + v, err := b.value(a, i) + if err != nil { + panic(err) + } + + s = append(s, fmt.Sprintf("%sK[%d]|% x| V[%d]|% x|", ind, i, k, i, v)) + } + } + } + + f(int64(iroot), "") + return strings.Join(s, "\n") +} + +func (root btree) put(dst []byte, a btreeStore, c func(a, b []byte) int, key, value []byte, canOverwrite bool) (prev []byte, err error) { + prev, _, err = root.put2(dst, a, c, key, func(key, old []byte) (new []byte, write bool, err error) { + new, write = value, true + return + }) + return +} + +func (root btree) put2(dst []byte, a btreeStore, c func(a, b []byte) int, key []byte, upd func(key, old []byte) (new []byte, write bool, err error)) (old []byte, written bool, err error) { + var r, value []byte + if r, err = a.Get(dst, int64(root)); err != nil { + return + } + + iroot := b2h(r) + var h int64 + if iroot == 0 { + p := newBTreeDataPage() + defer bufs.GCache.Put(p) + if value, written, err = upd(key, nil); err != nil || !written { + return + } + + if p, err = p.insertItem(a, 0, key, value); err != nil { + return + } + + h, err = a.Alloc(p) + if err != nil { + return nil, true, err + } + + err = a.Realloc(int64(root), h2b(r, h)[:7]) + return + } + + parentIndex := -1 + var parent int64 + ph := iroot + + p := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(p) + + for { + if p, err = a.Get(p[:cap(p)], ph); err != nil { + return + } + + var index int + var ok bool + + if index, ok, err = btreePage(p).find(a, c, key); err != nil { + return + } + + switch { + case ok: // Key found + if btreePage(p).isIndex() { + ph = btreeIndexPage(p).dataPage(index) + if p, err = a.Get(p, ph); err != nil { + return + } + + if old, err = btreeDataPage(p).valueCopy(a, 0); err != nil { + return + } + + if value, written, err = upd(key, old); err != nil || !written { + return + } + + if _, err = btreeDataPage(p).swap(a, 0, value, true); err != nil { + return + } + + err = a.Realloc(ph, p) + return + } + + if old, err = btreeDataPage(p).valueCopy(a, index); err != nil { + return + } + + if value, written, err = upd(key, old); err != nil || !written { + return + } + + if _, err = btreeDataPage(p).swap(a, index, value, true); err != nil { + return + } + + err = a.Realloc(ph, p) + return + case btreePage(p).isIndex(): + if btreePage(p).len() > 2*kIndex { + if p, err = btreeIndexPage(p).split(a, root, &ph, parent, parentIndex, &index); err != nil { + return + } + } + parentIndex = index + parent = ph + ph = btreeIndexPage(p).child(index) + default: + if value, written, err = upd(key, nil); err != nil || !written { + return + } + + if btreePage(p).len() < 2*kData { // page is not full + if p, err = btreeDataPage(p).insertItem(a, index, key, value); err != nil { + return + } + + err = a.Realloc(ph, p) + return + } + + // page is full + p, err = btreeDataPage(p).overflow(a, int64(root), ph, parent, parentIndex, index, key, value) + return + } + } +} + +//TODO actually use 'dst' to return 'value' +func (root btree) get(a btreeStore, dst []byte, c func(a, b []byte) int, key []byte) (b []byte, err error) { + var r []byte + if r, err = a.Get(dst, int64(root)); err != nil { + return + } + + iroot := b2h(r) + if iroot == 0 { + return + } + + ph := iroot + + for { + var p btreePage + if p, err = a.Get(p, ph); err != nil { + return + } + + var index int + var ok bool + if index, ok, err = p.find(a, c, key); err != nil { + return + } + + switch { + case ok: + if p.isIndex() { + dh := btreeIndexPage(p).dataPage(index) + dp, err := a.Get(dst, dh) + if err != nil { + return nil, err + } + + return btreeDataPage(dp).value(a, 0) + } + + return btreeDataPage(p).value(a, index) + case p.isIndex(): + ph = btreeIndexPage(p).child(index) + default: + return + } + } +} + +//TODO actually use 'dst' to return 'value' +func (root btree) extract(a btreeStore, dst []byte, c func(a, b []byte) int, key []byte) (value []byte, err error) { + var r []byte + if r, err = a.Get(dst, int64(root)); err != nil { + return + } + + iroot := b2h(r) + if iroot == 0 { + return + } + + ph := iroot + parentIndex := -1 + var parent int64 + + p := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(p) + + for { + if p, err = a.Get(p[:cap(p)], ph); err != nil { + return + } + + var index int + var ok bool + if index, ok, err = btreePage(p).find(a, c, key); err != nil { + return + } + + if ok { + if btreePage(p).isIndex() { + dph := btreeIndexPage(p).dataPage(index) + dp, err := a.Get(dst, dph) + if err != nil { + return nil, err + } + + if btreeDataPage(dp).len() > kData { + if dp, value, err = btreeDataPage(dp).extract(a, 0); err != nil { + return nil, err + } + + return value, a.Realloc(dph, dp) + } + + if btreeIndexPage(p).len() < kIndex && ph != iroot { + var err error + if p, err = btreeIndexPage(p).underflow(a, int64(root), iroot, parent, &ph, parentIndex, &index); err != nil { + return nil, err + } + } + parentIndex = index + 1 + parent = ph + ph = btreeIndexPage(p).child(parentIndex) + continue + } + + p, value, err = btreeDataPage(p).extract(a, index) + if btreePage(p).len() >= kData { + err = a.Realloc(ph, p) + return + } + + if ph != iroot { + err = btreeDataPage(p).underflow(a, int64(root), iroot, parent, ph, parentIndex) + return + } + + if btreePage(p).len() == 0 { + if err = a.Free(ph); err != nil { + return + } + + err = a.Realloc(int64(root), zeros[:7]) + return + } + err = a.Realloc(ph, p) + return + } + + if !btreePage(p).isIndex() { + return + } + + if btreePage(p).len() < kIndex && ph != iroot { + if p, err = btreeIndexPage(p).underflow(a, int64(root), iroot, parent, &ph, parentIndex, &index); err != nil { + return nil, err + } + } + parentIndex = index + parent = ph + ph = btreeIndexPage(p).child(index) + } +} + +func (root btree) deleteAny(a btreeStore) (bool, error) { + r := bufs.GCache.Get(7) + defer bufs.GCache.Put(r) + var err error + if r, err = a.Get(r, int64(root)); err != nil { + return false, err + } + + iroot := b2h(r) + if iroot == 0 { + return true, nil + } + + ph := iroot + parentIndex := -1 + var parent int64 + p := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(p) + + for { + if p, err = a.Get(p, ph); err != nil { + return false, err + } + + index := btreePage(p).len() / 2 + if btreePage(p).isIndex() { + dph := btreeIndexPage(p).dataPage(index) + dp := bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(dp) + if dp, err = a.Get(dp, dph); err != nil { + return false, err + } + + if btreeDataPage(dp).len() > kData { + if dp, _, err = btreeDataPage(dp).extract(a, 0); err != nil { + return false, err + } + + return false, a.Realloc(dph, dp) + } + + if btreeIndexPage(p).len() < kIndex && ph != iroot { + if p, err = btreeIndexPage(p).underflow(a, int64(root), iroot, parent, &ph, parentIndex, &index); err != nil { + return false, err + } + } + parentIndex = index + 1 + parent = ph + ph = btreeIndexPage(p).child(parentIndex) + continue + } + + p, _, err = btreeDataPage(p).extract(a, index) + if btreePage(p).len() >= kData { + err = a.Realloc(ph, p) + return false, err + } + + if ph != iroot { + err = btreeDataPage(p).underflow(a, int64(root), iroot, parent, ph, parentIndex) + return false, err + } + + if btreePage(p).len() == 0 { + if err = a.Free(ph); err != nil { + return true, err + } + + return true, a.Realloc(int64(root), zeros[:7]) + } + + return false, a.Realloc(ph, p) + } +} + +func (root btree) first(a btreeStore) (ph int64, p btreeDataPage, err error) { + r := bufs.GCache.Get(7) + defer bufs.GCache.Put(r) + if r, err = a.Get(r, int64(root)); err != nil { + return + } + + for ph = b2h(r); ph != 0; ph = btreeIndexPage(p).child(0) { + if p, err = a.Get(p, ph); err != nil { + return + } + + if !btreePage(p).isIndex() { + break + } + } + + return +} + +func (root btree) last(a btreeStore) (ph int64, p btreeDataPage, err error) { + r := bufs.GCache.Get(7) + defer bufs.GCache.Put(r) + if r, err = a.Get(r, int64(root)); err != nil { + return + } + + for ph = b2h(r); ph != 0; ph = btreeIndexPage(p).child(btreeIndexPage(p).len()) { + if p, err = a.Get(p, ph); err != nil { + return + } + + if !btreePage(p).isIndex() { + break + } + } + + return +} + +// key >= p[index].key +func (root btree) seek(a btreeStore, c func(a, b []byte) int, key []byte) (p btreeDataPage, index int, equal bool, err error) { + r := bufs.GCache.Get(7) + defer bufs.GCache.Put(r) + if r, err = a.Get(r, int64(root)); err != nil { + return + } + + for ph := b2h(r); ph != 0; ph = btreeIndexPage(p).child(index) { + if p, err = a.Get(p, ph); err != nil { + break + } + + if index, equal, err = btreePage(p).find(a, c, key); err != nil { + break + } + + if equal { + if !btreePage(p).isIndex() { + break + } + + p, err = a.Get(p, btreeIndexPage(p).dataPage(index)) + index = 0 + break + } + + if !btreePage(p).isIndex() { + break + } + } + return +} + +func (root btree) clear(a btreeStore) (err error) { + r := bufs.GCache.Get(7) + defer bufs.GCache.Put(r) + if r, err = a.Get(r, int64(root)); err != nil { + return + } + + iroot := b2h(r) + if iroot == 0 { + return + } + + if err = root.clear2(a, iroot); err != nil { + return + } + + var b [7]byte + return a.Realloc(int64(root), b[:]) +} + +func (root btree) clear2(a btreeStore, ph int64) (err error) { + var p = bufs.GCache.Get(maxBuf) + defer bufs.GCache.Put(p) + if p, err = a.Get(p, ph); err != nil { + return + } + + switch btreePage(p).isIndex() { + case true: + ip := btreeIndexPage(p) + for i := 0; i <= ip.len(); i++ { + root.clear2(a, ip.child(i)) + + } + case false: + dp := btreeDataPage(p) + for i := 0; i < dp.len(); i++ { + if err = dp.setKey(a, i, nil); err != nil { + return + } + + if err = dp.setValue(a, i, nil); err != nil { + return + } + } + } + return a.Free(ph) +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/errors.go b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/errors.go new file mode 100644 index 00000000..7dffe7f1 --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/errors.go @@ -0,0 +1,170 @@ +// Copyright 2014 The lldb Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Some errors returned by this package. +// +// Note that this package can return more errors than declared here, for +// example io.EOF from Filer.ReadAt(). + +package lldb + +import ( + "fmt" +) + +// ErrDecodeScalars is possibly returned from DecodeScalars +type ErrDecodeScalars struct { + B []byte // Data being decoded + I int // offending offset +} + +// Error implements the built in error type. +func (e *ErrDecodeScalars) Error() string { + return fmt.Sprintf("DecodeScalars: corrupted data @ %d/%d", e.I, len(e.B)) +} + +// ErrINVAL reports invalid values passed as parameters, for example negative +// offsets where only non-negative ones are allowed or read from the DB. +type ErrINVAL struct { + Src string + Val interface{} +} + +// Error implements the built in error type. +func (e *ErrINVAL) Error() string { + return fmt.Sprintf("%s: %+v", e.Src, e.Val) +} + +// ErrPERM is for example reported when a Filer is closed while BeginUpdate(s) +// are not balanced with EndUpdate(s)/Rollback(s) or when EndUpdate or Rollback +// is invoked which is not paired with a BeginUpdate. +type ErrPERM struct { + Src string +} + +// Error implements the built in error type. +func (e *ErrPERM) Error() string { + return fmt.Sprintf("%s: Operation not permitted", string(e.Src)) +} + +// ErrTag represents an ErrILSEQ kind. +type ErrType int + +// ErrILSEQ types +const ( + ErrOther ErrType = iota + + ErrAdjacentFree // Adjacent free blocks (.Off and .Arg) + ErrDecompress // Used compressed block: corrupted compression + ErrExpFreeTag // Expected a free block tag, got .Arg + ErrExpUsedTag // Expected a used block tag, got .Arg + ErrFLT // Free block is invalid or referenced multiple times + ErrFLTLoad // FLT truncated to .Off, need size >= .Arg + ErrFLTSize // Free block size (.Arg) doesn't belong to its list min size: .Arg2 + ErrFileSize // File .Name size (.Arg) != 0 (mod 16) + ErrFreeChaining // Free block, .prev.next doesn't point back to this block + ErrFreeTailBlock // Last block is free + ErrHead // Head of a free block list has non zero Prev (.Arg) + ErrInvalidRelocTarget // Reloc doesn't target (.Arg) a short or long used block + ErrInvalidWAL // Corrupted write ahead log. .Name: file name, .More: more + ErrLongFreeBlkTooLong // Long free block spans beyond EOF, size .Arg + ErrLongFreeBlkTooShort // Long free block must have at least 2 atoms, got only .Arg + ErrLongFreeNextBeyondEOF // Long free block .Next (.Arg) spans beyond EOF + ErrLongFreePrevBeyondEOF // Long free block .Prev (.Arg) spans beyond EOF + ErrLongFreeTailTag // Expected a long free block tail tag, got .Arg + ErrLostFreeBlock // Free block is not in any FLT list + ErrNullReloc // Used reloc block with nil target + ErrRelocBeyondEOF // Used reloc points (.Arg) beyond EOF + ErrShortFreeTailTag // Expected a short free block tail tag, got .Arg + ErrSmall // Request for a free block (.Arg) returned a too small one (.Arg2) at .Off + ErrTailTag // Block at .Off has invalid tail CC (compression code) tag, got .Arg + ErrUnexpReloc // Unexpected reloc block referred to from reloc block .Arg + ErrVerifyPadding // Used block has nonzero padding + ErrVerifyTailSize // Long free block size .Arg but tail size .Arg2 + ErrVerifyUsedSpan // Used block size (.Arg) spans beyond EOF +) + +// ErrILSEQ reports a corrupted file format. Details in fields according to Type. +type ErrILSEQ struct { + Type ErrType + Off int64 + Arg int64 + Arg2 int64 + Arg3 int64 + Name string + More interface{} +} + +// Error implements the built in error type. +func (e *ErrILSEQ) Error() string { + switch e.Type { + case ErrAdjacentFree: + return fmt.Sprintf("Adjacent free blocks at offset %#x and %#x", e.Off, e.Arg) + case ErrDecompress: + return fmt.Sprintf("Compressed block at offset %#x: Corrupted compressed content", e.Off) + case ErrExpFreeTag: + return fmt.Sprintf("Block at offset %#x: Expected a free block tag, got %#2x", e.Off, e.Arg) + case ErrExpUsedTag: + return fmt.Sprintf("Block at ofset %#x: Expected a used block tag, got %#2x", e.Off, e.Arg) + case ErrFLT: + return fmt.Sprintf("Free block at offset %#x is invalid or referenced multiple times", e.Off) + case ErrFLTLoad: + return fmt.Sprintf("FLT truncated to size %d, expected at least %d", e.Off, e.Arg) + case ErrFLTSize: + return fmt.Sprintf("Free block at offset %#x has size (%#x) should be at least (%#x)", e.Off, e.Arg, e.Arg2) + case ErrFileSize: + return fmt.Sprintf("File %q size (%#x) != 0 (mod 16)", e.Name, e.Arg) + case ErrFreeChaining: + return fmt.Sprintf("Free block at offset %#x: .prev.next doesn point back here.", e.Off) + case ErrFreeTailBlock: + return fmt.Sprintf("Free block at offset %#x: Cannot be last file block", e.Off) + case ErrHead: + return fmt.Sprintf("Block at offset %#x: Head of free block list has non zero .prev %#x", e.Off, e.Arg) + case ErrInvalidRelocTarget: + return fmt.Sprintf("Used reloc block at offset %#x: Target (%#x) is not a short or long used block", e.Off, e.Arg) + case ErrInvalidWAL: + return fmt.Sprintf("Corrupted write ahead log file: %q %v", e.Name, e.More) + case ErrLongFreeBlkTooLong: + return fmt.Sprintf("Long free block at offset %#x: Size (%#x) beyond EOF", e.Off, e.Arg) + case ErrLongFreeBlkTooShort: + return fmt.Sprintf("Long free block at offset %#x: Size (%#x) too small", e.Off, e.Arg) + case ErrLongFreeNextBeyondEOF: + return fmt.Sprintf("Long free block at offset %#x: Next (%#x) points beyond EOF", e.Off, e.Arg) + case ErrLongFreePrevBeyondEOF: + return fmt.Sprintf("Long free block at offset %#x: Prev (%#x) points beyond EOF", e.Off, e.Arg) + case ErrLongFreeTailTag: + return fmt.Sprintf("Block at offset %#x: Expected long free tail tag, got %#2x", e.Off, e.Arg) + case ErrLostFreeBlock: + return fmt.Sprintf("Free block at offset %#x: not in any FLT list", e.Off) + case ErrNullReloc: + return fmt.Sprintf("Used reloc block at offset %#x: Nil target", e.Off) + case ErrRelocBeyondEOF: + return fmt.Sprintf("Used reloc block at offset %#x: Link (%#x) points beyond EOF", e.Off, e.Arg) + case ErrShortFreeTailTag: + return fmt.Sprintf("Block at offset %#x: Expected short free tail tag, got %#2x", e.Off, e.Arg) + case ErrSmall: + return fmt.Sprintf("Request for of free block of size %d returned a too small (%d) one at offset %#x", e.Arg, e.Arg2, e.Off) + case ErrTailTag: + return fmt.Sprintf("Block at offset %#x: Invalid tail CC tag, got %#2x", e.Off, e.Arg) + case ErrUnexpReloc: + return fmt.Sprintf("Block at offset %#x: Unexpected reloc block. Referred to from reloc block at offset %#x", e.Off, e.Arg) + case ErrVerifyPadding: + return fmt.Sprintf("Used block at offset %#x: Nonzero padding", e.Off) + case ErrVerifyTailSize: + return fmt.Sprintf("Long free block at offset %#x: Size %#x, but tail size %#x", e.Off, e.Arg, e.Arg2) + case ErrVerifyUsedSpan: + return fmt.Sprintf("Used block at offset %#x: Size %#x spans beyond EOF", e.Off, e.Arg) + } + + more := "" + if e.More != nil { + more = fmt.Sprintf(", %v", e.More) + } + off := "" + if e.Off != 0 { + off = fmt.Sprintf(", off: %#x", e.Off) + } + + return fmt.Sprintf("Error%s%s", off, more) +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/falloc.go b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/falloc.go new file mode 100644 index 00000000..2969036e --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/falloc.go @@ -0,0 +1,1981 @@ +// Copyright 2014 The lldb Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// The storage space management. + +package lldb + +import ( + "bytes" + "errors" + "fmt" + "io" + "sort" + "strings" + "sync" + + "github.com/cznic/bufs" + "github.com/cznic/mathutil" + "github.com/cznic/zappy" +) + +const ( + maxBuf = maxRq + 20 // bufs,Buffers.Alloc +) + +// Options are passed to the NewAllocator to amend some configuration. The +// compatibility promise is the same as of struct types in the Go standard +// library - introducing changes can be made only by adding new exported +// fields, which is backward compatible as long as client code uses field names +// to assign values of imported struct types literals. +// +// NOTE: No options are currently defined. +type Options struct{} + +// AllocStats record statistics about a Filer. It can be optionally filled by +// Allocator.Verify, if successful. +type AllocStats struct { + Handles int64 // total valid handles in use + Compression int64 // number of compressed blocks + TotalAtoms int64 // total number of atoms == AllocAtoms + FreeAtoms + AllocBytes int64 // bytes allocated (after decompression, if/where used) + AllocAtoms int64 // atoms allocated/used, including relocation atoms + Relocations int64 // number of relocated used blocks + FreeAtoms int64 // atoms unused + AllocMap map[int64]int64 // allocated block size in atoms -> count of such blocks + FreeMap map[int64]int64 // free block size in atoms -> count of such blocks +} + +/* + +Allocator implements "raw" storage space management (allocation and +deallocation) for a low level of a DB engine. The storage is an abstraction +provided by a Filer. + +The terms MUST or MUST NOT, if/where used in the documentation of Allocator, +written in all caps as seen here, are a requirement for any possible +alternative implementations aiming for compatibility with this one. + +Filer file + +A Filer file, or simply 'file', is a linear, contiguous sequence of blocks. +Blocks may be either free (currently unused) or allocated (currently used). +Some blocks may eventually become virtual in a sense as they may not be +realized in the storage (sparse files). + +Free Lists Table + +File starts with a FLT. This table records heads of 14 doubly linked free +lists. The zero based index (I) vs minimal size of free blocks in that list, +except the last one which registers free blocks of size 4112+ atoms: + + MinSize == 2^I + + For example 0 -> 1, 1 -> 2, ... 12 -> 4096. + +Each entry in the FLT is 8 bytes in netwtork order, MSB MUST be zero, ie. the +slot value is effectively only 7 bytes. The value is the handle of the head of +the respective doubly linked free list. The FLT size is 14*8 == 112(0x70) +bytes. If the free blocks list for any particular size is empty, the respective +FLT slot is zero. Sizes of free blocks in one list MUST NOT overlap with sizes +of free lists in other list. For example, even though a free block of size 2 +technically is of minimal size >= 1, it MUST NOT be put to the list for slot 0 +(minimal size 1), but in slot 1( minimal size 2). + + slot 0: sizes [1, 2) + slot 1: sizes [2, 4) + slot 2: sizes [4, 8) + ... + slot 11: sizes [2048, 4096) + slot 12: sizes [4096, 4112) + slot 13: sizes [4112, inf) + +The last FLT slot collects all free blocks bigger than its minimal size. That +still respects the 'no overlap' invariant. + +File blocks + +A block is a linear, contiguous sequence of atoms. The first and last atoms of +a block provide information about, for example, whether the block is free or +used, what is the size of the block, etc. Details are discussed elsewhere. The +first block of a file starts immediately after FLT, ie. at file offset +112(0x70). + +Block atoms + +An atom is a fixed size piece of a block (and thus of a file too); it is 16 +bytes long. A consequence is that for a valid file: + + filesize == 0 (mod 16) + +The first atom of the first block is considered to be atom #1. + +Block handles + +A handle is an integer referring to a block. The reference is the number of the +atom the block starts with. Put in other way: + + handle == offset/16 - 6 + offset == 16 * (handle + 6) + +`offset` is the offset of the first byte of the block, measured in bytes +- as in fseek(3). Handle has type `int64`, but only the lower 7 bytes may be +nonzero while referring to a block, both in code as well as when persisted in +the the file's internal bookkeeping structures - see 'Block types' bellow. So a +handle is effectively only `uint56`. This also means that the maximum usable +size of a file is 2^56 atoms. That is 2^60 bytes == 1 exabyte (10^18 bytes). + +Nil handles + +A handle with numeric value of '0' refers to no block. + +Zero padding + +A padding is used to round-up a block size to be a whole number of atoms. Any +padding, if present, MUST be all zero bytes. Note that the size of padding is +in [0, 15]. + +Content wiping + +When a block is deallocated, its data content is not wiped as the added +overhead may be substantial while not necessarily needed. Client code should +however overwrite the content of any block having sensitive data with eg. zeros +(good compression) - before deallocating the block. + +Block tags + +Every block is tagged in its first byte (a head tag) and last byte (tail tag). +Block types are: + + 1. Short content used block (head tags 0x00-0xFB) + 2. Long content used block (head tag 0xFC) + 3. Relocated used block (head tag 0xFD) + 4. Short, single atom, free block (head tag 0xFE) + 5. Long free block (head tag 0xFF) + +Note: Relocated used block, 3. above (head tag 0xFD) MUST NOT refer to blocks +other then 1. or 2. above (head tags 0x00-0xFC). + +Content blocks + +Used blocks (head tags 0x00-0xFC) tail tag distinguish used/unused block and if +content is compressed or not. + +Content compression + +The tail flag of an used block is one of + + CC == 0 // Content is not compressed. + CC == 1 // Content is in zappy compression format. + +If compression of written content is enabled, there are two cases: If +compressed size < original size then the compressed content should be written +if it will save at least one atom of the block. If compressed size >= original +size then the compressed content should not be used. + +It's recommended to use compression. For example the BTrees implementation +assumes compression is used. Using compression may cause a slowdown in some +cases while it may as well cause a speedup. + +Short content block + +Short content block carries content of length between N == 0(0x00) and N == +251(0xFB) bytes. + + |<-first atom start ... last atom end->| + +---++-- ... --+-- ... --++------+ + | 0 || 1... | 0x*...0x*E || 0x*F | + +---++-- ... --+-- ... --++------+ + | N || content | padding || CC | + +---++-- ... --+-- ... --++------+ + + A == (N+1)/16 + 1 // The number of atoms in the block [1, 16] + padding == 15 - (N+1)%16 // Length of the zero padding + +Long content block + +Long content block carries content of length between N == 252(0xFC) and N == +65787(0x100FB) bytes. + + |<-first atom start ... last atom end->| + +------++------+-- ... --+-- ... --++------+ + | 0 || 1..2 | 3... | 0x*...0x*E || 0x*F | + +------++------+-- ... --+-- ... --++------+ + | 0xFC || M | content | padding || CC | + +------++------+-- ... --+-- ... --++------+ + + A == (N+3)/16 + 1 // The number of atoms in the block [16, 4112] + M == N % 0x10000 // Stored as 2 bytes in network byte order + padding == 15 - (N+3)%16 // Length of the zero padding + +Relocated used block + +Relocated block allows to permanently assign a handle to some content and +resize the content anytime afterwards without having to update all the possible +existing references; the handle can be constant while the content size may be +dynamic. When relocating a block, any space left by the original block content, +above this single atom block, MUST be reclaimed. + +Relocations MUST point only to a used short or long block == blocks with tags +0x00...0xFC. + + +------++------+---------++----+ + | 0 || 1..7 | 8...14 || 15 | + +------++------+---------++----+ + | 0xFD || H | padding || 0 | + +------++------+---------++----+ + +H is the handle of the relocated block in network byte order. + +Free blocks + +Free blocks are the result of space deallocation. Free blocks are organized in +one or more doubly linked lists, abstracted by the FLT interface. Free blocks +MUST be "registered" by putting them in such list. Allocator MUST reuse a big +enough free block, if such exists, before growing the file size. When a free +block is created by deallocation or reallocation it MUST be joined with any +adjacently existing free blocks before "registering". If the resulting free +block is now a last block of a file, the free block MUST be discarded and the +file size MUST be truncated accordingly instead. Put differently, there MUST +NOT ever be a free block at the file end. + +A single free atom + +Is an unused block of size 1 atom. + + +------++------+--------++------+ + | 0 || 1..7 | 8...14 || 15 | + +------++------+--------++------+ + | 0xFE || P | N || 0xFE | + +------++------+--------++------+ + +P and N, stored in network byte order, are the previous and next free block +handles in the doubly linked list to which this free block belongs. + +A long unused block + +Is an unused block of size > 1 atom. + + +------++------+-------+---------+- ... -+----------++------+ + | 0 || 1..7 | 8..14 | 15...21 | | Z-7..Z-1 || Z | + +------++------+-------+---------+- ... -+----------++------+ + | 0xFF || S | P | N | Leak | S || 0xFF | + +------++------+-------+---------+- ... -+----------++------+ + + Z == 16 * S - 1 + +S is the size of this unused block in atoms. P and N are the previous and next +free block handles in the doubly linked list to which this free block belongs. +Leak contains any data the block had before deallocating this block. See also +the subtitle 'Content wiping' above. S, P and N are stored in network byte +order. Large free blocks may trigger a consideration of file hole punching of +the Leak field - for some value of 'large'. + +Note: Allocator methods vs CRUD[1]: + + Alloc [C]reate + Get [R]ead + Realloc [U]pdate + Free [D]elete + +Note: No Allocator method returns io.EOF. + + [1]: http://en.wikipedia.org/wiki/Create,_read,_update_and_delete + +*/ +type Allocator struct { + f Filer + flt flt + Compress bool // enables content compression + cache cache + m map[int64]*node + lru lst + expHit int64 + expMiss int64 + cacheSz int + hit uint16 + miss uint16 + mu sync.Mutex +} + +// NewAllocator returns a new Allocator. To open an existing file, pass its +// Filer. To create a "new" file, pass a Filer which file is of zero size. +func NewAllocator(f Filer, opts *Options) (a *Allocator, err error) { + if opts == nil { // Enforce *Options is always passed + return nil, errors.New("NewAllocator: nil opts passed") + } + + a = &Allocator{ + f: f, + cacheSz: 10, + } + + a.cinit() + switch x := f.(type) { + case *RollbackFiler: + x.afterRollback = func() error { + a.cinit() + return a.flt.load(a.f, 0) + } + case *ACIDFiler0: + x.RollbackFiler.afterRollback = func() error { + a.cinit() + return a.flt.load(a.f, 0) + } + } + + sz, err := f.Size() + if err != nil { + return + } + + a.flt.init() + if sz == 0 { + var b [fltSz]byte + if err = a.f.BeginUpdate(); err != nil { + return + } + + if _, err = f.WriteAt(b[:], 0); err != nil { + a.f.Rollback() + return + } + + return a, a.f.EndUpdate() + } + + return a, a.flt.load(f, 0) +} + +// CacheStats reports cache statistics. +// +//TODO return a struct perhaps. +func (a *Allocator) CacheStats() (buffersUsed, buffersTotal int, bytesUsed, bytesTotal, hits, misses int64) { + buffersUsed = len(a.m) + buffersTotal = buffersUsed + len(a.cache) + bytesUsed = a.lru.size() + bytesTotal = bytesUsed + a.cache.size() + hits = a.expHit + misses = a.expMiss + return +} + +func (a *Allocator) cinit() { + for h, n := range a.m { + a.cache.put(a.lru.remove(n)) + delete(a.m, h) + } + if a.m == nil { + a.m = map[int64]*node{} + } +} + +func (a *Allocator) cadd(b []byte, h int64) { + if len(a.m) < a.cacheSz { + n := a.cache.get(len(b)) + n.h = h + copy(n.b, b) + a.m[h] = a.lru.pushFront(n) + return + } + + // cache full + delete(a.m, a.cache.put(a.lru.removeBack()).h) + n := a.cache.get(len(b)) + n.h = h + copy(n.b, b) + a.m[h] = a.lru.pushFront(n) + return +} + +func (a *Allocator) cfree(h int64) { + n, ok := a.m[h] + if !ok { // must have been evicted + return + } + + a.cache.put(a.lru.remove(n)) + delete(a.m, h) +} + +// Alloc allocates storage space for b and returns the handle of the new block +// with content set to b or an error, if any. The returned handle is valid only +// while the block is used - until the block is deallocated. No two valid +// handles share the same value within the same Filer, but any value of a +// handle not referring to any used block may become valid any time as a result +// of Alloc. +// +// Invoking Alloc on an empty Allocator is guaranteed to return handle with +// value 1. The intended use of content of handle 1 is a root "directory" of +// other data held by an Allocator. +// +// Passing handles not obtained initially from Alloc or not anymore valid to +// any other Allocator methods can result in an irreparably corrupted database. +func (a *Allocator) Alloc(b []byte) (handle int64, err error) { + buf := bufs.GCache.Get(zappy.MaxEncodedLen(len(b))) + defer bufs.GCache.Put(buf) + buf, _, cc, err := a.makeUsedBlock(buf, b) + if err != nil { + return + } + + if handle, err = a.alloc(buf, cc); err == nil { + a.cadd(b, handle) + } + return +} + +func (a *Allocator) alloc(b []byte, cc byte) (h int64, err error) { + rqAtoms := n2atoms(len(b)) + if h = a.flt.find(rqAtoms); h == 0 { // must grow + var sz int64 + if sz, err = a.f.Size(); err != nil { + return + } + + h = off2h(sz) + err = a.writeUsedBlock(h, cc, b) + return + } + + // Handle is the first item of a free blocks list. + tag, s, prev, next, err := a.nfo(h) + if err != nil { + return + } + + if tag != tagFreeShort && tag != tagFreeLong { + err = &ErrILSEQ{Type: ErrExpFreeTag, Off: h2off(h), Arg: int64(tag)} + return + } + + if prev != 0 { + err = &ErrILSEQ{Type: ErrHead, Off: h2off(h), Arg: prev} + return + } + + if s < int64(rqAtoms) { + err = &ErrILSEQ{Type: ErrSmall, Arg: int64(rqAtoms), Arg2: s, Off: h2off(h)} + return + } + + if err = a.unlink(h, s, prev, next); err != nil { + return + } + + if s > int64(rqAtoms) { + freeH := h + int64(rqAtoms) + freeAtoms := s - int64(rqAtoms) + if err = a.link(freeH, freeAtoms); err != nil { + return + } + } + return h, a.writeUsedBlock(h, cc, b) +} + +// Free deallocates the block referred to by handle or returns an error, if +// any. +// +// After Free succeeds, handle is invalid and must not be used. +// +// Handle must have been obtained initially from Alloc and must be still valid, +// otherwise a database may get irreparably corrupted. +func (a *Allocator) Free(handle int64) (err error) { + if handle <= 0 || handle > maxHandle { + return &ErrINVAL{"Allocator.Free: handle out of limits", handle} + } + + a.cfree(handle) + return a.free(handle, 0, true) +} + +func (a *Allocator) free(h, from int64, acceptRelocs bool) (err error) { + tag, atoms, _, n, err := a.nfo(h) + if err != nil { + return + } + + switch tag { + default: + // nop + case tagUsedLong: + // nop + case tagUsedRelocated: + if !acceptRelocs { + return &ErrILSEQ{Type: ErrUnexpReloc, Off: h2off(h), Arg: h2off(from)} + } + + if err = a.free(n, h, false); err != nil { + return + } + case tagFreeShort, tagFreeLong: + return &ErrINVAL{"Allocator.Free: attempt to free a free block at off", h2off(h)} + } + + return a.free2(h, atoms) +} + +func (a *Allocator) free2(h, atoms int64) (err error) { + sz, err := a.f.Size() + if err != nil { + return + } + + ltag, latoms, lp, ln, err := a.leftNfo(h) + if err != nil { + return + } + + if ltag != tagFreeShort && ltag != tagFreeLong { + latoms = 0 + } + + var rtag byte + var ratoms, rp, rn int64 + + isTail := h2off(h)+atoms*16 == sz + if !isTail { + if rtag, ratoms, rp, rn, err = a.nfo(h + atoms); err != nil { + return + } + } + + if rtag != tagFreeShort && rtag != tagFreeLong { + ratoms = 0 + } + + switch { + case latoms == 0 && ratoms == 0: + // -> isolated <- + if isTail { // cut tail + return a.f.Truncate(h2off(h)) + } + + return a.link(h, atoms) + case latoms == 0 && ratoms != 0: + // right join -> + if err = a.unlink(h+atoms, ratoms, rp, rn); err != nil { + return + } + + return a.link(h, atoms+ratoms) + case latoms != 0 && ratoms == 0: + // <- left join + if err = a.unlink(h-latoms, latoms, lp, ln); err != nil { + return + } + + if isTail { + return a.f.Truncate(h2off(h - latoms)) + } + + return a.link(h-latoms, latoms+atoms) + } + + // case latoms != 0 && ratoms != 0: + // <- middle join -> + lh, rh := h-latoms, h+atoms + if err = a.unlink(lh, latoms, lp, ln); err != nil { + return + } + + // Prev unlink may have invalidated rp or rn + if _, _, rp, rn, err = a.nfo(rh); err != nil { + return + } + + if err = a.unlink(rh, ratoms, rp, rn); err != nil { + return + } + + return a.link(h-latoms, latoms+atoms+ratoms) +} + +// Add a free block h to the appropriate free list +func (a *Allocator) link(h, atoms int64) (err error) { + if err = a.makeFree(h, atoms, 0, a.flt.head(atoms)); err != nil { + return + } + + return a.flt.setHead(h, atoms, a.f) +} + +// Remove free block h from the free list +func (a *Allocator) unlink(h, atoms, p, n int64) (err error) { + switch { + case p == 0 && n == 0: + // single item list, must be head + return a.flt.setHead(0, atoms, a.f) + case p == 0 && n != 0: + // head of list (has next item[s]) + if err = a.prev(n, 0); err != nil { + return + } + + // new head + return a.flt.setHead(n, atoms, a.f) + case p != 0 && n == 0: + // last item in list + return a.next(p, 0) + } + // case p != 0 && n != 0: + // intermediate item in a list + if err = a.next(p, n); err != nil { + return + } + + return a.prev(n, p) +} + +//TODO remove ? +// Return len(slice) == n, reuse src if possible. +func need(n int, src []byte) []byte { + if cap(src) < n { + bufs.GCache.Put(src) + return bufs.GCache.Get(n) + } + + return src[:n] +} + +// Get returns the data content of a block referred to by handle or an error if +// any. The returned slice may be a sub-slice of buf if buf was large enough +// to hold the entire content. Otherwise, a newly allocated slice will be +// returned. It is valid to pass a nil buf. +// +// If the content was stored using compression then it is transparently +// returned decompressed. +// +// Handle must have been obtained initially from Alloc and must be still valid, +// otherwise invalid data may be returned without detecting the error. +// +// Get is safe for concurrent access by multiple goroutines iff no other +// goroutine mutates the DB. +func (a *Allocator) Get(buf []byte, handle int64) (b []byte, err error) { + buf = buf[:cap(buf)] + a.mu.Lock() // X1+ + if n, ok := a.m[handle]; ok { + a.lru.moveToFront(n) + b = need(len(n.b), buf) + copy(b, n.b) + a.expHit++ + a.hit++ + a.mu.Unlock() // X1- + return + } + + a.expMiss++ + a.miss++ + if a.miss > 10 && len(a.m) < 500 { + if 100*a.hit/a.miss < 95 { + a.cacheSz++ + } + a.hit, a.miss = 0, 0 + } + a.mu.Unlock() // X1- + + defer func(h int64) { + if err == nil { + a.mu.Lock() // X2+ + a.cadd(b, h) + a.mu.Unlock() // X2- + } + }(handle) + + first := bufs.GCache.Get(16) + defer bufs.GCache.Put(first) + relocated := false + relocSrc := handle +reloc: + if handle <= 0 || handle > maxHandle { + return nil, &ErrINVAL{"Allocator.Get: handle out of limits", handle} + } + + off := h2off(handle) + if err = a.read(first, off); err != nil { + return + } + + switch tag := first[0]; tag { + default: + dlen := int(tag) + atoms := n2atoms(dlen) + switch atoms { + case 1: + switch tag := first[15]; tag { + default: + return nil, &ErrILSEQ{Type: ErrTailTag, Off: off, Arg: int64(tag)} + case tagNotCompressed: + b = need(dlen, buf) + copy(b, first[1:]) + return + case tagCompressed: + return zappy.Decode(buf, first[1:dlen+1]) + } + default: + cc := bufs.GCache.Get(1) + defer bufs.GCache.Put(cc) + dlen := int(tag) + atoms := n2atoms(dlen) + tailOff := off + 16*int64(atoms) - 1 + if err = a.read(cc, tailOff); err != nil { + return + } + + switch tag := cc[0]; tag { + default: + return nil, &ErrILSEQ{Type: ErrTailTag, Off: off, Arg: int64(tag)} + case tagNotCompressed: + b = need(dlen, buf) + off += 1 + if err = a.read(b, off); err != nil { + b = buf[:0] + } + return + case tagCompressed: + zbuf := bufs.GCache.Get(dlen) + defer bufs.GCache.Put(zbuf) + off += 1 + if err = a.read(zbuf, off); err != nil { + return buf[:0], err + } + + return zappy.Decode(buf, zbuf) + } + } + case 0: + return buf[:0], nil + case tagUsedLong: + cc := bufs.GCache.Get(1) + defer bufs.GCache.Put(cc) + dlen := m2n(int(first[1])<<8 | int(first[2])) + atoms := n2atoms(dlen) + tailOff := off + 16*int64(atoms) - 1 + if err = a.read(cc, tailOff); err != nil { + return + } + + switch tag := cc[0]; tag { + default: + return nil, &ErrILSEQ{Type: ErrTailTag, Off: off, Arg: int64(tag)} + case tagNotCompressed: + b = need(dlen, buf) + off += 3 + if err = a.read(b, off); err != nil { + b = buf[:0] + } + return + case tagCompressed: + zbuf := bufs.GCache.Get(dlen) + defer bufs.GCache.Put(zbuf) + off += 3 + if err = a.read(zbuf, off); err != nil { + return buf[:0], err + } + + return zappy.Decode(buf, zbuf) + } + case tagFreeShort, tagFreeLong: + return nil, &ErrILSEQ{Type: ErrExpUsedTag, Off: off, Arg: int64(tag)} + case tagUsedRelocated: + if relocated { + return nil, &ErrILSEQ{Type: ErrUnexpReloc, Off: off, Arg: relocSrc} + } + + handle = b2h(first[1:]) + relocated = true + goto reloc + } +} + +var reallocTestHook bool + +// Realloc sets the content of a block referred to by handle or returns an +// error, if any. +// +// Handle must have been obtained initially from Alloc and must be still valid, +// otherwise a database may get irreparably corrupted. +func (a *Allocator) Realloc(handle int64, b []byte) (err error) { + if handle <= 0 || handle > maxHandle { + return &ErrINVAL{"Realloc: handle out of limits", handle} + } + + a.cfree(handle) + if err = a.realloc(handle, b); err != nil { + return + } + + if reallocTestHook { + if err = cacheAudit(a.m, &a.lru); err != nil { + return + } + } + + a.cadd(b, handle) + return +} + +func (a *Allocator) realloc(handle int64, b []byte) (err error) { + var dlen, needAtoms0 int + + b8 := bufs.GCache.Get(8) + defer bufs.GCache.Put(b8) + dst := bufs.GCache.Get(zappy.MaxEncodedLen(len(b))) + defer bufs.GCache.Put(dst) + b, needAtoms0, cc, err := a.makeUsedBlock(dst, b) + if err != nil { + return + } + + needAtoms := int64(needAtoms0) + off := h2off(handle) + if err = a.read(b8[:], off); err != nil { + return + } + + switch tag := b8[0]; tag { + default: + dlen = int(b8[0]) + case tagUsedLong: + dlen = m2n(int(b8[1])<<8 | int(b8[2])) + case tagUsedRelocated: + if err = a.free(b2h(b8[1:]), handle, false); err != nil { + return err + } + + dlen = 0 + case tagFreeShort, tagFreeLong: + return &ErrINVAL{"Allocator.Realloc: invalid handle", handle} + } + + atoms := int64(n2atoms(dlen)) +retry: + switch { + case needAtoms < atoms: + // in place shrink + if err = a.writeUsedBlock(handle, cc, b); err != nil { + return + } + + fh, fa := handle+needAtoms, atoms-needAtoms + sz, err := a.f.Size() + if err != nil { + return err + } + + if h2off(fh)+16*fa == sz { + return a.f.Truncate(h2off(fh)) + } + + return a.free2(fh, fa) + case needAtoms == atoms: + // in place replace + return a.writeUsedBlock(handle, cc, b) + } + + // case needAtoms > atoms: + // in place extend or relocate + var sz int64 + if sz, err = a.f.Size(); err != nil { + return + } + + off = h2off(handle) + switch { + case off+atoms*16 == sz: + // relocating tail block - shortcut + return a.writeUsedBlock(handle, cc, b) + default: + if off+atoms*16 < sz { + // handle is not a tail block, check right neighbour + rh := handle + atoms + rtag, ratoms, p, n, e := a.nfo(rh) + if e != nil { + return e + } + + if rtag == tagFreeShort || rtag == tagFreeLong { + // Right neighbour is a free block + if needAtoms <= atoms+ratoms { + // can expand in place + if err = a.unlink(rh, ratoms, p, n); err != nil { + return + } + + atoms += ratoms + goto retry + + } + } + } + } + + if atoms > 1 { + if err = a.realloc(handle, nil); err != nil { + return + } + } + + var newH int64 + if newH, err = a.alloc(b, cc); err != nil { + return err + } + + rb := bufs.GCache.Cget(16) + defer bufs.GCache.Put(rb) + rb[0] = tagUsedRelocated + h2b(rb[1:], newH) + if err = a.writeAt(rb[:], h2off(handle)); err != nil { + return + } + + return a.writeUsedBlock(newH, cc, b) +} + +func (a *Allocator) writeAt(b []byte, off int64) (err error) { + var n int + if n, err = a.f.WriteAt(b, off); err != nil { + return + } + + if n != len(b) { + err = io.ErrShortWrite + } + return +} + +func (a *Allocator) write(off int64, b ...[]byte) (err error) { + rq := 0 + for _, part := range b { + rq += len(part) + } + buf := bufs.GCache.Get(rq) + defer bufs.GCache.Put(buf) + buf = buf[:0] + for _, part := range b { + buf = append(buf, part...) + } + return a.writeAt(buf, off) +} + +func (a *Allocator) read(b []byte, off int64) (err error) { + var rn int + if rn, err = a.f.ReadAt(b, off); rn != len(b) { + return &ErrILSEQ{Type: ErrOther, Off: off, More: err} + } + + return nil +} + +// nfo returns h's tag. If it's a free block then return also (s)ize (in +// atoms), (p)rev and (n)ext. If it's a used block then only (s)ize is returned +// (again in atoms). If it's a used relocate block then (n)ext is set to the +// relocation target handle. +func (a *Allocator) nfo(h int64) (tag byte, s, p, n int64, err error) { + off := h2off(h) + rq := int64(22) + sz, err := a.f.Size() + if err != nil { + return + } + + if off+rq >= sz { + if rq = sz - off; rq < 15 { + err = io.ErrUnexpectedEOF + return + } + } + + buf := bufs.GCache.Get(22) + defer bufs.GCache.Put(buf) + if err = a.read(buf[:rq], off); err != nil { + return + } + + switch tag = buf[0]; tag { + default: + s = int64(n2atoms(int(tag))) + case tagUsedLong: + s = int64(n2atoms(m2n(int(buf[1])<<8 | int(buf[2])))) + case tagFreeLong: + if rq < 22 { + err = io.ErrUnexpectedEOF + return + } + + s, p, n = b2h(buf[1:]), b2h(buf[8:]), b2h(buf[15:]) + case tagUsedRelocated: + s, n = 1, b2h(buf[1:]) + case tagFreeShort: + s, p, n = 1, b2h(buf[1:]), b2h(buf[8:]) + } + return +} + +// leftNfo returns nfo for h's left neighbor if h > 1 and the left neighbor is +// a free block. Otherwise all zero values are returned instead. +func (a *Allocator) leftNfo(h int64) (tag byte, s, p, n int64, err error) { + if !(h > 1) { + return + } + + buf := bufs.GCache.Get(8) + defer bufs.GCache.Put(buf) + off := h2off(h) + if err = a.read(buf[:], off-8); err != nil { + return + } + + switch tag := buf[7]; tag { + case tagFreeShort: + return a.nfo(h - 1) + case tagFreeLong: + return a.nfo(h - b2h(buf[:])) + } + return +} + +// Set h.prev = p +func (a *Allocator) prev(h, p int64) (err error) { + b := bufs.GCache.Get(7) + defer bufs.GCache.Put(b) + off := h2off(h) + if err = a.read(b[:1], off); err != nil { + return + } + + switch tag := b[0]; tag { + default: + return &ErrILSEQ{Type: ErrExpFreeTag, Off: off, Arg: int64(tag)} + case tagFreeShort: + off += 1 + case tagFreeLong: + off += 8 + } + return a.writeAt(h2b(b[:7], p), off) +} + +// Set h.next = n +func (a *Allocator) next(h, n int64) (err error) { + b := bufs.GCache.Get(7) + defer bufs.GCache.Put(b) + off := h2off(h) + if err = a.read(b[:1], off); err != nil { + return + } + + switch tag := b[0]; tag { + default: + return &ErrILSEQ{Type: ErrExpFreeTag, Off: off, Arg: int64(tag)} + case tagFreeShort: + off += 8 + case tagFreeLong: + off += 15 + } + return a.writeAt(h2b(b[:7], n), off) +} + +// Make the filer image @h a free block. +func (a *Allocator) makeFree(h, atoms, prev, next int64) (err error) { + buf := bufs.GCache.Get(22) + defer bufs.GCache.Put(buf) + switch { + case atoms == 1: + buf[0], buf[15] = tagFreeShort, tagFreeShort + h2b(buf[1:], prev) + h2b(buf[8:], next) + if err = a.write(h2off(h), buf[:16]); err != nil { + return + } + default: + + buf[0] = tagFreeLong + h2b(buf[1:], atoms) + h2b(buf[8:], prev) + h2b(buf[15:], next) + if err = a.write(h2off(h), buf[:22]); err != nil { + return + } + + h2b(buf[:], atoms) + buf[7] = tagFreeLong + if err = a.write(h2off(h+atoms)-8, buf[:8]); err != nil { + return + } + } + if prev != 0 { + if err = a.next(prev, h); err != nil { + return + } + } + + if next != 0 { + err = a.prev(next, h) + } + return +} + +func (a *Allocator) makeUsedBlock(dst []byte, b []byte) (w []byte, rqAtoms int, cc byte, err error) { + cc = tagNotCompressed + w = b + + var n int + if n = len(b); n > maxRq { + return nil, 0, 0, &ErrINVAL{"Allocator.makeUsedBlock: content size out of limits", n} + } + + rqAtoms = n2atoms(n) + if a.Compress && n > 14 { // attempt compression + if dst, err = zappy.Encode(dst, b); err != nil { + return + } + + n2 := len(dst) + if rqAtoms2 := n2atoms(n2); rqAtoms2 < rqAtoms { // compression saved at least a single atom + w, n, rqAtoms, cc = dst, n2, rqAtoms2, tagCompressed + } + } + return +} + +func (a *Allocator) writeUsedBlock(h int64, cc byte, b []byte) (err error) { + n := len(b) + rq := n2atoms(n) << 4 + buf := bufs.GCache.Get(rq) + defer bufs.GCache.Put(buf) + switch n <= maxShort { + case true: + buf[0] = byte(n) + copy(buf[1:], b) + case false: + m := n2m(n) + buf[0], buf[1], buf[2] = tagUsedLong, byte(m>>8), byte(m) + copy(buf[3:], b) + } + if p := n2padding(n); p != 0 { + copy(buf[rq-1-p:], zeros[:]) + } + buf[rq-1] = cc + return a.writeAt(buf, h2off(h)) +} + +func (a *Allocator) verifyUnused(h, totalAtoms int64, tag byte, log func(error) bool, fast bool) (atoms, prev, next int64, err error) { + switch tag { + default: + panic("internal error") + case tagFreeShort: + var b [16]byte + off := h2off(h) + if err = a.read(b[:], off); err != nil { + return + } + + if b[15] != tagFreeShort { + err = &ErrILSEQ{Type: ErrShortFreeTailTag, Off: off, Arg: int64(b[15])} + log(err) + return + } + + atoms, prev, next = 1, b2h(b[1:]), b2h(b[8:]) + case tagFreeLong: + var b [22]byte + off := h2off(h) + if err = a.read(b[:], off); err != nil { + return + } + + atoms, prev, next = b2h(b[1:]), b2h(b[8:]), b2h(b[15:]) + if fast { + return + } + + if atoms < 2 { + err = &ErrILSEQ{Type: ErrLongFreeBlkTooShort, Off: off, Arg: int64(atoms)} + break + } + + if h+atoms-1 > totalAtoms { + err = &ErrILSEQ{Type: ErrLongFreeBlkTooLong, Off: off, Arg: atoms} + break + } + + if prev > totalAtoms { + err = &ErrILSEQ{Type: ErrLongFreePrevBeyondEOF, Off: off, Arg: next} + break + } + + if next > totalAtoms { + err = &ErrILSEQ{Type: ErrLongFreeNextBeyondEOF, Off: off, Arg: next} + break + } + + toff := h2off(h+atoms) - 8 + if err = a.read(b[:8], toff); err != nil { + return + } + + if b[7] != tag { + err = &ErrILSEQ{Type: ErrLongFreeTailTag, Off: off, Arg: int64(b[7])} + break + } + + if s2 := b2h(b[:]); s2 != atoms { + err = &ErrILSEQ{Type: ErrVerifyTailSize, Off: off, Arg: atoms, Arg2: s2} + break + } + + } + if err != nil { + log(err) + } + return +} + +func (a *Allocator) verifyUsed(h, totalAtoms int64, tag byte, buf, ubuf []byte, log func(error) bool, fast bool) (compressed bool, dlen int, atoms, link int64, err error) { + var ( + padding int + doff int64 + padZeros [15]byte + tailBuf [16]byte + ) + + switch tag { + default: // Short used + dlen = int(tag) + atoms = int64((dlen+1)/16) + 1 + padding = 15 - (dlen+1)%16 + doff = h2off(h) + 1 + case tagUsedLong: + off := h2off(h) + 1 + var b2 [2]byte + if err = a.read(b2[:], off); err != nil { + return + } + + dlen = m2n(int(b2[0])<<8 | int(b2[1])) + atoms = int64((dlen+3)/16) + 1 + padding = 15 - (dlen+3)%16 + doff = h2off(h) + 3 + case tagUsedRelocated: + dlen = 7 + atoms = 1 + padding = 7 + doff = h2off(h) + 1 + case tagFreeShort, tagFreeLong: + panic("internal error") + } + + if fast { + if tag == tagUsedRelocated { + dlen = 0 + if err = a.read(buf[:7], doff); err != nil { + return + } + + link = b2h(buf) + } + + return false, dlen, atoms, link, nil + } + + if ok := h+atoms-1 <= totalAtoms; !ok { // invalid last block + err = &ErrILSEQ{Type: ErrVerifyUsedSpan, Off: h2off(h), Arg: atoms} + log(err) + return + } + + tailsz := 1 + padding + off := h2off(h) + 16*atoms - int64(tailsz) + if err = a.read(tailBuf[:tailsz], off); err != nil { + return false, 0, 0, 0, err + } + + if ok := bytes.Equal(padZeros[:padding], tailBuf[:padding]); !ok { + err = &ErrILSEQ{Type: ErrVerifyPadding, Off: h2off(h)} + log(err) + return + } + + var cc byte + switch cc = tailBuf[padding]; cc { + default: + err = &ErrILSEQ{Type: ErrTailTag, Off: h2off(h)} + log(err) + return + case tagCompressed: + compressed = true + if tag == tagUsedRelocated { + err = &ErrILSEQ{Type: ErrTailTag, Off: h2off(h)} + log(err) + return + } + + fallthrough + case tagNotCompressed: + if err = a.read(buf[:dlen], doff); err != nil { + return false, 0, 0, 0, err + } + } + + if cc == tagCompressed { + if ubuf, err = zappy.Decode(ubuf, buf[:dlen]); err != nil || len(ubuf) > maxRq { + err = &ErrILSEQ{Type: ErrDecompress, Off: h2off(h)} + log(err) + return + } + + dlen = len(ubuf) + } + + if tag == tagUsedRelocated { + link = b2h(buf) + if link == 0 { + err = &ErrILSEQ{Type: ErrNullReloc, Off: h2off(h)} + log(err) + return + } + + if link > totalAtoms { // invalid last block + err = &ErrILSEQ{Type: ErrRelocBeyondEOF, Off: h2off(h), Arg: link} + log(err) + return + } + } + + return +} + +var nolog = func(error) bool { return false } + +// Verify attempts to find any structural errors in a Filer wrt the +// organization of it as defined by Allocator. 'bitmap' is a scratch pad for +// necessary bookkeeping and will grow to at most to Allocator's +// Filer.Size()/128 (0,78%). Any problems found are reported to 'log' except +// non verify related errors like disk read fails etc. If 'log' returns false +// or the error doesn't allow to (reliably) continue, the verification process +// is stopped and an error is returned from the Verify function. Passing a nil +// log works like providing a log function always returning false. Any +// non-structural errors, like for instance Filer read errors, are NOT reported +// to 'log', but returned as the Verify's return value, because Verify cannot +// proceed in such cases. Verify returns nil only if it fully completed +// verifying Allocator's Filer without detecting any error. +// +// It is recommended to limit the number reported problems by returning false +// from 'log' after reaching some limit. Huge and corrupted DB can produce an +// overwhelming error report dataset. +// +// The verifying process will scan the whole DB at least 3 times (a trade +// between processing space and time consumed). It doesn't read the content of +// free blocks above the head/tail info bytes. If the 3rd phase detects lost +// free space, then a 4th scan (a faster one) is performed to precisely report +// all of them. +// +// If the DB/Filer to be verified is reasonably small, respective if its +// size/128 can comfortably fit within process's free memory, then it is +// recommended to consider using a MemFiler for the bit map. +// +// Statistics are returned via 'stats' if non nil. The statistics are valid +// only if Verify succeeded, ie. it didn't reported anything to log and it +// returned a nil error. +func (a *Allocator) Verify(bitmap Filer, log func(error) bool, stats *AllocStats) (err error) { + if log == nil { + log = nolog + } + + n, err := bitmap.Size() + if err != nil { + return + } + + if n != 0 { + return &ErrINVAL{"Allocator.Verify: bit map initial size non zero (%d)", n} + } + + var bits int64 + bitMask := [8]byte{1, 2, 4, 8, 16, 32, 64, 128} + byteBuf := []byte{0} + + //DONE + // +performance, this implementation is hopefully correct but _very_ + // naive, probably good as a prototype only. Use maybe a MemFiler + // "cache" etc. + // ---- + // Turns out the OS caching is as effective as it can probably get. + bit := func(on bool, h int64) (wasOn bool, err error) { + m := bitMask[h&7] + off := h >> 3 + var v byte + sz, err := bitmap.Size() + if err != nil { + return + } + + if off < sz { + if n, err := bitmap.ReadAt(byteBuf, off); n != 1 { + return false, &ErrILSEQ{Type: ErrOther, Off: off, More: fmt.Errorf("Allocator.Verify - reading bitmap: %s", err)} + } + + v = byteBuf[0] + } + switch wasOn = v&m != 0; on { + case true: + if !wasOn { + v |= m + bits++ + } + case false: + if wasOn { + v ^= m + bits-- + } + } + byteBuf[0] = v + if n, err := bitmap.WriteAt(byteBuf, off); n != 1 || err != nil { + return false, &ErrILSEQ{Type: ErrOther, Off: off, More: fmt.Errorf("Allocator.Verify - writing bitmap: %s", err)} + } + + return + } + + // Phase 1 - sequentially scan a.f to reliably determine block + // boundaries. Set a bit for every block start. + var ( + buf, ubuf [maxRq]byte + prevH, h, atoms int64 + wasOn bool + tag byte + st = AllocStats{ + AllocMap: map[int64]int64{}, + FreeMap: map[int64]int64{}, + } + dlen int + ) + + fsz, err := a.f.Size() + if err != nil { + return + } + + ok := fsz%16 == 0 + totalAtoms := (fsz - fltSz) / atomLen + if !ok { + err = &ErrILSEQ{Type: ErrFileSize, Name: a.f.Name(), Arg: fsz} + log(err) + return + } + + st.TotalAtoms = totalAtoms + prevTag := -1 + lastH := int64(-1) + + for h = 1; h <= totalAtoms; h += atoms { + prevH = h // For checking last block == used + + off := h2off(h) + if err = a.read(buf[:1], off); err != nil { + return + } + + switch tag = buf[0]; tag { + default: // Short used + fallthrough + case tagUsedLong, tagUsedRelocated: + var compressed bool + if compressed, dlen, atoms, _, err = a.verifyUsed(h, totalAtoms, tag, buf[:], ubuf[:], log, false); err != nil { + return + } + + if compressed { + st.Compression++ + } + st.AllocAtoms += atoms + switch { + case tag == tagUsedRelocated: + st.AllocMap[1]++ + st.Relocations++ + default: + st.AllocMap[atoms]++ + st.AllocBytes += int64(dlen) + st.Handles++ + } + case tagFreeShort, tagFreeLong: + if prevTag == tagFreeShort || prevTag == tagFreeLong { + err = &ErrILSEQ{Type: ErrAdjacentFree, Off: h2off(lastH), Arg: off} + log(err) + return + } + + if atoms, _, _, err = a.verifyUnused(h, totalAtoms, tag, log, false); err != nil { + return + } + + st.FreeMap[atoms]++ + st.FreeAtoms += atoms + } + + if wasOn, err = bit(true, h); err != nil { + return + } + + if wasOn { + panic("internal error") + } + + prevTag = int(tag) + lastH = h + } + + if totalAtoms != 0 && (tag == tagFreeShort || tag == tagFreeLong) { + err = &ErrILSEQ{Type: ErrFreeTailBlock, Off: h2off(prevH)} + log(err) + return + } + + // Phase 2 - check used blocks, turn off the map bit for every used + // block. + for h = 1; h <= totalAtoms; h += atoms { + off := h2off(h) + if err = a.read(buf[:1], off); err != nil { + return + } + + var link int64 + switch tag = buf[0]; tag { + default: // Short used + fallthrough + case tagUsedLong, tagUsedRelocated: + if _, _, atoms, link, err = a.verifyUsed(h, totalAtoms, tag, buf[:], ubuf[:], log, true); err != nil { + return + } + case tagFreeShort, tagFreeLong: + if atoms, _, _, err = a.verifyUnused(h, totalAtoms, tag, log, true); err != nil { + return + } + } + + turnoff := true + switch tag { + case tagUsedRelocated: + if err = a.read(buf[:1], h2off(link)); err != nil { + return + } + + switch linkedTag := buf[0]; linkedTag { + case tagFreeShort, tagFreeLong, tagUsedRelocated: + err = &ErrILSEQ{Type: ErrInvalidRelocTarget, Off: off, Arg: link} + log(err) + return + } + + case tagFreeShort, tagFreeLong: + turnoff = false + } + + if !turnoff { + continue + } + + if wasOn, err = bit(false, h); err != nil { + return + } + + if !wasOn { + panic("internal error") + } + + } + + // Phase 3 - using the flt check heads link to proper free blocks. For + // every free block, walk the list, verify the {next, prev} links and + // turn the respective map bit off. After processing all free lists, + // the map bits count should be zero. Otherwise there are "lost" free + // blocks. + + var prev, next, fprev, fnext int64 + rep := a.flt + + for _, list := range rep { + prev, next = 0, list.head + for ; next != 0; prev, next = next, fnext { + if wasOn, err = bit(false, next); err != nil { + return + } + + if !wasOn { + err = &ErrILSEQ{Type: ErrFLT, Off: h2off(next), Arg: h} + log(err) + return + } + + off := h2off(next) + if err = a.read(buf[:1], off); err != nil { + return + } + + switch tag = buf[0]; tag { + default: + panic("internal error") + case tagFreeShort, tagFreeLong: + if atoms, fprev, fnext, err = a.verifyUnused(next, totalAtoms, tag, log, true); err != nil { + return + } + + if min := list.minSize; atoms < min { + err = &ErrILSEQ{Type: ErrFLTSize, Off: h2off(next), Arg: atoms, Arg2: min} + log(err) + return + } + + if fprev != prev { + err = &ErrILSEQ{Type: ErrFreeChaining, Off: h2off(next)} + log(err) + return + } + } + } + + } + + if bits == 0 { // Verify succeeded + if stats != nil { + *stats = st + } + return + } + + // Phase 4 - if after phase 3 there are lost free blocks, report all of + // them to 'log' + for i := range ubuf { // setup zeros for compares + ubuf[i] = 0 + } + + var off, lh int64 + rem, err := bitmap.Size() + if err != nil { + return err + } + + for rem != 0 { + rq := int(mathutil.MinInt64(64*1024, rem)) + var n int + if n, err = bitmap.ReadAt(buf[:rq], off); n != rq { + return &ErrILSEQ{Type: ErrOther, Off: off, More: fmt.Errorf("bitmap ReadAt(size %d, off %#x): %s", rq, off, err)} + } + + if !bytes.Equal(buf[:rq], ubuf[:rq]) { + for d, v := range buf[:rq] { + if v != 0 { + for i, m := range bitMask { + if v&m != 0 { + lh = 8*(off+int64(d)) + int64(i) + err = &ErrILSEQ{Type: ErrLostFreeBlock, Off: h2off(lh)} + log(err) + return + } + } + } + } + } + + off += int64(rq) + rem -= int64(rq) + } + + return +} + +type fltSlot struct { + head int64 + minSize int64 +} + +func (f fltSlot) String() string { + return fmt.Sprintf("head %#x, minSize %#x\n", f.head, f.minSize) +} + +type flt [14]fltSlot + +func (f *flt) init() { + sz := 1 + for i := range *f { + f[i].minSize, f[i].head = int64(sz), 0 + sz <<= 1 + } + f[13].minSize = 4112 +} + +func (f *flt) load(fi Filer, off int64) (err error) { + b := bufs.GCache.Get(fltSz) + defer bufs.GCache.Put(b) + if _, err = fi.ReadAt(b[:], off); err != nil { + return + } + + for i := range *f { + off := 8*i + 1 + f[i].head = b2h(b[off:]) + } + return +} + +func (f *flt) find(rq int) (h int64) { + switch { + case rq < 1: + panic(rq) + case rq >= maxFLTRq: + h, f[13].head = f[13].head, 0 + return + default: + g := f[mathutil.Log2Uint16(uint16(rq)):] + for i := range g { + p := &g[i] + if rq <= int(p.minSize) { + if h = p.head; h != 0 { + p.head = 0 + return + } + } + } + return + } +} + +func (f *flt) head(atoms int64) (h int64) { + switch { + case atoms < 1: + panic(atoms) + case atoms >= maxFLTRq: + return f[13].head + default: + lg := mathutil.Log2Uint16(uint16(atoms)) + g := f[lg:] + for i := range g { + if atoms < g[i+1].minSize { + return g[i].head + } + } + panic("internal error") + } +} + +func (f *flt) setHead(h, atoms int64, fi Filer) (err error) { + switch { + case atoms < 1: + panic(atoms) + case atoms >= maxFLTRq: + b := bufs.GCache.Get(7) + defer bufs.GCache.Put(b) + if _, err = fi.WriteAt(h2b(b[:], h), 8*13+1); err != nil { + return + } + + f[13].head = h + return + default: + lg := mathutil.Log2Uint16(uint16(atoms)) + g := f[lg:] + for i := range f { + if atoms < g[i+1].minSize { + b := bufs.GCache.Get(7) + defer bufs.GCache.Put(b) + if _, err = fi.WriteAt(h2b(b[:], h), 8*int64(i+lg)+1); err != nil { + return + } + + g[i].head = h + return + } + } + panic("internal error") + } +} + +func (f *flt) String() string { + a := []string{} + for i, v := range *f { + a = append(a, fmt.Sprintf("[%2d] %s", i, v)) + } + return strings.Join(a, "") +} + +type node struct { + b []byte + h int64 + prev, next *node +} + +type cache []*node + +func (c *cache) get(n int) *node { + r, _ := c.get2(n) + return r +} + +func (c *cache) get2(n int) (r *node, isZeroed bool) { + s := *c + lens := len(s) + if lens == 0 { + return &node{b: make([]byte, n, mathutil.Min(2*n, maxBuf))}, true + } + + i := sort.Search(lens, func(x int) bool { return len(s[x].b) >= n }) + if i == lens { + i-- + s[i].b, isZeroed = make([]byte, n, mathutil.Min(2*n, maxBuf)), true + } + + r = s[i] + r.b = r.b[:n] + copy(s[i:], s[i+1:]) + s = s[:lens-1] + *c = s + return +} + +func (c *cache) cget(n int) (r *node) { + r, ok := c.get2(n) + if ok { + return + } + + for i := range r.b { + r.b[i] = 0 + } + return +} + +func (c *cache) size() (sz int64) { + for _, n := range *c { + sz += int64(cap(n.b)) + } + return +} + +func (c *cache) put(n *node) *node { + s := *c + n.b = n.b[:cap(n.b)] + lenb := len(n.b) + lens := len(s) + i := sort.Search(lens, func(x int) bool { return len(s[x].b) >= lenb }) + s = append(s, nil) + copy(s[i+1:], s[i:]) + s[i] = n + *c = s + return n +} + +type lst struct { + front, back *node +} + +func (l *lst) pushFront(n *node) *node { + if l.front == nil { + l.front, l.back, n.prev, n.next = n, n, nil, nil + return n + } + + n.prev, n.next, l.front.prev, l.front = nil, l.front, n, n + return n +} + +func (l *lst) remove(n *node) *node { + if n.prev == nil { + l.front = n.next + } else { + n.prev.next = n.next + } + if n.next == nil { + l.back = n.prev + } else { + n.next.prev = n.prev + } + n.prev, n.next = nil, nil + return n +} + +func (l *lst) removeBack() *node { + return l.remove(l.back) +} + +func (l *lst) moveToFront(n *node) *node { + return l.pushFront(l.remove(n)) +} + +func (l *lst) size() (sz int64) { + for n := l.front; n != nil; n = n.next { + sz += int64(cap(n.b)) + } + return +} + +func cacheAudit(m map[int64]*node, l *lst) (err error) { + cnt := 0 + for h, n := range m { + if g, e := n.h, h; g != e { + return fmt.Errorf("cacheAudit: invalid node handle %d != %d", g, e) + } + + if cnt, err = l.audit(n, true); err != nil { + return + } + } + + if g, e := cnt, len(m); g != e { + return fmt.Errorf("cacheAudit: invalid cache size %d != %d", g, e) + } + + return +} + +func (l *lst) audit(n *node, onList bool) (cnt int, err error) { + if !onList && (n.prev != nil || n.next != nil) { + return -1, fmt.Errorf("lst.audit: free node with non nil linkage") + } + + if l.front == nil && l.back != nil || l.back == nil && l.front != nil { + return -1, fmt.Errorf("lst.audit: one of .front/.back is nil while the other is non nil") + } + + if l.front == l.back && l.front != nil { + x := l.front + if x.prev != nil || x.next != nil { + return -1, fmt.Errorf("lst.audit: single node has non nil linkage") + } + + if onList && x != n { + return -1, fmt.Errorf("lst.audit: single node is alien") + } + } + + seen := false + var prev *node + x := l.front + for x != nil { + cnt++ + if x.prev != prev { + return -1, fmt.Errorf("lst.audit: broken .prev linkage") + } + + if x == n { + seen = true + } + + prev = x + x = x.next + } + + if prev != l.back { + return -1, fmt.Errorf("lst.audit: broken .back linkage") + } + + if onList && !seen { + return -1, fmt.Errorf("lst.audit: node missing in list") + } + + if !onList && seen { + return -1, fmt.Errorf("lst.audit: node should not be on the list") + } + + return +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/filer.go b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/filer.go new file mode 100644 index 00000000..38b38938 --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/filer.go @@ -0,0 +1,192 @@ +// Copyright 2014 The lldb Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// An abstraction of file like (persistent) storage with optional (abstracted) +// support for structural integrity. + +package lldb + +import ( + "fmt" + + "github.com/cznic/mathutil" +) + +func doubleTrouble(first, second error) error { + return fmt.Errorf("%q. Additionally, while attempting to recover (rollback): %q", first, second) +} + +// A Filer is a []byte-like model of a file or similar entity. It may +// optionally implement support for structural transaction safety. In contrast +// to a file stream, a Filer is not sequentially accessible. ReadAt and WriteAt +// are always "addressed" by an offset and are assumed to perform atomically. +// A Filer is not safe for concurrent access, it's designed for consumption by +// the other objects in package, which should use a Filer from one goroutine +// only or via a mutex. BeginUpdate, EndUpdate and Rollback must be either all +// implemented by a Filer for structural integrity - or they should be all +// no-ops; where/if that requirement is relaxed. +// +// If a Filer wraps another Filer implementation, it usually invokes the same +// methods on the "inner" one, after some possible argument translations etc. +// If a Filer implements the structural transactions handling methods +// (BeginUpdate, EndUpdate and Rollback) as no-ops _and_ wraps another Filer: +// it then still MUST invoke those methods on the inner Filer. This is +// important for the case where a RollbackFiler exists somewhere down the +// chain. It's also important for an Allocator - to know when it must +// invalidate its FLT cache. +type Filer interface { + // BeginUpdate increments the "nesting" counter (initially zero). Every + // call to BeginUpdate must be eventually "balanced" by exactly one of + // EndUpdate or Rollback. Calls to BeginUpdate may nest. + BeginUpdate() error + + // Analogous to os.File.Close(). + Close() error + + // EndUpdate decrements the "nesting" counter. If it's zero after that + // then assume the "storage" has reached structural integrity (after a + // batch of partial updates). If a Filer implements some support for + // that (write ahead log, journal, etc.) then the appropriate actions + // are to be taken for nesting == 0. Invocation of an unbalanced + // EndUpdate is an error. + EndUpdate() error + + // Analogous to os.File.Name(). + Name() string + + // PunchHole deallocates space inside a "file" in the byte range + // starting at off and continuing for size bytes. The actual hole + // created by PunchHole may be smaller than requested. The Filer size + // (as reported by `Size()` does not change when hole punching, even + // when punching the end of a file off. In contrast to the Linux + // implementation of FALLOC_FL_PUNCH_HOLE in `fallocate`(2); a Filer is + // free not only to ignore `PunchHole()` (implement it as a nop), but + // additionally no guarantees about the content of the hole, when + // eventually read back, are required, i.e. any data, not only zeros, + // can be read from the "hole", including just anything what was left + // there - with all of the possible security problems. + PunchHole(off, size int64) error + + // As os.File.ReadAt. Note: `off` is an absolute "file pointer" + // address and cannot be negative even when a Filer is a InnerFiler. + ReadAt(b []byte, off int64) (n int, err error) + + // Rollback cancels and undoes the innermost pending update level. + // Rollback decrements the "nesting" counter. If a Filer implements + // some support for keeping structural integrity (write ahead log, + // journal, etc.) then the appropriate actions are to be taken. + // Invocation of an unbalanced Rollback is an error. + Rollback() error + + // Analogous to os.File.FileInfo().Size(). + Size() (int64, error) + + // Analogous to os.Sync(). + Sync() (err error) + + // Analogous to os.File.Truncate(). + Truncate(size int64) error + + // Analogous to os.File.WriteAt(). Note: `off` is an absolute "file + // pointer" address and cannot be negative even when a Filer is a + // InnerFiler. + WriteAt(b []byte, off int64) (n int, err error) +} + +var _ Filer = &InnerFiler{} // Ensure InnerFiler is a Filer. + +// A InnerFiler is a Filer with added addressing/size translation. +type InnerFiler struct { + outer Filer + off int64 +} + +// NewInnerFiler returns a new InnerFiler wrapped by `outer` in a way which +// adds `off` to every access. +// +// For example, considering: +// +// inner := NewInnerFiler(outer, 10) +// +// then +// +// inner.WriteAt([]byte{42}, 4) +// +// translates to +// +// outer.WriteAt([]byte{42}, 14) +// +// But an attempt to emulate +// +// outer.WriteAt([]byte{17}, 9) +// +// by +// +// inner.WriteAt([]byte{17}, -1) +// +// will fail as the `off` parameter can never be < 0. Also note that +// +// inner.Size() == outer.Size() - off, +// +// i.e. `inner` pretends no `outer` exists. Finally, after e.g. +// +// inner.Truncate(7) +// outer.Size() == 17 +// +// will be true. +func NewInnerFiler(outer Filer, off int64) *InnerFiler { return &InnerFiler{outer, off} } + +// BeginUpdate implements Filer. +func (f *InnerFiler) BeginUpdate() error { return f.outer.BeginUpdate() } + +// Close implements Filer. +func (f *InnerFiler) Close() (err error) { return f.outer.Close() } + +// EndUpdate implements Filer. +func (f *InnerFiler) EndUpdate() error { return f.outer.EndUpdate() } + +// Name implements Filer. +func (f *InnerFiler) Name() string { return f.outer.Name() } + +// PunchHole implements Filer. `off`, `size` must be >= 0. +func (f *InnerFiler) PunchHole(off, size int64) error { return f.outer.PunchHole(f.off+off, size) } + +// ReadAt implements Filer. `off` must be >= 0. +func (f *InnerFiler) ReadAt(b []byte, off int64) (n int, err error) { + if off < 0 { + return 0, &ErrINVAL{f.outer.Name() + ":ReadAt invalid off", off} + } + + return f.outer.ReadAt(b, f.off+off) +} + +// Rollback implements Filer. +func (f *InnerFiler) Rollback() error { return f.outer.Rollback() } + +// Size implements Filer. +func (f *InnerFiler) Size() (int64, error) { + sz, err := f.outer.Size() + if err != nil { + return 0, err + } + + return mathutil.MaxInt64(sz-f.off, 0), nil +} + +// Sync() implements Filer. +func (f *InnerFiler) Sync() (err error) { + return f.outer.Sync() +} + +// Truncate implements Filer. +func (f *InnerFiler) Truncate(size int64) error { return f.outer.Truncate(size + f.off) } + +// WriteAt implements Filer. `off` must be >= 0. +func (f *InnerFiler) WriteAt(b []byte, off int64) (n int, err error) { + if off < 0 { + return 0, &ErrINVAL{f.outer.Name() + ":WriteAt invalid off", off} + } + + return f.outer.WriteAt(b, f.off+off) +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/gb.go b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/gb.go new file mode 100644 index 00000000..e9090a54 --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/gb.go @@ -0,0 +1,812 @@ +// Copyright 2014 The lldb Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Utilities to encode/decode and collate Go predeclared scalar types (and the +// typeless nil and []byte). The encoding format is a variation of the one +// used by the "encoding/gob" package. + +package lldb + +import ( + "bytes" + "fmt" + "math" + + "github.com/cznic/mathutil" +) + +const ( + gbNull = iota // 0x00 + gbFalse // 0x01 + gbTrue // 0x02 + gbFloat0 // 0x03 + gbFloat1 // 0x04 + gbFloat2 // 0x05 + gbFloat3 // 0x06 + gbFloat4 // 0x07 + gbFloat5 // 0x08 + gbFloat6 // 0x09 + gbFloat7 // 0x0a + gbFloat8 // 0x0b + gbComplex0 // 0x0c + gbComplex1 // 0x0d + gbComplex2 // 0x0e + gbComplex3 // 0x0f + gbComplex4 // 0x10 + gbComplex5 // 0x11 + gbComplex6 // 0x12 + gbComplex7 // 0x13 + gbComplex8 // 0x14 + gbBytes00 // 0x15 + gbBytes01 // 0x16 + gbBytes02 // 0x17 + gbBytes03 // 0x18 + gbBytes04 // 0x19 + gbBytes05 // 0x1a + gbBytes06 // 0x1b + gbBytes07 // 0x1c + gbBytes08 // 0x1d + gbBytes09 // 0x1e + gbBytes10 // 0x1f + gbBytes11 // 0x20 + gbBytes12 // 0x21 + gbBytes13 // 0x22 + gbBytes14 // 0x23 + gbBytes15 // 0x24 + gbBytes16 // 0x25 + gbBytes17 // Ox26 + gbBytes1 // 0x27 + gbBytes2 // 0x28: Offset by one to allow 64kB sized []byte. + gbString00 // 0x29 + gbString01 // 0x2a + gbString02 // 0x2b + gbString03 // 0x2c + gbString04 // 0x2d + gbString05 // 0x2e + gbString06 // 0x2f + gbString07 // 0x30 + gbString08 // 0x31 + gbString09 // 0x32 + gbString10 // 0x33 + gbString11 // 0x34 + gbString12 // 0x35 + gbString13 // 0x36 + gbString14 // 0x37 + gbString15 // 0x38 + gbString16 // 0x39 + gbString17 // 0x3a + gbString1 // 0x3b + gbString2 // 0x3c + gbUintP1 // 0x3d + gbUintP2 // 0x3e + gbUintP3 // 0x3f + gbUintP4 // 0x40 + gbUintP5 // 0x41 + gbUintP6 // 0x42 + gbUintP7 // 0x43 + gbUintP8 // 0x44 + gbIntM8 // 0x45 + gbIntM7 // 0x46 + gbIntM6 // 0x47 + gbIntM5 // 0x48 + gbIntM4 // 0x49 + gbIntM3 // 0x4a + gbIntM2 // 0x4b + gbIntM1 // 0x4c + gbIntP1 // 0x4d + gbIntP2 // 0x4e + gbIntP3 // 0x4f + gbIntP4 // 0x50 + gbIntP5 // 0x51 + gbIntP6 // 0x52 + gbIntP7 // 0x53 + gbIntP8 // 0x54 + gbInt0 // 0x55 + + gbIntMax = 255 - gbInt0 // 0xff == 170 +) + +// EncodeScalars encodes a vector of predeclared scalar type values to a +// []byte, making it suitable to store it as a "record" in a DB or to use it as +// a key of a BTree. +func EncodeScalars(scalars ...interface{}) (b []byte, err error) { + for _, scalar := range scalars { + switch x := scalar.(type) { + default: + return nil, &ErrINVAL{"EncodeScalars: unsupported type", fmt.Sprintf("%T in `%#v`", x, scalars)} + + case nil: + b = append(b, gbNull) + + case bool: + switch x { + case false: + b = append(b, gbFalse) + case true: + b = append(b, gbTrue) + } + + case float32: + encFloat(float64(x), &b) + case float64: + encFloat(x, &b) + + case complex64: + encComplex(complex128(x), &b) + case complex128: + encComplex(x, &b) + + case string: + n := len(x) + if n <= 17 { + b = append(b, byte(gbString00+n)) + b = append(b, []byte(x)...) + break + } + + if n > 65535 { + return nil, fmt.Errorf("EncodeScalars: cannot encode string of length %d (limit 65536)", n) + } + + pref := byte(gbString1) + if n > 255 { + pref++ + } + b = append(b, pref) + encUint0(uint64(n), &b) + b = append(b, []byte(x)...) + + case int8: + encInt(int64(x), &b) + case int16: + encInt(int64(x), &b) + case int32: + encInt(int64(x), &b) + case int64: + encInt(x, &b) + case int: + encInt(int64(x), &b) + + case uint8: + encUint(uint64(x), &b) + case uint16: + encUint(uint64(x), &b) + case uint32: + encUint(uint64(x), &b) + case uint64: + encUint(x, &b) + case uint: + encUint(uint64(x), &b) + case []byte: + n := len(x) + if n <= 17 { + b = append(b, byte(gbBytes00+n)) + b = append(b, []byte(x)...) + break + } + + if n > 655356 { + return nil, fmt.Errorf("EncodeScalars: cannot encode []byte of length %d (limit 65536)", n) + } + + pref := byte(gbBytes1) + if n > 255 { + pref++ + } + b = append(b, pref) + if n <= 255 { + b = append(b, byte(n)) + } else { + n-- + b = append(b, byte(n>>8), byte(n)) + } + b = append(b, x...) + } + } + return +} + +func encComplex(f complex128, b *[]byte) { + encFloatPrefix(gbComplex0, real(f), b) + encFloatPrefix(gbComplex0, imag(f), b) +} + +func encFloatPrefix(prefix byte, f float64, b *[]byte) { + u := math.Float64bits(f) + var n uint64 + for i := 0; i < 8; i++ { + n <<= 8 + n |= u & 0xFF + u >>= 8 + } + bits := mathutil.BitLenUint64(n) + if bits == 0 { + *b = append(*b, prefix) + return + } + + // 0 1 2 3 4 5 6 7 8 9 + // . 1 1 1 1 1 1 1 1 2 + encUintPrefix(prefix+1+byte((bits-1)>>3), n, b) +} + +func encFloat(f float64, b *[]byte) { + encFloatPrefix(gbFloat0, f, b) +} + +func encUint0(n uint64, b *[]byte) { + switch { + case n <= 0xff: + *b = append(*b, byte(n)) + case n <= 0xffff: + *b = append(*b, byte(n>>8), byte(n)) + case n <= 0xffffff: + *b = append(*b, byte(n>>16), byte(n>>8), byte(n)) + case n <= 0xffffffff: + *b = append(*b, byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) + case n <= 0xffffffffff: + *b = append(*b, byte(n>>32), byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) + case n <= 0xffffffffffff: + *b = append(*b, byte(n>>40), byte(n>>32), byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) + case n <= 0xffffffffffffff: + *b = append(*b, byte(n>>48), byte(n>>40), byte(n>>32), byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) + case n <= math.MaxUint64: + *b = append(*b, byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32), byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) + } +} + +func encUintPrefix(prefix byte, n uint64, b *[]byte) { + *b = append(*b, prefix) + encUint0(n, b) +} + +func encUint(n uint64, b *[]byte) { + bits := mathutil.Max(1, mathutil.BitLenUint64(n)) + encUintPrefix(gbUintP1+byte((bits-1)>>3), n, b) +} + +func encInt(n int64, b *[]byte) { + switch { + case n < -0x100000000000000: + *b = append(*b, byte(gbIntM8), byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32), byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) + case n < -0x1000000000000: + *b = append(*b, byte(gbIntM7), byte(n>>48), byte(n>>40), byte(n>>32), byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) + case n < -0x10000000000: + *b = append(*b, byte(gbIntM6), byte(n>>40), byte(n>>32), byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) + case n < -0x100000000: + *b = append(*b, byte(gbIntM5), byte(n>>32), byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) + case n < -0x1000000: + *b = append(*b, byte(gbIntM4), byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) + case n < -0x10000: + *b = append(*b, byte(gbIntM3), byte(n>>16), byte(n>>8), byte(n)) + case n < -0x100: + *b = append(*b, byte(gbIntM2), byte(n>>8), byte(n)) + case n < 0: + *b = append(*b, byte(gbIntM1), byte(n)) + case n <= gbIntMax: + *b = append(*b, byte(gbInt0+n)) + case n <= 0xff: + *b = append(*b, gbIntP1, byte(n)) + case n <= 0xffff: + *b = append(*b, gbIntP2, byte(n>>8), byte(n)) + case n <= 0xffffff: + *b = append(*b, gbIntP3, byte(n>>16), byte(n>>8), byte(n)) + case n <= 0xffffffff: + *b = append(*b, gbIntP4, byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) + case n <= 0xffffffffff: + *b = append(*b, gbIntP5, byte(n>>32), byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) + case n <= 0xffffffffffff: + *b = append(*b, gbIntP6, byte(n>>40), byte(n>>32), byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) + case n <= 0xffffffffffffff: + *b = append(*b, gbIntP7, byte(n>>48), byte(n>>40), byte(n>>32), byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) + case n <= 0x7fffffffffffffff: + *b = append(*b, gbIntP8, byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32), byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) + } +} + +func decodeFloat(b []byte) float64 { + var u uint64 + for i, v := range b { + u |= uint64(v) << uint((i+8-len(b))*8) + } + return math.Float64frombits(u) +} + +// DecodeScalars decodes a []byte produced by EncodeScalars. +func DecodeScalars(b []byte) (scalars []interface{}, err error) { + b0 := b + for len(b) != 0 { + switch tag := b[0]; tag { + //default: + //return nil, fmt.Errorf("tag %d(%#x) not supported", b[0], b[0]) + case gbNull: + scalars = append(scalars, nil) + b = b[1:] + case gbFalse: + scalars = append(scalars, false) + b = b[1:] + case gbTrue: + scalars = append(scalars, true) + b = b[1:] + case gbFloat0: + scalars = append(scalars, 0.0) + b = b[1:] + case gbFloat1, gbFloat2, gbFloat3, gbFloat4, gbFloat5, gbFloat6, gbFloat7, gbFloat8: + n := 1 + int(tag) - gbFloat0 + if len(b) < n-1 { + goto corrupted + } + + scalars = append(scalars, decodeFloat(b[1:n])) + b = b[n:] + case gbComplex0, gbComplex1, gbComplex2, gbComplex3, gbComplex4, gbComplex5, gbComplex6, gbComplex7, gbComplex8: + n := 1 + int(tag) - gbComplex0 + if len(b) < n-1 { + goto corrupted + } + + re := decodeFloat(b[1:n]) + b = b[n:] + + if len(b) == 0 { + goto corrupted + } + + tag = b[0] + if tag < gbComplex0 || tag > gbComplex8 { + goto corrupted + } + + n = 1 + int(tag) - gbComplex0 + if len(b) < n-1 { + goto corrupted + } + + scalars = append(scalars, complex(re, decodeFloat(b[1:n]))) + b = b[n:] + case gbBytes00, gbBytes01, gbBytes02, gbBytes03, gbBytes04, + gbBytes05, gbBytes06, gbBytes07, gbBytes08, gbBytes09, + gbBytes10, gbBytes11, gbBytes12, gbBytes13, gbBytes14, + gbBytes15, gbBytes16, gbBytes17: + n := int(tag - gbBytes00) + if len(b) < n+1 { + goto corrupted + } + + scalars = append(scalars, append([]byte(nil), b[1:n+1]...)) + b = b[n+1:] + case gbBytes1: + if len(b) < 2 { + goto corrupted + } + + n := int(b[1]) + b = b[2:] + if len(b) < n { + goto corrupted + } + + scalars = append(scalars, append([]byte(nil), b[:n]...)) + b = b[n:] + case gbBytes2: + if len(b) < 3 { + goto corrupted + } + + n := int(b[1])<<8 | int(b[2]) + 1 + b = b[3:] + if len(b) < n { + goto corrupted + } + + scalars = append(scalars, append([]byte(nil), b[:n]...)) + b = b[n:] + case gbString00, gbString01, gbString02, gbString03, gbString04, + gbString05, gbString06, gbString07, gbString08, gbString09, + gbString10, gbString11, gbString12, gbString13, gbString14, + gbString15, gbString16, gbString17: + n := int(tag - gbString00) + if len(b) < n+1 { + goto corrupted + } + + scalars = append(scalars, string(b[1:n+1])) + b = b[n+1:] + case gbString1: + if len(b) < 2 { + goto corrupted + } + + n := int(b[1]) + b = b[2:] + if len(b) < n { + goto corrupted + } + + scalars = append(scalars, string(b[:n])) + b = b[n:] + case gbString2: + if len(b) < 3 { + goto corrupted + } + + n := int(b[1])<<8 | int(b[2]) + b = b[3:] + if len(b) < n { + goto corrupted + } + + scalars = append(scalars, string(b[:n])) + b = b[n:] + case gbUintP1, gbUintP2, gbUintP3, gbUintP4, gbUintP5, gbUintP6, gbUintP7, gbUintP8: + b = b[1:] + n := 1 + int(tag) - gbUintP1 + if len(b) < n { + goto corrupted + } + + var u uint64 + for _, v := range b[:n] { + u = u<<8 | uint64(v) + } + scalars = append(scalars, u) + b = b[n:] + case gbIntM8, gbIntM7, gbIntM6, gbIntM5, gbIntM4, gbIntM3, gbIntM2, gbIntM1: + b = b[1:] + n := 8 - (int(tag) - gbIntM8) + if len(b) < n { + goto corrupted + } + u := uint64(math.MaxUint64) + for _, v := range b[:n] { + u = u<<8 | uint64(v) + } + scalars = append(scalars, int64(u)) + b = b[n:] + case gbIntP1, gbIntP2, gbIntP3, gbIntP4, gbIntP5, gbIntP6, gbIntP7, gbIntP8: + b = b[1:] + n := 1 + int(tag) - gbIntP1 + if len(b) < n { + goto corrupted + } + + i := int64(0) + for _, v := range b[:n] { + i = i<<8 | int64(v) + } + scalars = append(scalars, i) + b = b[n:] + default: + scalars = append(scalars, int64(b[0])-gbInt0) + b = b[1:] + } + } + return append([]interface{}(nil), scalars...), nil + +corrupted: + return nil, &ErrDecodeScalars{append([]byte(nil), b0...), len(b0) - len(b)} +} + +func collateComplex(x, y complex128) int { + switch rx, ry := real(x), real(y); { + case rx < ry: + return -1 + case rx == ry: + switch ix, iy := imag(x), imag(y); { + case ix < iy: + return -1 + case ix == iy: + return 0 + case ix > iy: + return 1 + } + } + //case rx > ry: + return 1 +} + +func collateFloat(x, y float64) int { + switch { + case x < y: + return -1 + case x == y: + return 0 + } + //case x > y: + return 1 +} + +func collateInt(x, y int64) int { + switch { + case x < y: + return -1 + case x == y: + return 0 + } + //case x > y: + return 1 +} + +func collateUint(x, y uint64) int { + switch { + case x < y: + return -1 + case x == y: + return 0 + } + //case x > y: + return 1 +} + +func collateIntUint(x int64, y uint64) int { + if y > math.MaxInt64 { + return -1 + } + + return collateInt(x, int64(y)) +} + +func collateUintInt(x uint64, y int64) int { + return -collateIntUint(y, x) +} + +func collateType(i interface{}) (r interface{}, err error) { + switch x := i.(type) { + default: + return nil, fmt.Errorf("invalid collate type %T", x) + case nil: + return i, nil + case bool: + return i, nil + case int8: + return int64(x), nil + case int16: + return int64(x), nil + case int32: + return int64(x), nil + case int64: + return i, nil + case int: + return int64(x), nil + case uint8: + return uint64(x), nil + case uint16: + return uint64(x), nil + case uint32: + return uint64(x), nil + case uint64: + return i, nil + case uint: + return uint64(x), nil + case float32: + return float64(x), nil + case float64: + return i, nil + case complex64: + return complex128(x), nil + case complex128: + return i, nil + case []byte: + return i, nil + case string: + return i, nil + } +} + +// Collate collates two arrays of Go predeclared scalar types (and the typeless +// nil or []byte). If any other type appears in x or y, Collate will return a +// non nil error. String items are collated using strCollate or lexically +// byte-wise (as when using Go comparison operators) when strCollate is nil. +// []byte items are collated using bytes.Compare. +// +// Collate returns: +// +// -1 if x < y +// 0 if x == y +// +1 if x > y +// +// The same value as defined above must be returned from strCollate. +// +// The "outer" ordering is: nil, bool, number, []byte, string. IOW, nil is +// "smaller" than anything else except other nil, numbers collate before +// []byte, []byte collate before strings, etc. +// +// Integers and real numbers collate as expected in math. However, complex +// numbers are not ordered in Go. Here the ordering is defined: Complex numbers +// are in comparison considered first only by their real part. Iff the result +// is equality then the imaginary part is used to determine the ordering. In +// this "second order" comparing, integers and real numbers are considered as +// complex numbers with a zero imaginary part. +func Collate(x, y []interface{}, strCollate func(string, string) int) (r int, err error) { + nx, ny := len(x), len(y) + + switch { + case nx == 0 && ny != 0: + return -1, nil + case nx == 0 && ny == 0: + return 0, nil + case nx != 0 && ny == 0: + return 1, nil + } + + r = 1 + if nx > ny { + x, y, r = y, x, -r + } + + var c int + for i, xi0 := range x { + yi0 := y[i] + xi, err := collateType(xi0) + if err != nil { + return 0, err + } + + yi, err := collateType(yi0) + if err != nil { + return 0, err + } + + switch x := xi.(type) { + default: + panic(fmt.Errorf("internal error: %T", x)) + + case nil: + switch yi.(type) { + case nil: + // nop + default: + return -r, nil + } + + case bool: + switch y := yi.(type) { + case nil: + return r, nil + case bool: + switch { + case !x && y: + return -r, nil + case x == y: + // nop + case x && !y: + return r, nil + } + default: + return -r, nil + } + + case int64: + switch y := yi.(type) { + case nil, bool: + return r, nil + case int64: + c = collateInt(x, y) + case uint64: + c = collateIntUint(x, y) + case float64: + c = collateFloat(float64(x), y) + case complex128: + c = collateComplex(complex(float64(x), 0), y) + case []byte: + return -r, nil + case string: + return -r, nil + } + + if c != 0 { + return c * r, nil + } + + case uint64: + switch y := yi.(type) { + case nil, bool: + return r, nil + case int64: + c = collateUintInt(x, y) + case uint64: + c = collateUint(x, y) + case float64: + c = collateFloat(float64(x), y) + case complex128: + c = collateComplex(complex(float64(x), 0), y) + case []byte: + return -r, nil + case string: + return -r, nil + } + + if c != 0 { + return c * r, nil + } + + case float64: + switch y := yi.(type) { + case nil, bool: + return r, nil + case int64: + c = collateFloat(x, float64(y)) + case uint64: + c = collateFloat(x, float64(y)) + case float64: + c = collateFloat(x, y) + case complex128: + c = collateComplex(complex(x, 0), y) + case []byte: + return -r, nil + case string: + return -r, nil + } + + if c != 0 { + return c * r, nil + } + + case complex128: + switch y := yi.(type) { + case nil, bool: + return r, nil + case int64: + c = collateComplex(x, complex(float64(y), 0)) + case uint64: + c = collateComplex(x, complex(float64(y), 0)) + case float64: + c = collateComplex(x, complex(y, 0)) + case complex128: + c = collateComplex(x, y) + case []byte: + return -r, nil + case string: + return -r, nil + } + + if c != 0 { + return c * r, nil + } + + case []byte: + switch y := yi.(type) { + case nil, bool, int64, uint64, float64, complex128: + return r, nil + case []byte: + c = bytes.Compare(x, y) + case string: + return -r, nil + } + + if c != 0 { + return c * r, nil + } + + case string: + switch y := yi.(type) { + case nil, bool, int64, uint64, float64, complex128: + return r, nil + case []byte: + return r, nil + case string: + switch { + case strCollate != nil: + c = strCollate(x, y) + case x < y: + return -r, nil + case x == y: + c = 0 + case x > y: + return r, nil + } + } + + if c != 0 { + return c * r, nil + } + } + } + + if nx == ny { + return 0, nil + } + + return -r, nil +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/lldb.go b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/lldb.go new file mode 100644 index 00000000..8f77ec8a --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/lldb.go @@ -0,0 +1,155 @@ +// Copyright 2014 The lldb 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 lldb (WIP) implements a low level database engine. The database +// model used could be considered a specific implementation of some small(est) +// intersection of models listed in [1]. As a settled term is lacking, it'll be +// called here a 'Virtual memory model' (VMM). +// +// Experimental release notes +// +// This is an experimental release. Don't open a DB from two applications or +// two instances of an application - it will get corrupted (no file locking is +// implemented and this task is delegated to lldb's clients). +// +// WARNING: THE LLDB API IS SUBJECT TO CHANGE. +// +// Filers +// +// A Filer is an abstraction of storage. A Filer may be a part of some process' +// virtual address space, an OS file, a networked, remote file etc. Persistence +// of the storage is optional, opaque to VMM and it is specific to a concrete +// Filer implementation. +// +// Space management +// +// Mechanism to allocate, reallocate (resize), deallocate (and later reclaim +// the unused) contiguous parts of a Filer, called blocks. Blocks are +// identified and referred to by a handle, an int64. +// +// BTrees +// +// In addition to the VMM like services, lldb provides volatile and +// non-volatile BTrees. Keys and values of a BTree are limited in size to 64kB +// each (a bit more actually). Support for larger keys/values, if desired, can +// be built atop a BTree to certain limits. +// +// Handles vs pointers +// +// A handle is the abstracted storage counterpart of a memory address. There +// is one fundamental difference, though. Resizing a block never results in a +// change to the handle which refers to the resized block, so a handle is more +// akin to an unique numeric id/key. Yet it shares one property of pointers - +// handles can be associated again with blocks after the original handle block +// was deallocated. In other words, a handle uniqueness domain is the state of +// the database and is not something comparable to e.g. an ever growing +// numbering sequence. +// +// Also, as with memory pointers, dangling handles can be created and blocks +// overwritten when such handles are used. Using a zero handle to refer to a +// block will not panic; however, the resulting error is effectively the same +// exceptional situation as dereferencing a nil pointer. +// +// Blocks +// +// Allocated/used blocks, are limited in size to only a little bit more than +// 64kB. Bigger semantic entities/structures must be built in lldb's client +// code. The content of a block has no semantics attached, it's only a fully +// opaque `[]byte`. +// +// Scalars +// +// Use of "scalars" applies to EncodeScalars, DecodeScalars and Collate. Those +// first two "to bytes" and "from bytes" functions are suggested for handling +// multi-valued Allocator content items and/or keys/values of BTrees (using +// Collate for keys). Types called "scalar" are: +// +// nil (the typeless one) +// bool +// all integral types: [u]int8, [u]int16, [u]int32, [u]int, [u]int64 +// all floating point types: float32, float64 +// all complex types: complex64, complex128 +// []byte (64kB max) +// string (64kb max) +// +// Specific implementations +// +// Included are concrete implementations of some of the VMM interfaces included +// to ease serving simple client code or for testing and possibly as an +// example. More details in the documentation of such implementations. +// +// [1]: http://en.wikipedia.org/wiki/Database_model +package lldb + +const ( + fltSz = 0x70 // size of the FLT + maxShort = 251 + maxRq = 65787 + maxFLTRq = 4112 + maxHandle = 1<<56 - 1 + atomLen = 16 + tagUsedLong = 0xfc + tagUsedRelocated = 0xfd + tagFreeShort = 0xfe + tagFreeLong = 0xff + tagNotCompressed = 0 + tagCompressed = 1 +) + +// Content size n -> blocksize in atoms. +func n2atoms(n int) int { + if n > maxShort { + n += 2 + } + return (n+1)/16 + 1 +} + +// Content size n -> number of padding zeros. +func n2padding(n int) int { + if n > maxShort { + n += 2 + } + return 15 - (n+1)&15 +} + +// Handle <-> offset +func h2off(h int64) int64 { return (h + 6) * 16 } +func off2h(off int64) int64 { return off/16 - 6 } + +// Get a 7B int64 from b +func b2h(b []byte) (h int64) { + for _, v := range b[:7] { + h = h<<8 | int64(v) + } + return +} + +// Put a 7B int64 into b +func h2b(b []byte, h int64) []byte { + for i := range b[:7] { + b[i], h = byte(h>>48), h<<8 + } + return b +} + +// Content length N (must be in [252, 65787]) to long used block M field. +func n2m(n int) (m int) { + return n % 0x10000 +} + +// Long used block M (must be in [0, 65535]) field to content length N. +func m2n(m int) (n int) { + if m <= maxShort { + m += 0x10000 + } + return m +} + +func bpack(a []byte) []byte { + if cap(a) > len(a) { + return append([]byte(nil), a...) + } + + return a +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/memfiler.go b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/memfiler.go new file mode 100644 index 00000000..417e92f3 --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/memfiler.go @@ -0,0 +1,344 @@ +// Copyright 2014 The lldb Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// A memory-only implementation of Filer. + +/* + +pgBits: 8 +BenchmarkMemFilerWrSeq 100000 19430 ns/op 1646.93 MB/s +BenchmarkMemFilerRdSeq 100000 17390 ns/op 1840.13 MB/s +BenchmarkMemFilerWrRand 1000000 1903 ns/op 133.94 MB/s +BenchmarkMemFilerRdRand 1000000 1153 ns/op 221.16 MB/s + +pgBits: 9 +BenchmarkMemFilerWrSeq 100000 16195 ns/op 1975.80 MB/s +BenchmarkMemFilerRdSeq 200000 13011 ns/op 2459.39 MB/s +BenchmarkMemFilerWrRand 1000000 2248 ns/op 227.28 MB/s +BenchmarkMemFilerRdRand 1000000 1177 ns/op 433.94 MB/s + +pgBits: 10 +BenchmarkMemFilerWrSeq 100000 16169 ns/op 1979.04 MB/s +BenchmarkMemFilerRdSeq 200000 12673 ns/op 2524.91 MB/s +BenchmarkMemFilerWrRand 1000000 5550 ns/op 184.30 MB/s +BenchmarkMemFilerRdRand 1000000 1699 ns/op 601.79 MB/s + +pgBits: 11 +BenchmarkMemFilerWrSeq 100000 13449 ns/op 2379.31 MB/s +BenchmarkMemFilerRdSeq 200000 12058 ns/op 2653.80 MB/s +BenchmarkMemFilerWrRand 500000 4335 ns/op 471.47 MB/s +BenchmarkMemFilerRdRand 1000000 2843 ns/op 719.47 MB/s + +pgBits: 12 +BenchmarkMemFilerWrSeq 200000 11976 ns/op 2672.00 MB/s +BenchmarkMemFilerRdSeq 200000 12255 ns/op 2611.06 MB/s +BenchmarkMemFilerWrRand 200000 8058 ns/op 507.14 MB/s +BenchmarkMemFilerRdRand 500000 4365 ns/op 936.15 MB/s + +pgBits: 13 +BenchmarkMemFilerWrSeq 200000 10852 ns/op 2948.69 MB/s +BenchmarkMemFilerRdSeq 200000 11561 ns/op 2767.77 MB/s +BenchmarkMemFilerWrRand 200000 9748 ns/op 840.15 MB/s +BenchmarkMemFilerRdRand 500000 7236 ns/op 1131.59 MB/s + +pgBits: 14 +BenchmarkMemFilerWrSeq 200000 10328 ns/op 3098.12 MB/s +BenchmarkMemFilerRdSeq 200000 11292 ns/op 2833.66 MB/s +BenchmarkMemFilerWrRand 100000 16768 ns/op 978.75 MB/s +BenchmarkMemFilerRdRand 200000 13033 ns/op 1258.43 MB/s + +pgBits: 15 +BenchmarkMemFilerWrSeq 200000 10309 ns/op 3103.93 MB/s +BenchmarkMemFilerRdSeq 200000 11126 ns/op 2876.12 MB/s +BenchmarkMemFilerWrRand 50000 31985 ns/op 1021.74 MB/s +BenchmarkMemFilerRdRand 100000 25217 ns/op 1297.65 MB/s + +pgBits: 16 +BenchmarkMemFilerWrSeq 200000 10324 ns/op 3099.45 MB/s +BenchmarkMemFilerRdSeq 200000 11201 ns/op 2856.80 MB/s +BenchmarkMemFilerWrRand 20000 55226 ns/op 1184.76 MB/s +BenchmarkMemFilerRdRand 50000 48316 ns/op 1355.16 MB/s + +pgBits: 17 +BenchmarkMemFilerWrSeq 200000 10377 ns/op 3083.53 MB/s +BenchmarkMemFilerRdSeq 200000 11018 ns/op 2904.18 MB/s +BenchmarkMemFilerWrRand 10000 143425 ns/op 913.12 MB/s +BenchmarkMemFilerRdRand 20000 95267 ns/op 1376.99 MB/s + +pgBits: 18 +BenchmarkMemFilerWrSeq 200000 10312 ns/op 3102.96 MB/s +BenchmarkMemFilerRdSeq 200000 11069 ns/op 2890.84 MB/s +BenchmarkMemFilerWrRand 5000 280910 ns/op 934.14 MB/s +BenchmarkMemFilerRdRand 10000 188500 ns/op 1388.17 MB/s + +*/ + +package lldb + +import ( + "bytes" + "fmt" + "io" + + "github.com/cznic/fileutil" + "github.com/cznic/mathutil" +) + +const ( + pgBits = 16 + pgSize = 1 << pgBits + pgMask = pgSize - 1 +) + +var _ Filer = &MemFiler{} // Ensure MemFiler is a Filer. + +type memFilerMap map[int64]*[pgSize]byte + +// MemFiler is a memory backed Filer. It implements BeginUpdate, EndUpdate and +// Rollback as no-ops. MemFiler is not automatically persistent, but it has +// ReadFrom and WriteTo methods. +type MemFiler struct { + m memFilerMap + nest int + size int64 +} + +// NewMemFiler returns a new MemFiler. +func NewMemFiler() *MemFiler { + return &MemFiler{m: memFilerMap{}} +} + +// BeginUpdate implements Filer. +func (f *MemFiler) BeginUpdate() error { + f.nest++ + return nil +} + +// Close implements Filer. +func (f *MemFiler) Close() (err error) { + if f.nest != 0 { + return &ErrPERM{(f.Name() + ":Close")} + } + + return +} + +// EndUpdate implements Filer. +func (f *MemFiler) EndUpdate() (err error) { + if f.nest == 0 { + return &ErrPERM{(f.Name() + ": EndUpdate")} + } + + f.nest-- + return +} + +// Name implements Filer. +func (f *MemFiler) Name() string { + return fmt.Sprintf("%p.memfiler", f) +} + +// PunchHole implements Filer. +func (f *MemFiler) PunchHole(off, size int64) (err error) { + if off < 0 { + return &ErrINVAL{f.Name() + ": PunchHole off", off} + } + + if size < 0 || off+size > f.size { + return &ErrINVAL{f.Name() + ": PunchHole size", size} + } + + first := off >> pgBits + if off&pgMask != 0 { + first++ + } + off += size - 1 + last := off >> pgBits + if off&pgMask != 0 { + last-- + } + if limit := f.size >> pgBits; last > limit { + last = limit + } + for pg := first; pg <= last; pg++ { + delete(f.m, pg) + } + return +} + +var zeroPage [pgSize]byte + +// ReadAt implements Filer. +func (f *MemFiler) ReadAt(b []byte, off int64) (n int, err error) { + avail := f.size - off + pgI := off >> pgBits + pgO := int(off & pgMask) + rem := len(b) + if int64(rem) >= avail { + rem = int(avail) + err = io.EOF + } + for rem != 0 && avail > 0 { + pg := f.m[pgI] + if pg == nil { + pg = &zeroPage + } + nc := copy(b[:mathutil.Min(rem, pgSize)], pg[pgO:]) + pgI++ + pgO = 0 + rem -= nc + n += nc + b = b[nc:] + } + return +} + +// ReadFrom is a helper to populate MemFiler's content from r. 'n' reports the +// number of bytes read from 'r'. +func (f *MemFiler) ReadFrom(r io.Reader) (n int64, err error) { + if err = f.Truncate(0); err != nil { + return + } + + var ( + b [pgSize]byte + rn int + off int64 + ) + + var rerr error + for rerr == nil { + if rn, rerr = r.Read(b[:]); rn != 0 { + f.WriteAt(b[:rn], off) + off += int64(rn) + n += int64(rn) + } + } + if !fileutil.IsEOF(rerr) { + err = rerr + } + return +} + +// Rollback implements Filer. +func (f *MemFiler) Rollback() (err error) { return } + +// Size implements Filer. +func (f *MemFiler) Size() (int64, error) { + return f.size, nil +} + +// Sync implements Filer. +func (f *MemFiler) Sync() error { + return nil +} + +// Truncate implements Filer. +func (f *MemFiler) Truncate(size int64) (err error) { + switch { + case size < 0: + return &ErrINVAL{"Truncate size", size} + case size == 0: + f.m = memFilerMap{} + f.size = 0 + return + } + + first := size >> pgBits + if size&pgMask != 0 { + first++ + } + last := f.size >> pgBits + if f.size&pgMask != 0 { + last++ + } + for ; first < last; first++ { + delete(f.m, first) + } + + f.size = size + return +} + +// WriteAt implements Filer. +func (f *MemFiler) WriteAt(b []byte, off int64) (n int, err error) { + pgI := off >> pgBits + pgO := int(off & pgMask) + n = len(b) + rem := n + var nc int + for rem != 0 { + if pgO == 0 && rem >= pgSize && bytes.Equal(b[:pgSize], zeroPage[:]) { + delete(f.m, pgI) + nc = pgSize + } else { + pg := f.m[pgI] + if pg == nil { + pg = new([pgSize]byte) + f.m[pgI] = pg + } + nc = copy((*pg)[pgO:], b) + } + pgI++ + pgO = 0 + rem -= nc + b = b[nc:] + } + f.size = mathutil.MaxInt64(f.size, off+int64(n)) + return +} + +// WriteTo is a helper to copy/persist MemFiler's content to w. If w is also +// an io.WriterAt then WriteTo may attempt to _not_ write any big, for some +// value of big, runs of zeros, i.e. it will attempt to punch holes, where +// possible, in `w` if that happens to be a freshly created or to zero length +// truncated OS file. 'n' reports the number of bytes written to 'w'. +func (f *MemFiler) WriteTo(w io.Writer) (n int64, err error) { + var ( + b [pgSize]byte + wn, rn int + off int64 + rerr error + ) + + if wa, ok := w.(io.WriterAt); ok { + lastPgI := f.size >> pgBits + for pgI := int64(0); pgI <= lastPgI; pgI++ { + sz := pgSize + if pgI == lastPgI { + sz = int(f.size & pgMask) + } + pg := f.m[pgI] + if pg != nil { + wn, err = wa.WriteAt(pg[:sz], off) + if err != nil { + return + } + + n += int64(wn) + off += int64(sz) + if wn != sz { + return n, io.ErrShortWrite + } + } + } + return + } + + var werr error + for rerr == nil { + if rn, rerr = f.ReadAt(b[:], off); rn != 0 { + off += int64(rn) + if wn, werr = w.Write(b[:rn]); werr != nil { + return n, werr + } + + n += int64(wn) + } + } + if !fileutil.IsEOF(rerr) { + err = rerr + } + return +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/osfiler.go b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/osfiler.go new file mode 100644 index 00000000..d6e189a1 --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/osfiler.go @@ -0,0 +1,130 @@ +// Copyright 2014 The lldb 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 lldb + +import ( + "io" + "os" + + "github.com/cznic/mathutil" +) + +var _ Filer = (*OSFiler)(nil) + +// OSFile is an os.File like minimal set of methods allowing to construct a +// Filer. +type OSFile interface { + Name() string + Stat() (fi os.FileInfo, err error) + Sync() (err error) + Truncate(size int64) (err error) + io.Closer + io.Reader + io.ReaderAt + io.Seeker + io.Writer + io.WriterAt +} + +// OSFiler is like a SimpleFileFiler but based on an OSFile. +type OSFiler struct { + f OSFile + nest int + size int64 // not set if < 0 +} + +// NewOSFiler returns a Filer from an OSFile. This Filer is like the +// SimpleFileFiler, it does not implement the transaction related methods. +func NewOSFiler(f OSFile) (r *OSFiler) { + return &OSFiler{ + f: f, + size: -1, + } +} + +// BeginUpdate implements Filer. +func (f *OSFiler) BeginUpdate() (err error) { + f.nest++ + return nil +} + +// Close implements Filer. +func (f *OSFiler) Close() (err error) { + if f.nest != 0 { + return &ErrPERM{(f.Name() + ":Close")} + } + + return f.f.Close() +} + +// EndUpdate implements Filer. +func (f *OSFiler) EndUpdate() (err error) { + if f.nest == 0 { + return &ErrPERM{(f.Name() + ":EndUpdate")} + } + + f.nest-- + return +} + +// Name implements Filer. +func (f *OSFiler) Name() string { + return f.f.Name() +} + +// PunchHole implements Filer. +func (f *OSFiler) PunchHole(off, size int64) (err error) { + return +} + +// ReadAt implements Filer. +func (f *OSFiler) ReadAt(b []byte, off int64) (n int, err error) { + return f.f.ReadAt(b, off) +} + +// Rollback implements Filer. +func (f *OSFiler) Rollback() (err error) { return } + +// Size implements Filer. +func (f *OSFiler) Size() (n int64, err error) { + if f.size < 0 { // boot + fi, err := f.f.Stat() + if err != nil { + return 0, err + } + + f.size = fi.Size() + } + return f.size, nil +} + +// Sync implements Filer. +func (f *OSFiler) Sync() (err error) { + return f.f.Sync() +} + +// Truncate implements Filer. +func (f *OSFiler) Truncate(size int64) (err error) { + if size < 0 { + return &ErrINVAL{"Truncate size", size} + } + + f.size = size + return f.f.Truncate(size) +} + +// WriteAt implements Filer. +func (f *OSFiler) WriteAt(b []byte, off int64) (n int, err error) { + if f.size < 0 { // boot + fi, err := os.Stat(f.f.Name()) + if err != nil { + return 0, err + } + + f.size = fi.Size() + } + f.size = mathutil.MaxInt64(f.size, int64(len(b))+off) + return f.f.WriteAt(b, off) +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/simplefilefiler.go b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/simplefilefiler.go new file mode 100644 index 00000000..de32e649 --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/simplefilefiler.go @@ -0,0 +1,123 @@ +// Copyright 2014 The lldb Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// A basic os.File backed Filer. + +package lldb + +import ( + "os" + + "github.com/cznic/fileutil" + "github.com/cznic/mathutil" +) + +var _ Filer = &SimpleFileFiler{} // Ensure SimpleFileFiler is a Filer. + +// SimpleFileFiler is an os.File backed Filer intended for use where structural +// consistency can be reached by other means (SimpleFileFiler is for example +// wrapped in eg. an RollbackFiler or ACIDFiler0) or where persistence is not +// required (temporary/working data sets). +// +// SimpleFileFiler is the most simple os.File backed Filer implementation as it +// does not really implement BeginUpdate and EndUpdate/Rollback in any way +// which would protect the structural integrity of data. If misused e.g. as a +// real database storage w/o other measures, it can easily cause data loss +// when, for example, a power outage occurs or the updating process terminates +// abruptly. +type SimpleFileFiler struct { + file *os.File + nest int + size int64 // not set if < 0 +} + +// NewSimpleFileFiler returns a new SimpleFileFiler. +func NewSimpleFileFiler(f *os.File) *SimpleFileFiler { + return &SimpleFileFiler{file: f, size: -1} +} + +// BeginUpdate implements Filer. +func (f *SimpleFileFiler) BeginUpdate() error { + f.nest++ + return nil +} + +// Close implements Filer. +func (f *SimpleFileFiler) Close() (err error) { + if f.nest != 0 { + return &ErrPERM{(f.Name() + ":Close")} + } + + return f.file.Close() +} + +// EndUpdate implements Filer. +func (f *SimpleFileFiler) EndUpdate() (err error) { + if f.nest == 0 { + return &ErrPERM{(f.Name() + ":EndUpdate")} + } + + f.nest-- + return +} + +// Name implements Filer. +func (f *SimpleFileFiler) Name() string { + return f.file.Name() +} + +// PunchHole implements Filer. +func (f *SimpleFileFiler) PunchHole(off, size int64) (err error) { + return fileutil.PunchHole(f.file, off, size) +} + +// ReadAt implements Filer. +func (f *SimpleFileFiler) ReadAt(b []byte, off int64) (n int, err error) { + return f.file.ReadAt(b, off) +} + +// Rollback implements Filer. +func (f *SimpleFileFiler) Rollback() (err error) { return } + +// Size implements Filer. +func (f *SimpleFileFiler) Size() (int64, error) { + if f.size < 0 { // boot + fi, err := os.Stat(f.file.Name()) + if err != nil { + return 0, err + } + + f.size = fi.Size() + } + return f.size, nil +} + +// Sync implements Filer. +func (f *SimpleFileFiler) Sync() error { + return f.file.Sync() +} + +// Truncate implements Filer. +func (f *SimpleFileFiler) Truncate(size int64) (err error) { + if size < 0 { + return &ErrINVAL{"Truncate size", size} + } + + f.size = size + return f.file.Truncate(size) +} + +// WriteAt implements Filer. +func (f *SimpleFileFiler) WriteAt(b []byte, off int64) (n int, err error) { + if f.size < 0 { // boot + fi, err := os.Stat(f.file.Name()) + if err != nil { + return 0, err + } + + f.size = fi.Size() + } + f.size = mathutil.MaxInt64(f.size, int64(len(b))+off) + return f.file.WriteAt(b, off) +} diff --git a/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/xact.go b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/xact.go new file mode 100644 index 00000000..01eac10c --- /dev/null +++ b/vendor/github.com/cznic/ql/vendored/github.com/cznic/exp/lldb/xact.go @@ -0,0 +1,642 @@ +// Copyright 2014 The lldb Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Structural transactions. + +package lldb + +//DONE+ TransactionalMemoryFiler +// ---- +// Use NewRollbackFiler(myMemFiler, ...) + +/* + +bfBits: 3 +BenchmarkRollbackFiler 20000000 102 ns/op 9.73 MB/s + +bfBits: 4 +BenchmarkRollbackFiler 50000000 55.7 ns/op 17.95 MB/s + +bfBits: 5 +BenchmarkRollbackFiler 100000000 32.2 ns/op 31.06 MB/s + +bfBits: 6 +BenchmarkRollbackFiler 100000000 20.6 ns/op 48.46 MB/s + +bfBits: 7 +BenchmarkRollbackFiler 100000000 15.1 ns/op 66.12 MB/s + +bfBits: 8 +BenchmarkRollbackFiler 100000000 10.5 ns/op 95.66 MB/s + +bfBits: 9 +BenchmarkRollbackFiler 200000000 8.02 ns/op 124.74 MB/s + +bfBits: 10 +BenchmarkRollbackFiler 200000000 9.25 ns/op 108.09 MB/s + +bfBits: 11 +BenchmarkRollbackFiler 100000000 11.7 ns/op 85.47 MB/s + +bfBits: 12 +BenchmarkRollbackFiler 100000000 17.2 ns/op 57.99 MB/s + +bfBits: 13 +BenchmarkRollbackFiler 100000000 32.7 ns/op 30.58 MB/s + +bfBits: 14 +BenchmarkRollbackFiler 50000000 39.6 ns/op 25.27 MB/s + +*/ + +import ( + "fmt" + "io" + "sync" + + "github.com/cznic/fileutil" + "github.com/cznic/mathutil" +) + +var ( + _ Filer = &bitFiler{} // Ensure bitFiler is a Filer. + _ Filer = &RollbackFiler{} // ditto +) + +const ( + bfBits = 9 + bfSize = 1 << bfBits + bfMask = bfSize - 1 +) + +var ( + bitmask = [8]byte{1, 2, 4, 8, 16, 32, 64, 128} + bitZeroPage bitPage + allDirtyFlags [bfSize >> 3]byte +) + +func init() { + for i := range allDirtyFlags { + allDirtyFlags[i] = 0xff + } +} + +type ( + bitPage struct { + prev, next *bitPage + data [bfSize]byte + flags [bfSize >> 3]byte + dirty bool + } + + bitFilerMap map[int64]*bitPage + + bitFiler struct { + parent Filer + m bitFilerMap + size int64 + sync.Mutex + } +) + +func newBitFiler(parent Filer) (f *bitFiler, err error) { + sz, err := parent.Size() + if err != nil { + return + } + + return &bitFiler{parent: parent, m: bitFilerMap{}, size: sz}, nil +} + +func (f *bitFiler) BeginUpdate() error { panic("internal error") } +func (f *bitFiler) EndUpdate() error { panic("internal error") } +func (f *bitFiler) Rollback() error { panic("internal error") } +func (f *bitFiler) Sync() error { panic("internal error") } + +func (f *bitFiler) Close() (err error) { return } +func (f *bitFiler) Name() string { return fmt.Sprintf("%p.bitfiler", f) } +func (f *bitFiler) Size() (int64, error) { return f.size, nil } + +func (f *bitFiler) PunchHole(off, size int64) (err error) { + first := off >> bfBits + if off&bfMask != 0 { + first++ + } + off += size - 1 + last := off >> bfBits + if off&bfMask != 0 { + last-- + } + if limit := f.size >> bfBits; last > limit { + last = limit + } + f.Lock() + for pgI := first; pgI <= last; pgI++ { + pg := &bitPage{} + pg.flags = allDirtyFlags + f.m[pgI] = pg + } + f.Unlock() + return +} + +func (f *bitFiler) ReadAt(b []byte, off int64) (n int, err error) { + avail := f.size - off + pgI := off >> bfBits + pgO := int(off & bfMask) + rem := len(b) + if int64(rem) >= avail { + rem = int(avail) + err = io.EOF + } + for rem != 0 && avail > 0 { + f.Lock() + pg := f.m[pgI] + if pg == nil { + pg = &bitPage{} + if f.parent != nil { + _, err = f.parent.ReadAt(pg.data[:], off&^bfMask) + if err != nil && !fileutil.IsEOF(err) { + f.Unlock() + return + } + + err = nil + } + f.m[pgI] = pg + } + f.Unlock() + nc := copy(b[:mathutil.Min(rem, bfSize)], pg.data[pgO:]) + pgI++ + pgO = 0 + rem -= nc + n += nc + b = b[nc:] + off += int64(nc) + } + return +} + +func (f *bitFiler) Truncate(size int64) (err error) { + f.Lock() + defer f.Unlock() + switch { + case size < 0: + return &ErrINVAL{"Truncate size", size} + case size == 0: + f.m = bitFilerMap{} + f.size = 0 + return + } + + first := size >> bfBits + if size&bfMask != 0 { + first++ + } + last := f.size >> bfBits + if f.size&bfMask != 0 { + last++ + } + for ; first < last; first++ { + delete(f.m, first) + } + + f.size = size + return +} + +func (f *bitFiler) WriteAt(b []byte, off int64) (n int, err error) { + off0 := off + pgI := off >> bfBits + pgO := int(off & bfMask) + n = len(b) + rem := n + var nc int + for rem != 0 { + f.Lock() + pg := f.m[pgI] + if pg == nil { + pg = &bitPage{} + if f.parent != nil { + _, err = f.parent.ReadAt(pg.data[:], off&^bfMask) + if err != nil && !fileutil.IsEOF(err) { + f.Unlock() + return + } + + err = nil + } + f.m[pgI] = pg + } + f.Unlock() + nc = copy(pg.data[pgO:], b) + pgI++ + pg.dirty = true + for i := pgO; i < pgO+nc; i++ { + pg.flags[i>>3] |= bitmask[i&7] + } + pgO = 0 + rem -= nc + b = b[nc:] + off += int64(nc) + } + f.size = mathutil.MaxInt64(f.size, off0+int64(n)) + return +} + +func (f *bitFiler) link() { + for pgI, pg := range f.m { + nx, ok := f.m[pgI+1] + if !ok || !nx.dirty { + continue + } + + nx.prev, pg.next = pg, nx + } +} + +func (f *bitFiler) dumpDirty(w io.WriterAt) (nwr int, err error) { + f.Lock() + defer f.Unlock() + f.link() + for pgI, pg := range f.m { + if !pg.dirty { + continue + } + + for pg.prev != nil && pg.prev.dirty { + pg = pg.prev + pgI-- + } + + for pg != nil && pg.dirty { + last := false + var off int64 + first := -1 + for i := 0; i < bfSize; i++ { + flag := pg.flags[i>>3]&bitmask[i&7] != 0 + switch { + case flag && !last: // Leading edge detected + off = pgI<= 0 { + i := bfSize + n, err := w.WriteAt(pg.data[first:i], off) + if n != i-first { + return 0, err + } + + nwr++ + } + + pg.dirty = false + pg = pg.next + pgI++ + } + } + return +} + +// RollbackFiler is a Filer implementing structural transaction handling. +// Structural transactions should be small and short lived because all non +// committed data are held in memory until committed or discarded by a +// Rollback. +// +// While using RollbackFiler, every intended update of the wrapped Filler, by +// WriteAt, Truncate or PunchHole, _must_ be made within a transaction. +// Attempts to do it outside of a transaction will return ErrPERM. OTOH, +// invoking ReadAt outside of a transaction is not a problem. +// +// No nested transactions: All updates within a transaction are held in memory. +// On a matching EndUpdate the updates held in memory are actually written to +// the wrapped Filer. +// +// Nested transactions: Correct data will be seen from RollbackFiler when any +// level of a nested transaction is rollbacked. The actual writing to the +// wrapped Filer happens only when the outer most transaction nesting level is +// closed. +// +// Invoking Rollback is an alternative to EndUpdate. It discards all changes +// made at the current transaction level and returns the "state" (possibly not +// yet persisted) of the Filer to what it was before the corresponding +// BeginUpdate. +// +// During an open transaction, all reads (using ReadAt) are "dirty" reads, +// seeing the uncommitted changes made to the Filer's data. +// +// Lldb databases should be based upon a RollbackFiler. +// +// With a wrapped MemFiler one gets transactional memory. With, for example a +// wrapped disk based SimpleFileFiler it protects against at least some HW +// errors - if Rollback is properly invoked on such failures and/or if there's +// some WAL or 2PC or whatever other safe mechanism based recovery procedure +// used by the client. +// +// The "real" writes to the wrapped Filer (or WAL instead) go through the +// writerAt supplied to NewRollbackFiler. +// +// List of functions/methods which are recommended to be wrapped in a +// BeginUpdate/EndUpdate structural transaction: +// +// Allocator.Alloc +// Allocator.Free +// Allocator.Realloc +// +// CreateBTree +// RemoveBTree +// BTree.Clear +// BTree.Delete +// BTree.DeleteAny +// BTree.Clear +// BTree.Extract +// BTree.Get (it can mutate the DB) +// BTree.Put +// BTree.Set +// +// NOTE: RollbackFiler is a generic solution intended to wrap Filers provided +// by this package which do not implement any of the transactional methods. +// RollbackFiler thus _does not_ invoke any of the transactional methods of its +// wrapped Filer. +// +// RollbackFiler is safe for concurrent use by multiple goroutines. +type RollbackFiler struct { + mu sync.RWMutex + inCallback bool + inCallbackMu sync.RWMutex + bitFiler *bitFiler + checkpoint func(int64) error + closed bool + f Filer + parent Filer + tlevel int // transaction nesting level, 0 == not in transaction + writerAt io.WriterAt + + // afterRollback, if not nil, is called after performing Rollback + // without errros. + afterRollback func() error +} + +// NewRollbackFiler returns a RollbackFiler wrapping f. +// +// The checkpoint parameter +// +// The checkpoint function is called after closing (by EndUpdate) the upper +// most level open transaction if all calls of writerAt were successful and the +// DB (or eg. a WAL) is thus now in a consistent state (virtually, in the ideal +// world with no write caches, no HW failures, no process crashes, ...). +// +// NOTE: In, for example, a 2PC it is necessary to reflect also the sz +// parameter as the new file size (as in the parameter to Truncate). All +// changes were successfully written already by writerAt before invoking +// checkpoint. +// +// The writerAt parameter +// +// The writerAt interface is used to commit the updates of the wrapped Filer. +// If any invocation of writerAt fails then a non nil error will be returned +// from EndUpdate and checkpoint will _not_ ne called. Neither is necessary to +// call Rollback. The rule of thumb: The [structural] transaction [level] is +// closed by invoking exactly once one of EndUpdate _or_ Rollback. +// +// It is presumed that writerAt uses WAL or 2PC or whatever other safe +// mechanism to physically commit the updates. +// +// Updates performed by invocations of writerAt are byte-precise, but not +// necessarily maximum possible length precise. IOW, for example an update +// crossing page boundaries may be performed by more than one writerAt +// invocation. No offset sorting is performed. This may change if it proves +// to be a problem. Such change would be considered backward compatible. +// +// NOTE: Using RollbackFiler, but failing to ever invoke a matching "closing" +// EndUpdate after an "opening" BeginUpdate means neither writerAt or +// checkpoint will ever get called - with all the possible data loss +// consequences. +func NewRollbackFiler(f Filer, checkpoint func(sz int64) error, writerAt io.WriterAt) (r *RollbackFiler, err error) { + if f == nil || checkpoint == nil || writerAt == nil { + return nil, &ErrINVAL{Src: "lldb.NewRollbackFiler, nil argument"} + } + + return &RollbackFiler{ + checkpoint: checkpoint, + f: f, + writerAt: writerAt, + }, nil +} + +// Implements Filer. +func (r *RollbackFiler) BeginUpdate() (err error) { + r.mu.Lock() + defer r.mu.Unlock() + + parent := r.f + if r.tlevel != 0 { + parent = r.bitFiler + } + r.bitFiler, err = newBitFiler(parent) + if err != nil { + return + } + + r.tlevel++ + return +} + +// Implements Filer. +// +// Close will return an error if not invoked at nesting level 0. However, to +// allow emergency closing from eg. a signal handler; if Close is invoked +// within an open transaction(s), it rollbacks any non committed open +// transactions and performs the Close operation. +// +// IOW: Regardless of the transaction nesting level the Close is always +// performed but any uncommitted transaction data are lost. +func (r *RollbackFiler) Close() (err error) { + r.mu.Lock() + defer r.mu.Unlock() + + if r.closed { + return &ErrPERM{r.f.Name() + ": Already closed"} + } + + r.closed = true + if err = r.f.Close(); err != nil { + return + } + + if r.tlevel != 0 { + err = &ErrPERM{r.f.Name() + ": Close inside an open transaction"} + } + + return +} + +// Implements Filer. +func (r *RollbackFiler) EndUpdate() (err error) { + r.mu.Lock() + defer r.mu.Unlock() + + if r.tlevel == 0 { + return &ErrPERM{r.f.Name() + " : EndUpdate outside of a transaction"} + } + + sz, err := r.size() // Cannot call .Size() -> deadlock + if err != nil { + return + } + + r.tlevel-- + bf := r.bitFiler + parent := bf.parent + w := r.writerAt + if r.tlevel != 0 { + w = parent + } + nwr, err := bf.dumpDirty(w) + if err != nil { + return + } + + switch { + case r.tlevel == 0: + r.bitFiler = nil + if nwr == 0 { + return + } + + return r.checkpoint(sz) + default: + r.bitFiler = parent.(*bitFiler) + sz, _ := bf.Size() // bitFiler.Size() never returns err != nil + return parent.Truncate(sz) + } +} + +// Implements Filer. +func (r *RollbackFiler) Name() string { + r.mu.RLock() + defer r.mu.RUnlock() + + return r.f.Name() +} + +// Implements Filer. +func (r *RollbackFiler) PunchHole(off, size int64) error { + r.mu.Lock() + defer r.mu.Unlock() + + if r.tlevel == 0 { + return &ErrPERM{r.f.Name() + ": PunchHole outside of a transaction"} + } + + if off < 0 { + return &ErrINVAL{r.f.Name() + ": PunchHole off", off} + } + + if size < 0 || off+size > r.bitFiler.size { + return &ErrINVAL{r.f.Name() + ": PunchHole size", size} + } + + return r.bitFiler.PunchHole(off, size) +} + +// Implements Filer. +func (r *RollbackFiler) ReadAt(b []byte, off int64) (n int, err error) { + r.inCallbackMu.RLock() + defer r.inCallbackMu.RUnlock() + if !r.inCallback { + r.mu.RLock() + defer r.mu.RUnlock() + } + if r.tlevel == 0 { + return r.f.ReadAt(b, off) + } + + return r.bitFiler.ReadAt(b, off) +} + +// Implements Filer. +func (r *RollbackFiler) Rollback() (err error) { + r.mu.Lock() + defer r.mu.Unlock() + + if r.tlevel == 0 { + return &ErrPERM{r.f.Name() + ": Rollback outside of a transaction"} + } + + if r.tlevel > 1 { + r.bitFiler = r.bitFiler.parent.(*bitFiler) + } + r.tlevel-- + if f := r.afterRollback; f != nil { + r.inCallbackMu.Lock() + r.inCallback = true + r.inCallbackMu.Unlock() + defer func() { + r.inCallbackMu.Lock() + r.inCallback = false + r.inCallbackMu.Unlock() + }() + return f() + } + return +} + +func (r *RollbackFiler) size() (sz int64, err error) { + if r.tlevel == 0 { + return r.f.Size() + } + + return r.bitFiler.Size() +} + +// Implements Filer. +func (r *RollbackFiler) Size() (sz int64, err error) { + r.mu.Lock() + defer r.mu.Unlock() + + return r.size() +} + +// Implements Filer. +func (r *RollbackFiler) Sync() error { + r.mu.Lock() + defer r.mu.Unlock() + + return r.f.Sync() +} + +// Implements Filer. +func (r *RollbackFiler) Truncate(size int64) error { + r.mu.Lock() + defer r.mu.Unlock() + + if r.tlevel == 0 { + return &ErrPERM{r.f.Name() + ": Truncate outside of a transaction"} + } + + return r.bitFiler.Truncate(size) +} + +// Implements Filer. +func (r *RollbackFiler) WriteAt(b []byte, off int64) (n int, err error) { + r.mu.Lock() + defer r.mu.Unlock() + + if r.tlevel == 0 { + return 0, &ErrPERM{r.f.Name() + ": WriteAt outside of a transaction"} + } + + return r.bitFiler.WriteAt(b, off) +} diff --git a/vendor/github.com/cznic/sortutil/LICENSE b/vendor/github.com/cznic/sortutil/LICENSE new file mode 100644 index 00000000..67983e0e --- /dev/null +++ b/vendor/github.com/cznic/sortutil/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2014 The sortutil Authors. 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 names of the authors nor the names of the +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/vendor/github.com/cznic/sortutil/sortutil.go b/vendor/github.com/cznic/sortutil/sortutil.go new file mode 100644 index 00000000..132d3546 --- /dev/null +++ b/vendor/github.com/cznic/sortutil/sortutil.go @@ -0,0 +1,271 @@ +// Copyright 2014 The sortutil 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 sortutil provides utilities supplementing the standard 'sort' package. +// +// Changelog +// +// 2015-06-17: Added utils for math/big.{Int,Rat}. +package sortutil + +import ( + "math/big" +) + +import "sort" + +// BigIntSlice attaches the methods of sort.Interface to []*big.Int, sorting in increasing order. +type BigIntSlice []*big.Int + +func (s BigIntSlice) Len() int { return len(s) } +func (s BigIntSlice) Less(i, j int) bool { return s[i].Cmp(s[j]) < 0 } +func (s BigIntSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// Sort is a convenience method. +func (s BigIntSlice) Sort() { + sort.Sort(s) +} + +// SearchBigInts searches for x in a sorted slice of *big.Int and returns the index +// as specified by sort.Search. The slice must be sorted in ascending order. +func SearchBigInts(a []*big.Int, x *big.Int) int { + return sort.Search(len(a), func(i int) bool { return a[i].Cmp(x) >= 0 }) +} + +// BigRatSlice attaches the methods of sort.Interface to []*big.Rat, sorting in increasing order. +type BigRatSlice []*big.Rat + +func (s BigRatSlice) Len() int { return len(s) } +func (s BigRatSlice) Less(i, j int) bool { return s[i].Cmp(s[j]) < 0 } +func (s BigRatSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// Sort is a convenience method. +func (s BigRatSlice) Sort() { + sort.Sort(s) +} + +// SearchBigRats searches for x in a sorted slice of *big.Int and returns the index +// as specified by sort.Search. The slice must be sorted in ascending order. +func SearchBigRats(a []*big.Rat, x *big.Rat) int { + return sort.Search(len(a), func(i int) bool { return a[i].Cmp(x) >= 0 }) +} + +// ByteSlice attaches the methods of sort.Interface to []byte, sorting in increasing order. +type ByteSlice []byte + +func (s ByteSlice) Len() int { return len(s) } +func (s ByteSlice) Less(i, j int) bool { return s[i] < s[j] } +func (s ByteSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// Sort is a convenience method. +func (s ByteSlice) Sort() { + sort.Sort(s) +} + +// SearchBytes searches for x in a sorted slice of bytes and returns the index +// as specified by sort.Search. The slice must be sorted in ascending order. +func SearchBytes(a []byte, x byte) int { + return sort.Search(len(a), func(i int) bool { return a[i] >= x }) +} + +// Float32Slice attaches the methods of sort.Interface to []float32, sorting in increasing order. +type Float32Slice []float32 + +func (s Float32Slice) Len() int { return len(s) } +func (s Float32Slice) Less(i, j int) bool { return s[i] < s[j] } +func (s Float32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// Sort is a convenience method. +func (s Float32Slice) Sort() { + sort.Sort(s) +} + +// SearchFloat32s searches for x in a sorted slice of float32 and returns the index +// as specified by sort.Search. The slice must be sorted in ascending order. +func SearchFloat32s(a []float32, x float32) int { + return sort.Search(len(a), func(i int) bool { return a[i] >= x }) +} + +// Int8Slice attaches the methods of sort.Interface to []int8, sorting in increasing order. +type Int8Slice []int8 + +func (s Int8Slice) Len() int { return len(s) } +func (s Int8Slice) Less(i, j int) bool { return s[i] < s[j] } +func (s Int8Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// Sort is a convenience method. +func (s Int8Slice) Sort() { + sort.Sort(s) +} + +// SearchInt8s searches for x in a sorted slice of int8 and returns the index +// as specified by sort.Search. The slice must be sorted in ascending order. +func SearchInt8s(a []int8, x int8) int { + return sort.Search(len(a), func(i int) bool { return a[i] >= x }) +} + +// Int16Slice attaches the methods of sort.Interface to []int16, sorting in increasing order. +type Int16Slice []int16 + +func (s Int16Slice) Len() int { return len(s) } +func (s Int16Slice) Less(i, j int) bool { return s[i] < s[j] } +func (s Int16Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// Sort is a convenience method. +func (s Int16Slice) Sort() { + sort.Sort(s) +} + +// SearchInt16s searches for x in a sorted slice of int16 and returns the index +// as specified by sort.Search. The slice must be sorted in ascending order. +func SearchInt16s(a []int16, x int16) int { + return sort.Search(len(a), func(i int) bool { return a[i] >= x }) +} + +// Int32Slice attaches the methods of sort.Interface to []int32, sorting in increasing order. +type Int32Slice []int32 + +func (s Int32Slice) Len() int { return len(s) } +func (s Int32Slice) Less(i, j int) bool { return s[i] < s[j] } +func (s Int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// Sort is a convenience method. +func (s Int32Slice) Sort() { + sort.Sort(s) +} + +// SearchInt32s searches for x in a sorted slice of int32 and returns the index +// as specified by sort.Search. The slice must be sorted in ascending order. +func SearchInt32s(a []int32, x int32) int { + return sort.Search(len(a), func(i int) bool { return a[i] >= x }) +} + +// Int64Slice attaches the methods of sort.Interface to []int64, sorting in increasing order. +type Int64Slice []int64 + +func (s Int64Slice) Len() int { return len(s) } +func (s Int64Slice) Less(i, j int) bool { return s[i] < s[j] } +func (s Int64Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// Sort is a convenience method. +func (s Int64Slice) Sort() { + sort.Sort(s) +} + +// SearchInt64s searches for x in a sorted slice of int64 and returns the index +// as specified by sort.Search. The slice must be sorted in ascending order. +func SearchInt64s(a []int64, x int64) int { + return sort.Search(len(a), func(i int) bool { return a[i] >= x }) +} + +// UintSlice attaches the methods of sort.Interface to []uint, sorting in increasing order. +type UintSlice []uint + +func (s UintSlice) Len() int { return len(s) } +func (s UintSlice) Less(i, j int) bool { return s[i] < s[j] } +func (s UintSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// Sort is a convenience method. +func (s UintSlice) Sort() { + sort.Sort(s) +} + +// SearchUints searches for x in a sorted slice of uints and returns the index +// as specified by sort.Search. The slice must be sorted in ascending order. +func SearchUints(a []uint, x uint) int { + return sort.Search(len(a), func(i int) bool { return a[i] >= x }) +} + +// Uint16Slice attaches the methods of sort.Interface to []uint16, sorting in increasing order. +type Uint16Slice []uint16 + +func (s Uint16Slice) Len() int { return len(s) } +func (s Uint16Slice) Less(i, j int) bool { return s[i] < s[j] } +func (s Uint16Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// Sort is a convenience method. +func (s Uint16Slice) Sort() { + sort.Sort(s) +} + +// SearchUint16s searches for x in a sorted slice of uint16 and returns the index +// as specified by sort.Search. The slice must be sorted in ascending order. +func SearchUint16s(a []uint16, x uint16) int { + return sort.Search(len(a), func(i int) bool { return a[i] >= x }) +} + +// Uint32Slice attaches the methods of sort.Interface to []uint32, sorting in increasing order. +type Uint32Slice []uint32 + +func (s Uint32Slice) Len() int { return len(s) } +func (s Uint32Slice) Less(i, j int) bool { return s[i] < s[j] } +func (s Uint32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// Sort is a convenience method. +func (s Uint32Slice) Sort() { + sort.Sort(s) +} + +// SearchUint32s searches for x in a sorted slice of uint32 and returns the index +// as specified by sort.Search. The slice must be sorted in ascending order. +func SearchUint32s(a []uint32, x uint32) int { + return sort.Search(len(a), func(i int) bool { return a[i] >= x }) +} + +// Uint64Slice attaches the methods of sort.Interface to []uint64, sorting in increasing order. +type Uint64Slice []uint64 + +func (s Uint64Slice) Len() int { return len(s) } +func (s Uint64Slice) Less(i, j int) bool { return s[i] < s[j] } +func (s Uint64Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// Sort is a convenience method. +func (s Uint64Slice) Sort() { + sort.Sort(s) +} + +// SearchUint64s searches for x in a sorted slice of uint64 and returns the index +// as specified by sort.Search. The slice must be sorted in ascending order. +func SearchUint64s(a []uint64, x uint64) int { + return sort.Search(len(a), func(i int) bool { return a[i] >= x }) +} + +// RuneSlice attaches the methods of sort.Interface to []rune, sorting in increasing order. +type RuneSlice []rune + +func (s RuneSlice) Len() int { return len(s) } +func (s RuneSlice) Less(i, j int) bool { return s[i] < s[j] } +func (s RuneSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// Sort is a convenience method. +func (s RuneSlice) Sort() { + sort.Sort(s) +} + +// SearchRunes searches for x in a sorted slice of uint64 and returns the index +// as specified by sort.Search. The slice must be sorted in ascending order. +func SearchRunes(a []rune, x rune) int { + return sort.Search(len(a), func(i int) bool { return a[i] >= x }) +} + +// Dedupe returns n, the number of distinct elements in data. The resulting +// elements are sorted in elements [0, n) or data[:n] for a slice. +func Dedupe(data sort.Interface) (n int) { + if n = data.Len(); n < 2 { + return n + } + + sort.Sort(data) + a, b := 0, 1 + for b < n { + if data.Less(a, b) { + a++ + if a != b { + data.Swap(a, b) + } + } + b++ + } + return a + 1 +} diff --git a/vendor/github.com/cznic/strutil/LICENSE b/vendor/github.com/cznic/strutil/LICENSE new file mode 100644 index 00000000..2fdd92cf --- /dev/null +++ b/vendor/github.com/cznic/strutil/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2014 The strutil Authors. 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 names of the authors nor the names of the +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/vendor/github.com/cznic/strutil/strutil.go b/vendor/github.com/cznic/strutil/strutil.go new file mode 100644 index 00000000..9876e179 --- /dev/null +++ b/vendor/github.com/cznic/strutil/strutil.go @@ -0,0 +1,645 @@ +// Copyright (c) 2014 The sortutil 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 strutil collects utils supplemental to the standard strings package. +package strutil + +import ( + "bytes" + "encoding/base32" + "encoding/base64" + "fmt" + "io" + "reflect" + "sort" + "strconv" + "strings" + "sync" +) + +// Base32ExtDecode decodes base32 extended (RFC 4648) text to binary data. +func Base32ExtDecode(text []byte) (data []byte, err error) { + n := base32.HexEncoding.DecodedLen(len(text)) + data = make([]byte, n) + decoder := base32.NewDecoder(base32.HexEncoding, bytes.NewBuffer(text)) + if n, err = decoder.Read(data); err != nil { + n = 0 + } + data = data[:n] + return +} + +// Base32ExtEncode encodes binary data to base32 extended (RFC 4648) encoded text. +func Base32ExtEncode(data []byte) (text []byte) { + n := base32.HexEncoding.EncodedLen(len(data)) + buf := bytes.NewBuffer(make([]byte, 0, n)) + encoder := base32.NewEncoder(base32.HexEncoding, buf) + encoder.Write(data) + encoder.Close() + if buf.Len() != n { + panic("internal error") + } + return buf.Bytes() +} + +// Base64Decode decodes base64 text to binary data. +func Base64Decode(text []byte) (data []byte, err error) { + n := base64.StdEncoding.DecodedLen(len(text)) + data = make([]byte, n) + decoder := base64.NewDecoder(base64.StdEncoding, bytes.NewBuffer(text)) + if n, err = decoder.Read(data); err != nil { + n = 0 + } + data = data[:n] + return +} + +// Base64Encode encodes binary data to base64 encoded text. +func Base64Encode(data []byte) (text []byte) { + n := base64.StdEncoding.EncodedLen(len(data)) + buf := bytes.NewBuffer(make([]byte, 0, n)) + encoder := base64.NewEncoder(base64.StdEncoding, buf) + encoder.Write(data) + encoder.Close() + if buf.Len() != n { + panic("internal error") + } + return buf.Bytes() +} + +// Formatter is an io.Writer extended by a fmt.Printf like function Format +type Formatter interface { + io.Writer + Format(format string, args ...interface{}) (n int, errno error) +} + +type indentFormatter struct { + io.Writer + indent []byte + indentLevel int + state int +} + +const ( + st0 = iota + stBOL + stPERC + stBOLPERC +) + +// IndentFormatter returns a new Formatter which interprets %i and %u in the +// Format() format string as indent and undent commands. The commands can +// nest. The Formatter writes to io.Writer 'w' and inserts one 'indent' +// string per current indent level value. +// Behaviour of commands reaching negative indent levels is undefined. +// IndentFormatter(os.Stdout, "\t").Format("abc%d%%e%i\nx\ny\n%uz\n", 3) +// output: +// abc3%e +// x +// y +// z +// The Go quoted string literal form of the above is: +// "abc%%e\n\tx\n\tx\nz\n" +// The commands can be scattered between separate invocations of Format(), +// i.e. the formatter keeps track of the indent level and knows if it is +// positioned on start of a line and should emit indentation(s). +// The same output as above can be produced by e.g.: +// f := IndentFormatter(os.Stdout, " ") +// f.Format("abc%d%%e%i\nx\n", 3) +// f.Format("y\n%uz\n") +func IndentFormatter(w io.Writer, indent string) Formatter { + return &indentFormatter{w, []byte(indent), 0, stBOL} +} + +func (f *indentFormatter) format(flat bool, format string, args ...interface{}) (n int, errno error) { + buf := []byte{} + for i := 0; i < len(format); i++ { + c := format[i] + switch f.state { + case st0: + switch c { + case '\n': + cc := c + if flat && f.indentLevel != 0 { + cc = ' ' + } + buf = append(buf, cc) + f.state = stBOL + case '%': + f.state = stPERC + default: + buf = append(buf, c) + } + case stBOL: + switch c { + case '\n': + cc := c + if flat && f.indentLevel != 0 { + cc = ' ' + } + buf = append(buf, cc) + case '%': + f.state = stBOLPERC + default: + if !flat { + for i := 0; i < f.indentLevel; i++ { + buf = append(buf, f.indent...) + } + } + buf = append(buf, c) + f.state = st0 + } + case stBOLPERC: + switch c { + case 'i': + f.indentLevel++ + f.state = stBOL + case 'u': + f.indentLevel-- + f.state = stBOL + default: + if !flat { + for i := 0; i < f.indentLevel; i++ { + buf = append(buf, f.indent...) + } + } + buf = append(buf, '%', c) + f.state = st0 + } + case stPERC: + switch c { + case 'i': + f.indentLevel++ + f.state = st0 + case 'u': + f.indentLevel-- + f.state = st0 + default: + buf = append(buf, '%', c) + f.state = st0 + } + default: + panic("unexpected state") + } + } + switch f.state { + case stPERC, stBOLPERC: + buf = append(buf, '%') + } + return f.Write([]byte(fmt.Sprintf(string(buf), args...))) +} + +func (f *indentFormatter) Format(format string, args ...interface{}) (n int, errno error) { + return f.format(false, format, args...) +} + +type flatFormatter indentFormatter + +// FlatFormatter returns a newly created Formatter with the same functionality as the one returned +// by IndentFormatter except it allows a newline in the 'format' string argument of Format +// to pass through iff indent level is currently zero. +// +// If indent level is non-zero then such new lines are changed to a space character. +// There is no indent string, the %i and %u format verbs are used solely to determine the indent level. +// +// The FlatFormatter is intended for flattening of normally nested structure textual representation to +// a one top level structure per line form. +// FlatFormatter(os.Stdout, " ").Format("abc%d%%e%i\nx\ny\n%uz\n", 3) +// output in the form of a Go quoted string literal: +// "abc3%%e x y z\n" +func FlatFormatter(w io.Writer) Formatter { + return (*flatFormatter)(IndentFormatter(w, "").(*indentFormatter)) +} + +func (f *flatFormatter) Format(format string, args ...interface{}) (n int, errno error) { + return (*indentFormatter)(f).format(true, format, args...) +} + +// Pool handles aligning of strings having equal values to the same string instance. +// Intended use is to conserve some memory e.g. where a large number of identically valued strings +// with non identical backing arrays may exists in several semantically distinct instances of some structs. +// Pool is *not* concurrent access safe. It doesn't handle common prefix/suffix aligning, +// e.g. having s1 == "abc" and s2 == "bc", s2 is not automatically aligned as s1[1:]. +type Pool struct { + pool map[string]string +} + +// NewPool returns a newly created Pool. +func NewPool() *Pool { + return &Pool{map[string]string{}} +} + +// Align returns a string with the same value as its argument. It guarantees that +// all aligned strings share a single instance in memory. +func (p *Pool) Align(s string) string { + if a, ok := p.pool[s]; ok { + return a + } + + s = StrPack(s) + p.pool[s] = s + return s +} + +// Count returns the number of items in the pool. +func (p *Pool) Count() int { + return len(p.pool) +} + +// GoPool is a concurrent access safe version of Pool. +type GoPool struct { + pool map[string]string + rwm *sync.RWMutex +} + +// NewGoPool returns a newly created GoPool. +func NewGoPool() (p *GoPool) { + return &GoPool{map[string]string{}, &sync.RWMutex{}} +} + +// Align returns a string with the same value as its argument. It guarantees that +// all aligned strings share a single instance in memory. +func (p *GoPool) Align(s string) (y string) { + if s != "" { + p.rwm.RLock() // R++ + if a, ok := p.pool[s]; ok { // found + p.rwm.RUnlock() // R-- + return a + } + + p.rwm.RUnlock() // R-- + // not found but with a race condition, retry within a write lock + p.rwm.Lock() // W++ + defer p.rwm.Unlock() // W-- + if a, ok := p.pool[s]; ok { // done in a race + return a + } + + // we won + s = StrPack(s) + p.pool[s] = s + return s + } + + return +} + +// Count returns the number of items in the pool. +func (p *GoPool) Count() int { + return len(p.pool) +} + +// Dict is a string <-> id bijection. Dict is *not* concurrent access safe for assigning new ids +// to strings not yet contained in the bijection. +// Id for an empty string is guaranteed to be 0, +// thus Id for any non empty string is guaranteed to be non zero. +type Dict struct { + si map[string]int + is []string +} + +// NewDict returns a newly created Dict. +func NewDict() (d *Dict) { + d = &Dict{map[string]int{}, []string{}} + d.Id("") + return +} + +// Count returns the number of items in the dict. +func (d *Dict) Count() int { + return len(d.is) +} + +// Id maps string s to its numeric identificator. +func (d *Dict) Id(s string) (y int) { + if y, ok := d.si[s]; ok { + return y + } + + s = StrPack(s) + y = len(d.is) + d.si[s] = y + d.is = append(d.is, s) + return +} + +// S maps an id to its string value and ok == true. Id values not contained in the bijection +// return "", false. +func (d *Dict) S(id int) (s string, ok bool) { + if id >= len(d.is) { + return "", false + } + return d.is[id], true +} + +// GoDict is a concurrent access safe version of Dict. +type GoDict struct { + si map[string]int + is []string + rwm *sync.RWMutex +} + +// NewGoDict returns a newly created GoDict. +func NewGoDict() (d *GoDict) { + d = &GoDict{map[string]int{}, []string{}, &sync.RWMutex{}} + d.Id("") + return +} + +// Count returns the number of items in the dict. +func (d *GoDict) Count() int { + return len(d.is) +} + +// Id maps string s to its numeric identificator. The implementation honors getting +// an existing id at the cost of assigning a new one. +func (d *GoDict) Id(s string) (y int) { + d.rwm.RLock() // R++ + if y, ok := d.si[s]; ok { // found + d.rwm.RUnlock() // R-- + return y + } + + d.rwm.RUnlock() // R-- + + // not found but with a race condition + d.rwm.Lock() // W++ recheck with write lock + defer d.rwm.Unlock() // W-- + if y, ok := d.si[s]; ok { // some other goroutine won already + return y + } + + // a race free not found state => insert the string + s = StrPack(s) + y = len(d.is) + d.si[s] = y + d.is = append(d.is, s) + return +} + +// S maps an id to its string value and ok == true. Id values not contained in the bijection +// return "", false. +func (d *GoDict) S(id int) (s string, ok bool) { + d.rwm.RLock() // R++ + defer d.rwm.RUnlock() // R-- + if id >= len(d.is) { + return "", false + } + return d.is[id], true +} + +// StrPack returns a new instance of s which is tightly packed in memory. +// It is intended for avoiding the situation where having a live reference +// to a string slice over an unreferenced biger underlying string keeps the biger one +// in memory anyway - it can't be GCed. +func StrPack(s string) string { + return string([]byte(s)) +} + +// JoinFields returns strings in flds joined by sep. Flds may contain arbitrary +// bytes, including the sep as they are safely escaped. JoinFields panics if +// sep is the backslash character or if len(sep) != 1. +func JoinFields(flds []string, sep string) string { + if len(sep) != 1 || sep == "\\" { + panic("invalid separator") + } + + a := make([]string, len(flds)) + for i, v := range flds { + v = strings.Replace(v, "\\", "\\0", -1) + a[i] = strings.Replace(v, sep, "\\1", -1) + } + return strings.Join(a, sep) +} + +// SplitFields splits s, which must be produced by JoinFields using the same +// sep, into flds. SplitFields panics if sep is the backslash character or if +// len(sep) != 1. +func SplitFields(s, sep string) (flds []string) { + if len(sep) != 1 || sep == "\\" { + panic("invalid separator") + } + + a := strings.Split(s, sep) + r := make([]string, len(a)) + for i, v := range a { + v = strings.Replace(v, "\\1", sep, -1) + r[i] = strings.Replace(v, "\\0", "\\", -1) + } + return r +} + +// PrettyPrintHooks allow to customize the result of PrettyPrint for types +// listed in the map value. +type PrettyPrintHooks map[reflect.Type]func(f Formatter, v interface{}, prefix, suffix string) + +// PrettyString returns the output of PrettyPrint as a string. +func PrettyString(v interface{}, prefix, suffix string, hooks PrettyPrintHooks) string { + var b bytes.Buffer + PrettyPrint(&b, v, prefix, suffix, hooks) + return b.String() +} + +// PrettyPrint pretty prints v to w. Zero values and unexported struct fields +// are omitted. +func PrettyPrint(w io.Writer, v interface{}, prefix, suffix string, hooks PrettyPrintHooks) { + if v == nil { + return + } + + f := IndentFormatter(w, "· ") + + defer func() { + if e := recover(); e != nil { + f.Format("\npanic: %v", e) + } + }() + + prettyPrint(nil, f, prefix, suffix, v, hooks) +} + +func prettyPrint(protect map[interface{}]struct{}, sf Formatter, prefix, suffix string, v interface{}, hooks PrettyPrintHooks) { + if v == nil { + return + } + + rt := reflect.TypeOf(v) + if handler := hooks[rt]; handler != nil { + handler(sf, v, prefix, suffix) + return + } + + rv := reflect.ValueOf(v) + switch rt.Kind() { + case reflect.Slice: + if rv.Len() == 0 { + return + } + + sf.Format("%s[]%T{ // len %d%i\n", prefix, rv.Index(0).Interface(), rv.Len()) + for i := 0; i < rv.Len(); i++ { + prettyPrint(protect, sf, fmt.Sprintf("%d: ", i), ",\n", rv.Index(i).Interface(), hooks) + } + suffix = strings.Replace(suffix, "%", "%%", -1) + sf.Format("%u}" + suffix) + case reflect.Array: + if reflect.Zero(rt).Interface() == rv.Interface() { + return + } + + sf.Format("%s[%d]%T{%i\n", prefix, rv.Len(), rv.Index(0).Interface()) + for i := 0; i < rv.Len(); i++ { + prettyPrint(protect, sf, fmt.Sprintf("%d: ", i), ",\n", rv.Index(i).Interface(), hooks) + } + suffix = strings.Replace(suffix, "%", "%%", -1) + sf.Format("%u}" + suffix) + case reflect.Struct: + if rt.NumField() == 0 { + return + } + + if reflect.DeepEqual(reflect.Zero(rt).Interface(), rv.Interface()) { + return + } + + sf.Format("%s%T{%i\n", prefix, v) + for i := 0; i < rt.NumField(); i++ { + f := rv.Field(i) + if !f.CanInterface() { + continue + } + + prettyPrint(protect, sf, fmt.Sprintf("%s: ", rt.Field(i).Name), ",\n", f.Interface(), hooks) + } + suffix = strings.Replace(suffix, "%", "%%", -1) + sf.Format("%u}" + suffix) + case reflect.Ptr: + if rv.IsNil() { + return + } + + rvi := rv.Interface() + if _, ok := protect[rvi]; ok { + suffix = strings.Replace(suffix, "%", "%%", -1) + sf.Format("%s&%T{ /* recursive/repetitive pointee not shown */ }"+suffix, prefix, rv.Elem().Interface()) + return + } + + if protect == nil { + protect = map[interface{}]struct{}{} + } + protect[rvi] = struct{}{} + prettyPrint(protect, sf, prefix+"&", suffix, rv.Elem().Interface(), hooks) + case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int8: + if v := rv.Int(); v != 0 { + suffix = strings.Replace(suffix, "%", "%%", -1) + sf.Format("%s%v"+suffix, prefix, v) + } + case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint8: + if v := rv.Uint(); v != 0 { + suffix = strings.Replace(suffix, "%", "%%", -1) + sf.Format("%s%v"+suffix, prefix, v) + } + case reflect.Float32, reflect.Float64: + if v := rv.Float(); v != 0 { + suffix = strings.Replace(suffix, "%", "%%", -1) + sf.Format("%s%v"+suffix, prefix, v) + } + case reflect.Complex64, reflect.Complex128: + if v := rv.Complex(); v != 0 { + suffix = strings.Replace(suffix, "%", "%%", -1) + sf.Format("%s%v"+suffix, prefix, v) + } + case reflect.Uintptr: + if v := rv.Uint(); v != 0 { + suffix = strings.Replace(suffix, "%", "%%", -1) + sf.Format("%s%v"+suffix, prefix, v) + } + case reflect.UnsafePointer: + s := fmt.Sprintf("%p", rv.Interface()) + if s == "0x0" { + return + } + + suffix = strings.Replace(suffix, "%", "%%", -1) + sf.Format("%s%s"+suffix, prefix, s) + case reflect.Bool: + if v := rv.Bool(); v { + suffix = strings.Replace(suffix, "%", "%%", -1) + sf.Format("%s%v"+suffix, prefix, rv.Bool()) + } + case reflect.String: + s := rv.Interface().(string) + if s == "" { + return + } + + suffix = strings.Replace(suffix, "%", "%%", -1) + sf.Format("%s%q"+suffix, prefix, s) + case reflect.Chan: + if reflect.Zero(rt).Interface() == rv.Interface() { + return + } + + c := rv.Cap() + s := "" + if c != 0 { + s = fmt.Sprintf("// capacity: %d", c) + } + suffix = strings.Replace(suffix, "%", "%%", -1) + sf.Format("%s%s %s%s"+suffix, prefix, rt.ChanDir(), rt.Elem().Name(), s) + case reflect.Func: + if rv.IsNil() { + return + } + + var in, out []string + for i := 0; i < rt.NumIn(); i++ { + x := reflect.Zero(rt.In(i)) + in = append(in, fmt.Sprintf("%T", x.Interface())) + } + if rt.IsVariadic() { + i := len(in) - 1 + in[i] = "..." + in[i][2:] + } + for i := 0; i < rt.NumOut(); i++ { + out = append(out, rt.Out(i).Name()) + } + s := "(" + strings.Join(in, ", ") + ")" + t := strings.Join(out, ", ") + if len(out) > 1 { + t = "(" + t + ")" + } + if t != "" { + t = " " + t + } + suffix = strings.Replace(suffix, "%", "%%", -1) + sf.Format("%sfunc%s%s { ... }"+suffix, prefix, s, t) + case reflect.Map: + keys := rv.MapKeys() + if len(keys) == 0 { + return + } + + var buf bytes.Buffer + nf := IndentFormatter(&buf, "· ") + var skeys []string + for i, k := range keys { + prettyPrint(protect, nf, "", "", k.Interface(), hooks) + skeys = append(skeys, fmt.Sprintf("%s%10d", buf.Bytes(), i)) + buf.Reset() + } + sort.Strings(skeys) + sf.Format("%s%T{%i\n", prefix, v) + for _, k := range skeys { + si := strings.TrimSpace(k[len(k)-10:]) + k = k[:len(k)-10] + n, _ := strconv.ParseUint(si, 10, 64) + mv := rv.MapIndex(keys[n]) + prettyPrint(protect, sf, fmt.Sprintf("%s: ", k), ",\n", mv.Interface(), hooks) + } + suffix = strings.Replace(suffix, "%", "%%", -1) + sf.Format("%u}" + suffix) + } +} diff --git a/vendor/github.com/cznic/zappy/LICENSE b/vendor/github.com/cznic/zappy/LICENSE new file mode 100644 index 00000000..bc67059c --- /dev/null +++ b/vendor/github.com/cznic/zappy/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2014 The zappy Authors. 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 names of the authors nor the names of the +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/vendor/github.com/cznic/zappy/decode.go b/vendor/github.com/cznic/zappy/decode.go new file mode 100644 index 00000000..867c8dee --- /dev/null +++ b/vendor/github.com/cznic/zappy/decode.go @@ -0,0 +1,38 @@ +// Copyright 2014 The zappy Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the SNAPPY-GO-LICENSE file. + +package zappy + +import ( + "encoding/binary" + "errors" +) + +// ErrCorrupt reports that the input is invalid. +var ErrCorrupt = errors.New("zappy: corrupt input") + +// DecodedLen returns the length of the decoded block. +func DecodedLen(src []byte) (int, error) { + v, _, err := decodedLen(src) + return v, err +} + +// decodedLen returns the length of the decoded block and the number of bytes +// that the length header occupied. +func decodedLen(src []byte) (blockLen, headerLen int, err error) { + v, n := binary.Uvarint(src) + if n == 0 { + return 0, 0, ErrCorrupt + } + + if uint64(int(v)) != v { + return 0, 0, errors.New("zappy: decoded block is too large") + } + + return int(v), n, nil +} diff --git a/vendor/github.com/cznic/zappy/decode_cgo.go b/vendor/github.com/cznic/zappy/decode_cgo.go new file mode 100644 index 00000000..993c9924 --- /dev/null +++ b/vendor/github.com/cznic/zappy/decode_cgo.go @@ -0,0 +1,121 @@ +// Copyright 2014 The zappy Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the SNAPPY-GO-LICENSE file. + +// +build cgo,!purego + +package zappy + +/* + +#include +#include + +// supports only uint32 encoded values +int uvarint(unsigned int* n, uint8_t* src, int len) { + int r = 0; + unsigned int v = 0; + unsigned int s = 0; + while ((len-- != 0) && (++r <= 5)) { + uint8_t b = *src++; + v = v | ((b&0x7f)<>1; + if ((u&1) != 0) + x = ~x; + *n = x; + return i; +} + +int decode(int s, int len_src, uint8_t* src, int len_dst, uint8_t* dst) { + int d = 0; + int length; + while (s < len_src) { + int n, i = varint(&n, src+s, len_src-s); + if (i <= 0) { + return -1; + } + + s += i; + if (n >= 0) { + length = n+1; + if ((length > len_dst-d) || (length > len_src-s)) + return -1; + + memcpy(dst+d, src+s, length); + d += length; + s += length; + continue; + } + + + length = -n; + int offset; + i = uvarint((unsigned int*)(&offset), src+s, len_src-s); + if (i <= 0) + return -1; + + s += i; + if (s > len_src) + return -1; + + int end = d+length; + if ((offset > d) || (end > len_dst)) + return -1; + + for( ; d < end; d++) + *(dst+d) = *(dst+d-offset); + } + return d; +} + +*/ +import "C" + +func puregoDecode() bool { return false } + +// Decode returns the decoded form of src. The returned slice may be a sub- +// slice of buf if buf was large enough to hold the entire decoded block. +// Otherwise, a newly allocated slice will be returned. +// It is valid to pass a nil buf. +func Decode(buf, src []byte) ([]byte, error) { + dLen, s, err := decodedLen(src) + if err != nil { + return nil, err + } + + if dLen == 0 { + if len(src) == 1 { + return nil, nil + } + + return nil, ErrCorrupt + } + + if len(buf) < dLen { + buf = make([]byte, dLen) + } + + d := int(C.decode(C.int(s), C.int(len(src)), (*C.uint8_t)(&src[0]), C.int(len(buf)), (*C.uint8_t)(&buf[0]))) + if d != dLen { + return nil, ErrCorrupt + } + + return buf[:d], nil +} diff --git a/vendor/github.com/cznic/zappy/decode_nocgo.go b/vendor/github.com/cznic/zappy/decode_nocgo.go new file mode 100644 index 00000000..75b782f8 --- /dev/null +++ b/vendor/github.com/cznic/zappy/decode_nocgo.go @@ -0,0 +1,89 @@ +// Copyright 2014 The zappy Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the SNAPPY-GO-LICENSE file. + +// +build !cgo purego + +package zappy + +import ( + "encoding/binary" +) + +func puregoDecode() bool { return true } + +// Decode returns the decoded form of src. The returned slice may be a sub- +// slice of buf if buf was large enough to hold the entire decoded block. +// Otherwise, a newly allocated slice will be returned. +// It is valid to pass a nil buf. +func Decode(buf, src []byte) ([]byte, error) { + dLen, s, err := decodedLen(src) + if err != nil { + return nil, err + } + + if dLen == 0 { + if len(src) == 1 { + return nil, nil + } + + return nil, ErrCorrupt + } + + if len(buf) < dLen { + buf = make([]byte, dLen) + } + + var d, offset, length int + for s < len(src) { + n, i := binary.Varint(src[s:]) + if i <= 0 { + return nil, ErrCorrupt + } + + s += i + if n >= 0 { + length = int(n + 1) + if length > len(buf)-d || length > len(src)-s { + return nil, ErrCorrupt + } + + copy(buf[d:], src[s:s+length]) + d += length + s += length + continue + } + + length = int(-n) + off64, i := binary.Uvarint(src[s:]) + if i <= 0 { + return nil, ErrCorrupt + } + + offset = int(off64) + s += i + if s > len(src) { + return nil, ErrCorrupt + } + + end := d + length + if offset > d || end > len(buf) { + return nil, ErrCorrupt + } + + for s, v := range buf[d-offset : end-offset] { + buf[d+s] = v + } + d = end + + } + if d != dLen { + return nil, ErrCorrupt + } + + return buf[:d], nil +} diff --git a/vendor/github.com/cznic/zappy/encode.go b/vendor/github.com/cznic/zappy/encode.go new file mode 100644 index 00000000..27ceba03 --- /dev/null +++ b/vendor/github.com/cznic/zappy/encode.go @@ -0,0 +1,37 @@ +// Copyright 2014 The zappy Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the SNAPPY-GO-LICENSE file. + +package zappy + +import ( + "encoding/binary" +) + +// We limit how far copy back-references can go, the same as the snappy C++ +// code. +const maxOffset = 1 << 20 + +// emitCopy writes a copy chunk and returns the number of bytes written. +func emitCopy(dst []byte, offset, length int) (n int) { + n = binary.PutVarint(dst, int64(-length)) + n += binary.PutUvarint(dst[n:], uint64(offset)) + return +} + +// emitLiteral writes a literal chunk and returns the number of bytes written. +func emitLiteral(dst, lit []byte) (n int) { + n = binary.PutVarint(dst, int64(len(lit)-1)) + n += copy(dst[n:], lit) + return +} + +// MaxEncodedLen returns the maximum length of a zappy block, given its +// uncompressed length. +func MaxEncodedLen(srcLen int) int { + return 10 + srcLen +} diff --git a/vendor/github.com/cznic/zappy/encode_cgo.go b/vendor/github.com/cznic/zappy/encode_cgo.go new file mode 100644 index 00000000..6c343f58 --- /dev/null +++ b/vendor/github.com/cznic/zappy/encode_cgo.go @@ -0,0 +1,140 @@ +// Copyright 2014 The zappy Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the SNAPPY-GO-LICENSE file. + +// +build cgo,!purego + +package zappy + +/* + +#include +#include + +#define MAXOFFSET 1<<20 + +int putUvarint(uint8_t* buf, unsigned int x) { + int i = 1; + for (; x >= 0x80; i++) { + *buf++ = x|0x80; + x >>= 7; + } + *buf = x; + return i; +} + +int putVarint(uint8_t* buf, int x) { + unsigned int ux = x << 1; + if (x < 0) + ux = ~ux; + return putUvarint(buf, ux); +} + +int emitLiteral(uint8_t* dst, uint8_t* lit, int len_lit) { + int n = putVarint(dst, len_lit-1); + memcpy(dst+n, lit, len_lit); + return n+len_lit; +} + +int emitCopy(uint8_t* dst, int off, int len) { + int n = putVarint(dst, -len); + return n+putUvarint(dst+n, (unsigned int)off); +} + +int encode(int d, uint8_t* dst, uint8_t* src, int len_src) { + int table[1<<12]; + int s = 0; + int t = 0; + int lit = 0; + int lim = 0; + memset(table, 0, sizeof(table)); + for (lim = len_src-3; s < lim; ) { + // Update the hash table. + uint32_t b0 = src[s]; + uint32_t b1 = src[s+1]; + uint32_t b2 = src[s+2]; + uint32_t b3 = src[s+3]; + uint32_t h = b0 | (b1<<8) | (b2<<16) | (b3<<24); + uint32_t i; +more: + i = (h*0x1e35a7bd)>>20; + t = table[i]; + table[i] = s; + // If t is invalid or src[s:s+4] differs from src[t:t+4], accumulate a literal byte. + if ((t == 0) || (s-t >= MAXOFFSET) || (b0 != src[t]) || (b1 != src[t+1]) || (b2 != src[t+2]) || (b3 != src[t+3])) { + s++; + if (s >= lim) + break; + + b0 = b1; + b1 = b2; + b2 = b3; + b3 = src[s+3]; + h = (h>>8) | ((b3)<<24); + goto more; + } + + // Otherwise, we have a match. First, emit any pending literal bytes. + if (lit != s) { + d += emitLiteral(dst+d, src+lit, s-lit); + } + // Extend the match to be as long as possible. + int s0 = s; + s += 4; + t += 4; + while ((s < len_src) && (src[s] == src[t])) { + s++; + t++; + } + d += emitCopy(dst+d, s-t, s-s0); + lit = s; + } + // Emit any final pending literal bytes and return. + if (lit != len_src) { + d += emitLiteral(dst+d, src+lit, len_src-lit); + } + return d; +} + +*/ +import "C" + +import ( + "encoding/binary" + "fmt" + "math" +) + +func puregoEncode() bool { return false } + +// Encode returns the encoded form of src. The returned slice may be a sub- +// slice of buf if buf was large enough to hold the entire encoded block. +// Otherwise, a newly allocated slice will be returned. +// It is valid to pass a nil buf. +func Encode(buf, src []byte) ([]byte, error) { + if n := MaxEncodedLen(len(src)); len(buf) < n { + buf = make([]byte, n) + } + + if len(src) > math.MaxInt32 { + return nil, fmt.Errorf("zappy.Encode: too long data: %d bytes", len(src)) + } + + // The block starts with the varint-encoded length of the decompressed bytes. + d := binary.PutUvarint(buf, uint64(len(src))) + + // Return early if src is short. + if len(src) <= 4 { + if len(src) != 0 { + d += emitLiteral(buf[d:], src) + } + return buf[:d], nil + } + + d = int(C.encode(C.int(d), (*C.uint8_t)(&buf[0]), (*C.uint8_t)(&src[0]), C.int(len(src)))) + return buf[:d], nil +} diff --git a/vendor/github.com/cznic/zappy/encode_nocgo.go b/vendor/github.com/cznic/zappy/encode_nocgo.go new file mode 100644 index 00000000..1d1df443 --- /dev/null +++ b/vendor/github.com/cznic/zappy/encode_nocgo.go @@ -0,0 +1,92 @@ +// Copyright 2014 The zappy Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the SNAPPY-GO-LICENSE file. + +// +build !cgo purego + +package zappy + +import ( + "encoding/binary" + "fmt" + "math" +) + +func puregoEncode() bool { return true } + +// Encode returns the encoded form of src. The returned slice may be a sub- +// slice of buf if buf was large enough to hold the entire encoded block. +// Otherwise, a newly allocated slice will be returned. +// It is valid to pass a nil buf. +func Encode(buf, src []byte) ([]byte, error) { + if n := MaxEncodedLen(len(src)); len(buf) < n { + buf = make([]byte, n) + } + + if len(src) > math.MaxInt32 { + return nil, fmt.Errorf("zappy.Encode: too long data: %d bytes", len(src)) + } + + // The block starts with the varint-encoded length of the decompressed bytes. + d := binary.PutUvarint(buf, uint64(len(src))) + + // Return early if src is short. + if len(src) <= 4 { + if len(src) != 0 { + d += emitLiteral(buf[d:], src) + } + return buf[:d], nil + } + + // Iterate over the source bytes. + var ( + table [1 << 12]int // Hash table + s int // The iterator position. + t int // The last position with the same hash as s. + lit int // The start position of any pending literal bytes. + ) + for lim := len(src) - 3; s < lim; { + // Update the hash table. + b0, b1, b2, b3 := src[s], src[s+1], src[s+2], src[s+3] + h := uint32(b0) | uint32(b1)<<8 | uint32(b2)<<16 | uint32(b3)<<24 + more: + p := &table[(h*0x1e35a7bd)>>20] + t, *p = *p, s + // If t is invalid or src[s:s+4] differs from src[t:t+4], accumulate a literal byte. + if t == 0 || s-t >= maxOffset || b0 != src[t] || b1 != src[t+1] || b2 != src[t+2] || b3 != src[t+3] { + s++ + if s >= lim { + break + } + + b0, b1, b2, b3 = b1, b2, b3, src[s+3] + h = h>>8 | uint32(b3)<<24 + goto more + } + + // Otherwise, we have a match. First, emit any pending literal bytes. + if lit != s { + d += emitLiteral(buf[d:], src[lit:s]) + } + // Extend the match to be as long as possible. + s0 := s + s, t = s+4, t+4 + for s < len(src) && src[s] == src[t] { + s++ + t++ + } + // Emit the copied bytes. + d += emitCopy(buf[d:], s-t, s-s0) + lit = s + } + + // Emit any final pending literal bytes and return. + if lit != len(src) { + d += emitLiteral(buf[d:], src[lit:]) + } + return buf[:d], nil +} diff --git a/vendor/github.com/cznic/zappy/zappy.go b/vendor/github.com/cznic/zappy/zappy.go new file mode 100644 index 00000000..e5bdfc01 --- /dev/null +++ b/vendor/github.com/cznic/zappy/zappy.go @@ -0,0 +1,241 @@ +// Copyright 2014 The zappy Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the SNAPPY-GO-LICENSE file. + +/* +Package zappy implements the zappy block-based compression format. It aims for +a combination of good speed and reasonable compression. + +Zappy is a format incompatible, API compatible fork of snappy[1]. The C++ +snappy implementation is at [2]. + +Reasons for the fork + +The snappy compression is pretty good. Yet it has one problem built into its +format definition[3] - the maximum length of a copy "instruction" is 64 bytes. +For some specific usage patterns with long runs of repeated data, it turns out +the compression is suboptimal. For example a 1:1000 "sparseness" 64kB bit index +with only few set bits is compressed to about 3kB (about 1000 of 64B copy, 3 +byte "instructions"). + +Format description + +Zappy uses much less complicated format than snappy. Each encoded block begins +with the uvarint-encoded[4] length of the decoded data, followed by a sequence +of chunks. Chunks begin and end on byte boundaries. The chunk starts with a +varint encoded number N: + + N >= 0: N+1 literal bytes follow. + + N < 0: copy -N bytes, starting at offset M (in the following uvarint). + +Performance issues + +Compression rate is roughly the same as of snappy for the reference data set: + + testdata/html: snappy 23320, zappy 22943, 0.984, orig 102400 + testdata/urls.10K: snappy 334437, zappy 355163, 1.062, orig 702087 + testdata/house.jpg: snappy 126711, zappy 126694, 1.000, orig 126958 + testdata/mapreduce-osdi-1.pdf: snappy 77227, zappy 77646, 1.005, orig 94330 + testdata/html_x_4: snappy 92350, zappy 22956, 0.249, orig 409600 + testdata/cp.html: snappy 11938, zappy 12961, 1.086, orig 24603 + testdata/fields.c: snappy 4825, zappy 5395, 1.118, orig 11150 + testdata/grammar.lsp: snappy 1814, zappy 1933, 1.066, orig 3721 + testdata/kennedy.xls: snappy 423518, zappy 440597, 1.040, orig 1029744 + testdata/alice29.txt: snappy 89550, zappy 104016, 1.162, orig 152089 + testdata/asyoulik.txt: snappy 79583, zappy 91345, 1.148, orig 125179 + testdata/lcet10.txt: snappy 238761, zappy 275488, 1.154, orig 426754 + testdata/plrabn12.txt: snappy 324567, zappy 376885, 1.161, orig 481861 + testdata/ptt5: snappy 96350, zappy 91465, 0.949, orig 513216 + testdata/sum: snappy 18927, zappy 20015, 1.057, orig 38240 + testdata/xargs.1: snappy 2532, zappy 2793, 1.103, orig 4227 + testdata/geo.protodata: snappy 23362, zappy 20759, 0.889, orig 118588 + testdata/kppkn.gtb: snappy 73962, zappy 87200, 1.179, orig 184320 + TOTAL: snappy 2043734, zappy 2136254, 1.045, orig 4549067 + +Zappy has better RLE handling (1/1000+1 non zero bytes in each index): + + Sparse bit index 16 B: snappy 9, zappy 9, 1.000 + Sparse bit index 32 B: snappy 10, zappy 10, 1.000 + Sparse bit index 64 B: snappy 11, zappy 10, 0.909 + Sparse bit index 128 B: snappy 16, zappy 14, 0.875 + Sparse bit index 256 B: snappy 22, zappy 14, 0.636 + Sparse bit index 512 B: snappy 36, zappy 16, 0.444 + Sparse bit index 1024 B: snappy 57, zappy 18, 0.316 + Sparse bit index 2048 B: snappy 111, zappy 32, 0.288 + Sparse bit index 4096 B: snappy 210, zappy 31, 0.148 + Sparse bit index 8192 B: snappy 419, zappy 75, 0.179 + Sparse bit index 16384 B: snappy 821, zappy 138, 0.168 + Sparse bit index 32768 B: snappy 1627, zappy 232, 0.143 + Sparse bit index 65536 B: snappy 3243, zappy 451, 0.139 + +When compiled with CGO_ENABLED=1, zappy is now faster than Go snappy. +Old=Go snappy, new=zappy: + + benchmark old MB/s new MB/s speedup + BenchmarkWordsDecode1e3 148.98 189.04 1.27x + BenchmarkWordsDecode1e4 150.29 182.51 1.21x + BenchmarkWordsDecode1e5 145.79 182.95 1.25x + BenchmarkWordsDecode1e6 167.43 187.69 1.12x + BenchmarkWordsEncode1e3 47.11 145.69 3.09x + BenchmarkWordsEncode1e4 81.47 136.50 1.68x + BenchmarkWordsEncode1e5 78.86 127.93 1.62x + BenchmarkWordsEncode1e6 96.81 142.95 1.48x + Benchmark_UFlat0 316.87 463.19 1.46x + Benchmark_UFlat1 231.56 350.32 1.51x + Benchmark_UFlat2 3656.68 8258.39 2.26x + Benchmark_UFlat3 892.56 1270.09 1.42x + Benchmark_UFlat4 315.84 959.08 3.04x + Benchmark_UFlat5 211.70 301.55 1.42x + Benchmark_UFlat6 211.59 258.29 1.22x + Benchmark_UFlat7 209.80 272.21 1.30x + Benchmark_UFlat8 254.59 301.70 1.19x + Benchmark_UFlat9 163.39 192.66 1.18x + Benchmark_UFlat10 155.46 189.70 1.22x + Benchmark_UFlat11 170.11 198.95 1.17x + Benchmark_UFlat12 148.32 178.78 1.21x + Benchmark_UFlat13 359.25 579.99 1.61x + Benchmark_UFlat14 197.27 291.33 1.48x + Benchmark_UFlat15 185.75 248.07 1.34x + Benchmark_UFlat16 362.74 582.66 1.61x + Benchmark_UFlat17 222.95 240.01 1.08x + Benchmark_ZFlat0 188.66 311.89 1.65x + Benchmark_ZFlat1 101.46 201.34 1.98x + Benchmark_ZFlat2 93.62 244.50 2.61x + Benchmark_ZFlat3 102.79 243.34 2.37x + Benchmark_ZFlat4 191.64 625.32 3.26x + Benchmark_ZFlat5 103.09 169.39 1.64x + Benchmark_ZFlat6 110.35 182.57 1.65x + Benchmark_ZFlat7 89.56 190.53 2.13x + Benchmark_ZFlat8 154.05 235.68 1.53x + Benchmark_ZFlat9 87.58 133.51 1.52x + Benchmark_ZFlat10 82.08 127.51 1.55x + Benchmark_ZFlat11 91.36 138.91 1.52x + Benchmark_ZFlat12 79.24 123.02 1.55x + Benchmark_ZFlat13 217.04 374.26 1.72x + Benchmark_ZFlat14 100.33 168.03 1.67x + Benchmark_ZFlat15 80.79 160.46 1.99x + Benchmark_ZFlat16 213.32 375.79 1.76x + Benchmark_ZFlat17 135.37 197.13 1.46x + +The package builds with CGO_ENABLED=0 as well, but the performance is worse. + + + $ CGO_ENABLED=0 go test -test.run=NONE -test.bench=. > old.benchcmp + $ CGO_ENABLED=1 go test -test.run=NONE -test.bench=. > new.benchcmp + $ benchcmp old.benchcmp new.benchcmp + benchmark old ns/op new ns/op delta + BenchmarkWordsDecode1e3 9735 5288 -45.68% + BenchmarkWordsDecode1e4 100229 55369 -44.76% + BenchmarkWordsDecode1e5 1037611 546420 -47.34% + BenchmarkWordsDecode1e6 9559352 5335307 -44.19% + BenchmarkWordsEncode1e3 16206 6629 -59.10% + BenchmarkWordsEncode1e4 140283 73161 -47.85% + BenchmarkWordsEncode1e5 1476657 781756 -47.06% + BenchmarkWordsEncode1e6 12702229 6997656 -44.91% + Benchmark_UFlat0 397307 221198 -44.33% + Benchmark_UFlat1 3890483 2008341 -48.38% + Benchmark_UFlat2 35810 15398 -57.00% + Benchmark_UFlat3 140850 74194 -47.32% + Benchmark_UFlat4 814575 426783 -47.61% + Benchmark_UFlat5 156995 81473 -48.10% + Benchmark_UFlat6 77645 43161 -44.41% + Benchmark_UFlat7 25415 13579 -46.57% + Benchmark_UFlat8 6372440 3412916 -46.44% + Benchmark_UFlat9 1453679 789956 -45.66% + Benchmark_UFlat10 1243146 660747 -46.85% + Benchmark_UFlat11 3903493 2146334 -45.02% + Benchmark_UFlat12 5106250 2696144 -47.20% + Benchmark_UFlat13 1641394 884969 -46.08% + Benchmark_UFlat14 262206 131174 -49.97% + Benchmark_UFlat15 32325 17047 -47.26% + Benchmark_UFlat16 366991 204877 -44.17% + Benchmark_UFlat17 1343988 770907 -42.64% + Benchmark_ZFlat0 579954 329812 -43.13% + Benchmark_ZFlat1 6564692 3504867 -46.61% + Benchmark_ZFlat2 902029 513700 -43.05% + Benchmark_ZFlat3 678722 384312 -43.38% + Benchmark_ZFlat4 1197389 654361 -45.35% + Benchmark_ZFlat5 262677 144939 -44.82% + Benchmark_ZFlat6 111249 60876 -45.28% + Benchmark_ZFlat7 39024 19420 -50.24% + Benchmark_ZFlat8 8046106 4387928 -45.47% + Benchmark_ZFlat9 2043167 1143139 -44.05% + Benchmark_ZFlat10 1781604 980528 -44.96% + Benchmark_ZFlat11 5478647 3078585 -43.81% + Benchmark_ZFlat12 7245995 3929863 -45.77% + Benchmark_ZFlat13 2432529 1371606 -43.61% + Benchmark_ZFlat14 420315 227494 -45.88% + Benchmark_ZFlat15 52378 26564 -49.28% + Benchmark_ZFlat16 567047 316196 -44.24% + Benchmark_ZFlat17 1630820 937310 -42.53% + + benchmark old MB/s new MB/s speedup + BenchmarkWordsDecode1e3 102.71 189.08 1.84x + BenchmarkWordsDecode1e4 99.77 180.60 1.81x + BenchmarkWordsDecode1e5 96.38 183.01 1.90x + BenchmarkWordsDecode1e6 104.61 187.43 1.79x + BenchmarkWordsEncode1e3 61.70 150.85 2.44x + BenchmarkWordsEncode1e4 71.28 136.68 1.92x + BenchmarkWordsEncode1e5 67.72 127.92 1.89x + BenchmarkWordsEncode1e6 78.73 142.90 1.82x + Benchmark_UFlat0 257.73 462.93 1.80x + Benchmark_UFlat1 180.46 349.59 1.94x + Benchmark_UFlat2 3545.30 8244.61 2.33x + Benchmark_UFlat3 669.72 1271.39 1.90x + Benchmark_UFlat4 502.84 959.74 1.91x + Benchmark_UFlat5 156.71 301.98 1.93x + Benchmark_UFlat6 143.60 258.33 1.80x + Benchmark_UFlat7 146.41 274.01 1.87x + Benchmark_UFlat8 161.59 301.72 1.87x + Benchmark_UFlat9 104.62 192.53 1.84x + Benchmark_UFlat10 100.70 189.45 1.88x + Benchmark_UFlat11 109.33 198.83 1.82x + Benchmark_UFlat12 94.37 178.72 1.89x + Benchmark_UFlat13 312.67 579.93 1.85x + Benchmark_UFlat14 145.84 291.52 2.00x + Benchmark_UFlat15 130.77 247.95 1.90x + Benchmark_UFlat16 323.14 578.82 1.79x + Benchmark_UFlat17 137.14 239.09 1.74x + Benchmark_ZFlat0 176.57 310.48 1.76x + Benchmark_ZFlat1 106.95 200.32 1.87x + Benchmark_ZFlat2 140.75 247.14 1.76x + Benchmark_ZFlat3 138.98 245.45 1.77x + Benchmark_ZFlat4 342.08 625.95 1.83x + Benchmark_ZFlat5 93.66 169.75 1.81x + Benchmark_ZFlat6 100.23 183.16 1.83x + Benchmark_ZFlat7 95.35 191.60 2.01x + Benchmark_ZFlat8 127.98 234.68 1.83x + Benchmark_ZFlat9 74.44 133.04 1.79x + Benchmark_ZFlat10 70.26 127.66 1.82x + Benchmark_ZFlat11 77.89 138.62 1.78x + Benchmark_ZFlat12 66.50 122.62 1.84x + Benchmark_ZFlat13 210.98 374.17 1.77x + Benchmark_ZFlat14 90.98 168.09 1.85x + Benchmark_ZFlat15 80.70 159.12 1.97x + Benchmark_ZFlat16 209.13 375.04 1.79x + Benchmark_ZFlat17 113.02 196.65 1.74x + $ + +Build tags + +If a constraint 'purego' appears in the build constraints [5] then a pure Go +version is built regardless of the $CGO_ENABLED value. + + $ touch zappy.go ; go install -tags purego github.com/cznic/zappy # for example + +Information sources + +... referenced from the above documentation. + + [1]: http://github.com/golang/snappy + [2]: http://code.google.com/p/snappy/ + [3]: http://code.google.com/p/snappy/source/browse/trunk/format_description.txt + [4]: http://golang.org/pkg/encoding/binary/ + [5]: http://golang.org/pkg/go/build/#hdr-Build_Constraints +*/ +package zappy diff --git a/vendor/github.com/golang/groupcache/lru/LICENSE b/vendor/github.com/golang/groupcache/lru/LICENSE new file mode 100644 index 00000000..37ec93a1 --- /dev/null +++ b/vendor/github.com/golang/groupcache/lru/LICENSE @@ -0,0 +1,191 @@ +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: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +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 +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/vendor/github.com/golang/groupcache/lru/lru.go b/vendor/github.com/golang/groupcache/lru/lru.go new file mode 100644 index 00000000..cdfe2991 --- /dev/null +++ b/vendor/github.com/golang/groupcache/lru/lru.go @@ -0,0 +1,121 @@ +/* +Copyright 2013 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package lru implements an LRU cache. +package lru + +import "container/list" + +// Cache is an LRU cache. It is not safe for concurrent access. +type Cache struct { + // MaxEntries is the maximum number of cache entries before + // an item is evicted. Zero means no limit. + MaxEntries int + + // OnEvicted optionally specificies a callback function to be + // executed when an entry is purged from the cache. + OnEvicted func(key Key, value interface{}) + + ll *list.List + cache map[interface{}]*list.Element +} + +// A Key may be any value that is comparable. See http://golang.org/ref/spec#Comparison_operators +type Key interface{} + +type entry struct { + key Key + value interface{} +} + +// New creates a new Cache. +// If maxEntries is zero, the cache has no limit and it's assumed +// that eviction is done by the caller. +func New(maxEntries int) *Cache { + return &Cache{ + MaxEntries: maxEntries, + ll: list.New(), + cache: make(map[interface{}]*list.Element), + } +} + +// Add adds a value to the cache. +func (c *Cache) Add(key Key, value interface{}) { + if c.cache == nil { + c.cache = make(map[interface{}]*list.Element) + c.ll = list.New() + } + if ee, ok := c.cache[key]; ok { + c.ll.MoveToFront(ee) + ee.Value.(*entry).value = value + return + } + ele := c.ll.PushFront(&entry{key, value}) + c.cache[key] = ele + if c.MaxEntries != 0 && c.ll.Len() > c.MaxEntries { + c.RemoveOldest() + } +} + +// Get looks up a key's value from the cache. +func (c *Cache) Get(key Key) (value interface{}, ok bool) { + if c.cache == nil { + return + } + if ele, hit := c.cache[key]; hit { + c.ll.MoveToFront(ele) + return ele.Value.(*entry).value, true + } + return +} + +// Remove removes the provided key from the cache. +func (c *Cache) Remove(key Key) { + if c.cache == nil { + return + } + if ele, hit := c.cache[key]; hit { + c.removeElement(ele) + } +} + +// RemoveOldest removes the oldest item from the cache. +func (c *Cache) RemoveOldest() { + if c.cache == nil { + return + } + ele := c.ll.Back() + if ele != nil { + c.removeElement(ele) + } +} + +func (c *Cache) removeElement(e *list.Element) { + c.ll.Remove(e) + kv := e.Value.(*entry) + delete(c.cache, kv.key) + if c.OnEvicted != nil { + c.OnEvicted(kv.key, kv.value) + } +} + +// Len returns the number of items in the cache. +func (c *Cache) Len() int { + if c.cache == nil { + return 0 + } + return c.ll.Len() +} diff --git a/vendor/github.com/lib/pq/LICENSE.md b/vendor/github.com/lib/pq/LICENSE.md new file mode 100644 index 00000000..5773904a --- /dev/null +++ b/vendor/github.com/lib/pq/LICENSE.md @@ -0,0 +1,8 @@ +Copyright (c) 2011-2013, 'pq' Contributors +Portions Copyright (C) 2011 Blake Mizerany + +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. diff --git a/vendor/github.com/lib/pq/buf.go b/vendor/github.com/lib/pq/buf.go new file mode 100644 index 00000000..666b0012 --- /dev/null +++ b/vendor/github.com/lib/pq/buf.go @@ -0,0 +1,91 @@ +package pq + +import ( + "bytes" + "encoding/binary" + + "github.com/lib/pq/oid" +) + +type readBuf []byte + +func (b *readBuf) int32() (n int) { + n = int(int32(binary.BigEndian.Uint32(*b))) + *b = (*b)[4:] + return +} + +func (b *readBuf) oid() (n oid.Oid) { + n = oid.Oid(binary.BigEndian.Uint32(*b)) + *b = (*b)[4:] + return +} + +// N.B: this is actually an unsigned 16-bit integer, unlike int32 +func (b *readBuf) int16() (n int) { + n = int(binary.BigEndian.Uint16(*b)) + *b = (*b)[2:] + return +} + +func (b *readBuf) string() string { + i := bytes.IndexByte(*b, 0) + if i < 0 { + errorf("invalid message format; expected string terminator") + } + s := (*b)[:i] + *b = (*b)[i+1:] + return string(s) +} + +func (b *readBuf) next(n int) (v []byte) { + v = (*b)[:n] + *b = (*b)[n:] + return +} + +func (b *readBuf) byte() byte { + return b.next(1)[0] +} + +type writeBuf struct { + buf []byte + pos int +} + +func (b *writeBuf) int32(n int) { + x := make([]byte, 4) + binary.BigEndian.PutUint32(x, uint32(n)) + b.buf = append(b.buf, x...) +} + +func (b *writeBuf) int16(n int) { + x := make([]byte, 2) + binary.BigEndian.PutUint16(x, uint16(n)) + b.buf = append(b.buf, x...) +} + +func (b *writeBuf) string(s string) { + b.buf = append(b.buf, (s + "\000")...) +} + +func (b *writeBuf) byte(c byte) { + b.buf = append(b.buf, c) +} + +func (b *writeBuf) bytes(v []byte) { + b.buf = append(b.buf, v...) +} + +func (b *writeBuf) wrap() []byte { + p := b.buf[b.pos:] + binary.BigEndian.PutUint32(p, uint32(len(p))) + return b.buf +} + +func (b *writeBuf) next(c byte) { + p := b.buf[b.pos:] + binary.BigEndian.PutUint32(p, uint32(len(p))) + b.pos = len(b.buf) + 1 + b.buf = append(b.buf, c, 0, 0, 0, 0) +} diff --git a/vendor/github.com/lib/pq/conn.go b/vendor/github.com/lib/pq/conn.go new file mode 100644 index 00000000..336c8944 --- /dev/null +++ b/vendor/github.com/lib/pq/conn.go @@ -0,0 +1,1847 @@ +package pq + +import ( + "bufio" + "crypto/md5" + "crypto/tls" + "crypto/x509" + "database/sql" + "database/sql/driver" + "encoding/binary" + "errors" + "fmt" + "io" + "io/ioutil" + "net" + "os" + "os/user" + "path" + "path/filepath" + "strconv" + "strings" + "time" + "unicode" + + "github.com/lib/pq/oid" +) + +// Common error types +var ( + ErrNotSupported = errors.New("pq: Unsupported command") + ErrInFailedTransaction = errors.New("pq: Could not complete operation in a failed transaction") + ErrSSLNotSupported = errors.New("pq: SSL is not enabled on the server") + ErrSSLKeyHasWorldPermissions = errors.New("pq: Private key file has group or world access. Permissions should be u=rw (0600) or less.") + ErrCouldNotDetectUsername = errors.New("pq: Could not detect default username. Please provide one explicitly.") +) + +type drv struct{} + +func (d *drv) Open(name string) (driver.Conn, error) { + return Open(name) +} + +func init() { + sql.Register("postgres", &drv{}) +} + +type parameterStatus struct { + // server version in the same format as server_version_num, or 0 if + // unavailable + serverVersion int + + // the current location based on the TimeZone value of the session, if + // available + currentLocation *time.Location +} + +type transactionStatus byte + +const ( + txnStatusIdle transactionStatus = 'I' + txnStatusIdleInTransaction transactionStatus = 'T' + txnStatusInFailedTransaction transactionStatus = 'E' +) + +func (s transactionStatus) String() string { + switch s { + case txnStatusIdle: + return "idle" + case txnStatusIdleInTransaction: + return "idle in transaction" + case txnStatusInFailedTransaction: + return "in a failed transaction" + default: + errorf("unknown transactionStatus %d", s) + } + + panic("not reached") +} + +type Dialer interface { + Dial(network, address string) (net.Conn, error) + DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) +} + +type defaultDialer struct{} + +func (d defaultDialer) Dial(ntw, addr string) (net.Conn, error) { + return net.Dial(ntw, addr) +} +func (d defaultDialer) DialTimeout(ntw, addr string, timeout time.Duration) (net.Conn, error) { + return net.DialTimeout(ntw, addr, timeout) +} + +type conn struct { + c net.Conn + buf *bufio.Reader + namei int + scratch [512]byte + txnStatus transactionStatus + + parameterStatus parameterStatus + + saveMessageType byte + saveMessageBuffer []byte + + // If true, this connection is bad and all public-facing functions should + // return ErrBadConn. + bad bool + + // If set, this connection should never use the binary format when + // receiving query results from prepared statements. Only provided for + // debugging. + disablePreparedBinaryResult bool + + // Whether to always send []byte parameters over as binary. Enables single + // round-trip mode for non-prepared Query calls. + binaryParameters bool +} + +// Handle driver-side settings in parsed connection string. +func (c *conn) handleDriverSettings(o values) (err error) { + boolSetting := func(key string, val *bool) error { + if value := o.Get(key); value != "" { + if value == "yes" { + *val = true + } else if value == "no" { + *val = false + } else { + return fmt.Errorf("unrecognized value %q for %s", value, key) + } + } + return nil + } + + err = boolSetting("disable_prepared_binary_result", &c.disablePreparedBinaryResult) + if err != nil { + return err + } + err = boolSetting("binary_parameters", &c.binaryParameters) + if err != nil { + return err + } + return nil +} + +func (c *conn) handlePgpass(o values) { + // if a password was supplied, do not process .pgpass + _, ok := o["password"] + if ok { + return + } + filename := os.Getenv("PGPASSFILE") + if filename == "" { + // XXX this code doesn't work on Windows where the default filename is + // XXX %APPDATA%\postgresql\pgpass.conf + user, err := user.Current() + if err != nil { + return + } + filename = filepath.Join(user.HomeDir, ".pgpass") + } + fileinfo, err := os.Stat(filename) + if err != nil { + return + } + mode := fileinfo.Mode() + if mode&(0x77) != 0 { + // XXX should warn about incorrect .pgpass permissions as psql does + return + } + file, err := os.Open(filename) + if err != nil { + return + } + defer file.Close() + scanner := bufio.NewScanner(io.Reader(file)) + hostname := o.Get("host") + ntw, _ := network(o) + port := o.Get("port") + db := o.Get("dbname") + username := o.Get("user") + // From: https://github.com/tg/pgpass/blob/master/reader.go + getFields := func(s string) []string { + fs := make([]string, 0, 5) + f := make([]rune, 0, len(s)) + + var esc bool + for _, c := range s { + switch { + case esc: + f = append(f, c) + esc = false + case c == '\\': + esc = true + case c == ':': + fs = append(fs, string(f)) + f = f[:0] + default: + f = append(f, c) + } + } + return append(fs, string(f)) + } + for scanner.Scan() { + line := scanner.Text() + if len(line) == 0 || line[0] == '#' { + continue + } + split := getFields(line) + if len(split) != 5 { + continue + } + if (split[0] == "*" || split[0] == hostname || (split[0] == "localhost" && (hostname == "" || ntw == "unix"))) && (split[1] == "*" || split[1] == port) && (split[2] == "*" || split[2] == db) && (split[3] == "*" || split[3] == username) { + o["password"] = split[4] + return + } + } +} + +func (c *conn) writeBuf(b byte) *writeBuf { + c.scratch[0] = b + return &writeBuf{ + buf: c.scratch[:5], + pos: 1, + } +} + +func Open(name string) (_ driver.Conn, err error) { + return DialOpen(defaultDialer{}, name) +} + +func DialOpen(d Dialer, name string) (_ driver.Conn, err error) { + // Handle any panics during connection initialization. Note that we + // specifically do *not* want to use errRecover(), as that would turn any + // connection errors into ErrBadConns, hiding the real error message from + // the user. + defer errRecoverNoErrBadConn(&err) + + o := make(values) + + // A number of defaults are applied here, in this order: + // + // * Very low precedence defaults applied in every situation + // * Environment variables + // * Explicitly passed connection information + o.Set("host", "localhost") + o.Set("port", "5432") + // N.B.: Extra float digits should be set to 3, but that breaks + // Postgres 8.4 and older, where the max is 2. + o.Set("extra_float_digits", "2") + for k, v := range parseEnviron(os.Environ()) { + o.Set(k, v) + } + + if strings.HasPrefix(name, "postgres://") || strings.HasPrefix(name, "postgresql://") { + name, err = ParseURL(name) + if err != nil { + return nil, err + } + } + + if err := parseOpts(name, o); err != nil { + return nil, err + } + + // Use the "fallback" application name if necessary + if fallback := o.Get("fallback_application_name"); fallback != "" { + if !o.Isset("application_name") { + o.Set("application_name", fallback) + } + } + + // We can't work with any client_encoding other than UTF-8 currently. + // However, we have historically allowed the user to set it to UTF-8 + // explicitly, and there's no reason to break such programs, so allow that. + // Note that the "options" setting could also set client_encoding, but + // parsing its value is not worth it. Instead, we always explicitly send + // client_encoding as a separate run-time parameter, which should override + // anything set in options. + if enc := o.Get("client_encoding"); enc != "" && !isUTF8(enc) { + return nil, errors.New("client_encoding must be absent or 'UTF8'") + } + o.Set("client_encoding", "UTF8") + // DateStyle needs a similar treatment. + if datestyle := o.Get("datestyle"); datestyle != "" { + if datestyle != "ISO, MDY" { + panic(fmt.Sprintf("setting datestyle must be absent or %v; got %v", + "ISO, MDY", datestyle)) + } + } else { + o.Set("datestyle", "ISO, MDY") + } + + // If a user is not provided by any other means, the last + // resort is to use the current operating system provided user + // name. + if o.Get("user") == "" { + u, err := userCurrent() + if err != nil { + return nil, err + } else { + o.Set("user", u) + } + } + + cn := &conn{} + err = cn.handleDriverSettings(o) + if err != nil { + return nil, err + } + cn.handlePgpass(o) + + cn.c, err = dial(d, o) + if err != nil { + return nil, err + } + cn.ssl(o) + cn.buf = bufio.NewReader(cn.c) + cn.startup(o) + + // reset the deadline, in case one was set (see dial) + if timeout := o.Get("connect_timeout"); timeout != "" && timeout != "0" { + err = cn.c.SetDeadline(time.Time{}) + } + return cn, err +} + +func dial(d Dialer, o values) (net.Conn, error) { + ntw, addr := network(o) + // SSL is not necessary or supported over UNIX domain sockets + if ntw == "unix" { + o["sslmode"] = "disable" + } + + // Zero or not specified means wait indefinitely. + if timeout := o.Get("connect_timeout"); timeout != "" && timeout != "0" { + seconds, err := strconv.ParseInt(timeout, 10, 0) + if err != nil { + return nil, fmt.Errorf("invalid value for parameter connect_timeout: %s", err) + } + duration := time.Duration(seconds) * time.Second + // connect_timeout should apply to the entire connection establishment + // procedure, so we both use a timeout for the TCP connection + // establishment and set a deadline for doing the initial handshake. + // The deadline is then reset after startup() is done. + deadline := time.Now().Add(duration) + conn, err := d.DialTimeout(ntw, addr, duration) + if err != nil { + return nil, err + } + err = conn.SetDeadline(deadline) + return conn, err + } + return d.Dial(ntw, addr) +} + +func network(o values) (string, string) { + host := o.Get("host") + + if strings.HasPrefix(host, "/") { + sockPath := path.Join(host, ".s.PGSQL."+o.Get("port")) + return "unix", sockPath + } + + return "tcp", net.JoinHostPort(host, o.Get("port")) +} + +type values map[string]string + +func (vs values) Set(k, v string) { + vs[k] = v +} + +func (vs values) Get(k string) (v string) { + return vs[k] +} + +func (vs values) Isset(k string) bool { + _, ok := vs[k] + return ok +} + +// scanner implements a tokenizer for libpq-style option strings. +type scanner struct { + s []rune + i int +} + +// newScanner returns a new scanner initialized with the option string s. +func newScanner(s string) *scanner { + return &scanner{[]rune(s), 0} +} + +// Next returns the next rune. +// It returns 0, false if the end of the text has been reached. +func (s *scanner) Next() (rune, bool) { + if s.i >= len(s.s) { + return 0, false + } + r := s.s[s.i] + s.i++ + return r, true +} + +// SkipSpaces returns the next non-whitespace rune. +// It returns 0, false if the end of the text has been reached. +func (s *scanner) SkipSpaces() (rune, bool) { + r, ok := s.Next() + for unicode.IsSpace(r) && ok { + r, ok = s.Next() + } + return r, ok +} + +// parseOpts parses the options from name and adds them to the values. +// +// The parsing code is based on conninfo_parse from libpq's fe-connect.c +func parseOpts(name string, o values) error { + s := newScanner(name) + + for { + var ( + keyRunes, valRunes []rune + r rune + ok bool + ) + + if r, ok = s.SkipSpaces(); !ok { + break + } + + // Scan the key + for !unicode.IsSpace(r) && r != '=' { + keyRunes = append(keyRunes, r) + if r, ok = s.Next(); !ok { + break + } + } + + // Skip any whitespace if we're not at the = yet + if r != '=' { + r, ok = s.SkipSpaces() + } + + // The current character should be = + if r != '=' || !ok { + return fmt.Errorf(`missing "=" after %q in connection info string"`, string(keyRunes)) + } + + // Skip any whitespace after the = + if r, ok = s.SkipSpaces(); !ok { + // If we reach the end here, the last value is just an empty string as per libpq. + o.Set(string(keyRunes), "") + break + } + + if r != '\'' { + for !unicode.IsSpace(r) { + if r == '\\' { + if r, ok = s.Next(); !ok { + return fmt.Errorf(`missing character after backslash`) + } + } + valRunes = append(valRunes, r) + + if r, ok = s.Next(); !ok { + break + } + } + } else { + quote: + for { + if r, ok = s.Next(); !ok { + return fmt.Errorf(`unterminated quoted string literal in connection string`) + } + switch r { + case '\'': + break quote + case '\\': + r, _ = s.Next() + fallthrough + default: + valRunes = append(valRunes, r) + } + } + } + + o.Set(string(keyRunes), string(valRunes)) + } + + return nil +} + +func (cn *conn) isInTransaction() bool { + return cn.txnStatus == txnStatusIdleInTransaction || + cn.txnStatus == txnStatusInFailedTransaction +} + +func (cn *conn) checkIsInTransaction(intxn bool) { + if cn.isInTransaction() != intxn { + cn.bad = true + errorf("unexpected transaction status %v", cn.txnStatus) + } +} + +func (cn *conn) Begin() (_ driver.Tx, err error) { + if cn.bad { + return nil, driver.ErrBadConn + } + defer cn.errRecover(&err) + + cn.checkIsInTransaction(false) + _, commandTag, err := cn.simpleExec("BEGIN") + if err != nil { + return nil, err + } + if commandTag != "BEGIN" { + cn.bad = true + return nil, fmt.Errorf("unexpected command tag %s", commandTag) + } + if cn.txnStatus != txnStatusIdleInTransaction { + cn.bad = true + return nil, fmt.Errorf("unexpected transaction status %v", cn.txnStatus) + } + return cn, nil +} + +func (cn *conn) Commit() (err error) { + if cn.bad { + return driver.ErrBadConn + } + defer cn.errRecover(&err) + + cn.checkIsInTransaction(true) + // We don't want the client to think that everything is okay if it tries + // to commit a failed transaction. However, no matter what we return, + // database/sql will release this connection back into the free connection + // pool so we have to abort the current transaction here. Note that you + // would get the same behaviour if you issued a COMMIT in a failed + // transaction, so it's also the least surprising thing to do here. + if cn.txnStatus == txnStatusInFailedTransaction { + if err := cn.Rollback(); err != nil { + return err + } + return ErrInFailedTransaction + } + + _, commandTag, err := cn.simpleExec("COMMIT") + if err != nil { + if cn.isInTransaction() { + cn.bad = true + } + return err + } + if commandTag != "COMMIT" { + cn.bad = true + return fmt.Errorf("unexpected command tag %s", commandTag) + } + cn.checkIsInTransaction(false) + return nil +} + +func (cn *conn) Rollback() (err error) { + if cn.bad { + return driver.ErrBadConn + } + defer cn.errRecover(&err) + + cn.checkIsInTransaction(true) + _, commandTag, err := cn.simpleExec("ROLLBACK") + if err != nil { + if cn.isInTransaction() { + cn.bad = true + } + return err + } + if commandTag != "ROLLBACK" { + return fmt.Errorf("unexpected command tag %s", commandTag) + } + cn.checkIsInTransaction(false) + return nil +} + +func (cn *conn) gname() string { + cn.namei++ + return strconv.FormatInt(int64(cn.namei), 10) +} + +func (cn *conn) simpleExec(q string) (res driver.Result, commandTag string, err error) { + b := cn.writeBuf('Q') + b.string(q) + cn.send(b) + + for { + t, r := cn.recv1() + switch t { + case 'C': + res, commandTag = cn.parseComplete(r.string()) + case 'Z': + cn.processReadyForQuery(r) + // done + return + case 'E': + err = parseError(r) + case 'T', 'D', 'I': + // ignore any results + default: + cn.bad = true + errorf("unknown response for simple query: %q", t) + } + } +} + +func (cn *conn) simpleQuery(q string) (res *rows, err error) { + defer cn.errRecover(&err) + + b := cn.writeBuf('Q') + b.string(q) + cn.send(b) + + for { + t, r := cn.recv1() + switch t { + case 'C', 'I': + // We allow queries which don't return any results through Query as + // well as Exec. We still have to give database/sql a rows object + // the user can close, though, to avoid connections from being + // leaked. A "rows" with done=true works fine for that purpose. + if err != nil { + cn.bad = true + errorf("unexpected message %q in simple query execution", t) + } + if res == nil { + res = &rows{ + cn: cn, + } + } + res.done = true + case 'Z': + cn.processReadyForQuery(r) + // done + return + case 'E': + res = nil + err = parseError(r) + case 'D': + if res == nil { + cn.bad = true + errorf("unexpected DataRow in simple query execution") + } + // the query didn't fail; kick off to Next + cn.saveMessage(t, r) + return + case 'T': + // res might be non-nil here if we received a previous + // CommandComplete, but that's fine; just overwrite it + res = &rows{cn: cn} + res.colNames, res.colFmts, res.colTyps = parsePortalRowDescribe(r) + + // To work around a bug in QueryRow in Go 1.2 and earlier, wait + // until the first DataRow has been received. + default: + cn.bad = true + errorf("unknown response for simple query: %q", t) + } + } +} + +// Decides which column formats to use for a prepared statement. The input is +// an array of type oids, one element per result column. +func decideColumnFormats(colTyps []oid.Oid, forceText bool) (colFmts []format, colFmtData []byte) { + if len(colTyps) == 0 { + return nil, colFmtDataAllText + } + + colFmts = make([]format, len(colTyps)) + if forceText { + return colFmts, colFmtDataAllText + } + + allBinary := true + allText := true + for i, o := range colTyps { + switch o { + // This is the list of types to use binary mode for when receiving them + // through a prepared statement. If a type appears in this list, it + // must also be implemented in binaryDecode in encode.go. + case oid.T_bytea: + fallthrough + case oid.T_int8: + fallthrough + case oid.T_int4: + fallthrough + case oid.T_int2: + colFmts[i] = formatBinary + allText = false + + default: + allBinary = false + } + } + + if allBinary { + return colFmts, colFmtDataAllBinary + } else if allText { + return colFmts, colFmtDataAllText + } else { + colFmtData = make([]byte, 2+len(colFmts)*2) + binary.BigEndian.PutUint16(colFmtData, uint16(len(colFmts))) + for i, v := range colFmts { + binary.BigEndian.PutUint16(colFmtData[2+i*2:], uint16(v)) + } + return colFmts, colFmtData + } +} + +func (cn *conn) prepareTo(q, stmtName string) *stmt { + st := &stmt{cn: cn, name: stmtName} + + b := cn.writeBuf('P') + b.string(st.name) + b.string(q) + b.int16(0) + + b.next('D') + b.byte('S') + b.string(st.name) + + b.next('S') + cn.send(b) + + cn.readParseResponse() + st.paramTyps, st.colNames, st.colTyps = cn.readStatementDescribeResponse() + st.colFmts, st.colFmtData = decideColumnFormats(st.colTyps, cn.disablePreparedBinaryResult) + cn.readReadyForQuery() + return st +} + +func (cn *conn) Prepare(q string) (_ driver.Stmt, err error) { + if cn.bad { + return nil, driver.ErrBadConn + } + defer cn.errRecover(&err) + + if len(q) >= 4 && strings.EqualFold(q[:4], "COPY") { + return cn.prepareCopyIn(q) + } + return cn.prepareTo(q, cn.gname()), nil +} + +func (cn *conn) Close() (err error) { + if cn.bad { + return driver.ErrBadConn + } + defer cn.errRecover(&err) + + // Don't go through send(); ListenerConn relies on us not scribbling on the + // scratch buffer of this connection. + err = cn.sendSimpleMessage('X') + if err != nil { + return err + } + + return cn.c.Close() +} + +// Implement the "Queryer" interface +func (cn *conn) Query(query string, args []driver.Value) (_ driver.Rows, err error) { + if cn.bad { + return nil, driver.ErrBadConn + } + defer cn.errRecover(&err) + + // Check to see if we can use the "simpleQuery" interface, which is + // *much* faster than going through prepare/exec + if len(args) == 0 { + return cn.simpleQuery(query) + } + + if cn.binaryParameters { + cn.sendBinaryModeQuery(query, args) + + cn.readParseResponse() + cn.readBindResponse() + rows := &rows{cn: cn} + rows.colNames, rows.colFmts, rows.colTyps = cn.readPortalDescribeResponse() + cn.postExecuteWorkaround() + return rows, nil + } else { + st := cn.prepareTo(query, "") + st.exec(args) + return &rows{ + cn: cn, + colNames: st.colNames, + colTyps: st.colTyps, + colFmts: st.colFmts, + }, nil + } +} + +// Implement the optional "Execer" interface for one-shot queries +func (cn *conn) Exec(query string, args []driver.Value) (res driver.Result, err error) { + if cn.bad { + return nil, driver.ErrBadConn + } + defer cn.errRecover(&err) + + // Check to see if we can use the "simpleExec" interface, which is + // *much* faster than going through prepare/exec + if len(args) == 0 { + // ignore commandTag, our caller doesn't care + r, _, err := cn.simpleExec(query) + return r, err + } + + if cn.binaryParameters { + cn.sendBinaryModeQuery(query, args) + + cn.readParseResponse() + cn.readBindResponse() + cn.readPortalDescribeResponse() + cn.postExecuteWorkaround() + res, _, err = cn.readExecuteResponse("Execute") + return res, err + } else { + // Use the unnamed statement to defer planning until bind + // time, or else value-based selectivity estimates cannot be + // used. + st := cn.prepareTo(query, "") + r, err := st.Exec(args) + if err != nil { + panic(err) + } + return r, err + } +} + +func (cn *conn) send(m *writeBuf) { + _, err := cn.c.Write(m.wrap()) + if err != nil { + panic(err) + } +} + +func (cn *conn) sendStartupPacket(m *writeBuf) { + // sanity check + if m.buf[0] != 0 { + panic("oops") + } + + _, err := cn.c.Write((m.wrap())[1:]) + if err != nil { + panic(err) + } +} + +// Send a message of type typ to the server on the other end of cn. The +// message should have no payload. This method does not use the scratch +// buffer. +func (cn *conn) sendSimpleMessage(typ byte) (err error) { + _, err = cn.c.Write([]byte{typ, '\x00', '\x00', '\x00', '\x04'}) + return err +} + +// saveMessage memorizes a message and its buffer in the conn struct. +// recvMessage will then return these values on the next call to it. This +// method is useful in cases where you have to see what the next message is +// going to be (e.g. to see whether it's an error or not) but you can't handle +// the message yourself. +func (cn *conn) saveMessage(typ byte, buf *readBuf) { + if cn.saveMessageType != 0 { + cn.bad = true + errorf("unexpected saveMessageType %d", cn.saveMessageType) + } + cn.saveMessageType = typ + cn.saveMessageBuffer = *buf +} + +// recvMessage receives any message from the backend, or returns an error if +// a problem occurred while reading the message. +func (cn *conn) recvMessage(r *readBuf) (byte, error) { + // workaround for a QueryRow bug, see exec + if cn.saveMessageType != 0 { + t := cn.saveMessageType + *r = cn.saveMessageBuffer + cn.saveMessageType = 0 + cn.saveMessageBuffer = nil + return t, nil + } + + x := cn.scratch[:5] + _, err := io.ReadFull(cn.buf, x) + if err != nil { + return 0, err + } + + // read the type and length of the message that follows + t := x[0] + n := int(binary.BigEndian.Uint32(x[1:])) - 4 + var y []byte + if n <= len(cn.scratch) { + y = cn.scratch[:n] + } else { + y = make([]byte, n) + } + _, err = io.ReadFull(cn.buf, y) + if err != nil { + return 0, err + } + *r = y + return t, nil +} + +// recv receives a message from the backend, but if an error happened while +// reading the message or the received message was an ErrorResponse, it panics. +// NoticeResponses are ignored. This function should generally be used only +// during the startup sequence. +func (cn *conn) recv() (t byte, r *readBuf) { + for { + var err error + r = &readBuf{} + t, err = cn.recvMessage(r) + if err != nil { + panic(err) + } + + switch t { + case 'E': + panic(parseError(r)) + case 'N': + // ignore + default: + return + } + } +} + +// recv1Buf is exactly equivalent to recv1, except it uses a buffer supplied by +// the caller to avoid an allocation. +func (cn *conn) recv1Buf(r *readBuf) byte { + for { + t, err := cn.recvMessage(r) + if err != nil { + panic(err) + } + + switch t { + case 'A', 'N': + // ignore + case 'S': + cn.processParameterStatus(r) + default: + return t + } + } +} + +// recv1 receives a message from the backend, panicking if an error occurs +// while attempting to read it. All asynchronous messages are ignored, with +// the exception of ErrorResponse. +func (cn *conn) recv1() (t byte, r *readBuf) { + r = &readBuf{} + t = cn.recv1Buf(r) + return t, r +} + +func (cn *conn) ssl(o values) { + verifyCaOnly := false + tlsConf := tls.Config{} + switch mode := o.Get("sslmode"); mode { + case "require", "": + tlsConf.InsecureSkipVerify = true + case "verify-ca": + // We must skip TLS's own verification since it requires full + // verification since Go 1.3. + tlsConf.InsecureSkipVerify = true + verifyCaOnly = true + case "verify-full": + tlsConf.ServerName = o.Get("host") + case "disable": + return + default: + errorf(`unsupported sslmode %q; only "require" (default), "verify-full", "verify-ca", and "disable" supported`, mode) + } + + cn.setupSSLClientCertificates(&tlsConf, o) + cn.setupSSLCA(&tlsConf, o) + + w := cn.writeBuf(0) + w.int32(80877103) + cn.sendStartupPacket(w) + + b := cn.scratch[:1] + _, err := io.ReadFull(cn.c, b) + if err != nil { + panic(err) + } + + if b[0] != 'S' { + panic(ErrSSLNotSupported) + } + + client := tls.Client(cn.c, &tlsConf) + if verifyCaOnly { + cn.verifyCA(client, &tlsConf) + } + cn.c = client +} + +// verifyCA carries out a TLS handshake to the server and verifies the +// presented certificate against the effective CA, i.e. the one specified in +// sslrootcert or the system CA if sslrootcert was not specified. +func (cn *conn) verifyCA(client *tls.Conn, tlsConf *tls.Config) { + err := client.Handshake() + if err != nil { + panic(err) + } + certs := client.ConnectionState().PeerCertificates + opts := x509.VerifyOptions{ + DNSName: client.ConnectionState().ServerName, + Intermediates: x509.NewCertPool(), + Roots: tlsConf.RootCAs, + } + for i, cert := range certs { + if i == 0 { + continue + } + opts.Intermediates.AddCert(cert) + } + _, err = certs[0].Verify(opts) + if err != nil { + panic(err) + } +} + +// This function sets up SSL client certificates based on either the "sslkey" +// and "sslcert" settings (possibly set via the environment variables PGSSLKEY +// and PGSSLCERT, respectively), or if they aren't set, from the .postgresql +// directory in the user's home directory. If the file paths are set +// explicitly, the files must exist. The key file must also not be +// world-readable, or this function will panic with +// ErrSSLKeyHasWorldPermissions. +func (cn *conn) setupSSLClientCertificates(tlsConf *tls.Config, o values) { + var missingOk bool + + sslkey := o.Get("sslkey") + sslcert := o.Get("sslcert") + if sslkey != "" && sslcert != "" { + // If the user has set an sslkey and sslcert, they *must* exist. + missingOk = false + } else { + // Automatically load certificates from ~/.postgresql. + user, err := user.Current() + if err != nil { + // user.Current() might fail when cross-compiling. We have to + // ignore the error and continue without client certificates, since + // we wouldn't know where to load them from. + return + } + + sslkey = filepath.Join(user.HomeDir, ".postgresql", "postgresql.key") + sslcert = filepath.Join(user.HomeDir, ".postgresql", "postgresql.crt") + missingOk = true + } + + // Check that both files exist, and report the error or stop, depending on + // which behaviour we want. Note that we don't do any more extensive + // checks than this (such as checking that the paths aren't directories); + // LoadX509KeyPair() will take care of the rest. + keyfinfo, err := os.Stat(sslkey) + if err != nil && missingOk { + return + } else if err != nil { + panic(err) + } + _, err = os.Stat(sslcert) + if err != nil && missingOk { + return + } else if err != nil { + panic(err) + } + + // If we got this far, the key file must also have the correct permissions + kmode := keyfinfo.Mode() + if kmode != kmode&0600 { + panic(ErrSSLKeyHasWorldPermissions) + } + + cert, err := tls.LoadX509KeyPair(sslcert, sslkey) + if err != nil { + panic(err) + } + tlsConf.Certificates = []tls.Certificate{cert} +} + +// Sets up RootCAs in the TLS configuration if sslrootcert is set. +func (cn *conn) setupSSLCA(tlsConf *tls.Config, o values) { + if sslrootcert := o.Get("sslrootcert"); sslrootcert != "" { + tlsConf.RootCAs = x509.NewCertPool() + + cert, err := ioutil.ReadFile(sslrootcert) + if err != nil { + panic(err) + } + + ok := tlsConf.RootCAs.AppendCertsFromPEM(cert) + if !ok { + errorf("couldn't parse pem in sslrootcert") + } + } +} + +// isDriverSetting returns true iff a setting is purely for configuring the +// driver's options and should not be sent to the server in the connection +// startup packet. +func isDriverSetting(key string) bool { + switch key { + case "host", "port": + return true + case "password": + return true + case "sslmode", "sslcert", "sslkey", "sslrootcert": + return true + case "fallback_application_name": + return true + case "connect_timeout": + return true + case "disable_prepared_binary_result": + return true + case "binary_parameters": + return true + + default: + return false + } +} + +func (cn *conn) startup(o values) { + w := cn.writeBuf(0) + w.int32(196608) + // Send the backend the name of the database we want to connect to, and the + // user we want to connect as. Additionally, we send over any run-time + // parameters potentially included in the connection string. If the server + // doesn't recognize any of them, it will reply with an error. + for k, v := range o { + if isDriverSetting(k) { + // skip options which can't be run-time parameters + continue + } + // The protocol requires us to supply the database name as "database" + // instead of "dbname". + if k == "dbname" { + k = "database" + } + w.string(k) + w.string(v) + } + w.string("") + cn.sendStartupPacket(w) + + for { + t, r := cn.recv() + switch t { + case 'K': + case 'S': + cn.processParameterStatus(r) + case 'R': + cn.auth(r, o) + case 'Z': + cn.processReadyForQuery(r) + return + default: + errorf("unknown response for startup: %q", t) + } + } +} + +func (cn *conn) auth(r *readBuf, o values) { + switch code := r.int32(); code { + case 0: + // OK + case 3: + w := cn.writeBuf('p') + w.string(o.Get("password")) + cn.send(w) + + t, r := cn.recv() + if t != 'R' { + errorf("unexpected password response: %q", t) + } + + if r.int32() != 0 { + errorf("unexpected authentication response: %q", t) + } + case 5: + s := string(r.next(4)) + w := cn.writeBuf('p') + w.string("md5" + md5s(md5s(o.Get("password")+o.Get("user"))+s)) + cn.send(w) + + t, r := cn.recv() + if t != 'R' { + errorf("unexpected password response: %q", t) + } + + if r.int32() != 0 { + errorf("unexpected authentication response: %q", t) + } + default: + errorf("unknown authentication response: %d", code) + } +} + +type format int + +const formatText format = 0 +const formatBinary format = 1 + +// One result-column format code with the value 1 (i.e. all binary). +var colFmtDataAllBinary []byte = []byte{0, 1, 0, 1} + +// No result-column format codes (i.e. all text). +var colFmtDataAllText []byte = []byte{0, 0} + +type stmt struct { + cn *conn + name string + colNames []string + colFmts []format + colFmtData []byte + colTyps []oid.Oid + paramTyps []oid.Oid + closed bool +} + +func (st *stmt) Close() (err error) { + if st.closed { + return nil + } + if st.cn.bad { + return driver.ErrBadConn + } + defer st.cn.errRecover(&err) + + w := st.cn.writeBuf('C') + w.byte('S') + w.string(st.name) + st.cn.send(w) + + st.cn.send(st.cn.writeBuf('S')) + + t, _ := st.cn.recv1() + if t != '3' { + st.cn.bad = true + errorf("unexpected close response: %q", t) + } + st.closed = true + + t, r := st.cn.recv1() + if t != 'Z' { + st.cn.bad = true + errorf("expected ready for query, but got: %q", t) + } + st.cn.processReadyForQuery(r) + + return nil +} + +func (st *stmt) Query(v []driver.Value) (r driver.Rows, err error) { + if st.cn.bad { + return nil, driver.ErrBadConn + } + defer st.cn.errRecover(&err) + + st.exec(v) + return &rows{ + cn: st.cn, + colNames: st.colNames, + colTyps: st.colTyps, + colFmts: st.colFmts, + }, nil +} + +func (st *stmt) Exec(v []driver.Value) (res driver.Result, err error) { + if st.cn.bad { + return nil, driver.ErrBadConn + } + defer st.cn.errRecover(&err) + + st.exec(v) + res, _, err = st.cn.readExecuteResponse("simple query") + return res, err +} + +func (st *stmt) exec(v []driver.Value) { + if len(v) >= 65536 { + errorf("got %d parameters but PostgreSQL only supports 65535 parameters", len(v)) + } + if len(v) != len(st.paramTyps) { + errorf("got %d parameters but the statement requires %d", len(v), len(st.paramTyps)) + } + + cn := st.cn + w := cn.writeBuf('B') + w.byte(0) // unnamed portal + w.string(st.name) + + if cn.binaryParameters { + cn.sendBinaryParameters(w, v) + } else { + w.int16(0) + w.int16(len(v)) + for i, x := range v { + if x == nil { + w.int32(-1) + } else { + b := encode(&cn.parameterStatus, x, st.paramTyps[i]) + w.int32(len(b)) + w.bytes(b) + } + } + } + w.bytes(st.colFmtData) + + w.next('E') + w.byte(0) + w.int32(0) + + w.next('S') + cn.send(w) + + cn.readBindResponse() + cn.postExecuteWorkaround() + +} + +func (st *stmt) NumInput() int { + return len(st.paramTyps) +} + +// parseComplete parses the "command tag" from a CommandComplete message, and +// returns the number of rows affected (if applicable) and a string +// identifying only the command that was executed, e.g. "ALTER TABLE". If the +// command tag could not be parsed, parseComplete panics. +func (cn *conn) parseComplete(commandTag string) (driver.Result, string) { + commandsWithAffectedRows := []string{ + "SELECT ", + // INSERT is handled below + "UPDATE ", + "DELETE ", + "FETCH ", + "MOVE ", + "COPY ", + } + + var affectedRows *string + for _, tag := range commandsWithAffectedRows { + if strings.HasPrefix(commandTag, tag) { + t := commandTag[len(tag):] + affectedRows = &t + commandTag = tag[:len(tag)-1] + break + } + } + // INSERT also includes the oid of the inserted row in its command tag. + // Oids in user tables are deprecated, and the oid is only returned when + // exactly one row is inserted, so it's unlikely to be of value to any + // real-world application and we can ignore it. + if affectedRows == nil && strings.HasPrefix(commandTag, "INSERT ") { + parts := strings.Split(commandTag, " ") + if len(parts) != 3 { + cn.bad = true + errorf("unexpected INSERT command tag %s", commandTag) + } + affectedRows = &parts[len(parts)-1] + commandTag = "INSERT" + } + // There should be no affected rows attached to the tag, just return it + if affectedRows == nil { + return driver.RowsAffected(0), commandTag + } + n, err := strconv.ParseInt(*affectedRows, 10, 64) + if err != nil { + cn.bad = true + errorf("could not parse commandTag: %s", err) + } + return driver.RowsAffected(n), commandTag +} + +type rows struct { + cn *conn + colNames []string + colTyps []oid.Oid + colFmts []format + done bool + rb readBuf +} + +func (rs *rows) Close() error { + // no need to look at cn.bad as Next() will + for { + err := rs.Next(nil) + switch err { + case nil: + case io.EOF: + return nil + default: + return err + } + } +} + +func (rs *rows) Columns() []string { + return rs.colNames +} + +func (rs *rows) Next(dest []driver.Value) (err error) { + if rs.done { + return io.EOF + } + + conn := rs.cn + if conn.bad { + return driver.ErrBadConn + } + defer conn.errRecover(&err) + + for { + t := conn.recv1Buf(&rs.rb) + switch t { + case 'E': + err = parseError(&rs.rb) + case 'C', 'I': + continue + case 'Z': + conn.processReadyForQuery(&rs.rb) + rs.done = true + if err != nil { + return err + } + return io.EOF + case 'D': + n := rs.rb.int16() + if err != nil { + conn.bad = true + errorf("unexpected DataRow after error %s", err) + } + if n < len(dest) { + dest = dest[:n] + } + for i := range dest { + l := rs.rb.int32() + if l == -1 { + dest[i] = nil + continue + } + dest[i] = decode(&conn.parameterStatus, rs.rb.next(l), rs.colTyps[i], rs.colFmts[i]) + } + return + default: + errorf("unexpected message after execute: %q", t) + } + } +} + +// QuoteIdentifier quotes an "identifier" (e.g. a table or a column name) to be +// used as part of an SQL statement. For example: +// +// tblname := "my_table" +// data := "my_data" +// err = db.Exec(fmt.Sprintf("INSERT INTO %s VALUES ($1)", pq.QuoteIdentifier(tblname)), data) +// +// Any double quotes in name will be escaped. The quoted identifier will be +// case sensitive when used in a query. If the input string contains a zero +// byte, the result will be truncated immediately before it. +func QuoteIdentifier(name string) string { + end := strings.IndexRune(name, 0) + if end > -1 { + name = name[:end] + } + return `"` + strings.Replace(name, `"`, `""`, -1) + `"` +} + +func md5s(s string) string { + h := md5.New() + h.Write([]byte(s)) + return fmt.Sprintf("%x", h.Sum(nil)) +} + +func (cn *conn) sendBinaryParameters(b *writeBuf, args []driver.Value) { + // Do one pass over the parameters to see if we're going to send any of + // them over in binary. If we are, create a paramFormats array at the + // same time. + var paramFormats []int + for i, x := range args { + _, ok := x.([]byte) + if ok { + if paramFormats == nil { + paramFormats = make([]int, len(args)) + } + paramFormats[i] = 1 + } + } + if paramFormats == nil { + b.int16(0) + } else { + b.int16(len(paramFormats)) + for _, x := range paramFormats { + b.int16(x) + } + } + + b.int16(len(args)) + for _, x := range args { + if x == nil { + b.int32(-1) + } else { + datum := binaryEncode(&cn.parameterStatus, x) + b.int32(len(datum)) + b.bytes(datum) + } + } +} + +func (cn *conn) sendBinaryModeQuery(query string, args []driver.Value) { + if len(args) >= 65536 { + errorf("got %d parameters but PostgreSQL only supports 65535 parameters", len(args)) + } + + b := cn.writeBuf('P') + b.byte(0) // unnamed statement + b.string(query) + b.int16(0) + + b.next('B') + b.int16(0) // unnamed portal and statement + cn.sendBinaryParameters(b, args) + b.bytes(colFmtDataAllText) + + b.next('D') + b.byte('P') + b.byte(0) // unnamed portal + + b.next('E') + b.byte(0) + b.int32(0) + + b.next('S') + cn.send(b) +} + +func (c *conn) processParameterStatus(r *readBuf) { + var err error + + param := r.string() + switch param { + case "server_version": + var major1 int + var major2 int + var minor int + _, err = fmt.Sscanf(r.string(), "%d.%d.%d", &major1, &major2, &minor) + if err == nil { + c.parameterStatus.serverVersion = major1*10000 + major2*100 + minor + } + + case "TimeZone": + c.parameterStatus.currentLocation, err = time.LoadLocation(r.string()) + if err != nil { + c.parameterStatus.currentLocation = nil + } + + default: + // ignore + } +} + +func (c *conn) processReadyForQuery(r *readBuf) { + c.txnStatus = transactionStatus(r.byte()) +} + +func (cn *conn) readReadyForQuery() { + t, r := cn.recv1() + switch t { + case 'Z': + cn.processReadyForQuery(r) + return + default: + cn.bad = true + errorf("unexpected message %q; expected ReadyForQuery", t) + } +} + +func (cn *conn) readParseResponse() { + t, r := cn.recv1() + switch t { + case '1': + return + case 'E': + err := parseError(r) + cn.readReadyForQuery() + panic(err) + default: + cn.bad = true + errorf("unexpected Parse response %q", t) + } +} + +func (cn *conn) readStatementDescribeResponse() (paramTyps []oid.Oid, colNames []string, colTyps []oid.Oid) { + for { + t, r := cn.recv1() + switch t { + case 't': + nparams := r.int16() + paramTyps = make([]oid.Oid, nparams) + for i := range paramTyps { + paramTyps[i] = r.oid() + } + case 'n': + return paramTyps, nil, nil + case 'T': + colNames, colTyps = parseStatementRowDescribe(r) + return paramTyps, colNames, colTyps + case 'E': + err := parseError(r) + cn.readReadyForQuery() + panic(err) + default: + cn.bad = true + errorf("unexpected Describe statement response %q", t) + } + } +} + +func (cn *conn) readPortalDescribeResponse() (colNames []string, colFmts []format, colTyps []oid.Oid) { + t, r := cn.recv1() + switch t { + case 'T': + return parsePortalRowDescribe(r) + case 'n': + return nil, nil, nil + case 'E': + err := parseError(r) + cn.readReadyForQuery() + panic(err) + default: + cn.bad = true + errorf("unexpected Describe response %q", t) + } + panic("not reached") +} + +func (cn *conn) readBindResponse() { + t, r := cn.recv1() + switch t { + case '2': + return + case 'E': + err := parseError(r) + cn.readReadyForQuery() + panic(err) + default: + cn.bad = true + errorf("unexpected Bind response %q", t) + } +} + +func (cn *conn) postExecuteWorkaround() { + // Work around a bug in sql.DB.QueryRow: in Go 1.2 and earlier it ignores + // any errors from rows.Next, which masks errors that happened during the + // execution of the query. To avoid the problem in common cases, we wait + // here for one more message from the database. If it's not an error the + // query will likely succeed (or perhaps has already, if it's a + // CommandComplete), so we push the message into the conn struct; recv1 + // will return it as the next message for rows.Next or rows.Close. + // However, if it's an error, we wait until ReadyForQuery and then return + // the error to our caller. + for { + t, r := cn.recv1() + switch t { + case 'E': + err := parseError(r) + cn.readReadyForQuery() + panic(err) + case 'C', 'D', 'I': + // the query didn't fail, but we can't process this message + cn.saveMessage(t, r) + return + default: + cn.bad = true + errorf("unexpected message during extended query execution: %q", t) + } + } +} + +// Only for Exec(), since we ignore the returned data +func (cn *conn) readExecuteResponse(protocolState string) (res driver.Result, commandTag string, err error) { + for { + t, r := cn.recv1() + switch t { + case 'C': + if err != nil { + cn.bad = true + errorf("unexpected CommandComplete after error %s", err) + } + res, commandTag = cn.parseComplete(r.string()) + case 'Z': + cn.processReadyForQuery(r) + return res, commandTag, err + case 'E': + err = parseError(r) + case 'T', 'D', 'I': + if err != nil { + cn.bad = true + errorf("unexpected %q after error %s", t, err) + } + // ignore any results + default: + cn.bad = true + errorf("unknown %s response: %q", protocolState, t) + } + } +} + +func parseStatementRowDescribe(r *readBuf) (colNames []string, colTyps []oid.Oid) { + n := r.int16() + colNames = make([]string, n) + colTyps = make([]oid.Oid, n) + for i := range colNames { + colNames[i] = r.string() + r.next(6) + colTyps[i] = r.oid() + r.next(6) + // format code not known when describing a statement; always 0 + r.next(2) + } + return +} + +func parsePortalRowDescribe(r *readBuf) (colNames []string, colFmts []format, colTyps []oid.Oid) { + n := r.int16() + colNames = make([]string, n) + colFmts = make([]format, n) + colTyps = make([]oid.Oid, n) + for i := range colNames { + colNames[i] = r.string() + r.next(6) + colTyps[i] = r.oid() + r.next(6) + colFmts[i] = format(r.int16()) + } + return +} + +// parseEnviron tries to mimic some of libpq's environment handling +// +// To ease testing, it does not directly reference os.Environ, but is +// designed to accept its output. +// +// Environment-set connection information is intended to have a higher +// precedence than a library default but lower than any explicitly +// passed information (such as in the URL or connection string). +func parseEnviron(env []string) (out map[string]string) { + out = make(map[string]string) + + for _, v := range env { + parts := strings.SplitN(v, "=", 2) + + accrue := func(keyname string) { + out[keyname] = parts[1] + } + unsupported := func() { + panic(fmt.Sprintf("setting %v not supported", parts[0])) + } + + // The order of these is the same as is seen in the + // PostgreSQL 9.1 manual. Unsupported but well-defined + // keys cause a panic; these should be unset prior to + // execution. Options which pq expects to be set to a + // certain value are allowed, but must be set to that + // value if present (they can, of course, be absent). + switch parts[0] { + case "PGHOST": + accrue("host") + case "PGHOSTADDR": + unsupported() + case "PGPORT": + accrue("port") + case "PGDATABASE": + accrue("dbname") + case "PGUSER": + accrue("user") + case "PGPASSWORD": + accrue("password") + case "PGSERVICE", "PGSERVICEFILE", "PGREALM": + unsupported() + case "PGOPTIONS": + accrue("options") + case "PGAPPNAME": + accrue("application_name") + case "PGSSLMODE": + accrue("sslmode") + case "PGSSLCERT": + accrue("sslcert") + case "PGSSLKEY": + accrue("sslkey") + case "PGSSLROOTCERT": + accrue("sslrootcert") + case "PGREQUIRESSL", "PGSSLCRL": + unsupported() + case "PGREQUIREPEER": + unsupported() + case "PGKRBSRVNAME", "PGGSSLIB": + unsupported() + case "PGCONNECT_TIMEOUT": + accrue("connect_timeout") + case "PGCLIENTENCODING": + accrue("client_encoding") + case "PGDATESTYLE": + accrue("datestyle") + case "PGTZ": + accrue("timezone") + case "PGGEQO": + accrue("geqo") + case "PGSYSCONFDIR", "PGLOCALEDIR": + unsupported() + } + } + + return out +} + +// isUTF8 returns whether name is a fuzzy variation of the string "UTF-8". +func isUTF8(name string) bool { + // Recognize all sorts of silly things as "UTF-8", like Postgres does + s := strings.Map(alnumLowerASCII, name) + return s == "utf8" || s == "unicode" +} + +func alnumLowerASCII(ch rune) rune { + if 'A' <= ch && ch <= 'Z' { + return ch + ('a' - 'A') + } + if 'a' <= ch && ch <= 'z' || '0' <= ch && ch <= '9' { + return ch + } + return -1 // discard +} diff --git a/vendor/github.com/lib/pq/copy.go b/vendor/github.com/lib/pq/copy.go new file mode 100644 index 00000000..101f1113 --- /dev/null +++ b/vendor/github.com/lib/pq/copy.go @@ -0,0 +1,267 @@ +package pq + +import ( + "database/sql/driver" + "encoding/binary" + "errors" + "fmt" + "sync" +) + +var ( + errCopyInClosed = errors.New("pq: copyin statement has already been closed") + errBinaryCopyNotSupported = errors.New("pq: only text format supported for COPY") + errCopyToNotSupported = errors.New("pq: COPY TO is not supported") + errCopyNotSupportedOutsideTxn = errors.New("pq: COPY is only allowed inside a transaction") +) + +// CopyIn creates a COPY FROM statement which can be prepared with +// Tx.Prepare(). The target table should be visible in search_path. +func CopyIn(table string, columns ...string) string { + stmt := "COPY " + QuoteIdentifier(table) + " (" + for i, col := range columns { + if i != 0 { + stmt += ", " + } + stmt += QuoteIdentifier(col) + } + stmt += ") FROM STDIN" + return stmt +} + +// CopyInSchema creates a COPY FROM statement which can be prepared with +// Tx.Prepare(). +func CopyInSchema(schema, table string, columns ...string) string { + stmt := "COPY " + QuoteIdentifier(schema) + "." + QuoteIdentifier(table) + " (" + for i, col := range columns { + if i != 0 { + stmt += ", " + } + stmt += QuoteIdentifier(col) + } + stmt += ") FROM STDIN" + return stmt +} + +type copyin struct { + cn *conn + buffer []byte + rowData chan []byte + done chan bool + + closed bool + + sync.Mutex // guards err + err error +} + +const ciBufferSize = 64 * 1024 + +// flush buffer before the buffer is filled up and needs reallocation +const ciBufferFlushSize = 63 * 1024 + +func (cn *conn) prepareCopyIn(q string) (_ driver.Stmt, err error) { + if !cn.isInTransaction() { + return nil, errCopyNotSupportedOutsideTxn + } + + ci := ©in{ + cn: cn, + buffer: make([]byte, 0, ciBufferSize), + rowData: make(chan []byte), + done: make(chan bool, 1), + } + // add CopyData identifier + 4 bytes for message length + ci.buffer = append(ci.buffer, 'd', 0, 0, 0, 0) + + b := cn.writeBuf('Q') + b.string(q) + cn.send(b) + +awaitCopyInResponse: + for { + t, r := cn.recv1() + switch t { + case 'G': + if r.byte() != 0 { + err = errBinaryCopyNotSupported + break awaitCopyInResponse + } + go ci.resploop() + return ci, nil + case 'H': + err = errCopyToNotSupported + break awaitCopyInResponse + case 'E': + err = parseError(r) + case 'Z': + if err == nil { + cn.bad = true + errorf("unexpected ReadyForQuery in response to COPY") + } + cn.processReadyForQuery(r) + return nil, err + default: + cn.bad = true + errorf("unknown response for copy query: %q", t) + } + } + + // something went wrong, abort COPY before we return + b = cn.writeBuf('f') + b.string(err.Error()) + cn.send(b) + + for { + t, r := cn.recv1() + switch t { + case 'c', 'C', 'E': + case 'Z': + // correctly aborted, we're done + cn.processReadyForQuery(r) + return nil, err + default: + cn.bad = true + errorf("unknown response for CopyFail: %q", t) + } + } +} + +func (ci *copyin) flush(buf []byte) { + // set message length (without message identifier) + binary.BigEndian.PutUint32(buf[1:], uint32(len(buf)-1)) + + _, err := ci.cn.c.Write(buf) + if err != nil { + panic(err) + } +} + +func (ci *copyin) resploop() { + for { + var r readBuf + t, err := ci.cn.recvMessage(&r) + if err != nil { + ci.cn.bad = true + ci.setError(err) + ci.done <- true + return + } + switch t { + case 'C': + // complete + case 'N': + // NoticeResponse + case 'Z': + ci.cn.processReadyForQuery(&r) + ci.done <- true + return + case 'E': + err := parseError(&r) + ci.setError(err) + default: + ci.cn.bad = true + ci.setError(fmt.Errorf("unknown response during CopyIn: %q", t)) + ci.done <- true + return + } + } +} + +func (ci *copyin) isErrorSet() bool { + ci.Lock() + isSet := (ci.err != nil) + ci.Unlock() + return isSet +} + +// setError() sets ci.err if one has not been set already. Caller must not be +// holding ci.Mutex. +func (ci *copyin) setError(err error) { + ci.Lock() + if ci.err == nil { + ci.err = err + } + ci.Unlock() +} + +func (ci *copyin) NumInput() int { + return -1 +} + +func (ci *copyin) Query(v []driver.Value) (r driver.Rows, err error) { + return nil, ErrNotSupported +} + +// Exec inserts values into the COPY stream. The insert is asynchronous +// and Exec can return errors from previous Exec calls to the same +// COPY stmt. +// +// You need to call Exec(nil) to sync the COPY stream and to get any +// errors from pending data, since Stmt.Close() doesn't return errors +// to the user. +func (ci *copyin) Exec(v []driver.Value) (r driver.Result, err error) { + if ci.closed { + return nil, errCopyInClosed + } + + if ci.cn.bad { + return nil, driver.ErrBadConn + } + defer ci.cn.errRecover(&err) + + if ci.isErrorSet() { + return nil, ci.err + } + + if len(v) == 0 { + return nil, ci.Close() + } + + numValues := len(v) + for i, value := range v { + ci.buffer = appendEncodedText(&ci.cn.parameterStatus, ci.buffer, value) + if i < numValues-1 { + ci.buffer = append(ci.buffer, '\t') + } + } + + ci.buffer = append(ci.buffer, '\n') + + if len(ci.buffer) > ciBufferFlushSize { + ci.flush(ci.buffer) + // reset buffer, keep bytes for message identifier and length + ci.buffer = ci.buffer[:5] + } + + return driver.RowsAffected(0), nil +} + +func (ci *copyin) Close() (err error) { + if ci.closed { // Don't do anything, we're already closed + return nil + } + ci.closed = true + + if ci.cn.bad { + return driver.ErrBadConn + } + defer ci.cn.errRecover(&err) + + if len(ci.buffer) > 0 { + ci.flush(ci.buffer) + } + // Avoid touching the scratch buffer as resploop could be using it. + err = ci.cn.sendSimpleMessage('c') + if err != nil { + return err + } + + <-ci.done + + if ci.isErrorSet() { + err = ci.err + return err + } + return nil +} diff --git a/vendor/github.com/lib/pq/doc.go b/vendor/github.com/lib/pq/doc.go new file mode 100644 index 00000000..19798dfc --- /dev/null +++ b/vendor/github.com/lib/pq/doc.go @@ -0,0 +1,212 @@ +/* +Package pq is a pure Go Postgres driver for the database/sql package. + +In most cases clients will use the database/sql package instead of +using this package directly. For example: + + import ( + "database/sql" + + _ "github.com/lib/pq" + ) + + func main() { + db, err := sql.Open("postgres", "user=pqgotest dbname=pqgotest sslmode=verify-full") + if err != nil { + log.Fatal(err) + } + + age := 21 + rows, err := db.Query("SELECT name FROM users WHERE age = $1", age) + … + } + +You can also connect to a database using a URL. For example: + + db, err := sql.Open("postgres", "postgres://pqgotest:password@localhost/pqgotest?sslmode=verify-full") + + +Connection String Parameters + + +Similarly to libpq, when establishing a connection using pq you are expected to +supply a connection string containing zero or more parameters. +A subset of the connection parameters supported by libpq are also supported by pq. +Additionally, pq also lets you specify run-time parameters (such as search_path or work_mem) +directly in the connection string. This is different from libpq, which does not allow +run-time parameters in the connection string, instead requiring you to supply +them in the options parameter. + +For compatibility with libpq, the following special connection parameters are +supported: + + * dbname - The name of the database to connect to + * user - The user to sign in as + * password - The user's password + * host - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost) + * port - The port to bind to. (default is 5432) + * sslmode - Whether or not to use SSL (default is require, this is not the default for libpq) + * fallback_application_name - An application_name to fall back to if one isn't provided. + * connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. + * sslcert - Cert file location. The file must contain PEM encoded data. + * sslkey - Key file location. The file must contain PEM encoded data. + * sslrootcert - The location of the root certificate file. The file must contain PEM encoded data. + +Valid values for sslmode are: + + * disable - No SSL + * require - Always SSL (skip verification) + * verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA) + * verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate) + +See http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING +for more information about connection string parameters. + +Use single quotes for values that contain whitespace: + + "user=pqgotest password='with spaces'" + +A backslash will escape the next character in values: + + "user=space\ man password='it\'s valid' + +Note that the connection parameter client_encoding (which sets the +text encoding for the connection) may be set but must be "UTF8", +matching with the same rules as Postgres. It is an error to provide +any other value. + +In addition to the parameters listed above, any run-time parameter that can be +set at backend start time can be set in the connection string. For more +information, see +http://www.postgresql.org/docs/current/static/runtime-config.html. + +Most environment variables as specified at http://www.postgresql.org/docs/current/static/libpq-envars.html +supported by libpq are also supported by pq. If any of the environment +variables not supported by pq are set, pq will panic during connection +establishment. Environment variables have a lower precedence than explicitly +provided connection parameters. + +The pgpass mechanism as described in http://www.postgresql.org/docs/current/static/libpq-pgpass.html +is supported, but on Windows PGPASSFILE must be specified explicitly. + +Queries + +database/sql does not dictate any specific format for parameter +markers in query strings, and pq uses the Postgres-native ordinal markers, +as shown above. The same marker can be reused for the same parameter: + + rows, err := db.Query(`SELECT name FROM users WHERE favorite_fruit = $1 + OR age BETWEEN $2 AND $2 + 3`, "orange", 64) + +pq does not support the LastInsertId() method of the Result type in database/sql. +To return the identifier of an INSERT (or UPDATE or DELETE), use the Postgres +RETURNING clause with a standard Query or QueryRow call: + + var userid int + err := db.QueryRow(`INSERT INTO users(name, favorite_fruit, age) + VALUES('beatrice', 'starfruit', 93) RETURNING id`).Scan(&userid) + +For more details on RETURNING, see the Postgres documentation: + + http://www.postgresql.org/docs/current/static/sql-insert.html + http://www.postgresql.org/docs/current/static/sql-update.html + http://www.postgresql.org/docs/current/static/sql-delete.html + +For additional instructions on querying see the documentation for the database/sql package. + +Errors + +pq may return errors of type *pq.Error which can be interrogated for error details: + + if err, ok := err.(*pq.Error); ok { + fmt.Println("pq error:", err.Code.Name()) + } + +See the pq.Error type for details. + + +Bulk imports + +You can perform bulk imports by preparing a statement returned by pq.CopyIn (or +pq.CopyInSchema) in an explicit transaction (sql.Tx). The returned statement +handle can then be repeatedly "executed" to copy data into the target table. +After all data has been processed you should call Exec() once with no arguments +to flush all buffered data. Any call to Exec() might return an error which +should be handled appropriately, but because of the internal buffering an error +returned by Exec() might not be related to the data passed in the call that +failed. + +CopyIn uses COPY FROM internally. It is not possible to COPY outside of an +explicit transaction in pq. + +Usage example: + + txn, err := db.Begin() + if err != nil { + log.Fatal(err) + } + + stmt, err := txn.Prepare(pq.CopyIn("users", "name", "age")) + if err != nil { + log.Fatal(err) + } + + for _, user := range users { + _, err = stmt.Exec(user.Name, int64(user.Age)) + if err != nil { + log.Fatal(err) + } + } + + _, err = stmt.Exec() + if err != nil { + log.Fatal(err) + } + + err = stmt.Close() + if err != nil { + log.Fatal(err) + } + + err = txn.Commit() + if err != nil { + log.Fatal(err) + } + + +Notifications + + +PostgreSQL supports a simple publish/subscribe model over database +connections. See http://www.postgresql.org/docs/current/static/sql-notify.html +for more information about the general mechanism. + +To start listening for notifications, you first have to open a new connection +to the database by calling NewListener. This connection can not be used for +anything other than LISTEN / NOTIFY. Calling Listen will open a "notification +channel"; once a notification channel is open, a notification generated on that +channel will effect a send on the Listener.Notify channel. A notification +channel will remain open until Unlisten is called, though connection loss might +result in some notifications being lost. To solve this problem, Listener sends +a nil pointer over the Notify channel any time the connection is re-established +following a connection loss. The application can get information about the +state of the underlying connection by setting an event callback in the call to +NewListener. + +A single Listener can safely be used from concurrent goroutines, which means +that there is often no need to create more than one Listener in your +application. However, a Listener is always connected to a single database, so +you will need to create a new Listener instance for every database you want to +receive notifications in. + +The channel name in both Listen and Unlisten is case sensitive, and can contain +any characters legal in an identifier (see +http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS +for more information). Note that the channel name will be truncated to 63 +bytes by the PostgreSQL server. + +You can find a complete, working example of Listener usage at +http://godoc.org/github.com/lib/pq/listen_example. + +*/ +package pq diff --git a/vendor/github.com/lib/pq/encode.go b/vendor/github.com/lib/pq/encode.go new file mode 100644 index 00000000..6681bd3e --- /dev/null +++ b/vendor/github.com/lib/pq/encode.go @@ -0,0 +1,570 @@ +package pq + +import ( + "bytes" + "database/sql/driver" + "encoding/binary" + "encoding/hex" + "errors" + "fmt" + "math" + "strconv" + "strings" + "sync" + "time" + + "github.com/lib/pq/oid" +) + +func binaryEncode(parameterStatus *parameterStatus, x interface{}) []byte { + switch v := x.(type) { + case []byte: + return v + default: + return encode(parameterStatus, x, oid.T_unknown) + } +} + +func encode(parameterStatus *parameterStatus, x interface{}, pgtypOid oid.Oid) []byte { + switch v := x.(type) { + case int64: + return strconv.AppendInt(nil, v, 10) + case float64: + return strconv.AppendFloat(nil, v, 'f', -1, 64) + case []byte: + if pgtypOid == oid.T_bytea { + return encodeBytea(parameterStatus.serverVersion, v) + } + + return v + case string: + if pgtypOid == oid.T_bytea { + return encodeBytea(parameterStatus.serverVersion, []byte(v)) + } + + return []byte(v) + case bool: + return strconv.AppendBool(nil, v) + case time.Time: + return formatTs(v) + + default: + errorf("encode: unknown type for %T", v) + } + + panic("not reached") +} + +func decode(parameterStatus *parameterStatus, s []byte, typ oid.Oid, f format) interface{} { + if f == formatBinary { + return binaryDecode(parameterStatus, s, typ) + } else { + return textDecode(parameterStatus, s, typ) + } +} + +func binaryDecode(parameterStatus *parameterStatus, s []byte, typ oid.Oid) interface{} { + switch typ { + case oid.T_bytea: + return s + case oid.T_int8: + return int64(binary.BigEndian.Uint64(s)) + case oid.T_int4: + return int64(int32(binary.BigEndian.Uint32(s))) + case oid.T_int2: + return int64(int16(binary.BigEndian.Uint16(s))) + + default: + errorf("don't know how to decode binary parameter of type %d", uint32(typ)) + } + + panic("not reached") +} + +func textDecode(parameterStatus *parameterStatus, s []byte, typ oid.Oid) interface{} { + switch typ { + case oid.T_bytea: + return parseBytea(s) + case oid.T_timestamptz: + return parseTs(parameterStatus.currentLocation, string(s)) + case oid.T_timestamp, oid.T_date: + return parseTs(nil, string(s)) + case oid.T_time: + return mustParse("15:04:05", typ, s) + case oid.T_timetz: + return mustParse("15:04:05-07", typ, s) + case oid.T_bool: + return s[0] == 't' + case oid.T_int8, oid.T_int4, oid.T_int2: + i, err := strconv.ParseInt(string(s), 10, 64) + if err != nil { + errorf("%s", err) + } + return i + case oid.T_float4, oid.T_float8: + bits := 64 + if typ == oid.T_float4 { + bits = 32 + } + f, err := strconv.ParseFloat(string(s), bits) + if err != nil { + errorf("%s", err) + } + return f + } + + return s +} + +// appendEncodedText encodes item in text format as required by COPY +// and appends to buf +func appendEncodedText(parameterStatus *parameterStatus, buf []byte, x interface{}) []byte { + switch v := x.(type) { + case int64: + return strconv.AppendInt(buf, v, 10) + case float64: + return strconv.AppendFloat(buf, v, 'f', -1, 64) + case []byte: + encodedBytea := encodeBytea(parameterStatus.serverVersion, v) + return appendEscapedText(buf, string(encodedBytea)) + case string: + return appendEscapedText(buf, v) + case bool: + return strconv.AppendBool(buf, v) + case time.Time: + return append(buf, formatTs(v)...) + case nil: + return append(buf, "\\N"...) + default: + errorf("encode: unknown type for %T", v) + } + + panic("not reached") +} + +func appendEscapedText(buf []byte, text string) []byte { + escapeNeeded := false + startPos := 0 + var c byte + + // check if we need to escape + for i := 0; i < len(text); i++ { + c = text[i] + if c == '\\' || c == '\n' || c == '\r' || c == '\t' { + escapeNeeded = true + startPos = i + break + } + } + if !escapeNeeded { + return append(buf, text...) + } + + // copy till first char to escape, iterate the rest + result := append(buf, text[:startPos]...) + for i := startPos; i < len(text); i++ { + c = text[i] + switch c { + case '\\': + result = append(result, '\\', '\\') + case '\n': + result = append(result, '\\', 'n') + case '\r': + result = append(result, '\\', 'r') + case '\t': + result = append(result, '\\', 't') + default: + result = append(result, c) + } + } + return result +} + +func mustParse(f string, typ oid.Oid, s []byte) time.Time { + str := string(s) + + // check for a 30-minute-offset timezone + if (typ == oid.T_timestamptz || typ == oid.T_timetz) && + str[len(str)-3] == ':' { + f += ":00" + } + t, err := time.Parse(f, str) + if err != nil { + errorf("decode: %s", err) + } + return t +} + +var invalidTimestampErr = errors.New("invalid timestamp") + +type timestampParser struct { + err error +} + +func (p *timestampParser) expect(str, char string, pos int) { + if p.err != nil { + return + } + if pos+1 > len(str) { + p.err = invalidTimestampErr + return + } + if c := str[pos : pos+1]; c != char && p.err == nil { + p.err = fmt.Errorf("expected '%v' at position %v; got '%v'", char, pos, c) + } +} + +func (p *timestampParser) mustAtoi(str string, begin int, end int) int { + if p.err != nil { + return 0 + } + if begin < 0 || end < 0 || begin > end || end > len(str) { + p.err = invalidTimestampErr + return 0 + } + result, err := strconv.Atoi(str[begin:end]) + if err != nil { + if p.err == nil { + p.err = fmt.Errorf("expected number; got '%v'", str) + } + return 0 + } + return result +} + +// The location cache caches the time zones typically used by the client. +type locationCache struct { + cache map[int]*time.Location + lock sync.Mutex +} + +// All connections share the same list of timezones. Benchmarking shows that +// about 5% speed could be gained by putting the cache in the connection and +// losing the mutex, at the cost of a small amount of memory and a somewhat +// significant increase in code complexity. +var globalLocationCache *locationCache = newLocationCache() + +func newLocationCache() *locationCache { + return &locationCache{cache: make(map[int]*time.Location)} +} + +// Returns the cached timezone for the specified offset, creating and caching +// it if necessary. +func (c *locationCache) getLocation(offset int) *time.Location { + c.lock.Lock() + defer c.lock.Unlock() + + location, ok := c.cache[offset] + if !ok { + location = time.FixedZone("", offset) + c.cache[offset] = location + } + + return location +} + +var infinityTsEnabled = false +var infinityTsNegative time.Time +var infinityTsPositive time.Time + +const ( + infinityTsEnabledAlready = "pq: infinity timestamp enabled already" + infinityTsNegativeMustBeSmaller = "pq: infinity timestamp: negative value must be smaller (before) than positive" +) + +/* + * If EnableInfinityTs is not called, "-infinity" and "infinity" will return + * []byte("-infinity") and []byte("infinity") respectively, and potentially + * cause error "sql: Scan error on column index 0: unsupported driver -> Scan pair: []uint8 -> *time.Time", + * when scanning into a time.Time value. + * + * Once EnableInfinityTs has been called, all connections created using this + * driver will decode Postgres' "-infinity" and "infinity" for "timestamp", + * "timestamp with time zone" and "date" types to the predefined minimum and + * maximum times, respectively. When encoding time.Time values, any time which + * equals or precedes the predefined minimum time will be encoded to + * "-infinity". Any values at or past the maximum time will similarly be + * encoded to "infinity". + * + * + * If EnableInfinityTs is called with negative >= positive, it will panic. + * Calling EnableInfinityTs after a connection has been established results in + * undefined behavior. If EnableInfinityTs is called more than once, it will + * panic. + */ +func EnableInfinityTs(negative time.Time, positive time.Time) { + if infinityTsEnabled { + panic(infinityTsEnabledAlready) + } + if !negative.Before(positive) { + panic(infinityTsNegativeMustBeSmaller) + } + infinityTsEnabled = true + infinityTsNegative = negative + infinityTsPositive = positive +} + +/* + * Testing might want to toggle infinityTsEnabled + */ +func disableInfinityTs() { + infinityTsEnabled = false +} + +// This is a time function specific to the Postgres default DateStyle +// setting ("ISO, MDY"), the only one we currently support. This +// accounts for the discrepancies between the parsing available with +// time.Parse and the Postgres date formatting quirks. +func parseTs(currentLocation *time.Location, str string) interface{} { + switch str { + case "-infinity": + if infinityTsEnabled { + return infinityTsNegative + } + return []byte(str) + case "infinity": + if infinityTsEnabled { + return infinityTsPositive + } + return []byte(str) + } + t, err := ParseTimestamp(currentLocation, str) + if err != nil { + panic(err) + } + return t +} + +func ParseTimestamp(currentLocation *time.Location, str string) (time.Time, error) { + p := timestampParser{} + + monSep := strings.IndexRune(str, '-') + // this is Gregorian year, not ISO Year + // In Gregorian system, the year 1 BC is followed by AD 1 + year := p.mustAtoi(str, 0, monSep) + daySep := monSep + 3 + month := p.mustAtoi(str, monSep+1, daySep) + p.expect(str, "-", daySep) + timeSep := daySep + 3 + day := p.mustAtoi(str, daySep+1, timeSep) + + var hour, minute, second int + if len(str) > monSep+len("01-01")+1 { + p.expect(str, " ", timeSep) + minSep := timeSep + 3 + p.expect(str, ":", minSep) + hour = p.mustAtoi(str, timeSep+1, minSep) + secSep := minSep + 3 + p.expect(str, ":", secSep) + minute = p.mustAtoi(str, minSep+1, secSep) + secEnd := secSep + 3 + second = p.mustAtoi(str, secSep+1, secEnd) + } + remainderIdx := monSep + len("01-01 00:00:00") + 1 + // Three optional (but ordered) sections follow: the + // fractional seconds, the time zone offset, and the BC + // designation. We set them up here and adjust the other + // offsets if the preceding sections exist. + + nanoSec := 0 + tzOff := 0 + + if remainderIdx+1 <= len(str) && str[remainderIdx:remainderIdx+1] == "." { + fracStart := remainderIdx + 1 + fracOff := strings.IndexAny(str[fracStart:], "-+ ") + if fracOff < 0 { + fracOff = len(str) - fracStart + } + fracSec := p.mustAtoi(str, fracStart, fracStart+fracOff) + nanoSec = fracSec * (1000000000 / int(math.Pow(10, float64(fracOff)))) + + remainderIdx += fracOff + 1 + } + if tzStart := remainderIdx; tzStart+1 <= len(str) && (str[tzStart:tzStart+1] == "-" || str[tzStart:tzStart+1] == "+") { + // time zone separator is always '-' or '+' (UTC is +00) + var tzSign int + if c := str[tzStart : tzStart+1]; c == "-" { + tzSign = -1 + } else if c == "+" { + tzSign = +1 + } else { + return time.Time{}, fmt.Errorf("expected '-' or '+' at position %v; got %v", tzStart, c) + } + tzHours := p.mustAtoi(str, tzStart+1, tzStart+3) + remainderIdx += 3 + var tzMin, tzSec int + if tzStart+4 <= len(str) && str[tzStart+3:tzStart+4] == ":" { + tzMin = p.mustAtoi(str, tzStart+4, tzStart+6) + remainderIdx += 3 + } + if tzStart+7 <= len(str) && str[tzStart+6:tzStart+7] == ":" { + tzSec = p.mustAtoi(str, tzStart+7, tzStart+9) + remainderIdx += 3 + } + tzOff = tzSign * ((tzHours * 60 * 60) + (tzMin * 60) + tzSec) + } + var isoYear int + if remainderIdx+3 <= len(str) && str[remainderIdx:remainderIdx+3] == " BC" { + isoYear = 1 - year + remainderIdx += 3 + } else { + isoYear = year + } + if remainderIdx < len(str) { + return time.Time{}, fmt.Errorf("expected end of input, got %v", str[remainderIdx:]) + } + t := time.Date(isoYear, time.Month(month), day, + hour, minute, second, nanoSec, + globalLocationCache.getLocation(tzOff)) + + if currentLocation != nil { + // Set the location of the returned Time based on the session's + // TimeZone value, but only if the local time zone database agrees with + // the remote database on the offset. + lt := t.In(currentLocation) + _, newOff := lt.Zone() + if newOff == tzOff { + t = lt + } + } + + return t, p.err +} + +// formatTs formats t into a format postgres understands. +func formatTs(t time.Time) (b []byte) { + if infinityTsEnabled { + // t <= -infinity : ! (t > -infinity) + if !t.After(infinityTsNegative) { + return []byte("-infinity") + } + // t >= infinity : ! (!t < infinity) + if !t.Before(infinityTsPositive) { + return []byte("infinity") + } + } + // Need to send dates before 0001 A.D. with " BC" suffix, instead of the + // minus sign preferred by Go. + // Beware, "0000" in ISO is "1 BC", "-0001" is "2 BC" and so on + bc := false + if t.Year() <= 0 { + // flip year sign, and add 1, e.g: "0" will be "1", and "-10" will be "11" + t = t.AddDate((-t.Year())*2+1, 0, 0) + bc = true + } + b = []byte(t.Format(time.RFC3339Nano)) + + _, offset := t.Zone() + offset = offset % 60 + if offset != 0 { + // RFC3339Nano already printed the minus sign + if offset < 0 { + offset = -offset + } + + b = append(b, ':') + if offset < 10 { + b = append(b, '0') + } + b = strconv.AppendInt(b, int64(offset), 10) + } + + if bc { + b = append(b, " BC"...) + } + return b +} + +// Parse a bytea value received from the server. Both "hex" and the legacy +// "escape" format are supported. +func parseBytea(s []byte) (result []byte) { + if len(s) >= 2 && bytes.Equal(s[:2], []byte("\\x")) { + // bytea_output = hex + s = s[2:] // trim off leading "\\x" + result = make([]byte, hex.DecodedLen(len(s))) + _, err := hex.Decode(result, s) + if err != nil { + errorf("%s", err) + } + } else { + // bytea_output = escape + for len(s) > 0 { + if s[0] == '\\' { + // escaped '\\' + if len(s) >= 2 && s[1] == '\\' { + result = append(result, '\\') + s = s[2:] + continue + } + + // '\\' followed by an octal number + if len(s) < 4 { + errorf("invalid bytea sequence %v", s) + } + r, err := strconv.ParseInt(string(s[1:4]), 8, 9) + if err != nil { + errorf("could not parse bytea value: %s", err.Error()) + } + result = append(result, byte(r)) + s = s[4:] + } else { + // We hit an unescaped, raw byte. Try to read in as many as + // possible in one go. + i := bytes.IndexByte(s, '\\') + if i == -1 { + result = append(result, s...) + break + } + result = append(result, s[:i]...) + s = s[i:] + } + } + } + + return result +} + +func encodeBytea(serverVersion int, v []byte) (result []byte) { + if serverVersion >= 90000 { + // Use the hex format if we know that the server supports it + result = make([]byte, 2+hex.EncodedLen(len(v))) + result[0] = '\\' + result[1] = 'x' + hex.Encode(result[2:], v) + } else { + // .. or resort to "escape" + for _, b := range v { + if b == '\\' { + result = append(result, '\\', '\\') + } else if b < 0x20 || b > 0x7e { + result = append(result, []byte(fmt.Sprintf("\\%03o", b))...) + } else { + result = append(result, b) + } + } + } + + return result +} + +// NullTime represents a time.Time that may be null. NullTime implements the +// sql.Scanner interface so it can be used as a scan destination, similar to +// sql.NullString. +type NullTime struct { + Time time.Time + Valid bool // Valid is true if Time is not NULL +} + +// Scan implements the Scanner interface. +func (nt *NullTime) Scan(value interface{}) error { + nt.Time, nt.Valid = value.(time.Time) + return nil +} + +// Value implements the driver Valuer interface. +func (nt NullTime) Value() (driver.Value, error) { + if !nt.Valid { + return nil, nil + } + return nt.Time, nil +} diff --git a/vendor/github.com/lib/pq/error.go b/vendor/github.com/lib/pq/error.go new file mode 100644 index 00000000..b4bb44ce --- /dev/null +++ b/vendor/github.com/lib/pq/error.go @@ -0,0 +1,508 @@ +package pq + +import ( + "database/sql/driver" + "fmt" + "io" + "net" + "runtime" +) + +// Error severities +const ( + Efatal = "FATAL" + Epanic = "PANIC" + Ewarning = "WARNING" + Enotice = "NOTICE" + Edebug = "DEBUG" + Einfo = "INFO" + Elog = "LOG" +) + +// Error represents an error communicating with the server. +// +// See http://www.postgresql.org/docs/current/static/protocol-error-fields.html for details of the fields +type Error struct { + Severity string + Code ErrorCode + Message string + Detail string + Hint string + Position string + InternalPosition string + InternalQuery string + Where string + Schema string + Table string + Column string + DataTypeName string + Constraint string + File string + Line string + Routine string +} + +// ErrorCode is a five-character error code. +type ErrorCode string + +// Name returns a more human friendly rendering of the error code, namely the +// "condition name". +// +// See http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html for +// details. +func (ec ErrorCode) Name() string { + return errorCodeNames[ec] +} + +// ErrorClass is only the class part of an error code. +type ErrorClass string + +// Name returns the condition name of an error class. It is equivalent to the +// condition name of the "standard" error code (i.e. the one having the last +// three characters "000"). +func (ec ErrorClass) Name() string { + return errorCodeNames[ErrorCode(ec+"000")] +} + +// Class returns the error class, e.g. "28". +// +// See http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html for +// details. +func (ec ErrorCode) Class() ErrorClass { + return ErrorClass(ec[0:2]) +} + +// errorCodeNames is a mapping between the five-character error codes and the +// human readable "condition names". It is derived from the list at +// http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html +var errorCodeNames = map[ErrorCode]string{ + // Class 00 - Successful Completion + "00000": "successful_completion", + // Class 01 - Warning + "01000": "warning", + "0100C": "dynamic_result_sets_returned", + "01008": "implicit_zero_bit_padding", + "01003": "null_value_eliminated_in_set_function", + "01007": "privilege_not_granted", + "01006": "privilege_not_revoked", + "01004": "string_data_right_truncation", + "01P01": "deprecated_feature", + // Class 02 - No Data (this is also a warning class per the SQL standard) + "02000": "no_data", + "02001": "no_additional_dynamic_result_sets_returned", + // Class 03 - SQL Statement Not Yet Complete + "03000": "sql_statement_not_yet_complete", + // Class 08 - Connection Exception + "08000": "connection_exception", + "08003": "connection_does_not_exist", + "08006": "connection_failure", + "08001": "sqlclient_unable_to_establish_sqlconnection", + "08004": "sqlserver_rejected_establishment_of_sqlconnection", + "08007": "transaction_resolution_unknown", + "08P01": "protocol_violation", + // Class 09 - Triggered Action Exception + "09000": "triggered_action_exception", + // Class 0A - Feature Not Supported + "0A000": "feature_not_supported", + // Class 0B - Invalid Transaction Initiation + "0B000": "invalid_transaction_initiation", + // Class 0F - Locator Exception + "0F000": "locator_exception", + "0F001": "invalid_locator_specification", + // Class 0L - Invalid Grantor + "0L000": "invalid_grantor", + "0LP01": "invalid_grant_operation", + // Class 0P - Invalid Role Specification + "0P000": "invalid_role_specification", + // Class 0Z - Diagnostics Exception + "0Z000": "diagnostics_exception", + "0Z002": "stacked_diagnostics_accessed_without_active_handler", + // Class 20 - Case Not Found + "20000": "case_not_found", + // Class 21 - Cardinality Violation + "21000": "cardinality_violation", + // Class 22 - Data Exception + "22000": "data_exception", + "2202E": "array_subscript_error", + "22021": "character_not_in_repertoire", + "22008": "datetime_field_overflow", + "22012": "division_by_zero", + "22005": "error_in_assignment", + "2200B": "escape_character_conflict", + "22022": "indicator_overflow", + "22015": "interval_field_overflow", + "2201E": "invalid_argument_for_logarithm", + "22014": "invalid_argument_for_ntile_function", + "22016": "invalid_argument_for_nth_value_function", + "2201F": "invalid_argument_for_power_function", + "2201G": "invalid_argument_for_width_bucket_function", + "22018": "invalid_character_value_for_cast", + "22007": "invalid_datetime_format", + "22019": "invalid_escape_character", + "2200D": "invalid_escape_octet", + "22025": "invalid_escape_sequence", + "22P06": "nonstandard_use_of_escape_character", + "22010": "invalid_indicator_parameter_value", + "22023": "invalid_parameter_value", + "2201B": "invalid_regular_expression", + "2201W": "invalid_row_count_in_limit_clause", + "2201X": "invalid_row_count_in_result_offset_clause", + "22009": "invalid_time_zone_displacement_value", + "2200C": "invalid_use_of_escape_character", + "2200G": "most_specific_type_mismatch", + "22004": "null_value_not_allowed", + "22002": "null_value_no_indicator_parameter", + "22003": "numeric_value_out_of_range", + "22026": "string_data_length_mismatch", + "22001": "string_data_right_truncation", + "22011": "substring_error", + "22027": "trim_error", + "22024": "unterminated_c_string", + "2200F": "zero_length_character_string", + "22P01": "floating_point_exception", + "22P02": "invalid_text_representation", + "22P03": "invalid_binary_representation", + "22P04": "bad_copy_file_format", + "22P05": "untranslatable_character", + "2200L": "not_an_xml_document", + "2200M": "invalid_xml_document", + "2200N": "invalid_xml_content", + "2200S": "invalid_xml_comment", + "2200T": "invalid_xml_processing_instruction", + // Class 23 - Integrity Constraint Violation + "23000": "integrity_constraint_violation", + "23001": "restrict_violation", + "23502": "not_null_violation", + "23503": "foreign_key_violation", + "23505": "unique_violation", + "23514": "check_violation", + "23P01": "exclusion_violation", + // Class 24 - Invalid Cursor State + "24000": "invalid_cursor_state", + // Class 25 - Invalid Transaction State + "25000": "invalid_transaction_state", + "25001": "active_sql_transaction", + "25002": "branch_transaction_already_active", + "25008": "held_cursor_requires_same_isolation_level", + "25003": "inappropriate_access_mode_for_branch_transaction", + "25004": "inappropriate_isolation_level_for_branch_transaction", + "25005": "no_active_sql_transaction_for_branch_transaction", + "25006": "read_only_sql_transaction", + "25007": "schema_and_data_statement_mixing_not_supported", + "25P01": "no_active_sql_transaction", + "25P02": "in_failed_sql_transaction", + // Class 26 - Invalid SQL Statement Name + "26000": "invalid_sql_statement_name", + // Class 27 - Triggered Data Change Violation + "27000": "triggered_data_change_violation", + // Class 28 - Invalid Authorization Specification + "28000": "invalid_authorization_specification", + "28P01": "invalid_password", + // Class 2B - Dependent Privilege Descriptors Still Exist + "2B000": "dependent_privilege_descriptors_still_exist", + "2BP01": "dependent_objects_still_exist", + // Class 2D - Invalid Transaction Termination + "2D000": "invalid_transaction_termination", + // Class 2F - SQL Routine Exception + "2F000": "sql_routine_exception", + "2F005": "function_executed_no_return_statement", + "2F002": "modifying_sql_data_not_permitted", + "2F003": "prohibited_sql_statement_attempted", + "2F004": "reading_sql_data_not_permitted", + // Class 34 - Invalid Cursor Name + "34000": "invalid_cursor_name", + // Class 38 - External Routine Exception + "38000": "external_routine_exception", + "38001": "containing_sql_not_permitted", + "38002": "modifying_sql_data_not_permitted", + "38003": "prohibited_sql_statement_attempted", + "38004": "reading_sql_data_not_permitted", + // Class 39 - External Routine Invocation Exception + "39000": "external_routine_invocation_exception", + "39001": "invalid_sqlstate_returned", + "39004": "null_value_not_allowed", + "39P01": "trigger_protocol_violated", + "39P02": "srf_protocol_violated", + // Class 3B - Savepoint Exception + "3B000": "savepoint_exception", + "3B001": "invalid_savepoint_specification", + // Class 3D - Invalid Catalog Name + "3D000": "invalid_catalog_name", + // Class 3F - Invalid Schema Name + "3F000": "invalid_schema_name", + // Class 40 - Transaction Rollback + "40000": "transaction_rollback", + "40002": "transaction_integrity_constraint_violation", + "40001": "serialization_failure", + "40003": "statement_completion_unknown", + "40P01": "deadlock_detected", + // Class 42 - Syntax Error or Access Rule Violation + "42000": "syntax_error_or_access_rule_violation", + "42601": "syntax_error", + "42501": "insufficient_privilege", + "42846": "cannot_coerce", + "42803": "grouping_error", + "42P20": "windowing_error", + "42P19": "invalid_recursion", + "42830": "invalid_foreign_key", + "42602": "invalid_name", + "42622": "name_too_long", + "42939": "reserved_name", + "42804": "datatype_mismatch", + "42P18": "indeterminate_datatype", + "42P21": "collation_mismatch", + "42P22": "indeterminate_collation", + "42809": "wrong_object_type", + "42703": "undefined_column", + "42883": "undefined_function", + "42P01": "undefined_table", + "42P02": "undefined_parameter", + "42704": "undefined_object", + "42701": "duplicate_column", + "42P03": "duplicate_cursor", + "42P04": "duplicate_database", + "42723": "duplicate_function", + "42P05": "duplicate_prepared_statement", + "42P06": "duplicate_schema", + "42P07": "duplicate_table", + "42712": "duplicate_alias", + "42710": "duplicate_object", + "42702": "ambiguous_column", + "42725": "ambiguous_function", + "42P08": "ambiguous_parameter", + "42P09": "ambiguous_alias", + "42P10": "invalid_column_reference", + "42611": "invalid_column_definition", + "42P11": "invalid_cursor_definition", + "42P12": "invalid_database_definition", + "42P13": "invalid_function_definition", + "42P14": "invalid_prepared_statement_definition", + "42P15": "invalid_schema_definition", + "42P16": "invalid_table_definition", + "42P17": "invalid_object_definition", + // Class 44 - WITH CHECK OPTION Violation + "44000": "with_check_option_violation", + // Class 53 - Insufficient Resources + "53000": "insufficient_resources", + "53100": "disk_full", + "53200": "out_of_memory", + "53300": "too_many_connections", + "53400": "configuration_limit_exceeded", + // Class 54 - Program Limit Exceeded + "54000": "program_limit_exceeded", + "54001": "statement_too_complex", + "54011": "too_many_columns", + "54023": "too_many_arguments", + // Class 55 - Object Not In Prerequisite State + "55000": "object_not_in_prerequisite_state", + "55006": "object_in_use", + "55P02": "cant_change_runtime_param", + "55P03": "lock_not_available", + // Class 57 - Operator Intervention + "57000": "operator_intervention", + "57014": "query_canceled", + "57P01": "admin_shutdown", + "57P02": "crash_shutdown", + "57P03": "cannot_connect_now", + "57P04": "database_dropped", + // Class 58 - System Error (errors external to PostgreSQL itself) + "58000": "system_error", + "58030": "io_error", + "58P01": "undefined_file", + "58P02": "duplicate_file", + // Class F0 - Configuration File Error + "F0000": "config_file_error", + "F0001": "lock_file_exists", + // Class HV - Foreign Data Wrapper Error (SQL/MED) + "HV000": "fdw_error", + "HV005": "fdw_column_name_not_found", + "HV002": "fdw_dynamic_parameter_value_needed", + "HV010": "fdw_function_sequence_error", + "HV021": "fdw_inconsistent_descriptor_information", + "HV024": "fdw_invalid_attribute_value", + "HV007": "fdw_invalid_column_name", + "HV008": "fdw_invalid_column_number", + "HV004": "fdw_invalid_data_type", + "HV006": "fdw_invalid_data_type_descriptors", + "HV091": "fdw_invalid_descriptor_field_identifier", + "HV00B": "fdw_invalid_handle", + "HV00C": "fdw_invalid_option_index", + "HV00D": "fdw_invalid_option_name", + "HV090": "fdw_invalid_string_length_or_buffer_length", + "HV00A": "fdw_invalid_string_format", + "HV009": "fdw_invalid_use_of_null_pointer", + "HV014": "fdw_too_many_handles", + "HV001": "fdw_out_of_memory", + "HV00P": "fdw_no_schemas", + "HV00J": "fdw_option_name_not_found", + "HV00K": "fdw_reply_handle", + "HV00Q": "fdw_schema_not_found", + "HV00R": "fdw_table_not_found", + "HV00L": "fdw_unable_to_create_execution", + "HV00M": "fdw_unable_to_create_reply", + "HV00N": "fdw_unable_to_establish_connection", + // Class P0 - PL/pgSQL Error + "P0000": "plpgsql_error", + "P0001": "raise_exception", + "P0002": "no_data_found", + "P0003": "too_many_rows", + // Class XX - Internal Error + "XX000": "internal_error", + "XX001": "data_corrupted", + "XX002": "index_corrupted", +} + +func parseError(r *readBuf) *Error { + err := new(Error) + for t := r.byte(); t != 0; t = r.byte() { + msg := r.string() + switch t { + case 'S': + err.Severity = msg + case 'C': + err.Code = ErrorCode(msg) + case 'M': + err.Message = msg + case 'D': + err.Detail = msg + case 'H': + err.Hint = msg + case 'P': + err.Position = msg + case 'p': + err.InternalPosition = msg + case 'q': + err.InternalQuery = msg + case 'W': + err.Where = msg + case 's': + err.Schema = msg + case 't': + err.Table = msg + case 'c': + err.Column = msg + case 'd': + err.DataTypeName = msg + case 'n': + err.Constraint = msg + case 'F': + err.File = msg + case 'L': + err.Line = msg + case 'R': + err.Routine = msg + } + } + return err +} + +// Fatal returns true if the Error Severity is fatal. +func (err *Error) Fatal() bool { + return err.Severity == Efatal +} + +// Get implements the legacy PGError interface. New code should use the fields +// of the Error struct directly. +func (err *Error) Get(k byte) (v string) { + switch k { + case 'S': + return err.Severity + case 'C': + return string(err.Code) + case 'M': + return err.Message + case 'D': + return err.Detail + case 'H': + return err.Hint + case 'P': + return err.Position + case 'p': + return err.InternalPosition + case 'q': + return err.InternalQuery + case 'W': + return err.Where + case 's': + return err.Schema + case 't': + return err.Table + case 'c': + return err.Column + case 'd': + return err.DataTypeName + case 'n': + return err.Constraint + case 'F': + return err.File + case 'L': + return err.Line + case 'R': + return err.Routine + } + return "" +} + +func (err Error) Error() string { + return "pq: " + err.Message +} + +// PGError is an interface used by previous versions of pq. It is provided +// only to support legacy code. New code should use the Error type. +type PGError interface { + Error() string + Fatal() bool + Get(k byte) (v string) +} + +func errorf(s string, args ...interface{}) { + panic(fmt.Errorf("pq: %s", fmt.Sprintf(s, args...))) +} + +func errRecoverNoErrBadConn(err *error) { + e := recover() + if e == nil { + // Do nothing + return + } + var ok bool + *err, ok = e.(error) + if !ok { + *err = fmt.Errorf("pq: unexpected error: %#v", e) + } +} + +func (c *conn) errRecover(err *error) { + e := recover() + switch v := e.(type) { + case nil: + // Do nothing + case runtime.Error: + c.bad = true + panic(v) + case *Error: + if v.Fatal() { + *err = driver.ErrBadConn + } else { + *err = v + } + case *net.OpError: + *err = driver.ErrBadConn + case error: + if v == io.EOF || v.(error).Error() == "remote error: handshake failure" { + *err = driver.ErrBadConn + } else { + *err = v + } + + default: + c.bad = true + panic(fmt.Sprintf("unknown error: %#v", e)) + } + + // Any time we return ErrBadConn, we need to remember it since *Tx doesn't + // mark the connection bad in database/sql. + if *err == driver.ErrBadConn { + c.bad = true + } +} diff --git a/vendor/github.com/lib/pq/hstore/hstore.go b/vendor/github.com/lib/pq/hstore/hstore.go new file mode 100644 index 00000000..72d5abf5 --- /dev/null +++ b/vendor/github.com/lib/pq/hstore/hstore.go @@ -0,0 +1,118 @@ +package hstore + +import ( + "database/sql" + "database/sql/driver" + "strings" +) + +// A wrapper for transferring Hstore values back and forth easily. +type Hstore struct { + Map map[string]sql.NullString +} + +// escapes and quotes hstore keys/values +// s should be a sql.NullString or string +func hQuote(s interface{}) string { + var str string + switch v := s.(type) { + case sql.NullString: + if !v.Valid { + return "NULL" + } + str = v.String + case string: + str = v + default: + panic("not a string or sql.NullString") + } + + str = strings.Replace(str, "\\", "\\\\", -1) + return `"` + strings.Replace(str, "\"", "\\\"", -1) + `"` +} + +// Scan implements the Scanner interface. +// +// Note h.Map is reallocated before the scan to clear existing values. If the +// hstore column's database value is NULL, then h.Map is set to nil instead. +func (h *Hstore) Scan(value interface{}) error { + if value == nil { + h.Map = nil + return nil + } + h.Map = make(map[string]sql.NullString) + var b byte + pair := [][]byte{{}, {}} + pi := 0 + inQuote := false + didQuote := false + sawSlash := false + bindex := 0 + for bindex, b = range value.([]byte) { + if sawSlash { + pair[pi] = append(pair[pi], b) + sawSlash = false + continue + } + + switch b { + case '\\': + sawSlash = true + continue + case '"': + inQuote = !inQuote + if !didQuote { + didQuote = true + } + continue + default: + if !inQuote { + switch b { + case ' ', '\t', '\n', '\r': + continue + case '=': + continue + case '>': + pi = 1 + didQuote = false + continue + case ',': + s := string(pair[1]) + if !didQuote && len(s) == 4 && strings.ToLower(s) == "null" { + h.Map[string(pair[0])] = sql.NullString{String: "", Valid: false} + } else { + h.Map[string(pair[0])] = sql.NullString{String: string(pair[1]), Valid: true} + } + pair[0] = []byte{} + pair[1] = []byte{} + pi = 0 + continue + } + } + } + pair[pi] = append(pair[pi], b) + } + if bindex > 0 { + s := string(pair[1]) + if !didQuote && len(s) == 4 && strings.ToLower(s) == "null" { + h.Map[string(pair[0])] = sql.NullString{String: "", Valid: false} + } else { + h.Map[string(pair[0])] = sql.NullString{String: string(pair[1]), Valid: true} + } + } + return nil +} + +// Value implements the driver Valuer interface. Note if h.Map is nil, the +// database column value will be set to NULL. +func (h Hstore) Value() (driver.Value, error) { + if h.Map == nil { + return nil, nil + } + parts := []string{} + for key, val := range h.Map { + thispart := hQuote(key) + "=>" + hQuote(val) + parts = append(parts, thispart) + } + return []byte(strings.Join(parts, ",")), nil +} diff --git a/vendor/github.com/lib/pq/listen_example/doc.go b/vendor/github.com/lib/pq/listen_example/doc.go new file mode 100644 index 00000000..5bc99f5c --- /dev/null +++ b/vendor/github.com/lib/pq/listen_example/doc.go @@ -0,0 +1,102 @@ +/* + +Below you will find a self-contained Go program which uses the LISTEN / NOTIFY +mechanism to avoid polling the database while waiting for more work to arrive. + + // + // You can see the program in action by defining a function similar to + // the following: + // + // CREATE OR REPLACE FUNCTION public.get_work() + // RETURNS bigint + // LANGUAGE sql + // AS $$ + // SELECT CASE WHEN random() >= 0.2 THEN int8 '1' END + // $$ + // ; + + package main + + import ( + "database/sql" + "fmt" + "time" + + "github.com/lib/pq" + ) + + func doWork(db *sql.DB, work int64) { + // work here + } + + func getWork(db *sql.DB) { + for { + // get work from the database here + var work sql.NullInt64 + err := db.QueryRow("SELECT get_work()").Scan(&work) + if err != nil { + fmt.Println("call to get_work() failed: ", err) + time.Sleep(10 * time.Second) + continue + } + if !work.Valid { + // no more work to do + fmt.Println("ran out of work") + return + } + + fmt.Println("starting work on ", work.Int64) + go doWork(db, work.Int64) + } + } + + func waitForNotification(l *pq.Listener) { + for { + select { + case <-l.Notify: + fmt.Println("received notification, new work available") + return + case <-time.After(90 * time.Second): + go func() { + l.Ping() + }() + // Check if there's more work available, just in case it takes + // a while for the Listener to notice connection loss and + // reconnect. + fmt.Println("received no work for 90 seconds, checking for new work") + return + } + } + } + + func main() { + var conninfo string = "" + + db, err := sql.Open("postgres", conninfo) + if err != nil { + panic(err) + } + + reportProblem := func(ev pq.ListenerEventType, err error) { + if err != nil { + fmt.Println(err.Error()) + } + } + + listener := pq.NewListener(conninfo, 10 * time.Second, time.Minute, reportProblem) + err = listener.Listen("getwork") + if err != nil { + panic(err) + } + + fmt.Println("entering main loop") + for { + // process all available work before waiting for notifications + getWork(db) + waitForNotification(listener) + } + } + + +*/ +package listen_example diff --git a/vendor/github.com/lib/pq/notify.go b/vendor/github.com/lib/pq/notify.go new file mode 100644 index 00000000..09f94244 --- /dev/null +++ b/vendor/github.com/lib/pq/notify.go @@ -0,0 +1,782 @@ +package pq + +// Package pq is a pure Go Postgres driver for the database/sql package. +// This module contains support for Postgres LISTEN/NOTIFY. + +import ( + "errors" + "fmt" + "sync" + "sync/atomic" + "time" +) + +// Notification represents a single notification from the database. +type Notification struct { + // Process ID (PID) of the notifying postgres backend. + BePid int + // Name of the channel the notification was sent on. + Channel string + // Payload, or the empty string if unspecified. + Extra string +} + +func recvNotification(r *readBuf) *Notification { + bePid := r.int32() + channel := r.string() + extra := r.string() + + return &Notification{bePid, channel, extra} +} + +const ( + connStateIdle int32 = iota + connStateExpectResponse + connStateExpectReadyForQuery +) + +type message struct { + typ byte + err error +} + +var errListenerConnClosed = errors.New("pq: ListenerConn has been closed") + +// ListenerConn is a low-level interface for waiting for notifications. You +// should use Listener instead. +type ListenerConn struct { + // guards cn and err + connectionLock sync.Mutex + cn *conn + err error + + connState int32 + + // the sending goroutine will be holding this lock + senderLock sync.Mutex + + notificationChan chan<- *Notification + + replyChan chan message +} + +// Creates a new ListenerConn. Use NewListener instead. +func NewListenerConn(name string, notificationChan chan<- *Notification) (*ListenerConn, error) { + return newDialListenerConn(defaultDialer{}, name, notificationChan) +} + +func newDialListenerConn(d Dialer, name string, c chan<- *Notification) (*ListenerConn, error) { + cn, err := DialOpen(d, name) + if err != nil { + return nil, err + } + + l := &ListenerConn{ + cn: cn.(*conn), + notificationChan: c, + connState: connStateIdle, + replyChan: make(chan message, 2), + } + + go l.listenerConnMain() + + return l, nil +} + +// We can only allow one goroutine at a time to be running a query on the +// connection for various reasons, so the goroutine sending on the connection +// must be holding senderLock. +// +// Returns an error if an unrecoverable error has occurred and the ListenerConn +// should be abandoned. +func (l *ListenerConn) acquireSenderLock() error { + // we must acquire senderLock first to avoid deadlocks; see ExecSimpleQuery + l.senderLock.Lock() + + l.connectionLock.Lock() + err := l.err + l.connectionLock.Unlock() + if err != nil { + l.senderLock.Unlock() + return err + } + return nil +} + +func (l *ListenerConn) releaseSenderLock() { + l.senderLock.Unlock() +} + +// setState advances the protocol state to newState. Returns false if moving +// to that state from the current state is not allowed. +func (l *ListenerConn) setState(newState int32) bool { + var expectedState int32 + + switch newState { + case connStateIdle: + expectedState = connStateExpectReadyForQuery + case connStateExpectResponse: + expectedState = connStateIdle + case connStateExpectReadyForQuery: + expectedState = connStateExpectResponse + default: + panic(fmt.Sprintf("unexpected listenerConnState %d", newState)) + } + + return atomic.CompareAndSwapInt32(&l.connState, expectedState, newState) +} + +// Main logic is here: receive messages from the postgres backend, forward +// notifications and query replies and keep the internal state in sync with the +// protocol state. Returns when the connection has been lost, is about to go +// away or should be discarded because we couldn't agree on the state with the +// server backend. +func (l *ListenerConn) listenerConnLoop() (err error) { + defer errRecoverNoErrBadConn(&err) + + r := &readBuf{} + for { + t, err := l.cn.recvMessage(r) + if err != nil { + return err + } + + switch t { + case 'A': + // recvNotification copies all the data so we don't need to worry + // about the scratch buffer being overwritten. + l.notificationChan <- recvNotification(r) + + case 'T', 'D': + // only used by tests; ignore + + case 'E': + // We might receive an ErrorResponse even when not in a query; it + // is expected that the server will close the connection after + // that, but we should make sure that the error we display is the + // one from the stray ErrorResponse, not io.ErrUnexpectedEOF. + if !l.setState(connStateExpectReadyForQuery) { + return parseError(r) + } + l.replyChan <- message{t, parseError(r)} + + case 'C', 'I': + if !l.setState(connStateExpectReadyForQuery) { + // protocol out of sync + return fmt.Errorf("unexpected CommandComplete") + } + // ExecSimpleQuery doesn't need to know about this message + + case 'Z': + if !l.setState(connStateIdle) { + // protocol out of sync + return fmt.Errorf("unexpected ReadyForQuery") + } + l.replyChan <- message{t, nil} + + case 'N', 'S': + // ignore + default: + return fmt.Errorf("unexpected message %q from server in listenerConnLoop", t) + } + } +} + +// This is the main routine for the goroutine receiving on the database +// connection. Most of the main logic is in listenerConnLoop. +func (l *ListenerConn) listenerConnMain() { + err := l.listenerConnLoop() + + // listenerConnLoop terminated; we're done, but we still have to clean up. + // Make sure nobody tries to start any new queries by making sure the err + // pointer is set. It is important that we do not overwrite its value; a + // connection could be closed by either this goroutine or one sending on + // the connection -- whoever closes the connection is assumed to have the + // more meaningful error message (as the other one will probably get + // net.errClosed), so that goroutine sets the error we expose while the + // other error is discarded. If the connection is lost while two + // goroutines are operating on the socket, it probably doesn't matter which + // error we expose so we don't try to do anything more complex. + l.connectionLock.Lock() + if l.err == nil { + l.err = err + } + l.cn.Close() + l.connectionLock.Unlock() + + // There might be a query in-flight; make sure nobody's waiting for a + // response to it, since there's not going to be one. + close(l.replyChan) + + // let the listener know we're done + close(l.notificationChan) + + // this ListenerConn is done +} + +// Send a LISTEN query to the server. See ExecSimpleQuery. +func (l *ListenerConn) Listen(channel string) (bool, error) { + return l.ExecSimpleQuery("LISTEN " + QuoteIdentifier(channel)) +} + +// Send an UNLISTEN query to the server. See ExecSimpleQuery. +func (l *ListenerConn) Unlisten(channel string) (bool, error) { + return l.ExecSimpleQuery("UNLISTEN " + QuoteIdentifier(channel)) +} + +// Send `UNLISTEN *` to the server. See ExecSimpleQuery. +func (l *ListenerConn) UnlistenAll() (bool, error) { + return l.ExecSimpleQuery("UNLISTEN *") +} + +// Ping the remote server to make sure it's alive. Non-nil error means the +// connection has failed and should be abandoned. +func (l *ListenerConn) Ping() error { + sent, err := l.ExecSimpleQuery("") + if !sent { + return err + } + if err != nil { + // shouldn't happen + panic(err) + } + return nil +} + +// Attempt to send a query on the connection. Returns an error if sending the +// query failed, and the caller should initiate closure of this connection. +// The caller must be holding senderLock (see acquireSenderLock and +// releaseSenderLock). +func (l *ListenerConn) sendSimpleQuery(q string) (err error) { + defer errRecoverNoErrBadConn(&err) + + // must set connection state before sending the query + if !l.setState(connStateExpectResponse) { + panic("two queries running at the same time") + } + + // Can't use l.cn.writeBuf here because it uses the scratch buffer which + // might get overwritten by listenerConnLoop. + b := &writeBuf{ + buf: []byte("Q\x00\x00\x00\x00"), + pos: 1, + } + b.string(q) + l.cn.send(b) + + return nil +} + +// Execute a "simple query" (i.e. one with no bindable parameters) on the +// connection. The possible return values are: +// 1) "executed" is true; the query was executed to completion on the +// database server. If the query failed, err will be set to the error +// returned by the database, otherwise err will be nil. +// 2) If "executed" is false, the query could not be executed on the remote +// server. err will be non-nil. +// +// After a call to ExecSimpleQuery has returned an executed=false value, the +// connection has either been closed or will be closed shortly thereafter, and +// all subsequently executed queries will return an error. +func (l *ListenerConn) ExecSimpleQuery(q string) (executed bool, err error) { + if err = l.acquireSenderLock(); err != nil { + return false, err + } + defer l.releaseSenderLock() + + err = l.sendSimpleQuery(q) + if err != nil { + // We can't know what state the protocol is in, so we need to abandon + // this connection. + l.connectionLock.Lock() + // Set the error pointer if it hasn't been set already; see + // listenerConnMain. + if l.err == nil { + l.err = err + } + l.connectionLock.Unlock() + l.cn.c.Close() + return false, err + } + + // now we just wait for a reply.. + for { + m, ok := <-l.replyChan + if !ok { + // We lost the connection to server, don't bother waiting for a + // a response. err should have been set already. + l.connectionLock.Lock() + err := l.err + l.connectionLock.Unlock() + return false, err + } + switch m.typ { + case 'Z': + // sanity check + if m.err != nil { + panic("m.err != nil") + } + // done; err might or might not be set + return true, err + + case 'E': + // sanity check + if m.err == nil { + panic("m.err == nil") + } + // server responded with an error; ReadyForQuery to follow + err = m.err + + default: + return false, fmt.Errorf("unknown response for simple query: %q", m.typ) + } + } +} + +func (l *ListenerConn) Close() error { + l.connectionLock.Lock() + if l.err != nil { + l.connectionLock.Unlock() + return errListenerConnClosed + } + l.err = errListenerConnClosed + l.connectionLock.Unlock() + // We can't send anything on the connection without holding senderLock. + // Simply close the net.Conn to wake up everyone operating on it. + return l.cn.c.Close() +} + +// Err() returns the reason the connection was closed. It is not safe to call +// this function until l.Notify has been closed. +func (l *ListenerConn) Err() error { + return l.err +} + +var errListenerClosed = errors.New("pq: Listener has been closed") + +var ErrChannelAlreadyOpen = errors.New("pq: channel is already open") +var ErrChannelNotOpen = errors.New("pq: channel is not open") + +type ListenerEventType int + +const ( + // Emitted only when the database connection has been initially + // initialized. err will always be nil. + ListenerEventConnected ListenerEventType = iota + + // Emitted after a database connection has been lost, either because of an + // error or because Close has been called. err will be set to the reason + // the database connection was lost. + ListenerEventDisconnected + + // Emitted after a database connection has been re-established after + // connection loss. err will always be nil. After this event has been + // emitted, a nil pq.Notification is sent on the Listener.Notify channel. + ListenerEventReconnected + + // Emitted after a connection to the database was attempted, but failed. + // err will be set to an error describing why the connection attempt did + // not succeed. + ListenerEventConnectionAttemptFailed +) + +type EventCallbackType func(event ListenerEventType, err error) + +// Listener provides an interface for listening to notifications from a +// PostgreSQL database. For general usage information, see section +// "Notifications". +// +// Listener can safely be used from concurrently running goroutines. +type Listener struct { + // Channel for receiving notifications from the database. In some cases a + // nil value will be sent. See section "Notifications" above. + Notify chan *Notification + + name string + minReconnectInterval time.Duration + maxReconnectInterval time.Duration + dialer Dialer + eventCallback EventCallbackType + + lock sync.Mutex + isClosed bool + reconnectCond *sync.Cond + cn *ListenerConn + connNotificationChan <-chan *Notification + channels map[string]struct{} +} + +// NewListener creates a new database connection dedicated to LISTEN / NOTIFY. +// +// name should be set to a connection string to be used to establish the +// database connection (see section "Connection String Parameters" above). +// +// minReconnectInterval controls the duration to wait before trying to +// re-establish the database connection after connection loss. After each +// consecutive failure this interval is doubled, until maxReconnectInterval is +// reached. Successfully completing the connection establishment procedure +// resets the interval back to minReconnectInterval. +// +// The last parameter eventCallback can be set to a function which will be +// called by the Listener when the state of the underlying database connection +// changes. This callback will be called by the goroutine which dispatches the +// notifications over the Notify channel, so you should try to avoid doing +// potentially time-consuming operations from the callback. +func NewListener(name string, + minReconnectInterval time.Duration, + maxReconnectInterval time.Duration, + eventCallback EventCallbackType) *Listener { + return NewDialListener(defaultDialer{}, name, minReconnectInterval, maxReconnectInterval, eventCallback) +} + +// NewDialListener is like NewListener but it takes a Dialer. +func NewDialListener(d Dialer, + name string, + minReconnectInterval time.Duration, + maxReconnectInterval time.Duration, + eventCallback EventCallbackType) *Listener { + + l := &Listener{ + name: name, + minReconnectInterval: minReconnectInterval, + maxReconnectInterval: maxReconnectInterval, + dialer: d, + eventCallback: eventCallback, + + channels: make(map[string]struct{}), + + Notify: make(chan *Notification, 32), + } + l.reconnectCond = sync.NewCond(&l.lock) + + go l.listenerMain() + + return l +} + +// Returns the notification channel for this listener. This is the same +// channel as Notify, and will not be recreated during the life time of the +// Listener. +func (l *Listener) NotificationChannel() <-chan *Notification { + return l.Notify +} + +// Listen starts listening for notifications on a channel. Calls to this +// function will block until an acknowledgement has been received from the +// server. Note that Listener automatically re-establishes the connection +// after connection loss, so this function may block indefinitely if the +// connection can not be re-established. +// +// Listen will only fail in three conditions: +// 1) The channel is already open. The returned error will be +// ErrChannelAlreadyOpen. +// 2) The query was executed on the remote server, but PostgreSQL returned an +// error message in response to the query. The returned error will be a +// pq.Error containing the information the server supplied. +// 3) Close is called on the Listener before the request could be completed. +// +// The channel name is case-sensitive. +func (l *Listener) Listen(channel string) error { + l.lock.Lock() + defer l.lock.Unlock() + + if l.isClosed { + return errListenerClosed + } + + // The server allows you to issue a LISTEN on a channel which is already + // open, but it seems useful to be able to detect this case to spot for + // mistakes in application logic. If the application genuinely does't + // care, it can check the exported error and ignore it. + _, exists := l.channels[channel] + if exists { + return ErrChannelAlreadyOpen + } + + if l.cn != nil { + // If gotResponse is true but error is set, the query was executed on + // the remote server, but resulted in an error. This should be + // relatively rare, so it's fine if we just pass the error to our + // caller. However, if gotResponse is false, we could not complete the + // query on the remote server and our underlying connection is about + // to go away, so we only add relname to l.channels, and wait for + // resync() to take care of the rest. + gotResponse, err := l.cn.Listen(channel) + if gotResponse && err != nil { + return err + } + } + + l.channels[channel] = struct{}{} + for l.cn == nil { + l.reconnectCond.Wait() + // we let go of the mutex for a while + if l.isClosed { + return errListenerClosed + } + } + + return nil +} + +// Unlisten removes a channel from the Listener's channel list. Returns +// ErrChannelNotOpen if the Listener is not listening on the specified channel. +// Returns immediately with no error if there is no connection. Note that you +// might still get notifications for this channel even after Unlisten has +// returned. +// +// The channel name is case-sensitive. +func (l *Listener) Unlisten(channel string) error { + l.lock.Lock() + defer l.lock.Unlock() + + if l.isClosed { + return errListenerClosed + } + + // Similarly to LISTEN, this is not an error in Postgres, but it seems + // useful to distinguish from the normal conditions. + _, exists := l.channels[channel] + if !exists { + return ErrChannelNotOpen + } + + if l.cn != nil { + // Similarly to Listen (see comment in that function), the caller + // should only be bothered with an error if it came from the backend as + // a response to our query. + gotResponse, err := l.cn.Unlisten(channel) + if gotResponse && err != nil { + return err + } + } + + // Don't bother waiting for resync if there's no connection. + delete(l.channels, channel) + return nil +} + +// UnlistenAll removes all channels from the Listener's channel list. Returns +// immediately with no error if there is no connection. Note that you might +// still get notifications for any of the deleted channels even after +// UnlistenAll has returned. +func (l *Listener) UnlistenAll() error { + l.lock.Lock() + defer l.lock.Unlock() + + if l.isClosed { + return errListenerClosed + } + + if l.cn != nil { + // Similarly to Listen (see comment in that function), the caller + // should only be bothered with an error if it came from the backend as + // a response to our query. + gotResponse, err := l.cn.UnlistenAll() + if gotResponse && err != nil { + return err + } + } + + // Don't bother waiting for resync if there's no connection. + l.channels = make(map[string]struct{}) + return nil +} + +// Ping the remote server to make sure it's alive. Non-nil return value means +// that there is no active connection. +func (l *Listener) Ping() error { + l.lock.Lock() + defer l.lock.Unlock() + + if l.isClosed { + return errListenerClosed + } + if l.cn == nil { + return errors.New("no connection") + } + + return l.cn.Ping() +} + +// Clean up after losing the server connection. Returns l.cn.Err(), which +// should have the reason the connection was lost. +func (l *Listener) disconnectCleanup() error { + l.lock.Lock() + defer l.lock.Unlock() + + // sanity check; can't look at Err() until the channel has been closed + select { + case _, ok := <-l.connNotificationChan: + if ok { + panic("connNotificationChan not closed") + } + default: + panic("connNotificationChan not closed") + } + + err := l.cn.Err() + l.cn.Close() + l.cn = nil + return err +} + +// Synchronize the list of channels we want to be listening on with the server +// after the connection has been established. +func (l *Listener) resync(cn *ListenerConn, notificationChan <-chan *Notification) error { + doneChan := make(chan error) + go func() { + for channel := range l.channels { + // If we got a response, return that error to our caller as it's + // going to be more descriptive than cn.Err(). + gotResponse, err := cn.Listen(channel) + if gotResponse && err != nil { + doneChan <- err + return + } + + // If we couldn't reach the server, wait for notificationChan to + // close and then return the error message from the connection, as + // per ListenerConn's interface. + if err != nil { + for _ = range notificationChan { + } + doneChan <- cn.Err() + return + } + } + doneChan <- nil + }() + + // Ignore notifications while synchronization is going on to avoid + // deadlocks. We have to send a nil notification over Notify anyway as + // we can't possibly know which notifications (if any) were lost while + // the connection was down, so there's no reason to try and process + // these messages at all. + for { + select { + case _, ok := <-notificationChan: + if !ok { + notificationChan = nil + } + + case err := <-doneChan: + return err + } + } +} + +// caller should NOT be holding l.lock +func (l *Listener) closed() bool { + l.lock.Lock() + defer l.lock.Unlock() + + return l.isClosed +} + +func (l *Listener) connect() error { + notificationChan := make(chan *Notification, 32) + cn, err := newDialListenerConn(l.dialer, l.name, notificationChan) + if err != nil { + return err + } + + l.lock.Lock() + defer l.lock.Unlock() + + err = l.resync(cn, notificationChan) + if err != nil { + cn.Close() + return err + } + + l.cn = cn + l.connNotificationChan = notificationChan + l.reconnectCond.Broadcast() + + return nil +} + +// Close disconnects the Listener from the database and shuts it down. +// Subsequent calls to its methods will return an error. Close returns an +// error if the connection has already been closed. +func (l *Listener) Close() error { + l.lock.Lock() + defer l.lock.Unlock() + + if l.isClosed { + return errListenerClosed + } + + if l.cn != nil { + l.cn.Close() + } + l.isClosed = true + + return nil +} + +func (l *Listener) emitEvent(event ListenerEventType, err error) { + if l.eventCallback != nil { + l.eventCallback(event, err) + } +} + +// Main logic here: maintain a connection to the server when possible, wait +// for notifications and emit events. +func (l *Listener) listenerConnLoop() { + var nextReconnect time.Time + + reconnectInterval := l.minReconnectInterval + for { + for { + err := l.connect() + if err == nil { + break + } + + if l.closed() { + return + } + l.emitEvent(ListenerEventConnectionAttemptFailed, err) + + time.Sleep(reconnectInterval) + reconnectInterval *= 2 + if reconnectInterval > l.maxReconnectInterval { + reconnectInterval = l.maxReconnectInterval + } + } + + if nextReconnect.IsZero() { + l.emitEvent(ListenerEventConnected, nil) + } else { + l.emitEvent(ListenerEventReconnected, nil) + l.Notify <- nil + } + + reconnectInterval = l.minReconnectInterval + nextReconnect = time.Now().Add(reconnectInterval) + + for { + notification, ok := <-l.connNotificationChan + if !ok { + // lost connection, loop again + break + } + l.Notify <- notification + } + + err := l.disconnectCleanup() + if l.closed() { + return + } + l.emitEvent(ListenerEventDisconnected, err) + + time.Sleep(nextReconnect.Sub(time.Now())) + } +} + +func (l *Listener) listenerMain() { + l.listenerConnLoop() + close(l.Notify) +} diff --git a/vendor/github.com/lib/pq/oid/doc.go b/vendor/github.com/lib/pq/oid/doc.go new file mode 100644 index 00000000..caaede24 --- /dev/null +++ b/vendor/github.com/lib/pq/oid/doc.go @@ -0,0 +1,6 @@ +// Package oid contains OID constants +// as defined by the Postgres server. +package oid + +// Oid is a Postgres Object ID. +type Oid uint32 diff --git a/vendor/github.com/lib/pq/oid/gen.go b/vendor/github.com/lib/pq/oid/gen.go new file mode 100644 index 00000000..cd4aea80 --- /dev/null +++ b/vendor/github.com/lib/pq/oid/gen.go @@ -0,0 +1,74 @@ +// +build ignore + +// Generate the table of OID values +// Run with 'go run gen.go'. +package main + +import ( + "database/sql" + "fmt" + "log" + "os" + "os/exec" + + _ "github.com/lib/pq" +) + +func main() { + datname := os.Getenv("PGDATABASE") + sslmode := os.Getenv("PGSSLMODE") + + if datname == "" { + os.Setenv("PGDATABASE", "pqgotest") + } + + if sslmode == "" { + os.Setenv("PGSSLMODE", "disable") + } + + db, err := sql.Open("postgres", "") + if err != nil { + log.Fatal(err) + } + cmd := exec.Command("gofmt") + cmd.Stderr = os.Stderr + w, err := cmd.StdinPipe() + if err != nil { + log.Fatal(err) + } + f, err := os.Create("types.go") + if err != nil { + log.Fatal(err) + } + cmd.Stdout = f + err = cmd.Start() + if err != nil { + log.Fatal(err) + } + fmt.Fprintln(w, "// generated by 'go run gen.go'; do not edit") + fmt.Fprintln(w, "\npackage oid") + fmt.Fprintln(w, "const (") + rows, err := db.Query(` + SELECT typname, oid + FROM pg_type WHERE oid < 10000 + ORDER BY oid; + `) + if err != nil { + log.Fatal(err) + } + var name string + var oid int + for rows.Next() { + err = rows.Scan(&name, &oid) + if err != nil { + log.Fatal(err) + } + fmt.Fprintf(w, "T_%s Oid = %d\n", name, oid) + } + if err = rows.Err(); err != nil { + log.Fatal(err) + } + fmt.Fprintln(w, ")") + w.Close() + cmd.Wait() +} diff --git a/vendor/github.com/lib/pq/oid/types.go b/vendor/github.com/lib/pq/oid/types.go new file mode 100644 index 00000000..03df05a6 --- /dev/null +++ b/vendor/github.com/lib/pq/oid/types.go @@ -0,0 +1,161 @@ +// generated by 'go run gen.go'; do not edit + +package oid + +const ( + T_bool Oid = 16 + T_bytea Oid = 17 + T_char Oid = 18 + T_name Oid = 19 + T_int8 Oid = 20 + T_int2 Oid = 21 + T_int2vector Oid = 22 + T_int4 Oid = 23 + T_regproc Oid = 24 + T_text Oid = 25 + T_oid Oid = 26 + T_tid Oid = 27 + T_xid Oid = 28 + T_cid Oid = 29 + T_oidvector Oid = 30 + T_pg_type Oid = 71 + T_pg_attribute Oid = 75 + T_pg_proc Oid = 81 + T_pg_class Oid = 83 + T_json Oid = 114 + T_xml Oid = 142 + T__xml Oid = 143 + T_pg_node_tree Oid = 194 + T__json Oid = 199 + T_smgr Oid = 210 + T_point Oid = 600 + T_lseg Oid = 601 + T_path Oid = 602 + T_box Oid = 603 + T_polygon Oid = 604 + T_line Oid = 628 + T__line Oid = 629 + T_cidr Oid = 650 + T__cidr Oid = 651 + T_float4 Oid = 700 + T_float8 Oid = 701 + T_abstime Oid = 702 + T_reltime Oid = 703 + T_tinterval Oid = 704 + T_unknown Oid = 705 + T_circle Oid = 718 + T__circle Oid = 719 + T_money Oid = 790 + T__money Oid = 791 + T_macaddr Oid = 829 + T_inet Oid = 869 + T__bool Oid = 1000 + T__bytea Oid = 1001 + T__char Oid = 1002 + T__name Oid = 1003 + T__int2 Oid = 1005 + T__int2vector Oid = 1006 + T__int4 Oid = 1007 + T__regproc Oid = 1008 + T__text Oid = 1009 + T__tid Oid = 1010 + T__xid Oid = 1011 + T__cid Oid = 1012 + T__oidvector Oid = 1013 + T__bpchar Oid = 1014 + T__varchar Oid = 1015 + T__int8 Oid = 1016 + T__point Oid = 1017 + T__lseg Oid = 1018 + T__path Oid = 1019 + T__box Oid = 1020 + T__float4 Oid = 1021 + T__float8 Oid = 1022 + T__abstime Oid = 1023 + T__reltime Oid = 1024 + T__tinterval Oid = 1025 + T__polygon Oid = 1027 + T__oid Oid = 1028 + T_aclitem Oid = 1033 + T__aclitem Oid = 1034 + T__macaddr Oid = 1040 + T__inet Oid = 1041 + T_bpchar Oid = 1042 + T_varchar Oid = 1043 + T_date Oid = 1082 + T_time Oid = 1083 + T_timestamp Oid = 1114 + T__timestamp Oid = 1115 + T__date Oid = 1182 + T__time Oid = 1183 + T_timestamptz Oid = 1184 + T__timestamptz Oid = 1185 + T_interval Oid = 1186 + T__interval Oid = 1187 + T__numeric Oid = 1231 + T_pg_database Oid = 1248 + T__cstring Oid = 1263 + T_timetz Oid = 1266 + T__timetz Oid = 1270 + T_bit Oid = 1560 + T__bit Oid = 1561 + T_varbit Oid = 1562 + T__varbit Oid = 1563 + T_numeric Oid = 1700 + T_refcursor Oid = 1790 + T__refcursor Oid = 2201 + T_regprocedure Oid = 2202 + T_regoper Oid = 2203 + T_regoperator Oid = 2204 + T_regclass Oid = 2205 + T_regtype Oid = 2206 + T__regprocedure Oid = 2207 + T__regoper Oid = 2208 + T__regoperator Oid = 2209 + T__regclass Oid = 2210 + T__regtype Oid = 2211 + T_record Oid = 2249 + T_cstring Oid = 2275 + T_any Oid = 2276 + T_anyarray Oid = 2277 + T_void Oid = 2278 + T_trigger Oid = 2279 + T_language_handler Oid = 2280 + T_internal Oid = 2281 + T_opaque Oid = 2282 + T_anyelement Oid = 2283 + T__record Oid = 2287 + T_anynonarray Oid = 2776 + T_pg_authid Oid = 2842 + T_pg_auth_members Oid = 2843 + T__txid_snapshot Oid = 2949 + T_uuid Oid = 2950 + T__uuid Oid = 2951 + T_txid_snapshot Oid = 2970 + T_fdw_handler Oid = 3115 + T_anyenum Oid = 3500 + T_tsvector Oid = 3614 + T_tsquery Oid = 3615 + T_gtsvector Oid = 3642 + T__tsvector Oid = 3643 + T__gtsvector Oid = 3644 + T__tsquery Oid = 3645 + T_regconfig Oid = 3734 + T__regconfig Oid = 3735 + T_regdictionary Oid = 3769 + T__regdictionary Oid = 3770 + T_anyrange Oid = 3831 + T_event_trigger Oid = 3838 + T_int4range Oid = 3904 + T__int4range Oid = 3905 + T_numrange Oid = 3906 + T__numrange Oid = 3907 + T_tsrange Oid = 3908 + T__tsrange Oid = 3909 + T_tstzrange Oid = 3910 + T__tstzrange Oid = 3911 + T_daterange Oid = 3912 + T__daterange Oid = 3913 + T_int8range Oid = 3926 + T__int8range Oid = 3927 +) diff --git a/vendor/github.com/lib/pq/url.go b/vendor/github.com/lib/pq/url.go new file mode 100644 index 00000000..f4d8a7c2 --- /dev/null +++ b/vendor/github.com/lib/pq/url.go @@ -0,0 +1,76 @@ +package pq + +import ( + "fmt" + "net" + nurl "net/url" + "sort" + "strings" +) + +// ParseURL no longer needs to be used by clients of this library since supplying a URL as a +// connection string to sql.Open() is now supported: +// +// sql.Open("postgres", "postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full") +// +// It remains exported here for backwards-compatibility. +// +// ParseURL converts a url to a connection string for driver.Open. +// Example: +// +// "postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full" +// +// converts to: +// +// "user=bob password=secret host=1.2.3.4 port=5432 dbname=mydb sslmode=verify-full" +// +// A minimal example: +// +// "postgres://" +// +// This will be blank, causing driver.Open to use all of the defaults +func ParseURL(url string) (string, error) { + u, err := nurl.Parse(url) + if err != nil { + return "", err + } + + if u.Scheme != "postgres" && u.Scheme != "postgresql" { + return "", fmt.Errorf("invalid connection protocol: %s", u.Scheme) + } + + var kvs []string + escaper := strings.NewReplacer(` `, `\ `, `'`, `\'`, `\`, `\\`) + accrue := func(k, v string) { + if v != "" { + kvs = append(kvs, k+"="+escaper.Replace(v)) + } + } + + if u.User != nil { + v := u.User.Username() + accrue("user", v) + + v, _ = u.User.Password() + accrue("password", v) + } + + if host, port, err := net.SplitHostPort(u.Host); err != nil { + accrue("host", u.Host) + } else { + accrue("host", host) + accrue("port", port) + } + + if u.Path != "" { + accrue("dbname", u.Path[1:]) + } + + q := u.Query() + for k := range q { + accrue(k, q.Get(k)) + } + + sort.Strings(kvs) // Makes testing easier (not a performance concern) + return strings.Join(kvs, " "), nil +} diff --git a/vendor/github.com/lib/pq/user_posix.go b/vendor/github.com/lib/pq/user_posix.go new file mode 100644 index 00000000..bf982524 --- /dev/null +++ b/vendor/github.com/lib/pq/user_posix.go @@ -0,0 +1,24 @@ +// Package pq is a pure Go Postgres driver for the database/sql package. + +// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris rumprun + +package pq + +import ( + "os" + "os/user" +) + +func userCurrent() (string, error) { + u, err := user.Current() + if err == nil { + return u.Username, nil + } + + name := os.Getenv("USER") + if name != "" { + return name, nil + } + + return "", ErrCouldNotDetectUsername +} diff --git a/vendor/github.com/lib/pq/user_windows.go b/vendor/github.com/lib/pq/user_windows.go new file mode 100644 index 00000000..2b691267 --- /dev/null +++ b/vendor/github.com/lib/pq/user_windows.go @@ -0,0 +1,27 @@ +// Package pq is a pure Go Postgres driver for the database/sql package. +package pq + +import ( + "path/filepath" + "syscall" +) + +// Perform Windows user name lookup identically to libpq. +// +// The PostgreSQL code makes use of the legacy Win32 function +// GetUserName, and that function has not been imported into stock Go. +// GetUserNameEx is available though, the difference being that a +// wider range of names are available. To get the output to be the +// same as GetUserName, only the base (or last) component of the +// result is returned. +func userCurrent() (string, error) { + pw_name := make([]uint16, 128) + pwname_size := uint32(len(pw_name)) - 1 + err := syscall.GetUserNameEx(syscall.NameSamCompatible, &pw_name[0], &pwname_size) + if err != nil { + return "", ErrCouldNotDetectUsername + } + s := syscall.UTF16ToString(pw_name) + u := filepath.Base(s) + return u, nil +} diff --git a/vendor/golang.org/x/net/context/LICENSE b/vendor/golang.org/x/net/context/LICENSE new file mode 100644 index 00000000..6a66aea5 --- /dev/null +++ b/vendor/golang.org/x/net/context/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. 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/vendor/golang.org/x/net/context/context.go b/vendor/golang.org/x/net/context/context.go new file mode 100644 index 00000000..134654cf --- /dev/null +++ b/vendor/golang.org/x/net/context/context.go @@ -0,0 +1,156 @@ +// Copyright 2014 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 context defines the Context type, which carries deadlines, +// cancelation signals, and other request-scoped values across API boundaries +// and between processes. +// +// Incoming requests to a server should create a Context, and outgoing calls to +// servers should accept a Context. The chain of function calls between must +// propagate the Context, optionally replacing it with a modified copy created +// using WithDeadline, WithTimeout, WithCancel, or WithValue. +// +// Programs that use Contexts should follow these rules to keep interfaces +// consistent across packages and enable static analysis tools to check context +// propagation: +// +// Do not store Contexts inside a struct type; instead, pass a Context +// explicitly to each function that needs it. The Context should be the first +// parameter, typically named ctx: +// +// func DoSomething(ctx context.Context, arg Arg) error { +// // ... use ctx ... +// } +// +// Do not pass a nil Context, even if a function permits it. Pass context.TODO +// if you are unsure about which Context to use. +// +// Use context Values only for request-scoped data that transits processes and +// APIs, not for passing optional parameters to functions. +// +// The same Context may be passed to functions running in different goroutines; +// Contexts are safe for simultaneous use by multiple goroutines. +// +// See http://blog.golang.org/context for example code for a server that uses +// Contexts. +package context // import "golang.org/x/net/context" + +import "time" + +// A Context carries a deadline, a cancelation signal, and other values across +// API boundaries. +// +// Context's methods may be called by multiple goroutines simultaneously. +type Context interface { + // Deadline returns the time when work done on behalf of this context + // should be canceled. Deadline returns ok==false when no deadline is + // set. Successive calls to Deadline return the same results. + Deadline() (deadline time.Time, ok bool) + + // Done returns a channel that's closed when work done on behalf of this + // context should be canceled. Done may return nil if this context can + // never be canceled. Successive calls to Done return the same value. + // + // WithCancel arranges for Done to be closed when cancel is called; + // WithDeadline arranges for Done to be closed when the deadline + // expires; WithTimeout arranges for Done to be closed when the timeout + // elapses. + // + // Done is provided for use in select statements: + // + // // Stream generates values with DoSomething and sends them to out + // // until DoSomething returns an error or ctx.Done is closed. + // func Stream(ctx context.Context, out chan<- Value) error { + // for { + // v, err := DoSomething(ctx) + // if err != nil { + // return err + // } + // select { + // case <-ctx.Done(): + // return ctx.Err() + // case out <- v: + // } + // } + // } + // + // See http://blog.golang.org/pipelines for more examples of how to use + // a Done channel for cancelation. + Done() <-chan struct{} + + // Err returns a non-nil error value after Done is closed. Err returns + // Canceled if the context was canceled or DeadlineExceeded if the + // context's deadline passed. No other values for Err are defined. + // After Done is closed, successive calls to Err return the same value. + Err() error + + // Value returns the value associated with this context for key, or nil + // if no value is associated with key. Successive calls to Value with + // the same key returns the same result. + // + // Use context values only for request-scoped data that transits + // processes and API boundaries, not for passing optional parameters to + // functions. + // + // A key identifies a specific value in a Context. Functions that wish + // to store values in Context typically allocate a key in a global + // variable then use that key as the argument to context.WithValue and + // Context.Value. A key can be any type that supports equality; + // packages should define keys as an unexported type to avoid + // collisions. + // + // Packages that define a Context key should provide type-safe accessors + // for the values stores using that key: + // + // // Package user defines a User type that's stored in Contexts. + // package user + // + // import "golang.org/x/net/context" + // + // // User is the type of value stored in the Contexts. + // type User struct {...} + // + // // key is an unexported type for keys defined in this package. + // // This prevents collisions with keys defined in other packages. + // type key int + // + // // userKey is the key for user.User values in Contexts. It is + // // unexported; clients use user.NewContext and user.FromContext + // // instead of using this key directly. + // var userKey key = 0 + // + // // NewContext returns a new Context that carries value u. + // func NewContext(ctx context.Context, u *User) context.Context { + // return context.WithValue(ctx, userKey, u) + // } + // + // // FromContext returns the User value stored in ctx, if any. + // func FromContext(ctx context.Context) (*User, bool) { + // u, ok := ctx.Value(userKey).(*User) + // return u, ok + // } + Value(key interface{}) interface{} +} + +// Background returns a non-nil, empty Context. It is never canceled, has no +// values, and has no deadline. It is typically used by the main function, +// initialization, and tests, and as the top-level Context for incoming +// requests. +func Background() Context { + return background +} + +// TODO returns a non-nil, empty Context. Code should use context.TODO when +// it's unclear which Context to use or it is not yet available (because the +// surrounding function has not yet been extended to accept a Context +// parameter). TODO is recognized by static analysis tools that determine +// whether Contexts are propagated correctly in a program. +func TODO() Context { + return todo +} + +// A CancelFunc tells an operation to abandon its work. +// A CancelFunc does not wait for the work to stop. +// After the first call, subsequent calls to a CancelFunc do nothing. +type CancelFunc func() diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go new file mode 100644 index 00000000..e45feec4 --- /dev/null +++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go @@ -0,0 +1,146 @@ +// Copyright 2015 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 ctxhttp provides helper functions for performing context-aware HTTP requests. +package ctxhttp // import "golang.org/x/net/context/ctxhttp" + +import ( + "io" + "net/http" + "net/url" + "strings" + + "golang.org/x/net/context" +) + +func nop() {} + +var ( + testHookContextDoneBeforeHeaders = nop + testHookDoReturned = nop + testHookDidBodyClose = nop +) + +// Do sends an HTTP request with the provided http.Client and returns an HTTP response. +// If the client is nil, http.DefaultClient is used. +// If the context is canceled or times out, ctx.Err() will be returned. +func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { + if client == nil { + client = http.DefaultClient + } + + // TODO(djd): Respect any existing value of req.Cancel. + cancel := make(chan struct{}) + req.Cancel = cancel + + type responseAndError struct { + resp *http.Response + err error + } + result := make(chan responseAndError, 1) + + // Make local copies of test hooks closed over by goroutines below. + // Prevents data races in tests. + testHookDoReturned := testHookDoReturned + testHookDidBodyClose := testHookDidBodyClose + + go func() { + resp, err := client.Do(req) + testHookDoReturned() + result <- responseAndError{resp, err} + }() + + var resp *http.Response + + select { + case <-ctx.Done(): + testHookContextDoneBeforeHeaders() + close(cancel) + // Clean up after the goroutine calling client.Do: + go func() { + if r := <-result; r.resp != nil { + testHookDidBodyClose() + r.resp.Body.Close() + } + }() + return nil, ctx.Err() + case r := <-result: + var err error + resp, err = r.resp, r.err + if err != nil { + return resp, err + } + } + + c := make(chan struct{}) + go func() { + select { + case <-ctx.Done(): + close(cancel) + case <-c: + // The response's Body is closed. + } + }() + resp.Body = ¬ifyingReader{resp.Body, c} + + return resp, nil +} + +// Get issues a GET request via the Do function. +func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + return Do(ctx, client, req) +} + +// Head issues a HEAD request via the Do function. +func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) { + req, err := http.NewRequest("HEAD", url, nil) + if err != nil { + return nil, err + } + return Do(ctx, client, req) +} + +// Post issues a POST request via the Do function. +func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) { + req, err := http.NewRequest("POST", url, body) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", bodyType) + return Do(ctx, client, req) +} + +// PostForm issues a POST request via the Do function. +func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) { + return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) +} + +// notifyingReader is an io.ReadCloser that closes the notify channel after +// Close is called or a Read fails on the underlying ReadCloser. +type notifyingReader struct { + io.ReadCloser + notify chan<- struct{} +} + +func (r *notifyingReader) Read(p []byte) (int, error) { + n, err := r.ReadCloser.Read(p) + if err != nil && r.notify != nil { + close(r.notify) + r.notify = nil + } + return n, err +} + +func (r *notifyingReader) Close() error { + err := r.ReadCloser.Close() + if r.notify != nil { + close(r.notify) + r.notify = nil + } + return err +} diff --git a/vendor/golang.org/x/net/context/go17.go b/vendor/golang.org/x/net/context/go17.go new file mode 100644 index 00000000..f8cda19a --- /dev/null +++ b/vendor/golang.org/x/net/context/go17.go @@ -0,0 +1,72 @@ +// Copyright 2016 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. + +// +build go1.7 + +package context + +import ( + "context" // standard library's context, as of Go 1.7 + "time" +) + +var ( + todo = context.TODO() + background = context.Background() +) + +// Canceled is the error returned by Context.Err when the context is canceled. +var Canceled = context.Canceled + +// DeadlineExceeded is the error returned by Context.Err when the context's +// deadline passes. +var DeadlineExceeded = context.DeadlineExceeded + +// WithCancel returns a copy of parent with a new Done channel. The returned +// context's Done channel is closed when the returned cancel function is called +// or when the parent context's Done channel is closed, whichever happens first. +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete. +func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { + ctx, f := context.WithCancel(parent) + return ctx, CancelFunc(f) +} + +// WithDeadline returns a copy of the parent context with the deadline adjusted +// to be no later than d. If the parent's deadline is already earlier than d, +// WithDeadline(parent, d) is semantically equivalent to parent. The returned +// context's Done channel is closed when the deadline expires, when the returned +// cancel function is called, or when the parent context's Done channel is +// closed, whichever happens first. +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete. +func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { + ctx, f := context.WithDeadline(parent, deadline) + return ctx, CancelFunc(f) +} + +// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete: +// +// func slowOperationWithTimeout(ctx context.Context) (Result, error) { +// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) +// defer cancel() // releases resources if slowOperation completes before timeout elapses +// return slowOperation(ctx) +// } +func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { + return WithDeadline(parent, time.Now().Add(timeout)) +} + +// WithValue returns a copy of parent in which the value associated with key is +// val. +// +// Use context Values only for request-scoped data that transits processes and +// APIs, not for passing optional parameters to functions. +func WithValue(parent Context, key interface{}, val interface{}) Context { + return context.WithValue(parent, key, val) +} diff --git a/vendor/golang.org/x/net/context/pre_go17.go b/vendor/golang.org/x/net/context/pre_go17.go new file mode 100644 index 00000000..5a30acab --- /dev/null +++ b/vendor/golang.org/x/net/context/pre_go17.go @@ -0,0 +1,300 @@ +// Copyright 2014 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. + +// +build !go1.7 + +package context + +import ( + "errors" + "fmt" + "sync" + "time" +) + +// An emptyCtx is never canceled, has no values, and has no deadline. It is not +// struct{}, since vars of this type must have distinct addresses. +type emptyCtx int + +func (*emptyCtx) Deadline() (deadline time.Time, ok bool) { + return +} + +func (*emptyCtx) Done() <-chan struct{} { + return nil +} + +func (*emptyCtx) Err() error { + return nil +} + +func (*emptyCtx) Value(key interface{}) interface{} { + return nil +} + +func (e *emptyCtx) String() string { + switch e { + case background: + return "context.Background" + case todo: + return "context.TODO" + } + return "unknown empty Context" +} + +var ( + background = new(emptyCtx) + todo = new(emptyCtx) +) + +// Canceled is the error returned by Context.Err when the context is canceled. +var Canceled = errors.New("context canceled") + +// DeadlineExceeded is the error returned by Context.Err when the context's +// deadline passes. +var DeadlineExceeded = errors.New("context deadline exceeded") + +// WithCancel returns a copy of parent with a new Done channel. The returned +// context's Done channel is closed when the returned cancel function is called +// or when the parent context's Done channel is closed, whichever happens first. +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete. +func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { + c := newCancelCtx(parent) + propagateCancel(parent, c) + return c, func() { c.cancel(true, Canceled) } +} + +// newCancelCtx returns an initialized cancelCtx. +func newCancelCtx(parent Context) *cancelCtx { + return &cancelCtx{ + Context: parent, + done: make(chan struct{}), + } +} + +// propagateCancel arranges for child to be canceled when parent is. +func propagateCancel(parent Context, child canceler) { + if parent.Done() == nil { + return // parent is never canceled + } + if p, ok := parentCancelCtx(parent); ok { + p.mu.Lock() + if p.err != nil { + // parent has already been canceled + child.cancel(false, p.err) + } else { + if p.children == nil { + p.children = make(map[canceler]bool) + } + p.children[child] = true + } + p.mu.Unlock() + } else { + go func() { + select { + case <-parent.Done(): + child.cancel(false, parent.Err()) + case <-child.Done(): + } + }() + } +} + +// parentCancelCtx follows a chain of parent references until it finds a +// *cancelCtx. This function understands how each of the concrete types in this +// package represents its parent. +func parentCancelCtx(parent Context) (*cancelCtx, bool) { + for { + switch c := parent.(type) { + case *cancelCtx: + return c, true + case *timerCtx: + return c.cancelCtx, true + case *valueCtx: + parent = c.Context + default: + return nil, false + } + } +} + +// removeChild removes a context from its parent. +func removeChild(parent Context, child canceler) { + p, ok := parentCancelCtx(parent) + if !ok { + return + } + p.mu.Lock() + if p.children != nil { + delete(p.children, child) + } + p.mu.Unlock() +} + +// A canceler is a context type that can be canceled directly. The +// implementations are *cancelCtx and *timerCtx. +type canceler interface { + cancel(removeFromParent bool, err error) + Done() <-chan struct{} +} + +// A cancelCtx can be canceled. When canceled, it also cancels any children +// that implement canceler. +type cancelCtx struct { + Context + + done chan struct{} // closed by the first cancel call. + + mu sync.Mutex + children map[canceler]bool // set to nil by the first cancel call + err error // set to non-nil by the first cancel call +} + +func (c *cancelCtx) Done() <-chan struct{} { + return c.done +} + +func (c *cancelCtx) Err() error { + c.mu.Lock() + defer c.mu.Unlock() + return c.err +} + +func (c *cancelCtx) String() string { + return fmt.Sprintf("%v.WithCancel", c.Context) +} + +// cancel closes c.done, cancels each of c's children, and, if +// removeFromParent is true, removes c from its parent's children. +func (c *cancelCtx) cancel(removeFromParent bool, err error) { + if err == nil { + panic("context: internal error: missing cancel error") + } + c.mu.Lock() + if c.err != nil { + c.mu.Unlock() + return // already canceled + } + c.err = err + close(c.done) + for child := range c.children { + // NOTE: acquiring the child's lock while holding parent's lock. + child.cancel(false, err) + } + c.children = nil + c.mu.Unlock() + + if removeFromParent { + removeChild(c.Context, c) + } +} + +// WithDeadline returns a copy of the parent context with the deadline adjusted +// to be no later than d. If the parent's deadline is already earlier than d, +// WithDeadline(parent, d) is semantically equivalent to parent. The returned +// context's Done channel is closed when the deadline expires, when the returned +// cancel function is called, or when the parent context's Done channel is +// closed, whichever happens first. +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete. +func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { + if cur, ok := parent.Deadline(); ok && cur.Before(deadline) { + // The current deadline is already sooner than the new one. + return WithCancel(parent) + } + c := &timerCtx{ + cancelCtx: newCancelCtx(parent), + deadline: deadline, + } + propagateCancel(parent, c) + d := deadline.Sub(time.Now()) + if d <= 0 { + c.cancel(true, DeadlineExceeded) // deadline has already passed + return c, func() { c.cancel(true, Canceled) } + } + c.mu.Lock() + defer c.mu.Unlock() + if c.err == nil { + c.timer = time.AfterFunc(d, func() { + c.cancel(true, DeadlineExceeded) + }) + } + return c, func() { c.cancel(true, Canceled) } +} + +// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to +// implement Done and Err. It implements cancel by stopping its timer then +// delegating to cancelCtx.cancel. +type timerCtx struct { + *cancelCtx + timer *time.Timer // Under cancelCtx.mu. + + deadline time.Time +} + +func (c *timerCtx) Deadline() (deadline time.Time, ok bool) { + return c.deadline, true +} + +func (c *timerCtx) String() string { + return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now())) +} + +func (c *timerCtx) cancel(removeFromParent bool, err error) { + c.cancelCtx.cancel(false, err) + if removeFromParent { + // Remove this timerCtx from its parent cancelCtx's children. + removeChild(c.cancelCtx.Context, c) + } + c.mu.Lock() + if c.timer != nil { + c.timer.Stop() + c.timer = nil + } + c.mu.Unlock() +} + +// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete: +// +// func slowOperationWithTimeout(ctx context.Context) (Result, error) { +// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) +// defer cancel() // releases resources if slowOperation completes before timeout elapses +// return slowOperation(ctx) +// } +func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { + return WithDeadline(parent, time.Now().Add(timeout)) +} + +// WithValue returns a copy of parent in which the value associated with key is +// val. +// +// Use context Values only for request-scoped data that transits processes and +// APIs, not for passing optional parameters to functions. +func WithValue(parent Context, key interface{}, val interface{}) Context { + return &valueCtx{parent, key, val} +} + +// A valueCtx carries a key-value pair. It implements Value for that key and +// delegates all other calls to the embedded Context. +type valueCtx struct { + Context + key, val interface{} +} + +func (c *valueCtx) String() string { + return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val) +} + +func (c *valueCtx) Value(key interface{}) interface{} { + if c.key == key { + return c.val + } + return c.Context.Value(key) +} diff --git a/vendor/manifest b/vendor/manifest index 63e5d752..8d776fb2 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -38,6 +38,62 @@ "revision": "f9b9f8f7aa27725f5cabb699bd9099ca7ce09143", "branch": "master" }, + { + "importpath": "github.com/cznic/b", + "repository": "https://github.com/cznic/b", + "revision": "47184dd8c1d2c7e7f87dae8448ee2007cdf0c6c4", + "branch": "master", + "notests": true + }, + { + "importpath": "github.com/cznic/bufs", + "repository": "https://github.com/cznic/bufs", + "revision": "3dcccbd7064a1689f9c093a988ea11ac00e21f51", + "branch": "master", + "notests": true + }, + { + "importpath": "github.com/cznic/fileutil", + "repository": "https://github.com/cznic/fileutil", + "revision": "1c9c88fbf552b3737c7b97e1f243860359687976", + "branch": "master", + "notests": true + }, + { + "importpath": "github.com/cznic/mathutil", + "repository": "https://github.com/cznic/mathutil", + "revision": "38a5fe05cd94d69433fd1c928417834c604f281d", + "branch": "master", + "notests": true + }, + { + "importpath": "github.com/cznic/ql", + "repository": "https://github.com/cznic/ql", + "revision": "f5e72a6fe84f25e7539555bdfcee8dc440d93894", + "branch": "master", + "notests": true + }, + { + "importpath": "github.com/cznic/sortutil", + "repository": "https://github.com/cznic/sortutil", + "revision": "4c7342852e65c2088c981288f2c5610d10b9f7f4", + "branch": "master", + "notests": true + }, + { + "importpath": "github.com/cznic/strutil", + "repository": "https://github.com/cznic/strutil", + "revision": "1eb03e3cc9d345307a45ec82bd3016cde4bd4464", + "branch": "master", + "notests": true + }, + { + "importpath": "github.com/cznic/zappy", + "repository": "https://github.com/cznic/zappy", + "revision": "4f5e6ef19fd692f1ef9b01206de4f1161a314e9a", + "branch": "master", + "notests": true + }, { "importpath": "github.com/d4l3k/messagediff", "repository": "https://github.com/d4l3k/messagediff", @@ -51,6 +107,14 @@ "branch": "newlexer", "notests": true }, + { + "importpath": "github.com/golang/groupcache/lru", + "repository": "https://github.com/golang/groupcache", + "revision": "02826c3e79038b59d737d3b1c0a1d937f71a4433", + "branch": "master", + "path": "/lru", + "notests": true + }, { "importpath": "github.com/golang/snappy", "repository": "https://github.com/golang/snappy", @@ -69,6 +133,13 @@ "revision": "29ae4ffbc9a6fe9fb2bc5029050ce6996ea1d3bc", "branch": "master" }, + { + "importpath": "github.com/lib/pq", + "repository": "https://github.com/lib/pq", + "revision": "ee1442bda7bd1b6a84e913bdb421cb1874ec629d", + "branch": "master", + "notests": true + }, { "importpath": "github.com/onsi/ginkgo", "repository": "https://github.com/onsi/ginkgo", @@ -147,6 +218,14 @@ "branch": "master", "path": "/blowfish" }, + { + "importpath": "golang.org/x/net/context", + "repository": "https://go.googlesource.com/net", + "revision": "c4c3ea71919de159c9e246d7be66deb7f0a39a58", + "branch": "master", + "path": "/context", + "notests": true + }, { "importpath": "golang.org/x/net/internal/iana", "repository": "https://go.googlesource.com/net",