<commit_before>package mysql

import (
	"bufio";
	"encoding/binary";
	"os";
	"fmt";
	"reflect";
)

type MySQLStatement struct {
	StatementId	uint32;
	Columns		uint16;
	Parameters	uint16;
	Warnings	uint16;

	ResultSet	*MySQLResultSet;
	mysql		*MySQLInstance;
}

func (sth *MySQLStatement) Execute(va ...) os.Error {
	if sth.Parameters != len(va) {
		return os.ErrorString(fmt.Sprintf("Parameter count mismatch. %d != %d", sth.Parameters, len(va)));
	}
	bitmap_len = (len(va) + 7)/8;
	mysql := sth.mysql;
	packUint24(mysql.writer, uint32(11+bitmap_len+(len(va))*2));
	packUint8(mysql.writer, uint8(1));
	packUint8(mysql.writer, uint8(COM_STMT_EXECUTE));
	packUint32(mysql.writer, uint32(sth.StatementId));
	packUint8(mysql.writer, uint8(0));
	packUint32(mysql.writer, uint32(1));
	b := make([]byte, bitmap_len);
	mysql.writer.Write(b); //TODO: Support null params.
	packUint8(mysql.writer, uint8(1));
	for i := 0
}

func readPrepareInit(br *bufio.Reader) (*MySQLStatement, os.Error) {
	ph := readHeader(br);
	s := new(MySQLStatement);
	ignoreBytes(br, 1);
	err := binary.Read(br, binary.LittleEndian, &s.StatementId);
	err = binary.Read(br, binary.LittleEndian, &s.Columns);
	err = binary.Read(br, binary.LittleEndian, &s.Parameters);
	if ph.Len >= 12 {
		ignoreBytes(br, 1);
		err = binary.Read(br, binary.LittleEndian, &s.Warnings);
//		fmt.Printf("Warnings = %x\n", s.Warnings);
	}
	return s, err;
}

//Currently just skips the pakets as I'm not sure if they are useful.
func readPrepareParameters(br *bufio.Reader, s *MySQLStatement) os.Error {
	for i := uint16(0); i < s.Parameters; i++ {
		ph := readHeader(br);
		ignoreBytes(br, int(ph.Len));
//		fmt.Printf("Ignoring %d bytes\n", ph.Len);
	}
	return nil;
}

func (mysql *MySQLInstance) prepare(arg string) (*MySQLStatement, os.Error) {
	plen := len(arg) + 1;
	var head [5]byte;
	head[0] = byte(plen);
	head[1] = byte(plen >> 8);
	head[2] = byte(plen >> 16);
	head[3] = 0;
	head[4] = uint8(COM_STMT_PREPARE);
	_, err := mysql.writer.Write(&head);
	err = mysql.writer.WriteString(arg);
	err = mysql.writer.Flush();
	if err != nil {
		fmt.Printf("%s\n", err);
		return nil, err;
	}
	sth, err := readPrepareInit(mysql.reader);
//	fmt.Printf("%#v\n", sth);
	if sth.Parameters > 0 {
		readPrepareParameters(mysql.reader, sth)
	}
	readEOFPacket(mysql.reader);
	if sth.Columns > 0 {
		rs, err := mysql.readResultSet(uint64(sth.Columns));
		sth.ResultSet = rs;
	}
	readEOFPacket(mysql.reader);
	sth.mysql = mysql;
	return sth, nil;
}
<commit_msg>Reflection is hard<commit_after>package mysql

import (
	"bufio";
	"encoding/binary";
	"os";
	"fmt";
	"reflect";
)

type MySQLStatement struct {
	StatementId	uint32;
	Columns		uint16;
	Parameters	uint16;
	Warnings	uint16;

	ResultSet	*MySQLResultSet;
	mysql		*MySQLInstance;
}

func encodeTypes(a ...) {
        v := reflect.NewValue(a).(*reflect.StructValue);
        fmt.Printf("%d\n", v.NumField());
        for i := 0; i < v.NumField(); i ++ {
                f := v.Field(i);
                fmt.Printf("%#v\n", f);
                if _, ok := f.(*reflect.StringValue); ok {
                        fmt.Printf("%s\n", "STRING");
                }
        }
}

func (sth *MySQLStatement) Execute(va ...) os.Error {
	if sth.Parameters != len(va) {
		return os.ErrorString(fmt.Sprintf("Parameter count mismatch. %d != %d", sth.Parameters, len(va)));
	}
	bitmap_len = (len(va) + 7)/8;
	mysql := sth.mysql;
	packUint24(mysql.writer, uint32(11+bitmap_len+(len(va))*2));
	packUint8(mysql.writer, uint8(1));
	packUint8(mysql.writer, uint8(COM_STMT_EXECUTE));
	packUint32(mysql.writer, uint32(sth.StatementId));
	packUint8(mysql.writer, uint8(0));
	packUint32(mysql.writer, uint32(1));
	b := make([]byte, bitmap_len);
	mysql.writer.Write(b); //TODO: Support null params.
	packUint8(mysql.writer, uint8(1));
	encodeTypes(va);}
}

func readPrepareInit(br *bufio.Reader) (*MySQLStatement, os.Error) {
	ph := readHeader(br);
	s := new(MySQLStatement);
	ignoreBytes(br, 1);
	err := binary.Read(br, binary.LittleEndian, &s.StatementId);
	err = binary.Read(br, binary.LittleEndian, &s.Columns);
	err = binary.Read(br, binary.LittleEndian, &s.Parameters);
	if ph.Len >= 12 {
		ignoreBytes(br, 1);
		err = binary.Read(br, binary.LittleEndian, &s.Warnings);
//		fmt.Printf("Warnings = %x\n", s.Warnings);
	}
	return s, err;
}

//Currently just skips the pakets as I'm not sure if they are useful.
func readPrepareParameters(br *bufio.Reader, s *MySQLStatement) os.Error {
	for i := uint16(0); i < s.Parameters; i++ {
		ph := readHeader(br);
		ignoreBytes(br, int(ph.Len));
//		fmt.Printf("Ignoring %d bytes\n", ph.Len);
	}
	return nil;
}

func (mysql *MySQLInstance) prepare(arg string) (*MySQLStatement, os.Error) {
	plen := len(arg) + 1;
	var head [5]byte;
	head[0] = byte(plen);
	head[1] = byte(plen >> 8);
	head[2] = byte(plen >> 16);
	head[3] = 0;
	head[4] = uint8(COM_STMT_PREPARE);
	_, err := mysql.writer.Write(&head);
	err = mysql.writer.WriteString(arg);
	err = mysql.writer.Flush();
	if err != nil {
		fmt.Printf("%s\n", err);
		return nil, err;
	}
	sth, err := readPrepareInit(mysql.reader);
//	fmt.Printf("%#v\n", sth);
	if sth.Parameters > 0 {
		readPrepareParameters(mysql.reader, sth)
	}
	readEOFPacket(mysql.reader);
	if sth.Columns > 0 {
		rs, err := mysql.readResultSet(uint64(sth.Columns));
		sth.ResultSet = rs;
	}
	readEOFPacket(mysql.reader);
	sth.mysql = mysql;
	return sth, nil;
}
<|endoftext|>


<commit_before>package ngorm

import (
	"strings"
	"testing"

	_ "github.com/cznic/ql/driver"
	"github.com/gernest/ngorm/fixture"
)

type Foo struct {
	ID    int
	Stuff string
}

func TestDB(t *testing.T) {
	db, err := Open("ql-mem", "test.db")
	if err != nil {
		t.Fatal(err)
	}

	// create table tests
	sql, err := db.CreateTableSQL(&Foo{})
	if err != nil {
		t.Fatal(err)
	}
	expect := `
BEGIN TRANSACTION;
	CREATE TABLE foos (id int,stuff string ) ;
COMMIT;`
	expect = strings.TrimSpace(expect)
	if sql.Q != expect {
		t.Errorf("expected %s got %s", expect, sql.Q)
	}
	_, err = db.CreateTable(&Foo{})
	if err != nil {
		t.Error(err)
	}

	// multiple tables
	sql, err = db.CreateTableSQL(
		&fixture.User{},
	)
	if err != nil {
		t.Fatal(err)
	}
	expect = `
BEGIN TRANSACTION;
	CREATE TABLE users (id int64,age int64,user_num int64,name string,email string,birthday time,created_at time,updated_at time,billing_address_id int64,shipping_address_id int64,latitude float64,company_id int,role string,password_hash blob,sequence uint ) ;
	CREATE TABLE user_languages (user_id uint,language_id uint ) ;
COMMIT;`
	expect = strings.TrimSpace(expect)
	if sql.Q != expect {
		t.Errorf("expected %s got %s", expect, sql.Q)
	}
	_, err = db.CreateTable(&fixture.User{})
	if err != nil {
		t.Error(err)
	}
}
<commit_msg>[ngorm] Ensure the connection is closed after exiting test function<commit_after>package ngorm

import (
	"strings"
	"testing"

	_ "github.com/cznic/ql/driver"
	"github.com/gernest/ngorm/fixture"
)

type Foo struct {
	ID    int
	Stuff string
}

func TestDB_CreateTable(t *testing.T) {
	db, err := Open("ql-mem", "test.db")
	if err != nil {
		t.Fatal(err)
	}
	defer func() { _ = db.Close() }()

	// create table tests
	sql, err := db.CreateTableSQL(&Foo{})
	if err != nil {
		t.Fatal(err)
	}
	expect := `
BEGIN TRANSACTION;
	CREATE TABLE foos (id int,stuff string ) ;
COMMIT;`
	expect = strings.TrimSpace(expect)
	if sql.Q != expect {
		t.Errorf("expected %s got %s", expect, sql.Q)
	}
	_, err = db.CreateTable(&Foo{})
	if err != nil {
		t.Error(err)
	}

	// multiple tables
	sql, err = db.CreateTableSQL(
		&fixture.User{},
	)
	if err != nil {
		t.Fatal(err)
	}
	expect = `
BEGIN TRANSACTION;
	CREATE TABLE users (id int64,age int64,user_num int64,name string,email string,birthday time,created_at time,updated_at time,billing_address_id int64,shipping_address_id int64,latitude float64,company_id int,role string,password_hash blob,sequence uint ) ;
	CREATE TABLE user_languages (user_id uint,language_id uint ) ;
COMMIT;`
	expect = strings.TrimSpace(expect)
	if sql.Q != expect {
		t.Errorf("expected %s got %s", expect, sql.Q)
	}
	_, err = db.CreateTable(&fixture.User{})
	if err != nil {
		t.Error(err)
	}
}
<|endoftext|>


<commit_before>// Copyright ©2014 The gonum 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 optimize

// Linesearch is a type that can perform a line search. Typically, these
// methods will not be called by the user directly, as they will be called by
// a LinesearchHelper struct.
type Linesearch interface {
	// Init initializes the linesearch method. LinesearchLocation contains the
	// function information at step == 0, and step contains the first step length
	// as specified by the NextDirectioner.
	Init(value, derivative float64, step float64) EvaluationType

	// Finished takes in the function result at the most recent linesearch location,
	// and returns true if the line search has been concluded.
	Finished(value, derivative float64) bool

	// Iterate takes in the function results
	// from evaluating the function at the previous step, and returns the
	// next step size and EvaluationType to evaluate.
	Iterate(value, derivative float64) (step float64, e EvaluationType, err error)
}

// NextDirectioner implements a strategy for computing a new line search direction
// at each major iteration. Typically, these methods will not be called by the user directly,
// as they will be called by a Linesearch struct.
type NextDirectioner interface {
	// InitDirection initializes the NextDirectioner at the given starting location,
	// putting the initial direction in place into dir, and returning the initial
	// step size. InitDirection must not modify Location.
	InitDirection(loc *Location, dir []float64) (step float64)

	// NextDirection updates the search direction and step size. Location is
	// the location seen at the conclusion of the most recent linesearch. The
	// next search direction is put in place into dir, and the next step size
	// is returned. NextDirection must not modify Location.
	NextDirection(loc *Location, dir []float64) (step float64)
}

// A Method can optimize an objective function.
type Method interface {
	// Initializes the method and returns the first location to evaluate
	Init(loc *Location, xNext []float64) (EvaluationType, IterationType, error)

	// Stores the next location to evaluate in xNext
	Iterate(loc *Location, xNext []float64) (EvaluationType, IterationType, error)

	// Needs specifies information about the objective function needed by the
	// optimizer beyond just the function value. The information is used
	// internally for initialization and must match evaluation types returned
	// by Init() and Iterate() during the optimization process.
	Needs() struct {
		Gradient bool
		Hessian  bool
	}
}

// StepSizer can set the next step size of the optimization given the last Location.
// Returned step size must be positive.
type StepSizer interface {
	Init(loc *Location, dir []float64) float64
	StepSize(loc *Location, dir []float64) float64
}

// Statuser returns the status of the Function being optimized. This can be used
// by the Function to terminate early, for example with an error. The user can
// use one of the pre-provided Status constants, or may call NewStatus to create
// a custom Status value.
type Statuser interface {
	Status() (Status, error)
}

// A Recorder can record the progress of the optimization, for example to print
// the progress to StdOut or to a log file. A Recorder must not modify any data.
type Recorder interface {
	Init() error
	Record(*Location, EvaluationType, IterationType, *Stats) error
}
<commit_msg>Update and improve documentation for Method, Linesearch and NextDirectioner<commit_after>// Copyright ©2014 The gonum 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 optimize

// A Method can optimize an objective function.
type Method interface {
	// Init initializes the method and stores the first location to evaluate
	// in xNext.
	Init(loc *Location, xNext []float64) (EvaluationType, IterationType, error)

	// Iterate performs one iteration of the method and stores the next
	// location to evaluate in xNext.
	Iterate(loc *Location, xNext []float64) (EvaluationType, IterationType, error)

	// Needs specifies information about the objective function needed by the
	// optimizer beyond just the function value. The information is used
	// internally for initialization and must match evaluation types returned
	// by Init() and Iterate() during the optimization process.
	Needs() struct {
		Gradient bool
		Hessian  bool
	}
}

// Linesearch is a type that can perform a line search. It tries to find an
// (approximate) minimum of the objective function along the search direction
// dir_k starting at the most recent location x_k, i.e., it tries to minimize a
// function
//  φ(step) := f(x_k + step * dir_k), step > 0.
// Typically, these methods will not be called by the user directly, as they
// will be called by the LinesearchHelper struct.
type Linesearch interface {
	// Init initializes the linesearch method. Value and derivative contain
	// φ(0) and φ'(0), respectively, and step contains the first trial step
	// length as returned by the NextDirectioner.InitDirection(). It returns
	// the type of evaluation to be performed at x_0 + step * dir_0.
	Init(value, derivative float64, step float64) EvaluationType

	// Finished takes in the values of φ and φ' evaluated at the previous step,
	// and returns whether a sufficiently accurate minimum of φ has been found.
	Finished(value, derivative float64) bool

	// Iterate takes in the values of φ and φ' evaluated at the previous step
	// and returns the next step size and the type of evaluation to be
	// performed at x_k + step * dir_k.
	Iterate(value, derivative float64) (step float64, e EvaluationType, err error)
}

// NextDirectioner implements a strategy for computing a new line search
// direction at each major iteration. Typically, these methods will not be
// called by the user directly, as they will be called by the LinesearchHelper
// struct.
type NextDirectioner interface {
	// InitDirection initializes the NextDirectioner at the given starting location,
	// putting the initial direction in place into dir, and returning the initial
	// step size. InitDirection must not modify Location.
	InitDirection(loc *Location, dir []float64) (step float64)

	// NextDirection updates the search direction and step size. Location is
	// the location seen at the conclusion of the most recent linesearch. The
	// next search direction is put in place into dir, and the next step size
	// is returned. NextDirection must not modify Location.
	NextDirection(loc *Location, dir []float64) (step float64)
}

// StepSizer can set the next step size of the optimization given the last Location.
// Returned step size must be positive.
type StepSizer interface {
	Init(loc *Location, dir []float64) float64
	StepSize(loc *Location, dir []float64) float64
}

// Statuser returns the status of the Function being optimized. This can be used
// by the Function to terminate early, for example with an error. The user can
// use one of the pre-provided Status constants, or may call NewStatus to create
// a custom Status value.
type Statuser interface {
	Status() (Status, error)
}

// A Recorder can record the progress of the optimization, for example to print
// the progress to StdOut or to a log file. A Recorder must not modify any data.
type Recorder interface {
	Init() error
	Record(*Location, EvaluationType, IterationType, *Stats) error
}
<|endoftext|>


<commit_before>package gocassa

import (
	"time"
)

// The Connection interface only exists because one can not connect to a keyspace if it does not exist, thus having a Create on KeySpace is not possible.
// Use ConnectToKeySpace to acquire an instance of KeySpace.
type Connection interface {
	CreateKeySpace(name string) error
	DropKeySpace(name string) error
	KeySpace(name string) KeySpace
}

type KeySpace interface {
	MapTable(tableName, id string, row interface{}) MapTable
	MultimapTable(tableName, fieldToIndexBy, uniqueKey string, row interface{}) MultimapTable
	TimeSeriesTable(tableName, timeField, uniqueKey string, bucketSize time.Duration, row interface{}) TimeSeriesTable
	MultiTimeSeriesTable(tableName, fieldToIndexByField, timeField, uniqueKey string, bucketSize time.Duration, row interface{}) MultiTimeSeriesTable
	Table(tableName string, row interface{}, keys Keys) Table
	DebugMode(bool)
	// QueryExecutor returns the configured executor for this KeySpace
	QueryExecutor() QueryExecutor
	// Tables returns the name of all configured column families in this keyspace
	Tables() ([]string, error)
	// Exists returns whether the specified column family exists within the keyspace
	Exists(string) (bool, error)
}

//
// Map recipe
//

type MapTable interface {
	SetWithOptions(v interface{}, opts Options) Op
	Set(v interface{}) Op
	UpdateWithOptions(id interface{}, m map[string]interface{}, opts Options) Op
	Update(id interface{}, m map[string]interface{}) Op
	Delete(id interface{}) Op
	Read(id, pointer interface{}) Op
	MultiRead(ids []interface{}, pointerToASlice interface{}) Op
	TableChanger
}

//
// Multimap recipe
//

// Multimap lets you list rows based on a field equality, eg. 'list all sales where seller id = v'.
type MultimapTable interface {
	SetWithOptions(v interface{}, opts Options) Op
	Set(v interface{}) Op
	UpdateWithOptions(v, id interface{}, m map[string]interface{}, opts Options) Op
	Update(v, id interface{}, m map[string]interface{}) Op
	Delete(v, id interface{}) Op
	DeleteAll(v interface{}) Op
	List(v, startId interface{}, limit int, pointerToASlice interface{}) Op
	Read(v, id, pointer interface{}) Op
	MultiRead(v interface{}, ids []interface{}, pointerToASlice interface{}) Op
	TableChanger
}

//
// TimeSeries recipe
//

// TimeSeries lets you list rows which have a field value between two date ranges.
type TimeSeriesTable interface {
	// timeField and idField must be present
	SetWithOptions(v interface{}, opts Options) Op
	Set(v interface{}) Op
	UpdateWithOptions(timeStamp time.Time, id interface{}, m map[string]interface{}, opts Options) Op
	Update(timeStamp time.Time, id interface{}, m map[string]interface{}) Op
	Delete(timeStamp time.Time, id interface{}) Op
	Read(timeStamp time.Time, id, pointer interface{}) Op
	List(start, end time.Time, pointerToASlice interface{}) Op
	TableChanger
}

//
// TimeSeries B recipe
//

// MultiTimeSeries is a cross between TimeSeries and Multimap tables.
type MultiTimeSeriesTable interface {
	// timeField and idField must be present
	SetWithOptions(v interface{}, opts Options) Op
	Set(v interface{}) Op
	UpdateWithOptions(v interface{}, timeStamp time.Time, id interface{}, m map[string]interface{}, opts Options) Op
	Update(v interface{}, timeStamp time.Time, id interface{}, m map[string]interface{}) Op
	Delete(v interface{}, timeStamp time.Time, id interface{}) Op
	Read(v interface{}, timeStamp time.Time, id, pointer interface{}) Op
	List(v interface{}, start, end time.Time, pointerToASlice interface{}) Op
	TableChanger
}

//
// Raw CQL
//

// A Query is a subset of a Table intended to be read
type Query interface {
	Read(pointerToASlice interface{}) Op
	ReadOne(pointer interface{}) Op
	Limit(int) Query
}

// A Filter is a subset of a Table, filtered by Relations.
// You can do writes or reads on a filter.
type Filter interface {
	// Selection modifiers
	Query() Query
	// Partial update.
	Update(m map[string]interface{}) Op // Probably this is danger zone (can't be implemented efficiently) on a selectuinb with more than 1 document
	UpdateWithOptions(m map[string]interface{}, opts Options) Op
	Delete() Op
}

type Keys struct {
	PartitionKeys     []string
	ClusteringColumns []string
}

type Op interface {
	Run() error
	// You do not need this in 95% of the use cases, use Run!
	// Using atmoic batched writes (logged batches in Cassandra terminolohu) comes at a high performance cost!
	RunAtomically() error
	Add(...Op) Op
}

// Danger zone! Do not use this interface unless you really know what you are doing
type TableChanger interface {
	Create() error
	CreateStatement() (string, error)
	Recreate() error
	// Name returns the name of the keyspace, as in C*
	Name() string
	//Drop() error
	//CreateIfDoesNotExist() error
}

type Table interface {
	// Set Inserts, or Replaces your row with the supplied struct. Be aware that what is not in your struct
	// will be deleted. To only overwrite some of the fields, use Query.Update.
	Set(v interface{}) Op
	SetWithOptions(v interface{}, opts Options) Op
	Where(relations ...Relation) Filter // Because we provide selections
	// Name returns the underlying table name, as stored in C*
	TableChanger
}

type QueryExecutor interface {
	Query(stmt string, params ...interface{}) ([]map[string]interface{}, error)
	Execute(stmt string, params ...interface{}) error
	ExecuteAtomically(stmt []string, params [][]interface{}) error
}
<commit_msg>Update interfaces.go<commit_after>package gocassa

import (
	"time"
)

// The Connection interface only exists because one can not connect to a keyspace if it does not exist, thus having a Create on KeySpace is not possible.
// Use ConnectToKeySpace to acquire an instance of KeySpace.
type Connection interface {
	CreateKeySpace(name string) error
	DropKeySpace(name string) error
	KeySpace(name string) KeySpace
}

type KeySpace interface {
	MapTable(tableName, id string, row interface{}) MapTable
	MultimapTable(tableName, fieldToIndexBy, uniqueKey string, row interface{}) MultimapTable
	TimeSeriesTable(tableName, timeField, uniqueKey string, bucketSize time.Duration, row interface{}) TimeSeriesTable
	MultiTimeSeriesTable(tableName, fieldToIndexByField, timeField, uniqueKey string, bucketSize time.Duration, row interface{}) MultiTimeSeriesTable
	Table(tableName string, row interface{}, keys Keys) Table
	DebugMode(bool)
	// QueryExecutor returns the configured executor for this KeySpace
	QueryExecutor() QueryExecutor
	// Tables returns the name of all configured column families in this keyspace
	Tables() ([]string, error)
	// Exists returns whether the specified column family exists within the keyspace
	Exists(string) (bool, error)
}

//
// Map recipe
//

type MapTable interface {
	SetWithOptions(v interface{}, opts Options) Op
	Set(v interface{}) Op
	UpdateWithOptions(id interface{}, m map[string]interface{}, opts Options) Op
	Update(id interface{}, m map[string]interface{}) Op
	Delete(id interface{}) Op
	Read(id, pointer interface{}) Op
	MultiRead(ids []interface{}, pointerToASlice interface{}) Op
	TableChanger
}

//
// Multimap recipe
//

// Multimap lets you list rows based on a field equality, eg. 'list all sales where seller id = v'.
type MultimapTable interface {
	SetWithOptions(v interface{}, opts Options) Op
	Set(v interface{}) Op
	UpdateWithOptions(v, id interface{}, m map[string]interface{}, opts Options) Op
	Update(v, id interface{}, m map[string]interface{}) Op
	Delete(v, id interface{}) Op
	DeleteAll(v interface{}) Op
	List(v, startId interface{}, limit int, pointerToASlice interface{}) Op
	Read(v, id, pointer interface{}) Op
	MultiRead(v interface{}, ids []interface{}, pointerToASlice interface{}) Op
	TableChanger
}

//
// TimeSeries recipe
//

// TimeSeries lets you list rows which have a field value between two date ranges.
type TimeSeriesTable interface {
	// timeField and idField must be present
	SetWithOptions(v interface{}, opts Options) Op
	Set(v interface{}) Op
	UpdateWithOptions(timeStamp time.Time, id interface{}, m map[string]interface{}, opts Options) Op
	Update(timeStamp time.Time, id interface{}, m map[string]interface{}) Op
	Delete(timeStamp time.Time, id interface{}) Op
	Read(timeStamp time.Time, id, pointer interface{}) Op
	List(start, end time.Time, pointerToASlice interface{}) Op
	TableChanger
}

//
// TimeSeries B recipe
//

// MultiTimeSeries is a cross between TimeSeries and Multimap tables.
type MultiTimeSeriesTable interface {
	// timeField and idField must be present
	SetWithOptions(v interface{}, opts Options) Op
	Set(v interface{}) Op
	UpdateWithOptions(v interface{}, timeStamp time.Time, id interface{}, m map[string]interface{}, opts Options) Op
	Update(v interface{}, timeStamp time.Time, id interface{}, m map[string]interface{}) Op
	Delete(v interface{}, timeStamp time.Time, id interface{}) Op
	Read(v interface{}, timeStamp time.Time, id, pointer interface{}) Op
	List(v interface{}, start, end time.Time, pointerToASlice interface{}) Op
	TableChanger
}

//
// Raw CQL
//

// A Query is a subset of a Table intended to be read
type Query interface {
	Read(pointerToASlice interface{}) Op
	ReadOne(pointer interface{}) Op
	Limit(int) Query
}

// A Filter is a subset of a Table, filtered by Relations.
// You can do writes or reads on a filter.
type Filter interface {
	// Selection modifiers
	Query() Query
	// Partial update.
	Update(m map[string]interface{}) Op // Probably this is danger zone (can't be implemented efficiently) on a selectuinb with more than 1 document
	UpdateWithOptions(m map[string]interface{}, opts Options) Op
	Delete() Op
}

type Keys struct {
	PartitionKeys     []string
	ClusteringColumns []string
}

type Op interface {
	Run() error
	// You do not need this in 95% of the use cases, use Run!
	// Using atomic batched writes (logged batches in Cassandra terminolohu) comes at a high performance cost!
	RunAtomically() error
	Add(...Op) Op
}

// Danger zone! Do not use this interface unless you really know what you are doing
type TableChanger interface {
	Create() error
	CreateStatement() (string, error)
	Recreate() error
	// Name returns the name of the keyspace, as in C*
	Name() string
	//Drop() error
	//CreateIfDoesNotExist() error
}

type Table interface {
	// Set Inserts, or Replaces your row with the supplied struct. Be aware that what is not in your struct
	// will be deleted. To only overwrite some of the fields, use Query.Update.
	Set(v interface{}) Op
	SetWithOptions(v interface{}, opts Options) Op
	Where(relations ...Relation) Filter // Because we provide selections
	// Name returns the underlying table name, as stored in C*
	TableChanger
}

type QueryExecutor interface {
	Query(stmt string, params ...interface{}) ([]map[string]interface{}, error)
	Execute(stmt string, params ...interface{}) error
	ExecuteAtomically(stmt []string, params [][]interface{}) error
}
<|endoftext|>


<commit_before>package filter

import (
	"bufio"
	"bytes"
	"unicode"

	"io"
)

// NewNodeReaderFilter 创建节点过滤器，实现敏感词的过滤
// 从可读流中读取敏感词数据(以指定的分隔符读取数据)
func NewNodeReaderFilter(rd io.Reader, delim byte) DirtyFilter {
	nf := &nodeFilter{
		root: newNode(),
	}
	buf := new(bytes.Buffer)
	io.Copy(buf, rd)
	buf.WriteByte(delim)
	for {
		line, err := buf.ReadString(delim)
		if err != nil {
			break
		}
		if line == "" {
			continue
		}
		nf.addDirtyWords(line)
	}
	buf.Reset()
	return nf
}

// NewNodeChanFilter 创建节点过滤器，实现敏感词的过滤
// 从通道中读取敏感词数据
func NewNodeChanFilter(text <-chan string) DirtyFilter {
	nf := &nodeFilter{
		root: newNode(),
	}
	for v := range text {
		nf.addDirtyWords(v)
	}
	return nf
}

// NewNodeFilter 创建节点过滤器，实现敏感词的过滤
// 从切片中读取敏感词数据
func NewNodeFilter(text []string) DirtyFilter {
	nf := &nodeFilter{
		root: newNode(),
	}
	for i, l := 0, len(text); i < l; i++ {
		nf.addDirtyWords(text[i])
	}
	return nf
}

func newNode() *node {
	return &node{
		child: make(map[rune]*node),
	}
}

type node struct {
	end   bool
	child map[rune]*node
}

type nodeFilter struct {
	root *node
}

func (nf *nodeFilter) addDirtyWords(text string) {
	n := nf.root
	uchars := []rune(text)
	for i, l := 0, len(uchars); i < l; i++ {
		if unicode.IsSpace(uchars[i]) {
			continue
		}
		if _, ok := n.child[uchars[i]]; !ok {
			n.child[uchars[i]] = newNode()
		}
		n = n.child[uchars[i]]
	}
	n.end = true
}

func (nf *nodeFilter) Filter(text string, excludes ...rune) ([]string, error) {
	buf := bytes.NewBufferString(text)
	defer buf.Reset()
	return nf.FilterReader(buf, excludes...)
}

func (nf *nodeFilter) FilterResult(text string, excludes ...rune) (map[string]int, error) {
	buf := bytes.NewBufferString(text)
	defer buf.Reset()
	return nf.FilterReaderResult(buf, excludes...)
}

func (nf *nodeFilter) FilterReader(reader io.Reader, excludes ...rune) ([]string, error) {
	data, err := nf.FilterReaderResult(reader, excludes...)
	if err != nil {
		return nil, err
	}
	var result []string
	for k := range data {
		result = append(result, k)
	}
	return result, nil
}

func (nf *nodeFilter) FilterReaderResult(reader io.Reader, excludes ...rune) (map[string]int, error) {
	var (
		uchars []rune
	)
	data := make(map[string]int)
	bi := bufio.NewReader(reader)
	for {
		ur, _, err := bi.ReadRune()
		if err != nil {
			if err != io.EOF {
				return nil, err
			}
			break
		}
		if nf.checkExclude(ur, excludes...) {
			continue
		}
		if (unicode.IsSpace(ur) || unicode.IsPunct(ur)) && len(uchars) > 0 {
			nf.doFilter(uchars[:], data)
			uchars = nil
			continue
		}
		uchars = append(uchars, ur)
	}
	if len(uchars) > 0 {
		nf.doFilter(uchars, data)
	}
	return data, nil
}

func (nf *nodeFilter) Replace(text string, delim rune, excludes ...rune) (string, error) {
	uchars := []rune(text)
	idexs := nf.doIndexes(uchars, excludes...)
	for i := 0; i < len(idexs); i++ {
		uchars[idexs[i]] = rune(delim)
	}
	return string(uchars), nil
}

func (nf *nodeFilter) checkExclude(u rune, excludes ...rune) bool {
	if len(excludes) == 0 {
		return false
	}
	var exist bool
	for i, l := 0, len(excludes); i < l; i++ {
		if u == excludes[i] {
			exist = true
			break
		}
	}
	return exist
}

func (nf *nodeFilter) doFilter(uchars []rune, data map[string]int) {
	var result []string
	ul := len(uchars)
	buf := new(bytes.Buffer)
	n := nf.root
	for i := 0; i < ul; i++ {
		if _, ok := n.child[uchars[i]]; !ok {
			continue
		}
		n = n.child[uchars[i]]
		buf.WriteRune(uchars[i])
		if n.end {
			result = append(result, buf.String())
		}
		for j := i + 1; j < ul; j++ {
			if _, ok := n.child[uchars[j]]; !ok {
				break
			}
			n = n.child[uchars[j]]
			buf.WriteRune(uchars[j])
			if n.end {
				result = append(result, buf.String())
			}
		}
		buf.Reset()
		n = nf.root
	}
	for i, l := 0, len(result); i < l; i++ {
		var c int
		if v, ok := data[result[i]]; ok {
			c = v
		}
		data[result[i]] = c + 1
	}
}

func (nf *nodeFilter) doIndexes(uchars []rune, excludes ...rune) (idexs []int) {
	var (
		tIdexs []int
		ul     = len(uchars)
		n      = nf.root
	)
	for i := 0; i < ul; i++ {
		if nf.checkExclude(uchars[i], excludes...) {
			continue
		}

		if _, ok := n.child[uchars[i]]; !ok {
			continue
		}
		n = n.child[uchars[i]]
		tIdexs = append(tIdexs, i)
		if n.end {
			idexs = nf.appendTo(idexs, tIdexs)
			tIdexs = nil
		}
		for j := i + 1; j < ul; j++ {
			if nf.checkExclude(uchars[j], excludes...) {
				tIdexs = append(tIdexs, j)
			} else {
				if _, ok := n.child[uchars[j]]; !ok {
					break
				}
				n = n.child[uchars[j]]
				tIdexs = append(tIdexs, j)
				if n.end {
					idexs = nf.appendTo(idexs, tIdexs)
				}
			}
		}
		if tIdexs != nil {
			tIdexs = nil
		}
		n = nf.root
	}
	return
}

func (nf *nodeFilter) appendTo(dst, src []int) []int {
	var t []int
	for i, il := 0, len(src); i < il; i++ {
		var exist bool
		for j, jl := 0, len(dst); j < jl; j++ {
			if src[i] == dst[j] {
				exist = true
				break
			}
		}
		if !exist {
			t = append(t, src[i])
		}
	}
	return append(dst, t...)
}
<commit_msg>fixed Replace<commit_after>package filter

import (
	"bufio"
	"bytes"
	"unicode"

	"io"
)

// NewNodeReaderFilter 创建节点过滤器，实现敏感词的过滤
// 从可读流中读取敏感词数据(以指定的分隔符读取数据)
func NewNodeReaderFilter(rd io.Reader, delim byte) DirtyFilter {
	nf := &nodeFilter{
		root: newNode(),
	}
	buf := new(bytes.Buffer)
	io.Copy(buf, rd)
	buf.WriteByte(delim)
	for {
		line, err := buf.ReadString(delim)
		if err != nil {
			break
		}
		if line == "" {
			continue
		}
		nf.addDirtyWords(line)
	}
	buf.Reset()
	return nf
}

// NewNodeChanFilter 创建节点过滤器，实现敏感词的过滤
// 从通道中读取敏感词数据
func NewNodeChanFilter(text <-chan string) DirtyFilter {
	nf := &nodeFilter{
		root: newNode(),
	}
	for v := range text {
		nf.addDirtyWords(v)
	}
	return nf
}

// NewNodeFilter 创建节点过滤器，实现敏感词的过滤
// 从切片中读取敏感词数据
func NewNodeFilter(text []string) DirtyFilter {
	nf := &nodeFilter{
		root: newNode(),
	}
	for i, l := 0, len(text); i < l; i++ {
		nf.addDirtyWords(text[i])
	}
	return nf
}

func newNode() *node {
	return &node{
		child: make(map[rune]*node),
	}
}

type node struct {
	end   bool
	child map[rune]*node
}

type nodeFilter struct {
	root *node
}

func (nf *nodeFilter) addDirtyWords(text string) {
	n := nf.root
	uchars := []rune(text)
	for i, l := 0, len(uchars); i < l; i++ {
		if unicode.IsSpace(uchars[i]) {
			continue
		}
		if _, ok := n.child[uchars[i]]; !ok {
			n.child[uchars[i]] = newNode()
		}
		n = n.child[uchars[i]]
	}
	n.end = true
}

func (nf *nodeFilter) Filter(text string, excludes ...rune) ([]string, error) {
	buf := bytes.NewBufferString(text)
	defer buf.Reset()
	return nf.FilterReader(buf, excludes...)
}

func (nf *nodeFilter) FilterResult(text string, excludes ...rune) (map[string]int, error) {
	buf := bytes.NewBufferString(text)
	defer buf.Reset()
	return nf.FilterReaderResult(buf, excludes...)
}

func (nf *nodeFilter) FilterReader(reader io.Reader, excludes ...rune) ([]string, error) {
	data, err := nf.FilterReaderResult(reader, excludes...)
	if err != nil {
		return nil, err
	}
	var result []string
	for k := range data {
		result = append(result, k)
	}
	return result, nil
}

func (nf *nodeFilter) FilterReaderResult(reader io.Reader, excludes ...rune) (map[string]int, error) {
	var (
		uchars []rune
	)
	data := make(map[string]int)
	bi := bufio.NewReader(reader)
	for {
		ur, _, err := bi.ReadRune()
		if err != nil {
			if err != io.EOF {
				return nil, err
			}
			break
		}
		if nf.checkExclude(ur, excludes...) {
			continue
		}
		if (unicode.IsSpace(ur) || unicode.IsPunct(ur)) && len(uchars) > 0 {
			nf.doFilter(uchars[:], data)
			uchars = nil
			continue
		}
		uchars = append(uchars, ur)
	}
	if len(uchars) > 0 {
		nf.doFilter(uchars, data)
	}
	return data, nil
}

func (nf *nodeFilter) Replace(text string, delim rune, excludes ...rune) (string, error) {
	uchars := []rune(text)
	idexs := nf.doIndexes(uchars, excludes...)
	if len(idexs) == 0 {
		return "", nil
	}
	for i := 0; i < len(idexs); i++ {
		uchars[idexs[i]] = rune(delim)
	}
	return string(uchars), nil
}

func (nf *nodeFilter) checkExclude(u rune, excludes ...rune) bool {
	if len(excludes) == 0 {
		return false
	}
	var exist bool
	for i, l := 0, len(excludes); i < l; i++ {
		if u == excludes[i] {
			exist = true
			break
		}
	}
	return exist
}

func (nf *nodeFilter) doFilter(uchars []rune, data map[string]int) {
	var result []string
	ul := len(uchars)
	buf := new(bytes.Buffer)
	n := nf.root
	for i := 0; i < ul; i++ {
		if _, ok := n.child[uchars[i]]; !ok {
			continue
		}
		n = n.child[uchars[i]]
		buf.WriteRune(uchars[i])
		if n.end {
			result = append(result, buf.String())
		}
		for j := i + 1; j < ul; j++ {
			if _, ok := n.child[uchars[j]]; !ok {
				break
			}
			n = n.child[uchars[j]]
			buf.WriteRune(uchars[j])
			if n.end {
				result = append(result, buf.String())
			}
		}
		buf.Reset()
		n = nf.root
	}
	for i, l := 0, len(result); i < l; i++ {
		var c int
		if v, ok := data[result[i]]; ok {
			c = v
		}
		data[result[i]] = c + 1
	}
}

func (nf *nodeFilter) doIndexes(uchars []rune, excludes ...rune) (idexs []int) {
	var (
		tIdexs []int
		ul     = len(uchars)
		n      = nf.root
	)
	for i := 0; i < ul; i++ {
		if nf.checkExclude(uchars[i], excludes...) {
			continue
		}

		if _, ok := n.child[uchars[i]]; !ok {
			continue
		}
		n = n.child[uchars[i]]
		tIdexs = append(tIdexs, i)
		if n.end {
			idexs = nf.appendTo(idexs, tIdexs)
			tIdexs = nil
		}
		for j := i + 1; j < ul; j++ {
			if nf.checkExclude(uchars[j], excludes...) {
				tIdexs = append(tIdexs, j)
			} else {
				if _, ok := n.child[uchars[j]]; !ok {
					break
				}
				n = n.child[uchars[j]]
				tIdexs = append(tIdexs, j)
				if n.end {
					idexs = nf.appendTo(idexs, tIdexs)
				}
			}
		}
		if tIdexs != nil {
			tIdexs = nil
		}
		n = nf.root
	}
	return
}

func (nf *nodeFilter) appendTo(dst, src []int) []int {
	var t []int
	for i, il := 0, len(src); i < il; i++ {
		var exist bool
		for j, jl := 0, len(dst); j < jl; j++ {
			if src[i] == dst[j] {
				exist = true
				break
			}
		}
		if !exist {
			t = append(t, src[i])
		}
	}
	return append(dst, t...)
}
<|endoftext|>


<commit_before>package app

import (
	"github.com/fragmenta/router"
	"github.com/kennygrant/gohackernews/src/comments/actions"
	"github.com/kennygrant/gohackernews/src/stories/actions"
	"github.com/kennygrant/gohackernews/src/users/actions"
)

// Define routes for this app
func setupRoutes(r *router.Router) {

	// Set the default file handler
	r.FileHandler = fileHandler
	r.ErrorHandler = errHandler

	// Add the home page route
	r.Add("/", storyactions.HandleHome)
	r.Add("/stories/create", storyactions.HandleCreateShow)
	r.Add("/stories/create", storyactions.HandleCreate).Post()
	r.Add("/stories/code{format:(.xml)?}", storyactions.HandleCode)
	r.Add("/stories{format:(.xml)?}", storyactions.HandleIndex)
	r.Add("/index{format:(.xml)?}", storyactions.HandleIndex)
	r.Add("/stories/{id:[0-9]+}/update", storyactions.HandleUpdateShow)
	r.Add("/stories/{id:[0-9]+}/update", storyactions.HandleUpdate).Post()
	r.Add("/stories/{id:[0-9]+}/destroy", storyactions.HandleDestroy).Post()
	r.Add("/stories/{id:[0-9]+}/upvote", storyactions.HandleUpvote).Post()
	r.Add("/stories/{id:[0-9]+}/downvote", storyactions.HandleDownvote).Post()
	r.Add("/stories/{id:[0-9]+}/flag", storyactions.HandleFlag).Post()
	r.Add("/stories/{id:[0-9]+}", storyactions.HandleShow)

	r.Add("/comments", commentactions.HandleIndex)
	r.Add("/comments/create", commentactions.HandleCreateShow)
	r.Add("/comments/create", commentactions.HandleCreate).Post()
	r.Add("/comments/{id:[0-9]+}/update", commentactions.HandleUpdateShow)
	r.Add("/comments/{id:[0-9]+}/update", commentactions.HandleUpdate).Post()
	r.Add("/comments/{id:[0-9]+}/destroy", commentactions.HandleDestroy).Post()
	r.Add("/comments/{id:[0-9]+}/upvote", commentactions.HandleUpvote).Post()
	r.Add("/comments/{id:[0-9]+}/downvote", commentactions.HandleDownvote).Post()
	r.Add("/comments/{id:[0-9]+}/flag", commentactions.HandleFlag).Post()
	r.Add("/comments/{id:[0-9]+}", commentactions.HandleShow)

	r.Add("/users", useractions.HandleIndex)
	r.Add("/users/create", useractions.HandleCreateShow)
	r.Add("/users/create", useractions.HandleCreate).Post()
	r.Add("/users/{id:[0-9]+}/update", useractions.HandleUpdateShow)
	r.Add("/users/{id:[0-9]+}/update", useractions.HandleUpdate).Post()
	r.Add("/users/{id:[0-9]+}/destroy", useractions.HandleDestroy).Post()
	r.Add("/users/{id:[0-9]+}", useractions.HandleShow)
	r.Add("/users/login", useractions.HandleLoginShow)
	r.Add("/users/login", useractions.HandleLogin).Post()
	r.Add("/users/logout", useractions.HandleLogout).Post()

	// Add a files route to handle static images under files
	// - nginx deals with this in production - perhaps only do this in dev?
	r.Add("/files/{path:.*}", fileHandler)
	r.Add("/favicon.ico", fileHandler)

}
<commit_msg>Fixed error in route order<commit_after>package app

import (
	"github.com/fragmenta/router"
	"github.com/kennygrant/gohackernews/src/comments/actions"
	"github.com/kennygrant/gohackernews/src/stories/actions"
	"github.com/kennygrant/gohackernews/src/users/actions"
)

// Define routes for this app
func setupRoutes(r *router.Router) {

	// Set the default file handler
	r.FileHandler = fileHandler
	r.ErrorHandler = errHandler

	// Add the home page route
	r.Add("/", storyactions.HandleHome)
	r.Add("/stories/{id:[0-9]+}", storyactions.HandleShow)

	r.Add("/stories/create", storyactions.HandleCreateShow)
	r.Add("/stories/create", storyactions.HandleCreate).Post()
	r.Add("/stories/code{format:(.xml)?}", storyactions.HandleCode)
	r.Add("/index{format:(.xml)?}", storyactions.HandleIndex)
	r.Add("/stories{format:(.xml)?}", storyactions.HandleIndex)
	r.Add("/stories/{id:[0-9]+}/update", storyactions.HandleUpdateShow)
	r.Add("/stories/{id:[0-9]+}/update", storyactions.HandleUpdate).Post()
	r.Add("/stories/{id:[0-9]+}/destroy", storyactions.HandleDestroy).Post()
	r.Add("/stories/{id:[0-9]+}/upvote", storyactions.HandleUpvote).Post()
	r.Add("/stories/{id:[0-9]+}/downvote", storyactions.HandleDownvote).Post()
	r.Add("/stories/{id:[0-9]+}/flag", storyactions.HandleFlag).Post()

	r.Add("/comments", commentactions.HandleIndex)
	r.Add("/comments/create", commentactions.HandleCreateShow)
	r.Add("/comments/create", commentactions.HandleCreate).Post()
	r.Add("/comments/{id:[0-9]+}/update", commentactions.HandleUpdateShow)
	r.Add("/comments/{id:[0-9]+}/update", commentactions.HandleUpdate).Post()
	r.Add("/comments/{id:[0-9]+}/destroy", commentactions.HandleDestroy).Post()
	r.Add("/comments/{id:[0-9]+}/upvote", commentactions.HandleUpvote).Post()
	r.Add("/comments/{id:[0-9]+}/downvote", commentactions.HandleDownvote).Post()
	r.Add("/comments/{id:[0-9]+}/flag", commentactions.HandleFlag).Post()
	r.Add("/comments/{id:[0-9]+}", commentactions.HandleShow)

	r.Add("/users", useractions.HandleIndex)
	r.Add("/users/create", useractions.HandleCreateShow)
	r.Add("/users/create", useractions.HandleCreate).Post()
	r.Add("/users/{id:[0-9]+}/update", useractions.HandleUpdateShow)
	r.Add("/users/{id:[0-9]+}/update", useractions.HandleUpdate).Post()
	r.Add("/users/{id:[0-9]+}/destroy", useractions.HandleDestroy).Post()
	r.Add("/users/{id:[0-9]+}", useractions.HandleShow)
	r.Add("/users/login", useractions.HandleLoginShow)
	r.Add("/users/login", useractions.HandleLogin).Post()
	r.Add("/users/logout", useractions.HandleLogout).Post()

	// Add a files route to handle static images under files
	// - nginx deals with this in production - perhaps only do this in dev?
	r.Add("/files/{path:.*}", fileHandler)
	r.Add("/favicon.ico", fileHandler)

}
<|endoftext|>


<commit_before>package api

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
	"strings"
)

const (
	API_BASE_URL       = "https://api.dmm.com/affiliate/v3"
	API_VERSION        = "3"
	SITE_ALLAGES       = "DMM.com"
	SITE_ADULT         = "DMM.R18"
	DEFAULT_API_OFFSET = 1
	DEFAULT_API_LENGTH = 100
	DEFAULT_MAX_LENGTH = 500
)

// RequestJson requests a retirived url and returns the response is parsed JSON-encoded data
//
// RequestJsonは指定されたURLにリクエストしJSONで返ってきたレスポンスをパースしたデータを返します。
func RequestJson(url string) (interface{}, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, fmt.Errorf("Error at API request:%#v", err)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	var result interface{}
	err = json.Unmarshal(body, &result)
	if err != nil {
		return nil, err
	}
	return result, nil
}

// TrimString wraps up strings.TrimString
//
// TrimStringはstrings.TrimStringのラップ関数です。
func TrimString(str string) string {
	return strings.TrimSpace(str)
}

// ValidateAffiliateId validates affiliate ID.
// (affiliate number range: 990 ~ 999)
//  e.g. dummy-999
//
// ValidateAffiliateIdはアフィリエイトID(例: dummy-999)のバリデーションを行います。
//（アフィリエイトの数値の範囲は 990〜999です）
func ValidateAffiliateId(affiliate_id string) bool {
	if affiliate_id == "" {
		return false
	}
	return regexp.MustCompile(`^.+-99[0-9]$`).Match([]byte(affiliate_id))
}

// ValidateSite validates site parameter.
//
// ValidateSiteはsiteパラメータのバリデーションを行います
func ValidateSite(site string) bool {
	if site == "" {
		return false
	}
	if site != SITE_ALLAGES && site != SITE_ADULT {
		return false
	}
	return true
}

// ValidateRange validates a retrieved number within the range ( number >= min && number <= max).
//
// ValidateRangeは指定された数値が最小値と最大値の範囲内にあるかどうか判定します。
func ValidateRange(target, min, max int64) bool {
	return target >= min && target <= max
}

// GetApiVersion returns API version.
//
// GetApiVersionはAPIのバージョンを返します。
func GetApiVersion() string {
	return API_VERSION
}
<commit_msg>fix api.go.<commit_after>package api

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
	"strings"
)

const (
	APIBaseURL       = "https://api.dmm.com/affiliate/v3"
	APIVersion       = "3"
	SiteGeneral      = "DMM.com"
	SiteAdult        = "DMM.R18"
	DefaultAPIOffset = 1
	DefaultAPILength = 100
	DefaultMaxLength = 500
)

// RequestJSON requests a retirived url and returns the response is parsed JSON-encoded data
//
// RequestJSONは指定されたURLにリクエストしJSONで返ってきたレスポンスをパースしたデータを返します。
func RequestJSON(url string) (interface{}, error) {
	// Ignore SSL Certificate Errors
	hc := &http.Client{
            Transport: &http.Transport{
                TLSClientConfig: &tls.Config{
                    InsecureSkipVerify: true,
                },
            },
        }

	resp, err := hc.Get(url)
	if err != nil {
		return nil, fmt.Errorf("Error at API request:%#v", err)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	var result interface{}
	err = json.Unmarshal(body, &result)
	if err != nil {
		return nil, err
	}
	return result, nil
}

// TrimString wraps up strings.TrimString
//
// TrimStringはstrings.TrimStringのラップ関数です。
func TrimString(str string) string {
	return strings.TrimSpace(str)
}

// ValidateAffiliateID validates affiliate ID.
// (affiliate number range: 990 ~ 999)
//  e.g. dummy-999
//
// ValidateAffiliateIDはアフィリエイトID(例: dummy-999)のバリデーションを行います。
//（アフィリエイトの数値の範囲は 990〜999です）
func ValidateAffiliateID(affiliateID string) bool {
	if affiliateID == "" {
		return false
	}
	return regexp.MustCompile(`^.+-99[0-9]$`).Match([]byte(affiliateID))
}

// ValidateSite validates site parameter.
//
// ValidateSiteはsiteパラメータのバリデーションを行います
func ValidateSite(site string) bool {
	if site == "" {
		return false
	}
	if site != SiteGeneral && site != SiteAdult {
		return false
	}
	return true
}

// ValidateRange validates a retrieved number within the range ( number >= min && number <= max).
//
// ValidateRangeは指定された数値が最小値と最大値の範囲内にあるかどうか判定します。
func ValidateRange(target, min, max int64) bool {
	return target >= min && target <= max
}

// GetAPIVersion returns API version.
//
// GetAPIVersionはAPIのバージョンを返します。
func GetAPIVersion() string {
	return APIVersion
}
<|endoftext|>


<commit_before>// Package api provides http handlers for all Chain operations.
package api

import (
	"bytes"
	"net/http"
	"time"

	"golang.org/x/net/context"

	"github.com/tessr/pat"

	"chain/api/appdb"
	"chain/api/asset"
	"chain/database/pg"
	"chain/encoding/json"
	"chain/fedchain/wire"
	chainhttp "chain/net/http"
	"chain/net/http/authn"
)

const sessionTokenLifetime = 2 * 7 * 24 * time.Hour

func Handler() chainhttp.Handler {
	h := chainhttp.PatServeMux{PatternServeMux: pat.New()}
	h.AddFunc("GET", "/v3/applications", tokenAuthn(listApplications))
	h.AddFunc("POST", "/v3/applications", tokenAuthn(createApplication))
	h.AddFunc("GET", "/v3/applications/:appID", getApplication)
	h.AddFunc("GET", "/v3/applications/:appID/members", listMembers)
	h.AddFunc("POST", "/v3/applications/:appID/members", addMember)
	h.AddFunc("PUT", "/v3/applications/:appID/members/:userID", updateMember)
	h.AddFunc("DELETE", "/v3/applications/:appID/members/:userID", removeMember)
	h.AddFunc("GET", "/v3/applications/:appID/wallets", listWallets)
	h.AddFunc("POST", "/v3/applications/:appID/wallets", createWallet)
	h.AddFunc("POST", "/v3/wallets/:walletID/buckets", createBucket)
	h.AddFunc("GET", "/v3/wallets/:walletID/balance", getWalletBalance)
	h.AddFunc("POST", "/v3/applications/:appID/asset-groups", createAssetGroup)
	h.AddFunc("POST", "/v3/asset-groups/:groupID/assets", createAsset)
	h.AddFunc("POST", "/v3/buckets/:bucketID/addresses", createAddr)
	h.AddFunc("POST", "/v3/assets/:assetID/issue", issueAsset)
	h.AddFunc("POST", "/v3/assets/transfer", transferAssets)
	h.AddFunc("POST", "/v3/wallets/transact/finalize", walletFinalize)
	h.AddFunc("POST", "/v3/users", createUser)
	h.AddFunc("POST", "/v3/login", userCredsAuthn(login))
	h.AddFunc("GET", "/v3/api-tokens", tokenAuthn(listAPITokens))
	h.AddFunc("POST", "/v3/api-tokens", tokenAuthn(createAPIToken))
	h.AddFunc("DELETE", "/v3/api-tokens/:tokenID", deleteAPIToken)
	return h
}

// /v3/applications/:appID/wallets
func createWallet(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	appID := req.URL.Query().Get(":appID")

	var wReq struct {
		Label string   `json:"label"`
		XPubs []string `json:"xpubs"`
	}
	err := readJSON(req.Body, &wReq)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	var keys []*appdb.Key
	for _, xpub := range wReq.XPubs {
		key, err := appdb.NewKey(xpub)
		if err != nil {
			writeHTTPError(ctx, w, err)
			return
		}
		keys = append(keys, key)
	}

	dbtx, ctx, err := pg.Begin(ctx)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}
	defer dbtx.Rollback()

	wID, err := appdb.CreateWallet(ctx, appID, wReq.Label, keys)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	err = dbtx.Commit()
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, 201, map[string]interface{}{
		"wallet_id":           wID,
		"label":               wReq.Label,
		"block_chain":         "sandbox",
		"keys":                keys,
		"signatures_required": 1,
	})
}

// /v3/wallets/:walletID/balance
func getWalletBalance(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	wID := req.URL.Query().Get(":walletID")
	bals, err := appdb.WalletBalance(ctx, wID)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, 200, bals)
}

// GET /v3/applications/:appID/wallets
func listWallets(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	aid := req.URL.Query().Get(":appID")
	wallets, err := appdb.ListWallets(ctx, aid)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, 200, wallets)
}

// /v3/applications/:appID/asset-groups
func createAssetGroup(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	appID := req.URL.Query().Get(":appID")

	var agReq struct {
		Label string   `json:"label"`
		XPubs []string `json:"xpubs"`
	}
	err := readJSON(req.Body, &agReq)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	var keys []*appdb.Key
	for _, xpub := range agReq.XPubs {
		key, err := appdb.NewKey(xpub)
		if err != nil {
			writeHTTPError(ctx, w, err)
			return
		}
		keys = append(keys, key)
	}

	dbtx, ctx, err := pg.Begin(ctx)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}
	defer dbtx.Rollback()

	agID, err := appdb.CreateAssetGroup(ctx, appID, agReq.Label, keys)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	err = dbtx.Commit()
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, 201, map[string]interface{}{
		"asset_group_id":      agID,
		"label":               agReq.Label,
		"block_chain":         "sandbox",
		"keys":                keys,
		"signatures_required": 1,
	})
}

// /v3/wallets/:walletID/buckets
func createBucket(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	walletID := req.URL.Query().Get(":walletID")

	var input struct {
		Label string `json:"label"`
	}
	err := readJSON(req.Body, &input)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	bucket, err := appdb.CreateBucket(ctx, walletID, input.Label)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, 201, bucket)
}

// /v3/asset-groups/:groupID/assets
func createAsset(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	groupID := req.URL.Query().Get(":groupID")

	var input struct{ Label string }
	err := readJSON(req.Body, &input)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	asset, err := asset.Create(ctx, groupID, input.Label)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, http.StatusCreated, map[string]interface{}{
		"id":             asset.Hash.String(),
		"asset_group_id": asset.GroupID,
		"label":          asset.Label,
	})
}

// /v3/assets/:assetID/issue
func issueAsset(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	var outs []asset.Output
	err := readJSON(req.Body, &outs)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	assetID := req.URL.Query().Get(":assetID")
	template, err := asset.Issue(ctx, assetID, outs)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, 200, map[string]interface{}{
		"template": template,
	})
}

// /v3/assets/transfer
func transferAssets(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	var x struct {
		Inputs  []asset.TransferInput
		Outputs []asset.Output
	}
	err := readJSON(req.Body, &x)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	template, err := asset.Transfer(ctx, x.Inputs, x.Outputs)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, 200, map[string]interface{}{
		"template": template,
	})
}

// /v3/wallets/transact/finalize
func walletFinalize(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	// TODO(kr): validate

	var tpl asset.Tx
	err := readJSON(req.Body, &tpl)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	tx := wire.NewMsgTx()
	err = tx.Deserialize(bytes.NewReader(tpl.Unsigned))
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	for i, in := range tx.TxIn {
		tplin := tpl.Inputs[i]
		for _, sig := range tplin.Sigs {
			in.SignatureScript = append(in.SignatureScript, sig.DER...)
		}
		in.SignatureScript = append(in.SignatureScript, tplin.RedeemScript...)
	}

	dbtx, ctx, err := pg.Begin(ctx)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}
	defer dbtx.Rollback()

	err = appdb.Commit(ctx, tx)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	err = dbtx.Commit()
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	var buf bytes.Buffer
	tx.Serialize(&buf)

	writeJSON(ctx, w, 200, map[string]interface{}{
		"transaction_id":  tx.TxSha().String(),
		"raw_transaction": json.HexBytes(buf.Bytes()),
	})
}

// POST /v3/users
func createUser(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	var in struct {
		Email    string
		Password string
	}

	err := readJSON(req.Body, &in)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	user, err := appdb.CreateUser(ctx, in.Email, in.Password)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, 200, user)
}

// POST /v3/login
func login(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	uid := authn.GetAuthID(ctx)
	expiresAt := time.Now().UTC().Add(sessionTokenLifetime)
	t, err := appdb.CreateAuthToken(ctx, uid, "session", &expiresAt)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}
	writeJSON(ctx, w, 200, t)
}

// optionalTime returns a pointer to t or nil, if t is zero.
// It is helpful for JSON structs with omitempty.
func optionalTime(t time.Time) *time.Time {
	if t.IsZero() {
		return nil
	}
	return &t
}
<commit_msg>api: authcheck endpoint<commit_after>// Package api provides http handlers for all Chain operations.
package api

import (
	"bytes"
	"net/http"
	"time"

	"golang.org/x/net/context"

	"github.com/tessr/pat"

	"chain/api/appdb"
	"chain/api/asset"
	"chain/database/pg"
	"chain/encoding/json"
	"chain/fedchain/wire"
	chainhttp "chain/net/http"
	"chain/net/http/authn"
)

const sessionTokenLifetime = 2 * 7 * 24 * time.Hour

func Handler() chainhttp.Handler {
	h := chainhttp.PatServeMux{PatternServeMux: pat.New()}
	h.AddFunc("GET", "/v3/applications", tokenAuthn(listApplications))
	h.AddFunc("POST", "/v3/applications", tokenAuthn(createApplication))
	h.AddFunc("GET", "/v3/applications/:appID", getApplication)
	h.AddFunc("GET", "/v3/applications/:appID/members", listMembers)
	h.AddFunc("POST", "/v3/applications/:appID/members", addMember)
	h.AddFunc("PUT", "/v3/applications/:appID/members/:userID", updateMember)
	h.AddFunc("DELETE", "/v3/applications/:appID/members/:userID", removeMember)
	h.AddFunc("GET", "/v3/applications/:appID/wallets", listWallets)
	h.AddFunc("POST", "/v3/applications/:appID/wallets", createWallet)
	h.AddFunc("POST", "/v3/wallets/:walletID/buckets", createBucket)
	h.AddFunc("GET", "/v3/wallets/:walletID/balance", getWalletBalance)
	h.AddFunc("POST", "/v3/applications/:appID/asset-groups", createAssetGroup)
	h.AddFunc("POST", "/v3/asset-groups/:groupID/assets", createAsset)
	h.AddFunc("POST", "/v3/buckets/:bucketID/addresses", createAddr)
	h.AddFunc("POST", "/v3/assets/:assetID/issue", issueAsset)
	h.AddFunc("POST", "/v3/assets/transfer", transferAssets)
	h.AddFunc("POST", "/v3/wallets/transact/finalize", walletFinalize)
	h.AddFunc("POST", "/v3/users", createUser)
	h.AddFunc("POST", "/v3/login", userCredsAuthn(login))
	h.AddFunc("POST", "/v3/authcheck", tokenAuthn(authcheck))
	h.AddFunc("GET", "/v3/api-tokens", tokenAuthn(listAPITokens))
	h.AddFunc("POST", "/v3/api-tokens", tokenAuthn(createAPIToken))
	h.AddFunc("DELETE", "/v3/api-tokens/:tokenID", deleteAPIToken)
	return h
}

// /v3/applications/:appID/wallets
func createWallet(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	appID := req.URL.Query().Get(":appID")

	var wReq struct {
		Label string   `json:"label"`
		XPubs []string `json:"xpubs"`
	}
	err := readJSON(req.Body, &wReq)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	var keys []*appdb.Key
	for _, xpub := range wReq.XPubs {
		key, err := appdb.NewKey(xpub)
		if err != nil {
			writeHTTPError(ctx, w, err)
			return
		}
		keys = append(keys, key)
	}

	dbtx, ctx, err := pg.Begin(ctx)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}
	defer dbtx.Rollback()

	wID, err := appdb.CreateWallet(ctx, appID, wReq.Label, keys)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	err = dbtx.Commit()
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, 201, map[string]interface{}{
		"wallet_id":           wID,
		"label":               wReq.Label,
		"block_chain":         "sandbox",
		"keys":                keys,
		"signatures_required": 1,
	})
}

// /v3/wallets/:walletID/balance
func getWalletBalance(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	wID := req.URL.Query().Get(":walletID")
	bals, err := appdb.WalletBalance(ctx, wID)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, 200, bals)
}

// GET /v3/applications/:appID/wallets
func listWallets(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	aid := req.URL.Query().Get(":appID")
	wallets, err := appdb.ListWallets(ctx, aid)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, 200, wallets)
}

// /v3/applications/:appID/asset-groups
func createAssetGroup(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	appID := req.URL.Query().Get(":appID")

	var agReq struct {
		Label string   `json:"label"`
		XPubs []string `json:"xpubs"`
	}
	err := readJSON(req.Body, &agReq)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	var keys []*appdb.Key
	for _, xpub := range agReq.XPubs {
		key, err := appdb.NewKey(xpub)
		if err != nil {
			writeHTTPError(ctx, w, err)
			return
		}
		keys = append(keys, key)
	}

	dbtx, ctx, err := pg.Begin(ctx)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}
	defer dbtx.Rollback()

	agID, err := appdb.CreateAssetGroup(ctx, appID, agReq.Label, keys)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	err = dbtx.Commit()
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, 201, map[string]interface{}{
		"asset_group_id":      agID,
		"label":               agReq.Label,
		"block_chain":         "sandbox",
		"keys":                keys,
		"signatures_required": 1,
	})
}

// /v3/wallets/:walletID/buckets
func createBucket(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	walletID := req.URL.Query().Get(":walletID")

	var input struct {
		Label string `json:"label"`
	}
	err := readJSON(req.Body, &input)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	bucket, err := appdb.CreateBucket(ctx, walletID, input.Label)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, 201, bucket)
}

// /v3/asset-groups/:groupID/assets
func createAsset(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	groupID := req.URL.Query().Get(":groupID")

	var input struct{ Label string }
	err := readJSON(req.Body, &input)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	asset, err := asset.Create(ctx, groupID, input.Label)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, http.StatusCreated, map[string]interface{}{
		"id":             asset.Hash.String(),
		"asset_group_id": asset.GroupID,
		"label":          asset.Label,
	})
}

// /v3/assets/:assetID/issue
func issueAsset(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	var outs []asset.Output
	err := readJSON(req.Body, &outs)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	assetID := req.URL.Query().Get(":assetID")
	template, err := asset.Issue(ctx, assetID, outs)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, 200, map[string]interface{}{
		"template": template,
	})
}

// /v3/assets/transfer
func transferAssets(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	var x struct {
		Inputs  []asset.TransferInput
		Outputs []asset.Output
	}
	err := readJSON(req.Body, &x)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	template, err := asset.Transfer(ctx, x.Inputs, x.Outputs)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, 200, map[string]interface{}{
		"template": template,
	})
}

// /v3/wallets/transact/finalize
func walletFinalize(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	// TODO(kr): validate

	var tpl asset.Tx
	err := readJSON(req.Body, &tpl)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	tx := wire.NewMsgTx()
	err = tx.Deserialize(bytes.NewReader(tpl.Unsigned))
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	for i, in := range tx.TxIn {
		tplin := tpl.Inputs[i]
		for _, sig := range tplin.Sigs {
			in.SignatureScript = append(in.SignatureScript, sig.DER...)
		}
		in.SignatureScript = append(in.SignatureScript, tplin.RedeemScript...)
	}

	dbtx, ctx, err := pg.Begin(ctx)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}
	defer dbtx.Rollback()

	err = appdb.Commit(ctx, tx)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	err = dbtx.Commit()
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	var buf bytes.Buffer
	tx.Serialize(&buf)

	writeJSON(ctx, w, 200, map[string]interface{}{
		"transaction_id":  tx.TxSha().String(),
		"raw_transaction": json.HexBytes(buf.Bytes()),
	})
}

// POST /v3/users
func createUser(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	var in struct {
		Email    string
		Password string
	}

	err := readJSON(req.Body, &in)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	user, err := appdb.CreateUser(ctx, in.Email, in.Password)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}

	writeJSON(ctx, w, 200, user)
}

// POST /v3/login
func login(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	uid := authn.GetAuthID(ctx)
	expiresAt := time.Now().UTC().Add(sessionTokenLifetime)
	t, err := appdb.CreateAuthToken(ctx, uid, "session", &expiresAt)
	if err != nil {
		writeHTTPError(ctx, w, err)
		return
	}
	writeJSON(ctx, w, 200, t)
}

// GET /v3/authcheck
func authcheck(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	writeJSON(ctx, w, 200, map[string]string{"message": "ok"})
}

// optionalTime returns a pointer to t or nil, if t is zero.
// It is helpful for JSON structs with omitempty.
func optionalTime(t time.Time) *time.Time {
	if t.IsZero() {
		return nil
	}
	return &t
}
<|endoftext|>


<commit_before>// Package ipfix decodes IPFIX packets
//: ----------------------------------------------------------------------------
//: Copyright (C) 2017 Verizon.  All Rights Reserved.
//: All Rights Reserved
//:
//: file:    reader.go
//: details: TODO
//: author:  Mehrdad Arshad Rad
//: date:    02/01/2017
//:
//: 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 ipfix

import (
	"encoding/binary"
	"errors"
)

// Reader represents the data bytes for reading
type Reader struct {
	data []byte
}

var errReader = errors.New("can not read the data")

// NewReader constructs a reader
func NewReader(b []byte) *Reader {
	return &Reader{
		data: b,
	}
}

// Uint8 reads a byte
func (r *Reader) Uint8() (uint8, error) {
	if len(r.data) < 1 {
		return 0, errReader
	}

	r.data = r.data[1:]

	return r.data[0], nil
}

// Uint16 reads two bytes as big-endian
func (r *Reader) Uint16() (uint16, error) {
	if len(r.data) < 2 {
		return 0, errReader
	}

	d := binary.BigEndian.Uint16(r.data)
	r.data = r.data[2:]

	return d, nil
}

// Uint32 reads four bytes as big-endian
func (r *Reader) Uint32() (uint32, error) {
	if len(r.data) < 4 {
		return 0, errReader
	}

	d := binary.BigEndian.Uint32(r.data)
	r.data = r.data[4:]

	return d, nil
}

// Uint64 reads eight bytes as big-endian
func (r *Reader) Uint64() (uint64, error) {
	if len(r.data) < 8 {
		return 0, errReader
	}

	d := binary.BigEndian.Uint64(r.data)
	r.data = r.data[8:]

	return d, nil
}

// Read reads n bytes and returns it
func (r *Reader) Read(n int) ([]byte, error) {
	if len(r.data) < n {
		return []byte{}, errReader
	}

	d := r.data[:n]
	r.data = r.data[n:]

	return d, nil
}

// Len returns the current length of the reader's data
func (r *Reader) Len() int {
	return len(r.data)
}
<commit_msg>fix uint8<commit_after>// Package ipfix decodes IPFIX packets
//: ----------------------------------------------------------------------------
//: Copyright (C) 2017 Verizon.  All Rights Reserved.
//: All Rights Reserved
//:
//: file:    reader.go
//: details: bytes reader
//: author:  Mehrdad Arshad Rad
//: date:    02/01/2017
//:
//: 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 ipfix

import (
	"encoding/binary"
	"errors"
)

// Reader represents the data bytes for reading
type Reader struct {
	data []byte
}

var errReader = errors.New("can not read the data")

// NewReader constructs a reader
func NewReader(b []byte) *Reader {
	return &Reader{
		data: b,
	}
}

// Uint8 reads a byte
func (r *Reader) Uint8() (uint8, error) {
	if len(r.data) < 1 {
		return 0, errReader
	}

	d := r.data[0]
	r.data = r.data[1:]

	return d, nil
}

// Uint16 reads two bytes as big-endian
func (r *Reader) Uint16() (uint16, error) {
	if len(r.data) < 2 {
		return 0, errReader
	}

	d := binary.BigEndian.Uint16(r.data)
	r.data = r.data[2:]

	return d, nil
}

// Uint32 reads four bytes as big-endian
func (r *Reader) Uint32() (uint32, error) {
	if len(r.data) < 4 {
		return 0, errReader
	}

	d := binary.BigEndian.Uint32(r.data)
	r.data = r.data[4:]

	return d, nil
}

// Uint64 reads eight bytes as big-endian
func (r *Reader) Uint64() (uint64, error) {
	if len(r.data) < 8 {
		return 0, errReader
	}

	d := binary.BigEndian.Uint64(r.data)
	r.data = r.data[8:]

	return d, nil
}

// Read reads n bytes and returns it
func (r *Reader) Read(n int) ([]byte, error) {
	if len(r.data) < n {
		return []byte{}, errReader
	}

	d := r.data[:n]
	r.data = r.data[n:]

	return d, nil
}

// Len returns the current length of the reader's data
func (r *Reader) Len() int {
	return len(r.data)
}
<|endoftext|>


<commit_before>package main

import (
	"strconv"

	"github.com/shirou/gopsutil/cpu"
)

// `cpuinfo` represent the CPU informations
type cpuinfo struct {
	count     string // number of CPUs
	vendorID  string // vendor name ex. AuthenticAMD, GenuineIntel
	modelName string // CPU model name
	cpuMhz    string //
}

// Get informations about the cpu by using `gopesutil` packages
func getCPUinfo() cpuinfo {
	info, err := cpu.Info() // cpu.Info() return a slice of InfoStat structs
	if err != nil {
		panic(err) //TODO do not panic but manage the error
	}

	result := cpuinfo{
		count:     strconv.Itoa(len(info)),
		vendorID:  info[0].VendorID, //BUG in `gopsutil`
		modelName: info[0].ModelName,
		cpuMhz:    strconv.FormatFloat(info[0].Mhz, 'f', 0, 64),
	}
	return result
}

//TODO count cores ?
//TODO count the physicals id = multiples sockets

//TODO We need to improve this. For now it take vendorID, modelName, etc from
//the first CPU assuming than all CPUs are the same (probably OK)and than there
//is only one socket (not true on servers)
//
// http://superuser.com/questions/388115/interpreting-output-of-cat-proc-cpuinfo
// http://unix.stackexchange.com/questions/146051/number-of-processors-in-proc-cpuinfo
//
// TODO add temperature
<commit_msg>Update comments<commit_after>package main

import (
	"strconv"

	"github.com/shirou/gopsutil/cpu"
)

// `cpuinfo` represent the CPU informations
type cpuinfo struct {
	count     string // number of CPUs
	vendorID  string // vendor name ex. AuthenticAMD, GenuineIntel
	modelName string // CPU model name
	cpuMhz    string //
	//TODO temperature and fan speed ?
}

// Get informations about the cpu by using `gopesutil` packages
func getCPUinfo() cpuinfo {
	info, err := cpu.Info() // cpu.Info() return a slice of InfoStat structs
	if err != nil {
		panic(err) //TODO do not panic but manage the error
	}

	result := cpuinfo{
		count:     strconv.Itoa(len(info)),
		vendorID:  info[0].VendorID, //BUG in `gopsutil`
		modelName: info[0].ModelName,
		cpuMhz:    strconv.FormatFloat(info[0].Mhz, 'f', 0, 64),
	}
	return result
}

//TODO count cores ?
//TODO count the physicals id = multiples sockets

//TODO We need to improve this. For now it take vendorID, modelName, etc from
//the first CPU assuming than all CPUs are the same (probably OK)and than there
//is only one socket (not true on servers)
//
// http://superuser.com/questions/388115/interpreting-output-of-cat-proc-cpuinfo
// http://unix.stackexchange.com/questions/146051/number-of-processors-in-proc-cpuinfo
//
// TODO add temperature
<|endoftext|>


<commit_before>// Copyright (c) 2012-2014 Jeremy Latt
// Copyright (c) 2014-2015 Edmund Huber
// Copyright (c) 2016-2017 Daniel Oaks <daniel@danieloaks.net>
// released under the MIT license

package irc

// These numerics have been retrieved from:
//   http://defs.ircdocs.horse/ and http://modern.ircdocs.horse/
//
// They're intended to represent a relatively-standard cross-section of the IRC
// server ecosystem out there. Custom numerics will be marked as such.

const (
	RPL_WELCOME                     = "001"
	RPL_YOURHOST                    = "002"
	RPL_CREATED                     = "003"
	RPL_MYINFO                      = "004"
	RPL_ISUPPORT                    = "005"
	RPL_SNOMASKIS                   = "008"
	RPL_BOUNCE                      = "010"
	RPL_TRACELINK                   = "200"
	RPL_TRACECONNECTING             = "201"
	RPL_TRACEHANDSHAKE              = "202"
	RPL_TRACEUNKNOWN                = "203"
	RPL_TRACEOPERATOR               = "204"
	RPL_TRACEUSER                   = "205"
	RPL_TRACESERVER                 = "206"
	RPL_TRACESERVICE                = "207"
	RPL_TRACENEWTYPE                = "208"
	RPL_TRACECLASS                  = "209"
	RPL_TRACERECONNECT              = "210"
	RPL_STATSLINKINFO               = "211"
	RPL_STATSCOMMANDS               = "212"
	RPL_ENDOFSTATS                  = "219"
	RPL_UMODEIS                     = "221"
	RPL_SERVLIST                    = "234"
	RPL_SERVLISTEND                 = "235"
	RPL_STATSUPTIME                 = "242"
	RPL_STATSOLINE                  = "243"
	RPL_LUSERCLIENT                 = "251"
	RPL_LUSEROP                     = "252"
	RPL_LUSERUNKNOWN                = "253"
	RPL_LUSERCHANNELS               = "254"
	RPL_LUSERME                     = "255"
	RPL_ADMINME                     = "256"
	RPL_ADMINLOC1                   = "257"
	RPL_ADMINLOC2                   = "258"
	RPL_ADMINEMAIL                  = "259"
	RPL_TRACELOG                    = "261"
	RPL_TRACEEND                    = "262"
	RPL_TRYAGAIN                    = "263"
	RPL_WHOISCERTFP                 = "276"
	RPL_AWAY                        = "301"
	RPL_USERHOST                    = "302"
	RPL_ISON                        = "303"
	RPL_UNAWAY                      = "305"
	RPL_NOWAWAY                     = "306"
	RPL_WHOISUSER                   = "311"
	RPL_WHOISSERVER                 = "312"
	RPL_WHOISOPERATOR               = "313"
	RPL_WHOWASUSER                  = "314"
	RPL_ENDOFWHO                    = "315"
	RPL_WHOISIDLE                   = "317"
	RPL_ENDOFWHOIS                  = "318"
	RPL_WHOISCHANNELS               = "319"
	RPL_LIST                        = "322"
	RPL_LISTEND                     = "323"
	RPL_CHANNELMODEIS               = "324"
	RPL_UNIQOPIS                    = "325"
	RPL_CHANNELCREATED              = "329"
	RPL_WHOISACCOUNT                = "330"
	RPL_NOTOPIC                     = "331"
	RPL_TOPIC                       = "332"
	RPL_TOPICTIME                   = "333"
	RPL_WHOISBOT                    = "335"
	RPL_WHOISACTUALLY               = "338"
	RPL_INVITING                    = "341"
	RPL_SUMMONING                   = "342"
	RPL_INVITELIST                  = "346"
	RPL_ENDOFINVITELIST             = "347"
	RPL_EXCEPTLIST                  = "348"
	RPL_ENDOFEXCEPTLIST             = "349"
	RPL_VERSION                     = "351"
	RPL_WHOREPLY                    = "352"
	RPL_NAMREPLY                    = "353"
	RPL_LINKS                       = "364"
	RPL_ENDOFLINKS                  = "365"
	RPL_ENDOFNAMES                  = "366"
	RPL_BANLIST                     = "367"
	RPL_ENDOFBANLIST                = "368"
	RPL_ENDOFWHOWAS                 = "369"
	RPL_INFO                        = "371"
	RPL_MOTD                        = "372"
	RPL_ENDOFINFO                   = "374"
	RPL_MOTDSTART                   = "375"
	RPL_ENDOFMOTD                   = "376"
	RPL_YOUREOPER                   = "381"
	RPL_REHASHING                   = "382"
	RPL_YOURESERVICE                = "383"
	RPL_TIME                        = "391"
	RPL_USERSSTART                  = "392"
	RPL_USERS                       = "393"
	RPL_ENDOFUSERS                  = "394"
	RPL_NOUSERS                     = "395"
	ERR_UNKNOWNERROR                = "400"
	ERR_NOSUCHNICK                  = "401"
	ERR_NOSUCHSERVER                = "402"
	ERR_NOSUCHCHANNEL               = "403"
	ERR_CANNOTSENDTOCHAN            = "404"
	ERR_TOOMANYCHANNELS             = "405"
	ERR_WASNOSUCHNICK               = "406"
	ERR_TOOMANYTARGETS              = "407"
	ERR_NOSUCHSERVICE               = "408"
	ERR_NOORIGIN                    = "409"
	ERR_INVALIDCAPCMD               = "410"
	ERR_NORECIPIENT                 = "411"
	ERR_NOTEXTTOSEND                = "412"
	ERR_NOTOPLEVEL                  = "413"
	ERR_WILDTOPLEVEL                = "414"
	ERR_BADMASK                     = "415"
	ERR_UNKNOWNCOMMAND              = "421"
	ERR_NOMOTD                      = "422"
	ERR_NOADMININFO                 = "423"
	ERR_FILEERROR                   = "424"
	ERR_NONICKNAMEGIVEN             = "431"
	ERR_ERRONEUSNICKNAME            = "432"
	ERR_NICKNAMEINUSE               = "433"
	ERR_NICKCOLLISION               = "436"
	ERR_UNAVAILRESOURCE             = "437"
	ERR_REG_UNAVAILABLE             = "440"
	ERR_USERNOTINCHANNEL            = "441"
	ERR_NOTONCHANNEL                = "442"
	ERR_USERONCHANNEL               = "443"
	ERR_NOLOGIN                     = "444"
	ERR_SUMMONDISABLED              = "445"
	ERR_USERSDISABLED               = "446"
	ERR_NOTREGISTERED               = "451"
	ERR_NEEDMOREPARAMS              = "461"
	ERR_ALREADYREGISTRED            = "462"
	ERR_NOPERMFORHOST               = "463"
	ERR_PASSWDMISMATCH              = "464"
	ERR_YOUREBANNEDCREEP            = "465"
	ERR_YOUWILLBEBANNED             = "466"
	ERR_KEYSET                      = "467"
	ERR_CHANNELISFULL               = "471"
	ERR_UNKNOWNMODE                 = "472"
	ERR_INVITEONLYCHAN              = "473"
	ERR_BANNEDFROMCHAN              = "474"
	ERR_BADCHANNELKEY               = "475"
	ERR_BADCHANMASK                 = "476"
	ERR_NOCHANMODES                 = "477"
	ERR_BANLISTFULL                 = "478"
	ERR_NOPRIVILEGES                = "481"
	ERR_CHANOPRIVSNEEDED            = "482"
	ERR_CANTKILLSERVER              = "483"
	ERR_RESTRICTED                  = "484"
	ERR_UNIQOPPRIVSNEEDED           = "485"
	ERR_NOOPERHOST                  = "491"
	ERR_UMODEUNKNOWNFLAG            = "501"
	ERR_USERSDONTMATCH              = "502"
	ERR_HELPNOTFOUND                = "524"
	ERR_CANNOTSENDRP                = "573"
	RPL_WHOISSECURE                 = "671"
	RPL_YOURLANGUAGESARE            = "687"
	RPL_WHOISLANGUAGE               = "690"
	RPL_HELPSTART                   = "704"
	RPL_HELPTXT                     = "705"
	RPL_ENDOFHELP                   = "706"
	ERR_NOPRIVS                     = "723"
	RPL_MONONLINE                   = "730"
	RPL_MONOFFLINE                  = "731"
	RPL_MONLIST                     = "732"
	RPL_ENDOFMONLIST                = "733"
	ERR_MONLISTFULL                 = "734"
	RPL_LOGGEDIN                    = "900"
	RPL_LOGGEDOUT                   = "901"
	ERR_NICKLOCKED                  = "902"
	RPL_SASLSUCCESS                 = "903"
	ERR_SASLFAIL                    = "904"
	ERR_SASLTOOLONG                 = "905"
	ERR_SASLABORTED                 = "906"
	ERR_SASLALREADY                 = "907"
	RPL_SASLMECHS                   = "908"
	RPL_REGISTRATION_SUCCESS        = "920"
	ERR_ACCOUNT_ALREADY_EXISTS      = "921"
	ERR_REG_UNSPECIFIED_ERROR       = "922"
	RPL_VERIFYSUCCESS               = "923"
	ERR_ACCOUNT_ALREADY_VERIFIED    = "924"
	ERR_ACCOUNT_INVALID_VERIFY_CODE = "925"
	RPL_REG_VERIFICATION_REQUIRED   = "927"
	ERR_REG_INVALID_CRED_TYPE       = "928"
	ERR_REG_INVALID_CALLBACK        = "929"
	ERR_TOOMANYLANGUAGES            = "981"
	ERR_NOLANGUAGE                  = "982"

	// draft numerics

	ERR_CANNOT_RESUME = "999"
)
<commit_msg>Make ERR_CANNOT_RESUME use RPL_NONE numeric<commit_after>// Copyright (c) 2012-2014 Jeremy Latt
// Copyright (c) 2014-2015 Edmund Huber
// Copyright (c) 2016-2017 Daniel Oaks <daniel@danieloaks.net>
// released under the MIT license

package irc

// These numerics have been retrieved from:
//   http://defs.ircdocs.horse/ and http://modern.ircdocs.horse/
//
// They're intended to represent a relatively-standard cross-section of the IRC
// server ecosystem out there. Custom numerics will be marked as such.

const (
	RPL_WELCOME                     = "001"
	RPL_YOURHOST                    = "002"
	RPL_CREATED                     = "003"
	RPL_MYINFO                      = "004"
	RPL_ISUPPORT                    = "005"
	RPL_SNOMASKIS                   = "008"
	RPL_BOUNCE                      = "010"
	RPL_TRACELINK                   = "200"
	RPL_TRACECONNECTING             = "201"
	RPL_TRACEHANDSHAKE              = "202"
	RPL_TRACEUNKNOWN                = "203"
	RPL_TRACEOPERATOR               = "204"
	RPL_TRACEUSER                   = "205"
	RPL_TRACESERVER                 = "206"
	RPL_TRACESERVICE                = "207"
	RPL_TRACENEWTYPE                = "208"
	RPL_TRACECLASS                  = "209"
	RPL_TRACERECONNECT              = "210"
	RPL_STATSLINKINFO               = "211"
	RPL_STATSCOMMANDS               = "212"
	RPL_ENDOFSTATS                  = "219"
	RPL_UMODEIS                     = "221"
	RPL_SERVLIST                    = "234"
	RPL_SERVLISTEND                 = "235"
	RPL_STATSUPTIME                 = "242"
	RPL_STATSOLINE                  = "243"
	RPL_LUSERCLIENT                 = "251"
	RPL_LUSEROP                     = "252"
	RPL_LUSERUNKNOWN                = "253"
	RPL_LUSERCHANNELS               = "254"
	RPL_LUSERME                     = "255"
	RPL_ADMINME                     = "256"
	RPL_ADMINLOC1                   = "257"
	RPL_ADMINLOC2                   = "258"
	RPL_ADMINEMAIL                  = "259"
	RPL_TRACELOG                    = "261"
	RPL_TRACEEND                    = "262"
	RPL_TRYAGAIN                    = "263"
	RPL_WHOISCERTFP                 = "276"
	RPL_AWAY                        = "301"
	RPL_USERHOST                    = "302"
	RPL_ISON                        = "303"
	RPL_UNAWAY                      = "305"
	RPL_NOWAWAY                     = "306"
	RPL_WHOISUSER                   = "311"
	RPL_WHOISSERVER                 = "312"
	RPL_WHOISOPERATOR               = "313"
	RPL_WHOWASUSER                  = "314"
	RPL_ENDOFWHO                    = "315"
	RPL_WHOISIDLE                   = "317"
	RPL_ENDOFWHOIS                  = "318"
	RPL_WHOISCHANNELS               = "319"
	RPL_LIST                        = "322"
	RPL_LISTEND                     = "323"
	RPL_CHANNELMODEIS               = "324"
	RPL_UNIQOPIS                    = "325"
	RPL_CHANNELCREATED              = "329"
	RPL_WHOISACCOUNT                = "330"
	RPL_NOTOPIC                     = "331"
	RPL_TOPIC                       = "332"
	RPL_TOPICTIME                   = "333"
	RPL_WHOISBOT                    = "335"
	RPL_WHOISACTUALLY               = "338"
	RPL_INVITING                    = "341"
	RPL_SUMMONING                   = "342"
	RPL_INVITELIST                  = "346"
	RPL_ENDOFINVITELIST             = "347"
	RPL_EXCEPTLIST                  = "348"
	RPL_ENDOFEXCEPTLIST             = "349"
	RPL_VERSION                     = "351"
	RPL_WHOREPLY                    = "352"
	RPL_NAMREPLY                    = "353"
	RPL_LINKS                       = "364"
	RPL_ENDOFLINKS                  = "365"
	RPL_ENDOFNAMES                  = "366"
	RPL_BANLIST                     = "367"
	RPL_ENDOFBANLIST                = "368"
	RPL_ENDOFWHOWAS                 = "369"
	RPL_INFO                        = "371"
	RPL_MOTD                        = "372"
	RPL_ENDOFINFO                   = "374"
	RPL_MOTDSTART                   = "375"
	RPL_ENDOFMOTD                   = "376"
	RPL_YOUREOPER                   = "381"
	RPL_REHASHING                   = "382"
	RPL_YOURESERVICE                = "383"
	RPL_TIME                        = "391"
	RPL_USERSSTART                  = "392"
	RPL_USERS                       = "393"
	RPL_ENDOFUSERS                  = "394"
	RPL_NOUSERS                     = "395"
	ERR_UNKNOWNERROR                = "400"
	ERR_NOSUCHNICK                  = "401"
	ERR_NOSUCHSERVER                = "402"
	ERR_NOSUCHCHANNEL               = "403"
	ERR_CANNOTSENDTOCHAN            = "404"
	ERR_TOOMANYCHANNELS             = "405"
	ERR_WASNOSUCHNICK               = "406"
	ERR_TOOMANYTARGETS              = "407"
	ERR_NOSUCHSERVICE               = "408"
	ERR_NOORIGIN                    = "409"
	ERR_INVALIDCAPCMD               = "410"
	ERR_NORECIPIENT                 = "411"
	ERR_NOTEXTTOSEND                = "412"
	ERR_NOTOPLEVEL                  = "413"
	ERR_WILDTOPLEVEL                = "414"
	ERR_BADMASK                     = "415"
	ERR_UNKNOWNCOMMAND              = "421"
	ERR_NOMOTD                      = "422"
	ERR_NOADMININFO                 = "423"
	ERR_FILEERROR                   = "424"
	ERR_NONICKNAMEGIVEN             = "431"
	ERR_ERRONEUSNICKNAME            = "432"
	ERR_NICKNAMEINUSE               = "433"
	ERR_NICKCOLLISION               = "436"
	ERR_UNAVAILRESOURCE             = "437"
	ERR_REG_UNAVAILABLE             = "440"
	ERR_USERNOTINCHANNEL            = "441"
	ERR_NOTONCHANNEL                = "442"
	ERR_USERONCHANNEL               = "443"
	ERR_NOLOGIN                     = "444"
	ERR_SUMMONDISABLED              = "445"
	ERR_USERSDISABLED               = "446"
	ERR_NOTREGISTERED               = "451"
	ERR_NEEDMOREPARAMS              = "461"
	ERR_ALREADYREGISTRED            = "462"
	ERR_NOPERMFORHOST               = "463"
	ERR_PASSWDMISMATCH              = "464"
	ERR_YOUREBANNEDCREEP            = "465"
	ERR_YOUWILLBEBANNED             = "466"
	ERR_KEYSET                      = "467"
	ERR_CHANNELISFULL               = "471"
	ERR_UNKNOWNMODE                 = "472"
	ERR_INVITEONLYCHAN              = "473"
	ERR_BANNEDFROMCHAN              = "474"
	ERR_BADCHANNELKEY               = "475"
	ERR_BADCHANMASK                 = "476"
	ERR_NOCHANMODES                 = "477"
	ERR_BANLISTFULL                 = "478"
	ERR_NOPRIVILEGES                = "481"
	ERR_CHANOPRIVSNEEDED            = "482"
	ERR_CANTKILLSERVER              = "483"
	ERR_RESTRICTED                  = "484"
	ERR_UNIQOPPRIVSNEEDED           = "485"
	ERR_NOOPERHOST                  = "491"
	ERR_UMODEUNKNOWNFLAG            = "501"
	ERR_USERSDONTMATCH              = "502"
	ERR_HELPNOTFOUND                = "524"
	ERR_CANNOTSENDRP                = "573"
	RPL_WHOISSECURE                 = "671"
	RPL_YOURLANGUAGESARE            = "687"
	RPL_WHOISLANGUAGE               = "690"
	RPL_HELPSTART                   = "704"
	RPL_HELPTXT                     = "705"
	RPL_ENDOFHELP                   = "706"
	ERR_NOPRIVS                     = "723"
	RPL_MONONLINE                   = "730"
	RPL_MONOFFLINE                  = "731"
	RPL_MONLIST                     = "732"
	RPL_ENDOFMONLIST                = "733"
	ERR_MONLISTFULL                 = "734"
	RPL_LOGGEDIN                    = "900"
	RPL_LOGGEDOUT                   = "901"
	ERR_NICKLOCKED                  = "902"
	RPL_SASLSUCCESS                 = "903"
	ERR_SASLFAIL                    = "904"
	ERR_SASLTOOLONG                 = "905"
	ERR_SASLABORTED                 = "906"
	ERR_SASLALREADY                 = "907"
	RPL_SASLMECHS                   = "908"
	RPL_REGISTRATION_SUCCESS        = "920"
	ERR_ACCOUNT_ALREADY_EXISTS      = "921"
	ERR_REG_UNSPECIFIED_ERROR       = "922"
	RPL_VERIFYSUCCESS               = "923"
	ERR_ACCOUNT_ALREADY_VERIFIED    = "924"
	ERR_ACCOUNT_INVALID_VERIFY_CODE = "925"
	RPL_REG_VERIFICATION_REQUIRED   = "927"
	ERR_REG_INVALID_CRED_TYPE       = "928"
	ERR_REG_INVALID_CALLBACK        = "929"
	ERR_TOOMANYLANGUAGES            = "981"
	ERR_NOLANGUAGE                  = "982"

	// draft numerics
	// these haven't been assigned actual codes, so we use RPL_NONE's code (300),
	// since RPL_NONE is intended to be used when testing / debugging / etc features.

	ERR_CANNOT_RESUME = "300"
)
<|endoftext|>


<commit_before>package issues

import (
	"fmt"
	"github.com/fatih/color"
	"github.com/wjdp/htmltest/htmldoc"
)

const textNil string = "<nil>" // Text substitution when primary or secondary part of issue is nil

// LevelNone : option to suppress output, actual error types follow
const LevelNone int = 99

// LevelError : Fatal problems, presence of an error causes tests to fail
const LevelError int = 3

// LevelWarning : An advisory, tests still pass
const LevelWarning int = 2

// LevelInfo : Verbose information, normally hidden, not too noisy
const LevelInfo int = 1

// LevelDebug : Debug output, normally hidden, very noisy
const LevelDebug int = 0

// Issue struct representing a single issue with a document.
// Set all except Document and Reference, set one or the other.
type Issue struct {
	Level     int                // Level of the issue, use the consts at the top of this file
	Document  *htmldoc.Document  // Document this issue pertains to
	Reference *htmldoc.Reference // Reference this issue pertains to
	Message   string             // Error message, keep short
	store     *IssueStore        // Internal ref to the store this issue is owned by
}

// Textual description of the primary item in the issue
func (issue *Issue) primary() string {
	if issue.Document != nil {
		return issue.Document.SitePath
	} else if issue.Reference != nil && issue.Reference.Document != nil {
		return issue.Reference.Document.SitePath
	}
	return textNil
}

// Textual description of the secondary item in the issue
func (issue *Issue) secondary() string {
	if issue.Reference != nil {
		return issue.Reference.Path
	}
	return textNil
}

// Text to print
func (issue *Issue) text() string {
	pri := issue.primary()
	sec := issue.secondary()
	if pri != textNil || sec != textNil {
		return fmt.Sprintf("%v --- %v --> %v", issue.Message, issue.primary(),
			issue.secondary())
	}
	return issue.Message
}

// Print to stdout with colour
func (issue *Issue) print(force bool, prefix string) {
	if (issue.Level < issue.store.logLevel) && !force {
		return
	}

	switch issue.Level {
	case LevelError:
		color.Set(color.FgRed)
	case LevelWarning:
		color.Set(color.FgYellow)
	case LevelInfo:
		color.Set(color.FgBlue)
	case LevelDebug:
		color.Set(color.FgMagenta)
	}

	fmt.Println(prefix + issue.text())

	color.Unset()
}
<commit_msg>Group consts in issue.go<commit_after>package issues

import (
	"fmt"
	"github.com/fatih/color"
	"github.com/wjdp/htmltest/htmldoc"
)

const (
	// LevelNone : option to suppress output, actual error types follow
	LevelNone int = 99
	// LevelError : Fatal problems, presence of an error causes tests to fail
	LevelError int = 3
	// LevelWarning : An advisory, tests still pass
	LevelWarning int = 2
	// LevelInfo : Verbose information, normally hidden, not too noisy
	LevelInfo int = 1
	// LevelDebug : Debug output, normally hidden, very noisy
	LevelDebug int = 0
	// Text substitution when primary or secondary part of issue is nil
	textNil string = "<nil>"
)

// Issue struct representing a single issue with a document.
// Set all except Document and Reference, set one or the other.
type Issue struct {
	Level     int                // Level of the issue, use the consts at the top of this file
	Document  *htmldoc.Document  // Document this issue pertains to
	Reference *htmldoc.Reference // Reference this issue pertains to
	Message   string             // Error message, keep short
	store     *IssueStore        // Internal ref to the store this issue is owned by
}

// Textual description of the primary item in the issue
func (issue *Issue) primary() string {
	if issue.Document != nil {
		return issue.Document.SitePath
	} else if issue.Reference != nil && issue.Reference.Document != nil {
		return issue.Reference.Document.SitePath
	}
	return textNil
}

// Textual description of the secondary item in the issue
func (issue *Issue) secondary() string {
	if issue.Reference != nil {
		return issue.Reference.Path
	}
	return textNil
}

// Text to print
func (issue *Issue) text() string {
	pri := issue.primary()
	sec := issue.secondary()
	if pri != textNil || sec != textNil {
		return fmt.Sprintf("%v --- %v --> %v", issue.Message, issue.primary(),
			issue.secondary())
	}
	return issue.Message
}

// Print to stdout with colour
func (issue *Issue) print(force bool, prefix string) {
	if (issue.Level < issue.store.logLevel) && !force {
		return
	}

	switch issue.Level {
	case LevelError:
		color.Set(color.FgRed)
	case LevelWarning:
		color.Set(color.FgYellow)
	case LevelInfo:
		color.Set(color.FgBlue)
	case LevelDebug:
		color.Set(color.FgMagenta)
	}

	fmt.Println(prefix + issue.text())

	color.Unset()
}
<|endoftext|>


<commit_before>package QesyGo

import (
	"time"
)

func Crontab(f func()) {
	Println("Server Cron Run...... ")
	timer1 := time.NewTicker(1 * time.Second)
	for {
		select {
		case <-timer1.C:
			f()
		}
	}
}
<commit_msg>add CrontabMicro cron<commit_after>package QesyGo

import (
	"time"
)

func Crontab(f func()) {
	Println("Server Cron Run...... ")
	timer1 := time.NewTicker(1 * time.Second)
	for {
		select {
		case <-timer1.C:
			f()
		}
	}
}

func CrontabMicro(f func()) {
	Println("Server CrontabMicro Run...... ")
	timer1 := time.NewTicker(1 * time.Millisecond)
	for {
		select {
		case <-timer1.C:
			f()
		}
	}
}
<|endoftext|>


<commit_before>package models

import (
	"fmt"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"regexp"
	"strconv"
	"strings"
)

type ShipFit struct {
	Name  string    `bson:"name" json:"name"`
	Ship  EVEType   `bson:"ship" json:"ship"`
	Items []EVEType `bson:"items,omitempty" json:"items"`
}

func ParseFit(fitStr string) ShipFit {
	fit := ShipFit{}
	itemArr := strings.Split(fitStr, "\r\n")
	// fmt.Println(len(itemArr))
	shipStr := strings.Replace(itemArr[0], "[", "", -1)
	shipStr = strings.Replace(shipStr, "]", "", -1)
	// fmt.Println(shipStr)

	shiptmp := strings.Split(shipStr, ",")
	shipName := shiptmp[0]
	fitName := strings.Replace(shiptmp[1], " ", "", -1)
	ship := EVEType{}
	err := c_eve_types.Find(bson.M{"name": shipName}).One(&ship)
	if err != nil {
		panic(err)
	}
	fmt.Println(ship)
	fit.Ship = ship
	fit.Name = fitName

	for _, typeName := range itemArr[1:] {
		fmt.Println(typeName)
		if typeName == "" {
			continue
		}

		equipment := EVEType{}
		amount := 1

		re := regexp.MustCompile(".*x[0-9]$")
		if re.MatchString(typeName) {
			amountSepIndex := strings.LastIndex(typeName, " ")
			etype := typeName[:amountSepIndex]
			amountStr := strings.Replace(typeName[amountSepIndex:], " ", "", -1)
			amount, _ = strconv.Atoi(strings.Replace(amountStr, "x", "", 1))
			typeName = etype
		}

		err := c_eve_types.Find(bson.M{"name": typeName}).One(&equipment)
		if err != nil {
			if err == mgo.ErrNotFound {
				fit.Items = append(fit.Items, EVEType{Name: mgo.ErrNotFound.Error()})
			} else {
				fmt.Println("%s not found in database.", typeName)
				panic(err)
			}
		}
		equipment.Amount = amount
		fmt.Println(equipment)
		fit.Items = append(fit.Items, equipment)
	}

	// fmt.Println(fit.Items)

	return fit
}

func LinkOfFit(fit ShipFit) string {
	result := fit.Ship.TypeID + ":"

	for _, item := range fit.Items {
		result = result + item.TypeID + ";" + strconv.Itoa(item.Amount) + ":"
	}

	result = result + ":"

	return result
}
<commit_msg>Fixed an issue when ammo more than 10<commit_after>package models

import (
	"fmt"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"regexp"
	"strconv"
	"strings"
)

type ShipFit struct {
	Name  string    `bson:"name" json:"name"`
	Ship  EVEType   `bson:"ship" json:"ship"`
	Items []EVEType `bson:"items,omitempty" json:"items"`
}

func ParseFit(fitStr string) ShipFit {
	fit := ShipFit{}
	itemArr := strings.Split(fitStr, "\r\n")
	// fmt.Println(len(itemArr))
	shipStr := strings.Replace(itemArr[0], "[", "", -1)
	shipStr = strings.Replace(shipStr, "]", "", -1)
	// fmt.Println(shipStr)

	shiptmp := strings.Split(shipStr, ",")
	shipName := shiptmp[0]
	fitName := strings.Replace(shiptmp[1], " ", "", -1)
	ship := EVEType{}
	err := c_eve_types.Find(bson.M{"name": shipName}).One(&ship)
	if err != nil {
		panic(err)
	}
	fmt.Println(ship)
	fit.Ship = ship
	fit.Name = fitName

	for _, typeName := range itemArr[1:] {
		fmt.Println(typeName)
		if typeName == "" {
			continue
		}

		equipment := EVEType{}
		amount := 1

		typeName = strings.Split(typeName, ",")[0]

		re := regexp.MustCompile(".*x[0-9]*$")
		if re.MatchString(typeName) {
			amountSepIndex := strings.LastIndex(typeName, " ")
			etype := typeName[:amountSepIndex]
			amountStr := strings.Replace(typeName[amountSepIndex:], " ", "", -1)
			amount, _ = strconv.Atoi(strings.Replace(amountStr, "x", "", 1))
			typeName = etype
		}

		err := c_eve_types.Find(bson.M{"name": typeName}).One(&equipment)
		if err != nil {
			if err == mgo.ErrNotFound {
				fit.Items = append(fit.Items, EVEType{Name: mgo.ErrNotFound.Error()})
			} else {
				fmt.Println("%s not found in database.", typeName)
				panic(err)
			}
		}
		equipment.Amount = amount
		fmt.Println(equipment)
		fit.Items = append(fit.Items, equipment)
	}

	// fmt.Println(fit.Items)

	return fit
}

func LinkOfFit(fit ShipFit) string {
	result := fit.Ship.TypeID + ":"

	for _, item := range fit.Items {
		result = result + item.TypeID + ";" + strconv.Itoa(item.Amount) + ":"
	}

	result = result + ":"

	return result
}
<|endoftext|>


<commit_before>package mol2

import (
	"errors"
	"unicode/utf8"
)

type Lexer struct {
	buf []byte
	line, column, pos int
	column_new, line_new, pos_new int
}

func NewLexer(buffer []byte) *Lexer {
	lex := new(Lexer)
	lex.line = 0
	lex.column = 0
	lex.pos = 0
	lex.buf = buffer

	return lex
}

func (lex *Lexer) Coords() (int, int) {
	return lex.line, lex.column
}

func (lex *Lexer) SkipWS() (bool, int) {
	return false, 0
}

func (lex *Lexer) readRune() rune {
	r, size := utf8.DecodeRune(lex.buf[lex.pos_new:])
	lex.pos_new += size
	if r == '\n' {
		lex.column_new = 0
		lex.line_new ++
	} else {
		lex.column_new ++
	}

	return r
}

func (lex *Lexer) fixCoords() {
	lex.pos = lex.pos_new
	lex.line = lex.line_new
	lex.column = lex.column_new
}

func (lex *Lexer) dropCoords() {
	lex.pos_new = lex.pos
	lex.line_new = lex.line
	lex.column_new = lex.column
}

func (lex *Lexer) NextAtom() (bool, error) {
	pattern := "@<TRIPOS>ATOM"
	err_text := "was expected '" + pattern + "'"
	if (len(lex.buf) - lex.pos) < len(pattern) {
		return false, errors.New(err_text)
	}
	for _, r := range pattern {
		buf_rune := lex.readRune()
		if r != buf_rune {
			lex.dropCoords()
			return false, errors.New(err_text)
		}
	}
	lex.column += len(pattern)
	lex.pos += len(pattern)

	return true, nil
}
<commit_msg>add Id parsing<commit_after>package mol2

import (
	"errors"
	"unicode"
	"unicode/utf8"
)

type Lexer struct {
	buf []byte
	line, column, pos int
	column_new, line_new, pos_new int
}

func NewLexer(buffer []byte) *Lexer {
	lex := new(Lexer)
	lex.line = 0
	lex.column = 0
	lex.pos = 0
	lex.buf = buffer

	return lex
}

func (lex *Lexer) Coords() (int, int) {
	return lex.line, lex.column
}

func (lex *Lexer) SkipWS() (bool, int) {
	return false, 0
}

func (lex *Lexer) readRune() rune {
	r, size := utf8.DecodeRune(lex.buf[lex.pos_new:])
	lex.pos_new += size
	if r == '\n' {
		lex.column_new = 0
		lex.line_new ++
	} else {
		lex.column_new ++
	}

	return r
}

func (lex *Lexer) fixCoords() {
	lex.pos = lex.pos_new
	lex.line = lex.line_new
	lex.column = lex.column_new
}

func (lex *Lexer) dropCoords() {
	lex.pos_new = lex.pos
	lex.line_new = lex.line
	lex.column_new = lex.column
}

func (lex *Lexer) NextAtom() (bool, error) {
	pattern := "@<TRIPOS>ATOM"
	err_text := "was expected '" + pattern + "'"
	if (len(lex.buf) - lex.pos) < len(pattern) {
		return false, errors.New(err_text)
	}
	for _, r := range pattern {
		buf_rune := lex.readRune()
		if r != buf_rune {
			lex.dropCoords()
			return false, errors.New(err_text)
		}
	}
	lex.fixCoords()

	return true, nil
}

func (lex *Lexer) NextId() (bool, string, error) {
	buf := ""
	r := lex.readRune()
	for unicode.IsSpace(r) == false {
		buf += string(r)
		r = lex.readRune()
	}
	if len(buf) == 0 {
		return false, "", errors.New("Id was expected")
	}

	return true, buf, nil
}
<|endoftext|>