<commit_before>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package Scanner

export EOF;
const (
	ILLEGAL = iota;
	EOF = iota;
	IDENT = iota;
	STRING = iota;
	NUMBER = iota;

	COMMA = iota;
	COLON = iota;
	SEMICOLON = iota;
	PERIOD = iota;

	LPAREN = iota;
	RPAREN = iota;
	LBRACK = iota;
	RBRACK = iota;
	LBRACE = iota;
	RBRACE = iota;

	ASSIGN = iota;
	DEFINE = iota;

	INC = iota;
	DEC = iota;
	NOT = iota;

	OR = iota;
	BOR = iota;
	AND = iota;
	BAND = iota;

	ADD = iota;
	SUB = iota;
	MUL = iota;
	QUO = iota;
	REM = iota;

	EQL = iota;
	NEQ = iota;
	LSS = iota;
	LEQ = iota;
	GTR = iota;
	GEQ = iota;

	// keywords
	BREAK = iota;
	CASE = iota;
	CONST = iota;
	CONTINUE = iota;
	DEFAULT = iota;
	ELSE = iota;
	EXPORT = iota;
	FALLTHROUGH = iota;
	FALSE = iota;
	FOR = iota;
	FUNC = iota;
	GO = iota;
	GOTO = iota;
	IF = iota;
	IMPORT = iota;
	INTERFACE = iota;
	MAP = iota;
	NEW = iota;
	NIL = iota;
	PACKAGE = iota;
	RANGE = iota;
	RETURN = iota;
	SELECT = iota;
	STRUCT = iota;
	SWITCH = iota;
	TRUE = iota;
	TYPE = iota;
	VAR = iota;
)

var (
	Keywords *map [string] int;
)

export TokenName
func TokenName(tok int) string {
	switch (tok) {
	case ILLEGAL: return "ILLEGAL";
	case EOF: return "EOF";
	case IDENT: return "IDENT";
	case STRING: return "STRING";
	case NUMBER: return "NUMBER";

	case COMMA: return "COMMA";
	case COLON: return "COLON";
	case SEMICOLON: return "SEMICOLON";
	case PERIOD: return "PERIOD";

	case LPAREN: return "LPAREN";
	case RPAREN: return "RPAREN";
	case LBRACK: return "LBRACK";
	case RBRACK: return "RBRACK";
	case LBRACE: return "LBRACE";
	case RBRACE: return "RBRACE";

	case ASSIGN: return "ASSIGN";
	case DEFINE: return "DEFINE";

	case INC: return "INC";
	case DEC: return "DEC";
	case NOT: return "NOT";

	case OR: return "OR";
	case BOR: return "BOR";
	case AND: return "AND";
	case BAND: return "BAND";

	case ADD: return "ADD";
	case SUB: return "SUB";
	case MUL: return "MUL";
	case REM: return "REM";
	case QUO: return "QUO";
	case REM: return "REM";

	case EQL: return "EQL";
	case NEQ: return "NEQ";
	case LSS: return "LSS";
	case LEQ: return "LEQ";
	case GTR: return "GTR";
	case GEQ: return "GEQ";

	case BREAK: return "BREAK";
	case CASE: return "CASE";
	case CONST: return "CONST";
	case CONTINUE: return "CONTINUE";
	case DEFAULT: return "DEFAULT";
	case ELSE: return "ELSE";
	case EXPORT: return "EXPORT";
	case FALLTHROUGH: return "FALLTHROUGH";
	case FALSE: return "FALSE";
	case FOR: return "FOR";
	case FUNC: return "FUNC";
	case GO: return "GO";
	case GOTO: return "GOTO";
	case IF: return "IF";
	case IMPORT: return "IMPORT";
	case INTERFACE: return "INTERFACE";
	case MAP: return "MAP";
	case NEW: return "NEW";
	case NIL: return "NIL";
	case PACKAGE: return "PACKAGE";
	case RANGE: return "RANGE";
	case RETURN: return "RETURN";
	case SELECT: return "SELECT";
	case STRUCT: return "STRUCT";
	case SWITCH: return "SWITCH";
	case TRUE: return "TRUE";
	case TYPE: return "TYPE";
	case VAR: return "VAR";
	}

	return "???";
}

func is_whitespace (ch int) bool {
	return ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t';
}

func is_letter (ch int) bool {
	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 128 ;
}

func is_oct_digit (ch int) bool {
	return '0' <= ch && ch <= '7';
}

func is_dec_digit (ch int) bool {
	return '0' <= ch && ch <= '9';
}

func is_hex_digit (ch int) bool {
	return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F';
}

export Scanner
type Scanner struct {
	src string;
	pos int;
	ch int;  // one char look-ahead
}

func (S *Scanner) Next () {
	src := S.src;  // TODO only needed because of 6g bug
	if S.pos < len(src) {
		S.ch = int(S.src[S.pos]);
		S.pos++;
		if (S.ch >= 128) {
			panic "UTF-8 not handled"
		}
	} else {
		S.ch = -1;
	}
}

func Init () {
	Keywords = new(map [string] int);

	Keywords["break"] = BREAK;
	Keywords["case"] = CASE;
	Keywords["const"] = CONST;
	Keywords["continue"] = CONTINUE;
	Keywords["default"] = DEFAULT;
	Keywords["else"] = ELSE;
	Keywords["export"] = EXPORT;
	Keywords["fallthrough"] = FALLTHROUGH;
	Keywords["false"] = FALSE;
	Keywords["for"] = FOR;
	Keywords["func"] = FUNC;
	Keywords["go"] = GO;
	Keywords["goto"] = GOTO;
	Keywords["if"] = IF;
	Keywords["import"] = IMPORT;
	Keywords["interface"] = INTERFACE;
	Keywords["map"] = MAP;
	Keywords["new"] = NEW;
	Keywords["nil"] = NIL;
	Keywords["package"] = PACKAGE;
	Keywords["range"] = RANGE;
	Keywords["return"] = RETURN;
	Keywords["select"] = SELECT;
	Keywords["struct"] = STRUCT;
	Keywords["switch"] = SWITCH;
	Keywords["true"] = TRUE;
	Keywords["type"] = TYPE;
	Keywords["var"] = VAR;
}

func (S *Scanner) Open (src string) {
	if Keywords == nil {
		Init();
	}

	S.src = src;
	S.pos = 0;
	S.Next();
}

func (S *Scanner) SkipWhitespace () {
	for is_whitespace(S.ch) {
		S.Next();
	}
}

func (S *Scanner) SkipComment () {
	if S.ch == '/' {
		// comment
		for S.Next(); S.ch != '\n' && S.ch >= 0; S.Next() {}

	} else {
		/* comment */
		for S.Next(); S.ch >= 0; {
			c := S.ch;
			S.Next();
			if c == '*' && S.ch == '/' {
				S.Next();
				return;
			}
		}
		panic "comment not terminated";
	}
}

func (S *Scanner) ScanIdentifier () int {
	beg := S.pos - 1;
	for is_letter(S.ch) || is_dec_digit(S.ch) {
		S.Next();
	}
	end := S.pos - 1;

	var tok int;
	var present bool;
	tok, present = Keywords[S.src[beg : end]];
	if !present {
		tok = IDENT;
	}

	return tok;
}

func (S *Scanner) ScanNumber () {
	// TODO complete this routine

	for is_dec_digit(S.ch) {
		S.Next();
	}
}

func (S *Scanner) ScanOctDigits(n int) {
	for ; n > 0; n-- {
		if !is_oct_digit(S.ch) {
			panic "illegal char escape";
		}
		S.Next();
	}
}

func (S *Scanner) ScanHexDigits(n int) {
	for ; n > 0; n-- {
		if !is_hex_digit(S.ch) {
			panic "illegal char escape";
		}
		S.Next();
	}
}

func (S *Scanner) ScanEscape () {
	// TODO: fix this routine

	switch (S.ch) {
	case 'a': fallthrough;
	case 'b': fallthrough;
	case 'f': fallthrough;
	case 'n': fallthrough;
	case 'r': fallthrough;
	case 't': fallthrough;
	case 'v': fallthrough;
	case '\\': fallthrough;
	case '\'': fallthrough;
	case '"':
		S.Next();

	case '0', '1', '2', '3', '4', '5', '6', '7':
		S.ScanOctDigits(3);

	case 'x':
		S.Next();
		S.ScanHexDigits(2);

	case 'u':
		S.Next();
		S.ScanHexDigits(4);

	case 'U':
		S.Next();
		S.ScanHexDigits(8);

	default:
		panic "illegal char escape";
	}
}

func (S *Scanner) ScanChar () {
	S.Next();  // consume '\'

	if (S.ch == '\\') {
		S.Next();
		S.ScanEscape();
	} else {
		S.Next();
	}

	if S.ch == '\'' {
		S.Next();
	} else {
		panic "char not terminated";
	}
}

func (S *Scanner) ScanString () {
	for S.Next(); S.ch != '"'; S.Next() {
		if S.ch == '\n' || S.ch < 0 {
			panic "string not terminated";
		}
	}
	S.Next();
}

func (S *Scanner) ScanRawString () {
	for S.Next(); S.ch != '`'; S.Next() {
		if S.ch == '\n' || S.ch < 0 {
			panic "string not terminated";
		}
	}
	S.Next();
}

func (S *Scanner) Scan () (tok, beg, end int) {
	S.SkipWhitespace();

	var tok int = ILLEGAL;
	var beg int = S.pos - 1;
	var end int = beg;

	if is_letter(S.ch) {
		tok = S.ScanIdentifier();

	} else if is_dec_digit(S.ch) {
		S.ScanNumber();
		tok = NUMBER;

	} else {
		switch S.ch {
			case -1:
				tok = EOF;

			case '/':
				S.Next();
				if S.ch == '/' || S.ch == '*' {
					S.SkipComment();
					tok, beg, end = S.Scan();
					return tok, beg, end;
				} else {
					tok = QUO;
				}

			case '"':
				S.ScanString();
				tok = STRING;

			case '\'':
				S.ScanChar();
				tok = NUMBER;

			case '`':
				S.ScanRawString();
				tok = STRING;

			case ':':
				S.Next();
				if (S.ch == '=') {
					S.Next();
					tok = DEFINE;
				} else {
					tok = COLON;
				}

			case '.':
				S.Next();
				tok = PERIOD;

			case ',':
				S.Next();
				tok = COMMA;

			case '+':
				S.Next();
				if (S.ch == '+') {
					S.Next();
					tok = INC;
				} else {
					tok = ADD;
				}

			case '-':
				S.Next();
				if (S.ch == '-') {
					S.Next();
					tok = DEC;
				} else {
					tok = SUB;
				}

			case '*':
				S.Next();
				tok = MUL;

			case '/':
				S.Next();
				tok = QUO;

			case '%':
				S.Next();
				tok = REM;

			case '<':
				S.Next();
				if (S.ch == '=') {
					S.Next();
					tok = LEQ;
				} else {
					tok = LSS;
				}

			case '>':
				S.Next();
				if (S.ch == '=') {
					S.Next();
					tok = GEQ;
				} else {
					tok = GTR;
				}

			case '=':
				S.Next();
				if (S.ch == '=') {
					S.Next();
					tok = EQL;
				} else {
					tok = ASSIGN;
				}

			case '!':
				S.Next();
				if (S.ch == '=') {
					S.Next();
					tok = NEQ;
				} else {
					tok = NOT;
				}

			case ';':
				S.Next();
				tok = SEMICOLON;

			case '(':
				S.Next();
				tok = LPAREN;

			case ')':
				S.Next();
				tok = LPAREN;

			case '[':
				S.Next();
				tok = LBRACK;

			case ']':
				S.Next();
				tok = RBRACK;

			case '{':
				S.Next();
				tok = LBRACE;

			case '}':
				S.Next();
				tok = RBRACE;

			case '&':
				S.Next();
				if S.ch == '&' {
					S.Next();
					tok = AND;
				} else {
					tok = BAND;
				}

			case '|':
				S.Next();
				if S.ch == '|' {
					S.Next();
					tok = OR;
				} else {
					tok = BOR;
				}

			default:
				S.Next();  // make progress
		}
	}

	end = S.pos - 1;
	return tok, beg, end;
}
<commit_msg>- more Go scanner work<commit_after>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package Scanner

export EOF;
const (
	ILLEGAL = iota;
	EOF = iota;
	IDENT = iota;
	STRING = iota;
	NUMBER = iota;

	COMMA = iota;
	COLON = iota;
	SEMICOLON = iota;
	PERIOD = iota;

	LPAREN = iota;
	RPAREN = iota;
	LBRACK = iota;
	RBRACK = iota;
	LBRACE = iota;
	RBRACE = iota;

	ASSIGN = iota;
	DEFINE = iota;

	INC = iota;
	DEC = iota;
	NOT = iota;

	AND = iota;
	OR = iota;
	XOR = iota;

	ADD = iota;
	SUB = iota;
	MUL = iota;
	QUO = iota;
	REM = iota;

	EQL = iota;
	NEQ = iota;
	LSS = iota;
	LEQ = iota;
	GTR = iota;
	GEQ = iota;

	SHL = iota;
	SHR = iota;

	ADD_ASSIGN = iota;
	SUB_ASSIGN = iota;
	MUL_ASSIGN = iota;
	QUO_ASSIGN = iota;
	REM_ASSIGN = iota;

	AND_ASSIGN = iota;
	OR_ASSIGN = iota;
	XOR_ASSIGN = iota;

	SHL_ASSIGN = iota;
	SHR_ASSIGN = iota;

	CAND = iota;
	COR = iota;

	// keywords
	BREAK = iota;
	CASE = iota;
	CONST = iota;
	CONTINUE = iota;
	DEFAULT = iota;
	ELSE = iota;
	EXPORT = iota;
	FALLTHROUGH = iota;
	FALSE = iota;
	FOR = iota;
	FUNC = iota;
	GO = iota;
	GOTO = iota;
	IF = iota;
	IMPORT = iota;
	INTERFACE = iota;
	MAP = iota;
	NEW = iota;
	NIL = iota;
	PACKAGE = iota;
	RANGE = iota;
	RETURN = iota;
	SELECT = iota;
	STRUCT = iota;
	SWITCH = iota;
	TRUE = iota;
	TYPE = iota;
	VAR = iota;
)

var (
	Keywords *map [string] int;
)

export TokenName
func TokenName(tok int) string {
	switch (tok) {
	case ILLEGAL: return "ILLEGAL";
	case EOF: return "EOF";
	case IDENT: return "IDENT";
	case STRING: return "STRING";
	case NUMBER: return "NUMBER";

	case COMMA: return "COMMA";
	case COLON: return "COLON";
	case SEMICOLON: return "SEMICOLON";
	case PERIOD: return "PERIOD";

	case LPAREN: return "LPAREN";
	case RPAREN: return "RPAREN";
	case LBRACK: return "LBRACK";
	case RBRACK: return "RBRACK";
	case LBRACE: return "LBRACE";
	case RBRACE: return "RBRACE";

	case ASSIGN: return "ASSIGN";
	case DEFINE: return "DEFINE";

	case INC: return "INC";
	case DEC: return "DEC";
	case NOT: return "NOT";

	case AND: return "AND";
	case OR: return "OR";
	case XOR: return "XOR";

	case ADD: return "ADD";
	case SUB: return "SUB";
	case MUL: return "MUL";
	case REM: return "REM";
	case QUO: return "QUO";
	case REM: return "REM";

	case EQL: return "EQL";
	case NEQ: return "NEQ";
	case LSS: return "LSS";
	case LEQ: return "LEQ";
	case GTR: return "GTR";
	case GEQ: return "GEQ";

	case SHL: return SHL;
	case SHR: return SHR;

	case ADD_ASSIGN: return "ADD_ASSIGN";
	case SUB_ASSIGN: return "SUB_ASSIGN";
	case MUL_ASSIGN: return "MUL_ASSIGN";
	case QUO_ASSIGN: return "QUO_ASSIGN";
	case REM_ASSIGN: return "REM_ASSIGN";

	case AND_ASSIGN: return "AND_ASSIGN";
	case OR_ASSIGN: return "OR_ASSIGN";
	case XOR_ASSIGN: return "XOR_ASSIGN";

	case SHL_ASSIGN: return "SHL_ASSIGN";
	case SHR_ASSIGN: return "SHR_ASSIGN";

	case CAND: return "CAND";
	case COR: return "COR";

	case BREAK: return "BREAK";
	case CASE: return "CASE";
	case CONST: return "CONST";
	case CONTINUE: return "CONTINUE";
	case DEFAULT: return "DEFAULT";
	case ELSE: return "ELSE";
	case EXPORT: return "EXPORT";
	case FALLTHROUGH: return "FALLTHROUGH";
	case FALSE: return "FALSE";
	case FOR: return "FOR";
	case FUNC: return "FUNC";
	case GO: return "GO";
	case GOTO: return "GOTO";
	case IF: return "IF";
	case IMPORT: return "IMPORT";
	case INTERFACE: return "INTERFACE";
	case MAP: return "MAP";
	case NEW: return "NEW";
	case NIL: return "NIL";
	case PACKAGE: return "PACKAGE";
	case RANGE: return "RANGE";
	case RETURN: return "RETURN";
	case SELECT: return "SELECT";
	case STRUCT: return "STRUCT";
	case SWITCH: return "SWITCH";
	case TRUE: return "TRUE";
	case TYPE: return "TYPE";
	case VAR: return "VAR";
	}

	return "???";
}

func is_whitespace (ch int) bool {
	return ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t';
}

func is_letter (ch int) bool {
	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 128 ;
}

func is_oct_digit (ch int) bool {
	return '0' <= ch && ch <= '7';
}

func is_dec_digit (ch int) bool {
	return '0' <= ch && ch <= '9';
}

func is_hex_digit (ch int) bool {
	return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F';
}

export Scanner
type Scanner struct {
	src string;
	pos int;
	ch int;  // one char look-ahead
}

func (S *Scanner) Next () {
	src := S.src;  // TODO only needed because of 6g bug
	if S.pos < len(src) {
		S.ch = int(S.src[S.pos]);
		S.pos++;
		if (S.ch >= 128) {
			panic "UTF-8 not handled"
		}
	} else {
		S.ch = -1;
	}
}

func Init () {
	Keywords = new(map [string] int);

	Keywords["break"] = BREAK;
	Keywords["case"] = CASE;
	Keywords["const"] = CONST;
	Keywords["continue"] = CONTINUE;
	Keywords["default"] = DEFAULT;
	Keywords["else"] = ELSE;
	Keywords["export"] = EXPORT;
	Keywords["fallthrough"] = FALLTHROUGH;
	Keywords["false"] = FALSE;
	Keywords["for"] = FOR;
	Keywords["func"] = FUNC;
	Keywords["go"] = GO;
	Keywords["goto"] = GOTO;
	Keywords["if"] = IF;
	Keywords["import"] = IMPORT;
	Keywords["interface"] = INTERFACE;
	Keywords["map"] = MAP;
	Keywords["new"] = NEW;
	Keywords["nil"] = NIL;
	Keywords["package"] = PACKAGE;
	Keywords["range"] = RANGE;
	Keywords["return"] = RETURN;
	Keywords["select"] = SELECT;
	Keywords["struct"] = STRUCT;
	Keywords["switch"] = SWITCH;
	Keywords["true"] = TRUE;
	Keywords["type"] = TYPE;
	Keywords["var"] = VAR;
}

func (S *Scanner) Open (src string) {
	if Keywords == nil {
		Init();
	}

	S.src = src;
	S.pos = 0;
	S.Next();
}

func (S *Scanner) SkipWhitespace () {
	for is_whitespace(S.ch) {
		S.Next();
	}
}

func (S *Scanner) SkipComment () {
	if S.ch == '/' {
		// comment
		for S.Next(); S.ch != '\n' && S.ch >= 0; S.Next() {}

	} else {
		/* comment */
		for S.Next(); S.ch >= 0; {
			c := S.ch;
			S.Next();
			if c == '*' && S.ch == '/' {
				S.Next();
				return;
			}
		}
		panic "comment not terminated";
	}
}

func (S *Scanner) ScanIdentifier () int {
	beg := S.pos - 1;
	for is_letter(S.ch) || is_dec_digit(S.ch) {
		S.Next();
	}
	end := S.pos - 1;

	var tok int;
	var present bool;
	tok, present = Keywords[S.src[beg : end]];
	if !present {
		tok = IDENT;
	}

	return tok;
}

func (S *Scanner) ScanMantissa () {
     	for is_dec_digit(S.ch) {
	      	S.Next();
	}
}

func (S *Scanner) ScanNumber () int {
	// TODO complete this routine
	if S.ch == '.' {
	   	S.Next();
	}
	S.ScanMantissa();
	if S.ch == 'e' || S.ch == 'E' {
	   	S.Next();
		if S.ch == '-' || S.ch == '+' {
		   	S.Next();
		}
		S.ScanMantissa();
	}
	return NUMBER;
}

func (S *Scanner) ScanOctDigits(n int) {
	for ; n > 0; n-- {
		if !is_oct_digit(S.ch) {
			panic "illegal char escape";
		}
		S.Next();
	}
}

func (S *Scanner) ScanHexDigits(n int) {
	for ; n > 0; n-- {
		if !is_hex_digit(S.ch) {
			panic "illegal char escape";
		}
		S.Next();
	}
}

func (S *Scanner) ScanEscape () {
	// TODO: fix this routine

	switch (S.ch) {
	case 'a': fallthrough;
	case 'b': fallthrough;
	case 'f': fallthrough;
	case 'n': fallthrough;
	case 'r': fallthrough;
	case 't': fallthrough;
	case 'v': fallthrough;
	case '\\': fallthrough;
	case '\'': fallthrough;
	case '"':
		S.Next();

	case '0', '1', '2', '3', '4', '5', '6', '7':
		S.ScanOctDigits(3);

	case 'x':
		S.Next();
		S.ScanHexDigits(2);

	case 'u':
		S.Next();
		S.ScanHexDigits(4);

	case 'U':
		S.Next();
		S.ScanHexDigits(8);

	default:
		panic "illegal char escape";
	}
}

func (S *Scanner) ScanChar () int {
	if (S.ch == '\\') {
		S.Next();
		S.ScanEscape();
	} else {
		S.Next();
	}

	if S.ch == '\'' {
		S.Next();
	} else {
		panic "char not terminated";
	}
	return NUMBER;
}

func (S *Scanner) ScanString () int {
	for ; S.ch != '"'; S.Next() {
		if S.ch == '\n' || S.ch < 0 {
			panic "string not terminated";
		}
	}
	S.Next();
	return STRING;
}

func (S *Scanner) ScanRawString () int {
	for ; S.ch != '`'; S.Next() {
		if S.ch == '\n' || S.ch < 0 {
			panic "string not terminated";
		}
	}
	S.Next();
	return STRING;
}

func (S *Scanner) Select2 (tok0, tok1 int) int {
     	if S.ch == '=' {
	   	S.Next();
	   	return tok1;
	}
	return tok0;
}

func (S *Scanner) Select3 (tok0, tok1, ch2, tok2 int) int {
	if S.ch == '=' {
	   	S.Next();
		return tok1;
	}
	if S.ch == ch2 {
	   	S.Next();
		return tok2;
	}
	return tok0;
}

func (S *Scanner) Select4 (tok0, tok1, ch2, tok2, tok3 int) int {
	if S.ch == '=' {
	   	S.Next();
		return tok1;
	}
	if S.ch == ch2 {
	   	S.Next();
		if S.ch == '=' {
		   	S.Next();
			return tok3;
		}
		return tok2;
	}
	return tok0;
}

func (S *Scanner) Scan () (tok, beg, end int) {
	S.SkipWhitespace();

	var tok int = ILLEGAL;
	var beg int = S.pos - 1;
	var end int = beg;

	switch ch := S.ch; {
	case is_letter(ch): tok = S.ScanIdentifier();
	case is_dec_digit(ch): tok = S.ScanNumber();
	default:
		S.Next();
		switch ch {
			case -1: tok = EOF;
			case '"': tok = S.ScanString();
			case '\'': tok = S.ScanChar();
			case '`': tok = S.ScanRawString();
			case ':': tok = S.Select2(COLON, DEFINE);
			case '.':
				if is_dec_digit(S.ch) {
				     	tok = S.ScanNumber();
				} else {
				        tok = PERIOD;
				}
			case ',': tok = COMMA;
			case ';': tok = SEMICOLON;
			case '(': tok = LPAREN;
			case ')': tok = RPAREN;
			case '[': tok = LBRACK;
			case ']': tok = RBRACK;
			case '{': tok = LBRACE;
			case '}': tok = RBRACE;
			case '+': tok = S.Select3(ADD, ADD_ASSIGN, '+', INC);
			case '-': tok = S.Select3(SUB, SUB_ASSIGN, '-', DEC);
			case '*': tok = S.Select2(MUL, MUL_ASSIGN);
			case '/':
				if S.ch == '/' || S.ch == '*' {
					S.SkipComment();
					// cannot simply return because of 6g bug
					tok, beg, end = S.Scan();
					return tok, beg, end;
				}
				tok = S.Select2(QUO, QUO_ASSIGN);
			case '%': tok = S.Select2(REM, REM_ASSIGN);
			case '^': tok = S.Select2(XOR, XOR_ASSIGN);
			case '<': tok = S.Select4(LSS, LEQ, '<', SHL, SHL_ASSIGN);
			case '>': tok = S.Select4(GTR, GEQ, '>', SHR, SHR_ASSIGN);
			case '=': tok = S.Select2(ASSIGN, EQL);
			case '!': tok = S.Select2(NOT, NEQ);
			case '&': tok = S.Select3(AND, AND_ASSIGN, '&', CAND);
			case '|': tok = S.Select3(OR, OR_ASSIGN, '|', COR);
			default: tok = ILLEGAL;

		}
	}

	end = S.pos - 1;
	return tok, beg, end;
}
<|endoftext|>


<commit_before>package util

import (
	"fmt"
	"runtime"
)

const BINARY_VERSION = "0.2.23"

func Version(app string) string {
	return fmt.Sprintf("%s v%s (built w/%s)", app, BINARY_VERSION, runtime.Version())
}
<commit_msg>bump 0.2.24-alpha<commit_after>package util

import (
	"fmt"
	"runtime"
)

const BINARY_VERSION = "0.2.24-alpha"

func Version(app string) string {
	return fmt.Sprintf("%s v%s (built w/%s)", app, BINARY_VERSION, runtime.Version())
}
<|endoftext|>


<commit_before>package speaker

import (
	"math"
	"sync"
	"time"

	"github.com/faiface/pixel/audio"
	"github.com/hajimehoshi/oto"
	"github.com/pkg/errors"
)

var (
	mu      sync.Mutex
	mixer   audio.Mixer
	samples [][2]float64
	buf     []byte
	player  *oto.Player
)

// Init initializes audio playback through speaker. Must be called before using this package. The
// value of audio.SampleRate must be set (or left to the default) before calling this function.
//
// The bufferSize argument specifies the length of the speaker's buffer. Bigger bufferSize means
// lower CPU usage and more reliable playback. Lower bufferSize means better responsiveness and less
// delay.
func Init(bufferSize time.Duration) error {
	mu.Lock()
	defer mu.Unlock()

	if player != nil {
		panic("already called Init")
	}

	numSamples := int(math.Ceil(bufferSize.Seconds() * audio.SampleRate))
	numBytes := numSamples * 4

	var err error
	player, err = oto.NewPlayer(int(audio.SampleRate), 2, 2, numBytes)
	if err != nil {
		return errors.Wrap(err, "failed to initialize speaker")
	}

	samples = make([][2]float64, numSamples)
	buf = make([]byte, numBytes)

	go func() {
		for {
			update()
		}
	}()

	return nil
}

// Lock locks the speaker. While locked, speaker won't pull new data from the playing Stramers. Lock
// if you want to modify any currently playing Streamers to avoid race conditions.
func Lock() {
	mu.Lock()
}

// Unlock unlocks the speaker. Call after modifying any currently playing Streamer.
func Unlock() {
	mu.Unlock()
}

// Play starts playing all provided Streamers through the speaker.
func Play(s ...audio.Streamer) {
	mu.Lock()
	mixer.Play(s...)
	mu.Unlock()
}

// update pulls new data from the playing Streamers and sends it to the speaker. Blocks until the
// data is sent and started playing.
func update() {
	mu.Lock()
	mixer.Stream(samples)
	mu.Unlock()

	for i := range samples {
		for c := range samples[i] {
			val := samples[i][c]
			if val < -1 {
				val = -1
			}
			if val > +1 {
				val = +1
			}
			valInt16 := int16(val * (1<<15 - 1))
			low := byte(valInt16 % (1 << 8))
			high := byte(valInt16 / (1 << 8))
			buf[i*4+c*2+0] = low
			buf[i*4+c*2+1] = high
		}
	}

	player.Write(buf)
}
<commit_msg>audio: speaker: allow to call Init more than once<commit_after>package speaker

import (
	"math"
	"sync"
	"time"

	"github.com/faiface/pixel/audio"
	"github.com/hajimehoshi/oto"
	"github.com/pkg/errors"
)

var (
	mu      sync.Mutex
	mixer   audio.Mixer
	samples [][2]float64
	buf     []byte
	player  *oto.Player
	done    chan struct{}
)

// Init initializes audio playback through speaker. Must be called before using this package. The
// value of audio.SampleRate must be set (or left to the default) before calling this function.
//
// The bufferSize argument specifies the length of the speaker's buffer. Bigger bufferSize means
// lower CPU usage and more reliable playback. Lower bufferSize means better responsiveness and less
// delay.
func Init(bufferSize time.Duration) error {
	mu.Lock()
	defer mu.Unlock()

	if player != nil {
		done <- struct{}{}
		<-done
		player.Close()
	}

	mixer = audio.Mixer{}

	numSamples := int(math.Ceil(bufferSize.Seconds() * audio.SampleRate))
	numBytes := numSamples * 4

	samples = make([][2]float64, numSamples)
	buf = make([]byte, numBytes)

	var err error
	player, err = oto.NewPlayer(int(audio.SampleRate), 2, 2, numBytes)
	if err != nil {
		return errors.Wrap(err, "failed to initialize speaker")
	}

	done = make(chan struct{})

	go func() {
		for {
			select {
			default:
				update()
			case <-done:
				done <- struct{}{}
				return
			}
		}
	}()

	return nil
}

// Lock locks the speaker. While locked, speaker won't pull new data from the playing Stramers. Lock
// if you want to modify any currently playing Streamers to avoid race conditions.
func Lock() {
	mu.Lock()
}

// Unlock unlocks the speaker. Call after modifying any currently playing Streamer.
func Unlock() {
	mu.Unlock()
}

// Play starts playing all provided Streamers through the speaker.
func Play(s ...audio.Streamer) {
	mu.Lock()
	mixer.Play(s...)
	mu.Unlock()
}

// update pulls new data from the playing Streamers and sends it to the speaker. Blocks until the
// data is sent and started playing.
func update() {
	mu.Lock()
	mixer.Stream(samples)
	mu.Unlock()

	for i := range samples {
		for c := range samples[i] {
			val := samples[i][c]
			if val < -1 {
				val = -1
			}
			if val > +1 {
				val = +1
			}
			valInt16 := int16(val * (1<<15 - 1))
			low := byte(valInt16 % (1 << 8))
			high := byte(valInt16 / (1 << 8))
			buf[i*4+c*2+0] = low
			buf[i*4+c*2+1] = high
		}
	}

	player.Write(buf)
}
<|endoftext|>


<commit_before>// Copyright © 2017 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package errors

import (
	"fmt"
	"io"
	"strings"

	errs "github.com/pkg/errors"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
)

type ErrType string

// These constants represent error types
const (
	AlreadyExists    ErrType = "already exists"
	Internal         ErrType = "internal"
	InvalidArgument  ErrType = "invalid argument"
	NotFound         ErrType = "not found"
	OutOfRange       ErrType = "out of range"
	PermissionDenied ErrType = "permission denied"
	Unknown          ErrType = "unknown"
)

// GetErrType returns the type of err
func GetErrType(err error) ErrType {
	switch errs.Cause(err).(type) {
	case *ErrAlreadyExists:
		return AlreadyExists
	case *ErrInternal:
		return Internal
	case *ErrInvalidArgument:
		return InvalidArgument
	case *ErrNotFound:
		return NotFound
	case *ErrPermissionDenied:
		return PermissionDenied
	}
	return Unknown
}

// BuildGRPCError returns the error with a GRPC code
func BuildGRPCError(err error) error {
	if err == nil {
		return nil
	}
	code := grpc.Code(err)
	if code != codes.Unknown {
		return err // it already is a gRPC error
	}
	switch errs.Cause(err).(type) {
	case *ErrAlreadyExists:
		code = codes.AlreadyExists
	case *ErrInternal:
		code = codes.Internal
	case *ErrInvalidArgument:
		code = codes.InvalidArgument
	case *ErrNotFound:
		code = codes.NotFound
	case *ErrPermissionDenied:
		code = codes.PermissionDenied
	}
	switch err {
	case context.Canceled:
		code = codes.Canceled
	case io.EOF:
		code = codes.OutOfRange
	}
	return grpc.Errorf(code, err.Error())
}

// FromGRPCError creates a regular error with the same type as the gRPC error
func FromGRPCError(err error) error {
	if err == nil {
		return nil
	}
	code := grpc.Code(err)
	desc := grpc.ErrorDesc(err)
	switch code {
	case codes.AlreadyExists:
		return NewErrAlreadyExists(strings.TrimSuffix(desc, " already exists"))
	case codes.Internal:
		return NewErrInternal(strings.TrimPrefix(desc, "Internal error: "))
	case codes.InvalidArgument:
		if split := strings.Split(desc, " not valid: "); len(split) == 2 {
			return NewErrInvalidArgument(split[0], split[1])
		}
		return NewErrInvalidArgument("Argument", desc)
	case codes.NotFound:
		return NewErrNotFound(strings.TrimSuffix(desc, " not found"))
	case codes.PermissionDenied:
		return NewErrPermissionDenied(strings.TrimPrefix(desc, "permission denied: "))
	case codes.Unknown: // This also includes all non-gRPC errors
		if desc == "EOF" {
			return io.EOF
		}
		return errs.New(desc)
	}
	return NewErrInternal(fmt.Sprintf("[%s] %s", code, desc))
}

// NewErrAlreadyExists returns a new ErrAlreadyExists for the given entitiy
func NewErrAlreadyExists(entity string) error {
	return &ErrAlreadyExists{entity: entity}
}

// ErrAlreadyExists indicates that an entity already exists
type ErrAlreadyExists struct {
	entity string
}

// Error implements the error interface
func (err ErrAlreadyExists) Error() string {
	return fmt.Sprintf("%s already exists", err.entity)
}

// NewErrInternal returns a new ErrInternal with the given message
func NewErrInternal(message string) error {
	return &ErrInternal{message: message}
}

// ErrInternal indicates that an internal error occured
type ErrInternal struct {
	message string
}

// Error implements the error interface
func (err ErrInternal) Error() string {
	return fmt.Sprintf("Internal error: %s", err.message)
}

// NewErrInvalidArgument returns a new ErrInvalidArgument for the given entitiy
func NewErrInvalidArgument(argument string, reason string) error {
	return &ErrInvalidArgument{argument: argument, reason: reason}
}

// ErrInvalidArgument indicates that an argument was invalid
type ErrInvalidArgument struct {
	argument string
	reason   string
}

// Error implements the error interface
func (err ErrInvalidArgument) Error() string {
	return fmt.Sprintf("%s not valid: %s", err.argument, err.reason)
}

// NewErrNotFound returns a new ErrNotFound for the given entitiy
func NewErrNotFound(entity string) error {
	return &ErrNotFound{entity: entity}
}

// ErrNotFound indicates that an entity was not found
type ErrNotFound struct {
	entity string
}

// Error implements the error interface
func (err ErrNotFound) Error() string {
	return fmt.Sprintf("%s not found", err.entity)
}

// NewErrPermissionDenied returns a new ErrPermissionDenied with the given reason
func NewErrPermissionDenied(reason string) error {
	return &ErrPermissionDenied{reason: reason}
}

// ErrPermissionDenied indicates that permissions were not sufficient
type ErrPermissionDenied struct {
	reason string
}

// Error implements the error interface
func (err ErrPermissionDenied) Error() string {
	return fmt.Sprintf("permission denied: %s", err.reason)
}

// Wrapf returns an error annotating err with the format specifier.
// If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error {
	return errs.Wrapf(err, format, args...)
}

// Wrap returns an error annotating err with message.
// If err is nil, Wrap returns nil.
func Wrap(err error, message string) error {
	return errs.Wrap(err, message)
}

// New returns an error with the supplied message.
// New also records the stack trace at the point it was called.
func New(message string) error {
	return errs.New(message)
}
<commit_msg>errors: add helpers to determine type<commit_after>// Copyright © 2017 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package errors

import (
	"fmt"
	"io"
	"strings"

	errs "github.com/pkg/errors"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
)

type ErrType string

// These constants represent error types
const (
	AlreadyExists    ErrType = "already exists"
	Internal         ErrType = "internal"
	InvalidArgument  ErrType = "invalid argument"
	NotFound         ErrType = "not found"
	OutOfRange       ErrType = "out of range"
	PermissionDenied ErrType = "permission denied"
	Unknown          ErrType = "unknown"
)

// GetErrType returns the type of err
func GetErrType(err error) ErrType {
	switch errs.Cause(err).(type) {
	case *ErrAlreadyExists:
		return AlreadyExists
	case *ErrInternal:
		return Internal
	case *ErrInvalidArgument:
		return InvalidArgument
	case *ErrNotFound:
		return NotFound
	case *ErrPermissionDenied:
		return PermissionDenied
	}
	return Unknown
}

func IsPermissionDenied(err error) bool {
	return GetErrType(err) == PermissionDenied
}
func IsNotFound(err error) bool {
	return GetErrType(err) == NotFound
}
func IsInvalidArgument(err error) bool {
	return GetErrType(err) == InvalidArgument
}
func IsInternal(err error) bool {
	return GetErrType(err) == Internal
}
func IsAlreadyExists(err error) bool {
	return GetErrType(err) == AlreadyExists
}

// BuildGRPCError returns the error with a GRPC code
func BuildGRPCError(err error) error {
	if err == nil {
		return nil
	}
	code := grpc.Code(err)
	if code != codes.Unknown {
		return err // it already is a gRPC error
	}
	switch errs.Cause(err).(type) {
	case *ErrAlreadyExists:
		code = codes.AlreadyExists
	case *ErrInternal:
		code = codes.Internal
	case *ErrInvalidArgument:
		code = codes.InvalidArgument
	case *ErrNotFound:
		code = codes.NotFound
	case *ErrPermissionDenied:
		code = codes.PermissionDenied
	}
	switch err {
	case context.Canceled:
		code = codes.Canceled
	case io.EOF:
		code = codes.OutOfRange
	}
	return grpc.Errorf(code, err.Error())
}

// FromGRPCError creates a regular error with the same type as the gRPC error
func FromGRPCError(err error) error {
	if err == nil {
		return nil
	}
	code := grpc.Code(err)
	desc := grpc.ErrorDesc(err)
	switch code {
	case codes.AlreadyExists:
		return NewErrAlreadyExists(strings.TrimSuffix(desc, " already exists"))
	case codes.Internal:
		return NewErrInternal(strings.TrimPrefix(desc, "Internal error: "))
	case codes.InvalidArgument:
		if split := strings.Split(desc, " not valid: "); len(split) == 2 {
			return NewErrInvalidArgument(split[0], split[1])
		}
		return NewErrInvalidArgument("Argument", desc)
	case codes.NotFound:
		return NewErrNotFound(strings.TrimSuffix(desc, " not found"))
	case codes.PermissionDenied:
		return NewErrPermissionDenied(strings.TrimPrefix(desc, "permission denied: "))
	case codes.Unknown: // This also includes all non-gRPC errors
		if desc == "EOF" {
			return io.EOF
		}
		return errs.New(desc)
	}
	return NewErrInternal(fmt.Sprintf("[%s] %s", code, desc))
}

// NewErrAlreadyExists returns a new ErrAlreadyExists for the given entitiy
func NewErrAlreadyExists(entity string) error {
	return &ErrAlreadyExists{entity: entity}
}

// ErrAlreadyExists indicates that an entity already exists
type ErrAlreadyExists struct {
	entity string
}

// Error implements the error interface
func (err ErrAlreadyExists) Error() string {
	return fmt.Sprintf("%s already exists", err.entity)
}

// NewErrInternal returns a new ErrInternal with the given message
func NewErrInternal(message string) error {
	return &ErrInternal{message: message}
}

// ErrInternal indicates that an internal error occured
type ErrInternal struct {
	message string
}

// Error implements the error interface
func (err ErrInternal) Error() string {
	return fmt.Sprintf("Internal error: %s", err.message)
}

// NewErrInvalidArgument returns a new ErrInvalidArgument for the given entitiy
func NewErrInvalidArgument(argument string, reason string) error {
	return &ErrInvalidArgument{argument: argument, reason: reason}
}

// ErrInvalidArgument indicates that an argument was invalid
type ErrInvalidArgument struct {
	argument string
	reason   string
}

// Error implements the error interface
func (err ErrInvalidArgument) Error() string {
	return fmt.Sprintf("%s not valid: %s", err.argument, err.reason)
}

// NewErrNotFound returns a new ErrNotFound for the given entitiy
func NewErrNotFound(entity string) error {
	return &ErrNotFound{entity: entity}
}

// ErrNotFound indicates that an entity was not found
type ErrNotFound struct {
	entity string
}

// Error implements the error interface
func (err ErrNotFound) Error() string {
	return fmt.Sprintf("%s not found", err.entity)
}

// NewErrPermissionDenied returns a new ErrPermissionDenied with the given reason
func NewErrPermissionDenied(reason string) error {
	return &ErrPermissionDenied{reason: reason}
}

// ErrPermissionDenied indicates that permissions were not sufficient
type ErrPermissionDenied struct {
	reason string
}

// Error implements the error interface
func (err ErrPermissionDenied) Error() string {
	return fmt.Sprintf("permission denied: %s", err.reason)
}

// Wrapf returns an error annotating err with the format specifier.
// If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error {
	return errs.Wrapf(err, format, args...)
}

// Wrap returns an error annotating err with message.
// If err is nil, Wrap returns nil.
func Wrap(err error, message string) error {
	return errs.Wrap(err, message)
}

// New returns an error with the supplied message.
// New also records the stack trace at the point it was called.
func New(message string) error {
	return errs.New(message)
}
<|endoftext|>


<commit_before>package sfml

//#include <SFML/Graphics.h>
import "C"

const (
	FactorZero             BlendFactor = C.sfBlendFactorZero
	FactorOne              BlendFactor = C.sfBlendFactorOne
	FactorSrcColor         BlendFactor = C.sfBlendFactorSrcColor
	FactorOneMinusSrcColor BlendFactor = C.sfBlendFactorOneMinusSrcColor
	FactorDstColor         BlendFactor = C.sfBlendFactorDstColor
	FactorOneMinusDstColor BlendFactor = C.sfBlendFactorOneMinusDstColor
	FactorSrcAlpha         BlendFactor = C.sfBlendFactorSrcAlpha
	FactorOneMinusSrcAlpha BlendFactor = C.sfBlendFactorOneMinusSrcAlpha
	FactorDstAlpha         BlendFactor = C.sfBlendFactorDstAlpha
	FactorOneMinusDstAlpha BlendFactor = C.sfBlendFactorOneMinusDstAlpha
)

const (
	EquationAdd      BlendEquation = C.sfBlendEquationAdd
	EquationSubtract BlendEquation = C.sfBlendEquationSubtract
)

var (
	BlendAlpha    = *goBlendMode(&C.sfBlendAlpha)
	BlendAdd      = *goBlendMode(&C.sfBlendAdd)
	BlendMultiply = *goBlendMode(&C.sfBlendMultiply)
	BlendNone     = *goBlendMode(&C.sfBlendNone)
)

type BlendFactor int
type BlendEquation int

type BlendMode struct {
	ColorSrcFactor BlendFactor
	ColorDstFactor BlendFactor
	ColorEquation  BlendEquation
	AlphaSrcFactor BlendFactor
	AlphaDstFactor BlendFactor
	AlphaEquation  BlendEquation
}

func goBlendMode(b *C.sfBlendMode) *BlendMode {
	return &BlendMode{
		BlendFactor(b.colorSrcFactor),
		BlendFactor(b.colorDstFactor),
		BlendEquation(b.colorEquation),
		BlendFactor(b.alphaSrcFactor),
		BlendFactor(b.alphaDstFactor),
		BlendEquation(b.alphaEquation),
	}
}

func cBlendMode(b *BlendMode) C.sfBlendMode {
	return C.sfBlendMode{
		C.sfBlendFactor(b.ColorSrcFactor),
		C.sfBlendFactor(b.ColorDstFactor),
		C.sfBlendEquation(b.ColorEquation),
		C.sfBlendFactor(b.AlphaSrcFactor),
		C.sfBlendFactor(b.AlphaDstFactor),
		C.sfBlendEquation(b.AlphaEquation),
	}
}
<commit_msg>Fixes #2<commit_after>package sfml

//#include <SFML/Graphics.h>
import "C"

const (
	FactorZero             BlendFactor = C.sfBlendFactorZero
	FactorOne              BlendFactor = C.sfBlendFactorOne
	FactorSrcColor         BlendFactor = C.sfBlendFactorSrcColor
	FactorOneMinusSrcColor BlendFactor = C.sfBlendFactorOneMinusSrcColor
	FactorDstColor         BlendFactor = C.sfBlendFactorDstColor
	FactorOneMinusDstColor BlendFactor = C.sfBlendFactorOneMinusDstColor
	FactorSrcAlpha         BlendFactor = C.sfBlendFactorSrcAlpha
	FactorOneMinusSrcAlpha BlendFactor = C.sfBlendFactorOneMinusSrcAlpha
	FactorDstAlpha         BlendFactor = C.sfBlendFactorDstAlpha
	FactorOneMinusDstAlpha BlendFactor = C.sfBlendFactorOneMinusDstAlpha
)

const (
	EquationAdd      BlendEquation = C.sfBlendEquationAdd
	EquationSubtract BlendEquation = C.sfBlendEquationSubtract
)

var (
	BlendAlpha = BlendMode{
		FactorSrcAlpha,
		FactorOneMinusSrcAlpha,
		EquationAdd,
		FactorOne,
		FactorOneMinusSrcAlpha,
		EquationAdd,
	}
	BlendAdd = BlendMode{
		FactorSrcAlpha,
		FactorOne,
		EquationAdd,
		FactorOne,
		FactorOne,
		EquationAdd,
	}
	BlendMultiply = BlendMode{
		FactorDstColor,
		FactorZero,
		EquationAdd,
		FactorDstColor,
		FactorZero,
		EquationAdd,
	}
	BlendNone = BlendMode{
		FactorOne,
		FactorZero,
		EquationAdd,
		FactorOne,
		FactorZero,
		EquationAdd,
	}
)

type BlendFactor int
type BlendEquation int

type BlendMode struct {
	ColorSrcFactor BlendFactor
	ColorDstFactor BlendFactor
	ColorEquation  BlendEquation
	AlphaSrcFactor BlendFactor
	AlphaDstFactor BlendFactor
	AlphaEquation  BlendEquation
}

func goBlendMode(b *C.sfBlendMode) *BlendMode {
	return &BlendMode{
		BlendFactor(b.colorSrcFactor),
		BlendFactor(b.colorDstFactor),
		BlendEquation(b.colorEquation),
		BlendFactor(b.alphaSrcFactor),
		BlendFactor(b.alphaDstFactor),
		BlendEquation(b.alphaEquation),
	}
}

func cBlendMode(b *BlendMode) C.sfBlendMode {
	return C.sfBlendMode{
		C.sfBlendFactor(b.ColorSrcFactor),
		C.sfBlendFactor(b.ColorDstFactor),
		C.sfBlendEquation(b.ColorEquation),
		C.sfBlendFactor(b.AlphaSrcFactor),
		C.sfBlendFactor(b.AlphaDstFactor),
		C.sfBlendEquation(b.AlphaEquation),
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"

	cfitsio "github.com/sbinet/go-cfitsio"
)

func main() {

	flag.Usage = func() {
		const msg = `Usage: go-cfitsio-tablist filename[ext][col filter][row filter]

List the contents of a FITS table

Examples:
  tablist tab.fits[GTI]           - list the GTI extension
  tablist tab.fits[1][#row < 101] - list first 100 rows
  tablist tab.fits[1][col X;Y]    - list X and Y cols only
  tablist tab.fits[1][col -PI]    - list all but the PI col
  tablist tab.fits[1][col -PI][#row < 101]  - combined case

Display formats can be modified with the TDISPn keywords.
`
		fmt.Fprintf(os.Stderr, "%v\n", msg)
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(1)
	}

	fname := flag.Arg(0)
	f, err := cfitsio.Open(fname, cfitsio.ReadOnly)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	ihdu := f.HDUNum() // get the current HDU position
	if ihdu == 0 {
		// this is the primary array.
		// try to move to the first extension and see if it is a table
		ihdu = 1
	}
	hdu := f.HDUs()[ihdu]

	if hdu.Type() == cfitsio.IMAGE_HDU {
		fmt.Printf("Error: this program only displays tables, not images\n")
		os.Exit(1)
	}

	table := hdu.(*cfitsio.Table)
	nrows := table.NumRows()
	//ncols := table.NumCols()

	w := os.Stdout
	for icol, col := range table.Cols() {
		fmt.Fprintf(w, "\n[row] -+- %s (%T)\n", col.Name, col.Value)

		for i := int64(0); i < nrows; i++ {
			fmt.Fprintf(w, "%4d ", i)
			err := table.ReadRow(i)
			if err != nil {
				panic(err)
			}
			fmt.Fprintf(w, "  |  %-10v\n", table.Cols()[icol].Value)
		}
	}
}
<commit_msg>tablist: better error handling<commit_after>package main

import (
	"flag"
	"fmt"
	"os"

	cfitsio "github.com/sbinet/go-cfitsio"
)

func main() {

	flag.Usage = func() {
		const msg = `Usage: go-cfitsio-tablist filename[ext][col filter][row filter]

List the contents of a FITS table

Examples:
  tablist tab.fits[GTI]           - list the GTI extension
  tablist tab.fits[1][#row < 101] - list first 100 rows
  tablist tab.fits[1][col X;Y]    - list X and Y cols only
  tablist tab.fits[1][col -PI]    - list all but the PI col
  tablist tab.fits[1][col -PI][#row < 101]  - combined case

Display formats can be modified with the TDISPn keywords.
`
		fmt.Fprintf(os.Stderr, "%v\n", msg)
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(1)
	}

	fname := flag.Arg(0)
	f, err := cfitsio.Open(fname, cfitsio.ReadOnly)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	ihdu := f.HDUNum() // get the current HDU position
	if ihdu == 0 {
		// this is the primary array.
		// try to move to the first extension and see if it is a table
		ihdu = 1
	}
	if ihdu >= len(f.HDUs()) {
		fmt.Printf("Error: input file has no extension\n")
		os.Exit(1)
	}
	hdu := f.HDU(ihdu)

	if hdu.Type() == cfitsio.IMAGE_HDU {
		fmt.Printf("Error: this program only displays tables, not images\n")
		os.Exit(1)
	}

	table := hdu.(*cfitsio.Table)
	nrows := table.NumRows()
	//ncols := table.NumCols()

	w := os.Stdout
	for icol, col := range table.Cols() {
		fmt.Fprintf(w, "\n[row] -+- %s (%T)\n", col.Name, col.Value)

		for i := int64(0); i < nrows; i++ {
			fmt.Fprintf(w, "%4d ", i)
			err := table.ReadRow(i)
			if err != nil {
				panic(err)
			}
			fmt.Fprintf(w, "  |  %-10v\n", table.Cols()[icol].Value)
		}
	}
}
<|endoftext|>


<commit_before>package server

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/bouk/httprouter"
	"github.com/influxdata/chronograf"
	"github.com/influxdata/chronograf/uuid"
)

// ValidTemplateRequest checks if the request sent to the server is the correct format.
func ValidTemplateRequest(template *chronograf.Template) error {
	switch template.Type {
	default:
		return fmt.Errorf("Unknown template type %s", template.Type)
	case "query", "constant", "csv", "fieldKeys", "tagKeys", "tagValues":
	}

	for _, v := range template.Values {
		switch v.Type {
		default:
			return fmt.Errorf("Unknown template variable type %s", v.Type)
		case "csv", "fieldKey", "tagKey", "tagValue":
		}
	}

	if template.Type == "query" && template.Query == nil {
		return fmt.Errorf("No query set for template of type 'query'")
	}
	return nil
}

type templateLinks struct {
	Self string `json:"self"` // Self link mapping to this resource
}

type templateResponse struct {
	chronograf.Template
	Links templateLinks `json:"links"`
}

func newTemplateResponses(dID chronograf.DashboardID, tmps []chronograf.Template) []templateResponse {
	res := make([]templateResponse, len(tmps))
	for i, t := range tmps {
		res[i] = newTemplateResponse(dID, t)
	}
	return res
}

func newTemplateResponse(dID chronograf.DashboardID, tmp chronograf.Template) templateResponse {
	base := "/chronograf/v1/dashboards"
	return templateResponse{
		Template: tmp,
		Links: templateLinks{
			Self: fmt.Sprintf("%s/%d/templates/%s", base, dID, tmp.ID),
		},
	}
}

// Templates returns all templates from a dashboard within the store
func (s *Service) Templates(w http.ResponseWriter, r *http.Request) {
	id, err := paramID("id", r)
	if err != nil {
		Error(w, http.StatusUnprocessableEntity, err.Error(), s.Logger)
		return
	}

	ctx := r.Context()
	e, err := s.DashboardsStore.Get(ctx, chronograf.DashboardID(id))
	if err != nil {
		notFound(w, id, s.Logger)
		return
	}

	boards := newDashboardResponse(e)
	templates := boards.Templates
	encodeJSON(w, http.StatusOK, templates, s.Logger)
}

// NewTemplate adds a template to an existing dashboard
func (s *Service) NewTemplate(w http.ResponseWriter, r *http.Request) {
	id, err := paramID("id", r)
	if err != nil {
		Error(w, http.StatusUnprocessableEntity, err.Error(), s.Logger)
		return
	}

	ctx := r.Context()
	dash, err := s.DashboardsStore.Get(ctx, chronograf.DashboardID(id))
	if err != nil {
		notFound(w, id, s.Logger)
		return
	}

	var template chronograf.Template
	if err := json.NewDecoder(r.Body).Decode(&template); err != nil {
		invalidJSON(w, s.Logger)
		return
	}

	if err := ValidTemplateRequest(&template); err != nil {
		invalidData(w, err, s.Logger)
		return
	}

	ids := uuid.V4{}
	tid, err := ids.Generate()
	if err != nil {
		msg := fmt.Sprintf("Error creating template ID for dashboard %d: %v", id, err)
		Error(w, http.StatusInternalServerError, msg, s.Logger)
		return
	}
	template.ID = chronograf.TemplateID(tid)

	dash.Templates = append(dash.Templates, template)
	if err := s.DashboardsStore.Update(ctx, dash); err != nil {
		msg := fmt.Sprintf("Error adding template %s to dashboard %d: %v", tid, id, err)
		Error(w, http.StatusInternalServerError, msg, s.Logger)
		return
	}

	res := newTemplateResponse(dash.ID, template)
	encodeJSON(w, http.StatusOK, res, s.Logger)
}

// TemplateID retrieves a specific template from a dashboard
func (s *Service) TemplateID(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	id, err := paramID("id", r)
	if err != nil {
		Error(w, http.StatusUnprocessableEntity, err.Error(), s.Logger)
		return
	}

	dash, err := s.DashboardsStore.Get(ctx, chronograf.DashboardID(id))
	if err != nil {
		notFound(w, id, s.Logger)
		return
	}

	tid := httprouter.GetParamFromContext(ctx, "tid")
	for _, t := range dash.Templates {
		if t.ID == chronograf.TemplateID(tid) {
			res := newTemplateResponse(chronograf.DashboardID(id), t)
			encodeJSON(w, http.StatusOK, res, s.Logger)
		}
	}

	notFound(w, id, s.Logger)
}

// RemoveTemplate removes a specific template from an existing dashboard
func (s *Service) RemoveTemplate(w http.ResponseWriter, r *http.Request) {
	id, err := paramID("id", r)
	if err != nil {
		Error(w, http.StatusUnprocessableEntity, err.Error(), s.Logger)
		return
	}

	ctx := r.Context()
	dash, err := s.DashboardsStore.Get(ctx, chronograf.DashboardID(id))
	if err != nil {
		notFound(w, id, s.Logger)
		return
	}

	tid := httprouter.GetParamFromContext(ctx, "tid")
	pos := -1
	for i, t := range dash.Templates {
		if t.ID == chronograf.TemplateID(tid) {
			pos = i
			break
		}
	}
	if pos == -1 {
		notFound(w, id, s.Logger)
		return
	}

	dash.Templates = append(dash.Templates[:pos], dash.Templates[pos+1:]...)
	if err := s.DashboardsStore.Update(ctx, dash); err != nil {
		msg := fmt.Sprintf("Error removing template %s from dashboard %d: %v", tid, id, err)
		Error(w, http.StatusInternalServerError, msg, s.Logger)
		return
	}

	w.WriteHeader(http.StatusNoContent)
}

// ReplaceTemplate replaces a template entirely within an existing dashboard
func (s *Service) ReplaceTemplate(w http.ResponseWriter, r *http.Request) {
	id, err := paramID("id", r)
	if err != nil {
		Error(w, http.StatusUnprocessableEntity, err.Error(), s.Logger)
		return
	}

	ctx := r.Context()
	dash, err := s.DashboardsStore.Get(ctx, chronograf.DashboardID(id))
	if err != nil {
		notFound(w, id, s.Logger)
		return
	}

	tid := httprouter.GetParamFromContext(ctx, "tid")
	pos := -1
	for i, t := range dash.Templates {
		if t.ID == chronograf.TemplateID(tid) {
			pos = i
			break
		}
	}
	if pos == -1 {
		notFound(w, id, s.Logger)
		return
	}

	var template chronograf.Template
	if err := json.NewDecoder(r.Body).Decode(&template); err != nil {
		invalidJSON(w, s.Logger)
		return
	}

	if err := ValidTemplateRequest(&template); err != nil {
		invalidData(w, err, s.Logger)
		return
	}
	template.ID = chronograf.TemplateID(tid)

	dash.Templates[pos] = template
	if err := s.DashboardsStore.Update(ctx, dash); err != nil {
		msg := fmt.Sprintf("Error updating template %s in dashboard %d: %v", tid, id, err)
		Error(w, http.StatusInternalServerError, msg, s.Logger)
		return
	}

	res := newTemplateResponse(chronograf.DashboardID(id), template)
	encodeJSON(w, http.StatusOK, res, s.Logger)
}
<commit_msg>Update templates API response<commit_after>package server

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/bouk/httprouter"
	"github.com/influxdata/chronograf"
	"github.com/influxdata/chronograf/uuid"
)

// ValidTemplateRequest checks if the request sent to the server is the correct format.
func ValidTemplateRequest(template *chronograf.Template) error {
	switch template.Type {
	default:
		return fmt.Errorf("Unknown template type %s", template.Type)
	case "query", "constant", "csv", "fieldKeys", "tagKeys", "tagValues":
	}

	for _, v := range template.Values {
		switch v.Type {
		default:
			return fmt.Errorf("Unknown template variable type %s", v.Type)
		case "csv", "fieldKey", "tagKey", "tagValue":
		}
	}

	if template.Type == "query" && template.Query == nil {
		return fmt.Errorf("No query set for template of type 'query'")
	}
	return nil
}

type templateLinks struct {
	Self string `json:"self"` // Self link mapping to this resource
}

type templateResponse struct {
	chronograf.Template
	Links templateLinks `json:"links"`
}

func newTemplateResponses(dID chronograf.DashboardID, tmps []chronograf.Template) []templateResponse {
	res := make([]templateResponse, len(tmps))
	for i, t := range tmps {
		res[i] = newTemplateResponse(dID, t)
	}
	return res
}

type templatesResponses struct {
	Templates []templateResponse `json:"templates"`
}

func newTemplateResponse(dID chronograf.DashboardID, tmp chronograf.Template) templateResponse {
	base := "/chronograf/v1/dashboards"
	return templateResponse{
		Template: tmp,
		Links: templateLinks{
			Self: fmt.Sprintf("%s/%d/templates/%s", base, dID, tmp.ID),
		},
	}
}

// Templates returns all templates from a dashboard within the store
func (s *Service) Templates(w http.ResponseWriter, r *http.Request) {
	id, err := paramID("id", r)
	if err != nil {
		Error(w, http.StatusUnprocessableEntity, err.Error(), s.Logger)
		return
	}

	ctx := r.Context()
	d, err := s.DashboardsStore.Get(ctx, chronograf.DashboardID(id))
	if err != nil {
		notFound(w, id, s.Logger)
		return
	}

	res := templatesResponses{
		Templates: newTemplateResponses(chronograf.DashboardID(id), d.Templates),
	}
	encodeJSON(w, http.StatusOK, res, s.Logger)
}

// NewTemplate adds a template to an existing dashboard
func (s *Service) NewTemplate(w http.ResponseWriter, r *http.Request) {
	id, err := paramID("id", r)
	if err != nil {
		Error(w, http.StatusUnprocessableEntity, err.Error(), s.Logger)
		return
	}

	ctx := r.Context()
	dash, err := s.DashboardsStore.Get(ctx, chronograf.DashboardID(id))
	if err != nil {
		notFound(w, id, s.Logger)
		return
	}

	var template chronograf.Template
	if err := json.NewDecoder(r.Body).Decode(&template); err != nil {
		invalidJSON(w, s.Logger)
		return
	}

	if err := ValidTemplateRequest(&template); err != nil {
		invalidData(w, err, s.Logger)
		return
	}

	ids := uuid.V4{}
	tid, err := ids.Generate()
	if err != nil {
		msg := fmt.Sprintf("Error creating template ID for dashboard %d: %v", id, err)
		Error(w, http.StatusInternalServerError, msg, s.Logger)
		return
	}
	template.ID = chronograf.TemplateID(tid)

	dash.Templates = append(dash.Templates, template)
	if err := s.DashboardsStore.Update(ctx, dash); err != nil {
		msg := fmt.Sprintf("Error adding template %s to dashboard %d: %v", tid, id, err)
		Error(w, http.StatusInternalServerError, msg, s.Logger)
		return
	}

	res := newTemplateResponse(dash.ID, template)
	encodeJSON(w, http.StatusOK, res, s.Logger)
}

// TemplateID retrieves a specific template from a dashboard
func (s *Service) TemplateID(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	id, err := paramID("id", r)
	if err != nil {
		Error(w, http.StatusUnprocessableEntity, err.Error(), s.Logger)
		return
	}

	dash, err := s.DashboardsStore.Get(ctx, chronograf.DashboardID(id))
	if err != nil {
		notFound(w, id, s.Logger)
		return
	}

	tid := httprouter.GetParamFromContext(ctx, "tid")
	for _, t := range dash.Templates {
		if t.ID == chronograf.TemplateID(tid) {
			res := newTemplateResponse(chronograf.DashboardID(id), t)
			encodeJSON(w, http.StatusOK, res, s.Logger)
		}
	}

	notFound(w, id, s.Logger)
}

// RemoveTemplate removes a specific template from an existing dashboard
func (s *Service) RemoveTemplate(w http.ResponseWriter, r *http.Request) {
	id, err := paramID("id", r)
	if err != nil {
		Error(w, http.StatusUnprocessableEntity, err.Error(), s.Logger)
		return
	}

	ctx := r.Context()
	dash, err := s.DashboardsStore.Get(ctx, chronograf.DashboardID(id))
	if err != nil {
		notFound(w, id, s.Logger)
		return
	}

	tid := httprouter.GetParamFromContext(ctx, "tid")
	pos := -1
	for i, t := range dash.Templates {
		if t.ID == chronograf.TemplateID(tid) {
			pos = i
			break
		}
	}
	if pos == -1 {
		notFound(w, id, s.Logger)
		return
	}

	dash.Templates = append(dash.Templates[:pos], dash.Templates[pos+1:]...)
	if err := s.DashboardsStore.Update(ctx, dash); err != nil {
		msg := fmt.Sprintf("Error removing template %s from dashboard %d: %v", tid, id, err)
		Error(w, http.StatusInternalServerError, msg, s.Logger)
		return
	}

	w.WriteHeader(http.StatusNoContent)
}

// ReplaceTemplate replaces a template entirely within an existing dashboard
func (s *Service) ReplaceTemplate(w http.ResponseWriter, r *http.Request) {
	id, err := paramID("id", r)
	if err != nil {
		Error(w, http.StatusUnprocessableEntity, err.Error(), s.Logger)
		return
	}

	ctx := r.Context()
	dash, err := s.DashboardsStore.Get(ctx, chronograf.DashboardID(id))
	if err != nil {
		notFound(w, id, s.Logger)
		return
	}

	tid := httprouter.GetParamFromContext(ctx, "tid")
	pos := -1
	for i, t := range dash.Templates {
		if t.ID == chronograf.TemplateID(tid) {
			pos = i
			break
		}
	}
	if pos == -1 {
		notFound(w, id, s.Logger)
		return
	}

	var template chronograf.Template
	if err := json.NewDecoder(r.Body).Decode(&template); err != nil {
		invalidJSON(w, s.Logger)
		return
	}

	if err := ValidTemplateRequest(&template); err != nil {
		invalidData(w, err, s.Logger)
		return
	}
	template.ID = chronograf.TemplateID(tid)

	dash.Templates[pos] = template
	if err := s.DashboardsStore.Update(ctx, dash); err != nil {
		msg := fmt.Sprintf("Error updating template %s in dashboard %d: %v", tid, id, err)
		Error(w, http.StatusInternalServerError, msg, s.Logger)
		return
	}

	res := newTemplateResponse(chronograf.DashboardID(id), template)
	encodeJSON(w, http.StatusOK, res, s.Logger)
}
<|endoftext|>


<commit_before>package gosseract

import (
	"testing"

	. "github.com/otiai10/mint"
)

func TestVersion(t *testing.T) {
	version := Version()
	Expect(t, version).Match("[0-9]{1}.[0-9]{2}(.[0-9a-z]*)")
}

func TestNewClient(t *testing.T) {
	client := NewClient()
	defer client.Close()

	Expect(t, client).TypeOf("*gosseract.Client")
}

func TestClient_SetImage(t *testing.T) {
	client := NewClient()
	defer client.Close()

	client.Trim = true
	client.SetImage("./test/data/001-gosseract.png")

	client.SetPageSegMode(PSM_SINGLE_BLOCK)

	text, err := client.Text()
	Expect(t, err).ToBe(nil)
	Expect(t, text).ToBe("otiai10 / gosseract")

	client.Languages = []string{"eng"}
	client.SetWhitelist("aegitosr10/")
	text, err = client.Text()
	Expect(t, err).ToBe(nil)
	Expect(t, text).ToBe("otiai10 / gosseraet")
}

func TestClient_SetLanguage(t *testing.T) {
	client := NewClient()
	defer client.Close()
	client.SetLanguage("eng", "deu")
}
<commit_msg>Version string can be "3.03"<commit_after>package gosseract

import (
	"testing"

	. "github.com/otiai10/mint"
)

func TestVersion(t *testing.T) {
	version := Version()
	Expect(t, version).Match("[0-9]{1}.[0-9]{2}(.[0-9a-z]*)?")
}

func TestNewClient(t *testing.T) {
	client := NewClient()
	defer client.Close()

	Expect(t, client).TypeOf("*gosseract.Client")
}

func TestClient_SetImage(t *testing.T) {
	client := NewClient()
	defer client.Close()

	client.Trim = true
	client.SetImage("./test/data/001-gosseract.png")

	client.SetPageSegMode(PSM_SINGLE_BLOCK)

	text, err := client.Text()
	Expect(t, err).ToBe(nil)
	Expect(t, text).ToBe("otiai10 / gosseract")

	client.Languages = []string{"eng"}
	client.SetWhitelist("aegitosr10/")
	text, err = client.Text()
	Expect(t, err).ToBe(nil)
	Expect(t, text).ToBe("otiai10 / gosseraet")
}

func TestClient_SetLanguage(t *testing.T) {
	client := NewClient()
	defer client.Close()
	client.SetLanguage("eng", "deu")
}
<|endoftext|>


<commit_before>package gigasecond

// Write a function AddGigasecond that works with time.Time.
// Also define a variable Birthday set to your (or someone else's) birthday.
// Run go test -v to see your gigasecond anniversary.

import (
	"os"
	"testing"
	"time"
)

const targetTestVersion = 4

// date formats used in test data
const (
	fmtD  = "2006-01-02"
	fmtDT = "2006-01-02T15:04:05"
)

func TestAddGigasecond(t *testing.T) {
	if testVersion != targetTestVersion {
		t.Fatalf("Found testVersion = %v, want %v.", testVersion, targetTestVersion)
	}
	for _, tc := range addCases {
		in := parse(tc.in, t)
		want := parse(tc.want, t)
		got := AddGigasecond(in)
		if !got.Equal(want) {
			t.Fatalf(`AddGigasecond(%s)
   = %s
want %s`, in, got, want)
		}
	}
	t.Log("Tested", len(addCases), "cases.")
}

func parse(s string, t *testing.T) time.Time {
	tt, err := time.Parse(fmtDT, s) // try full date time format first
	if err != nil {
		tt, err = time.Parse(fmtD, s) // also allow just date
	}
	if err != nil {
		// can't run tests if input won't parse.  if this seems to be a
		// development or ci environment, raise an error.  if this condition
		// makes it to the solver though, ask for a bug report.
		_, statErr := os.Stat("example_gen.go")
		if statErr == nil || os.Getenv("TRAVIS_GO_VERSION") > "" {
			t.Fatal(err)
		} else {
			t.Log(err)
			t.Skip("(Not your problem.  " +
				"please file issue at https://github.com/exercism/xgo.)")
		}
	}
	return tt
}

func BenchmarkAddGigasecond(b *testing.B) {
	for i := 0; i < b.N; i++ {
		AddGigasecond(time.Time{})
	}
}
<commit_msg>Gigasecond exercise - removes irrelevant comment<commit_after>package gigasecond

// Write a function AddGigasecond that works with time.Time.

import (
	"os"
	"testing"
	"time"
)

const targetTestVersion = 4

// date formats used in test data
const (
	fmtD  = "2006-01-02"
	fmtDT = "2006-01-02T15:04:05"
)

func TestAddGigasecond(t *testing.T) {
	if testVersion != targetTestVersion {
		t.Fatalf("Found testVersion = %v, want %v.", testVersion, targetTestVersion)
	}
	for _, tc := range addCases {
		in := parse(tc.in, t)
		want := parse(tc.want, t)
		got := AddGigasecond(in)
		if !got.Equal(want) {
			t.Fatalf(`AddGigasecond(%s)
   = %s
want %s`, in, got, want)
		}
	}
	t.Log("Tested", len(addCases), "cases.")
}

func parse(s string, t *testing.T) time.Time {
	tt, err := time.Parse(fmtDT, s) // try full date time format first
	if err != nil {
		tt, err = time.Parse(fmtD, s) // also allow just date
	}
	if err != nil {
		// can't run tests if input won't parse.  if this seems to be a
		// development or ci environment, raise an error.  if this condition
		// makes it to the solver though, ask for a bug report.
		_, statErr := os.Stat("example_gen.go")
		if statErr == nil || os.Getenv("TRAVIS_GO_VERSION") > "" {
			t.Fatal(err)
		} else {
			t.Log(err)
			t.Skip("(Not your problem.  " +
				"please file issue at https://github.com/exercism/xgo.)")
		}
	}
	return tt
}

func BenchmarkAddGigasecond(b *testing.B) {
	for i := 0; i < b.N; i++ {
		AddGigasecond(time.Time{})
	}
}
<|endoftext|>


<commit_before>// Package unionfind implements a UnionFind (disjoint-set) data structure,
// as described, for example, here: http://algs4.cs.princeton.edu/15uf .
//
// The Union() and Connected() operations take O(log* N) “log-star” time,
// which is close to O(1).
//
// The MakeSet() operation when used with multiple arguments, union elements
// in one set.
//
// Basic usage:
//
//   u := unionfind.New()
//
//   // Create sets.
//   u.MakeSet(1, 2, 3, 4)
//
//   // Join them together.
//   u.Union(1, 2)
//   u.Union(3, 4)
//   u.Union(2, 3)
//
//   // Check if they're connected.
//   fmt.Println(u.Connected(1, 4))
//
package unionfind

import (
	"fmt"
	"strings"
)

// Maintains sets and a number of connected elements.
type UnionFind struct {
	sets  map[interface{}]*set
	count int
}

type set struct {
	parent interface{}
	rank   int
}

// New return an initialized UnionFind data structure.
func New() *UnionFind {
	return &UnionFind{
		sets: make(map[interface{}]*set),
	}
}

// MakeSet makes an independent set of one element.  If called with multiple
// arguments, an independent set for every element is made.
func (u *UnionFind) MakeSet(a ...interface{}) {
	if len(a) == 0 {
		return
	}

	for _, elem := range a {
		if elem == nil {
			continue
		}

		// Skip already made sets.
		if _, ok := u.sets[elem]; ok {
			continue
		}

		u.sets[elem] = &set{parent: elem}
		u.count++
	}
}

// Union merges two independent sets as one. The number of sets is decreased by 1.
func (u *UnionFind) Union(x, y interface{}) {
	a := u.Find(x)
	b := u.Find(y)

	// Already connected.
	if a == b {
		return
	}

	// Weighting.
	switch {
	case u.sets[a].rank < u.sets[b].rank:
		u.sets[a].parent = b

	case u.sets[a].rank > u.sets[b].rank:
		u.sets[b].parent = a

	case u.sets[a].rank == u.sets[b].rank:
		u.sets[b].parent = a
		u.sets[a].rank++
	}

	u.count--
}

<<<<<<< HEAD
<<<<<<< HEAD
// Find returns the root element of the set. The root element is the same for
=======
// Find returns the root element of the set.  The root element is the same for
>>>>>>> 7343bd6... Comments
=======
// Find returns the root element of the set. The root element is the same for
>>>>>>> 2360783... ...
// all elements within the same set.
func (u UnionFind) Find(x interface{}) interface{} {
	if _, ok := u.sets[x]; !ok {
		panic(fmt.Sprintf("set %v hasn't been made yet with MakeSet", x))
	}

	// The root.
	if u.sets[x].parent == x {
		return x
	}

	// Path compression.
	u.sets[x].parent = u.Find(u.sets[x].parent)

	return u.sets[x].parent
}

// Exists returns true if the element belongs to any set, false otherwise.
func (u UnionFind) Exists(x interface{}) bool {
	if _, ok := u.sets[x]; ok {
		return true
	} else {
		return false
	}
}

// Connected returns true if the elements belong to the same set,
// false otherwise.
func (u UnionFind) Connected(x, y interface{}) bool {
	return u.Find(x) == u.Find(y)
}

<<<<<<< HEAD
<<<<<<< HEAD
// Count returns the number of independent sets.
=======
// Count returns the number of sets.
>>>>>>> 7343bd6... Comments
=======
// Count returns the number of independent sets.
>>>>>>> 48618ea... Comments
func (u UnionFind) Count() int {
	return u.count
}

func (u UnionFind) prepareDump() []string {
	m := make(map[interface{}][]interface{})

	for k, v := range u.sets {
		parent := u.Find(v.parent)

		if _, ok := m[parent]; !ok {
			m[parent] = []interface{}{}
		}
		m[parent] = append(m[parent], k)
	}

	s := []string{}
	for _, e := range m {
		s = append(s, fmt.Sprintf("%v", e))
	}
	return s
}

// String returns a text representation of a UnionFind data structure.
func (u UnionFind) String() string {
	return strings.Join(u.prepareDump(), " ")
}
<commit_msg>Comments<commit_after>// Package unionfind implements a UnionFind (disjoint-set) data structure,
// as described, for example, here: http://algs4.cs.princeton.edu/15uf .
//
// The Union() and Connected() operations take O(log* N) “log-star” time,
// which is close to O(1).
//
// The MakeSet() operation when used with multiple arguments, union elements
// in one set.
//
// Basic usage:
//
//   u := unionfind.New()
//
//   // Create sets.
//   u.MakeSet(1, 2, 3, 4)
//
//   // Join them together.
//   u.Union(1, 2)
//   u.Union(3, 4)
//   u.Union(2, 3)
//
//   // Check if they're connected.
//   fmt.Println(u.Connected(1, 4))
//
package unionfind

import (
	"fmt"
	"strings"
)

// Maintains sets and a number of connected elements.
type UnionFind struct {
	sets  map[interface{}]*set
	count int
}

type set struct {
	parent interface{}
	rank   int
}

// New return an initialized UnionFind data structure.
func New() *UnionFind {
	return &UnionFind{
		sets: make(map[interface{}]*set),
	}
}

// MakeSet makes an independent set of one element.  If called with multiple
// arguments, an independent set for every element is made.
func (u *UnionFind) MakeSet(a ...interface{}) {
	if len(a) == 0 {
		return
	}

	for _, elem := range a {
		if elem == nil {
			continue
		}

		// Skip already made sets.
		if _, ok := u.sets[elem]; ok {
			continue
		}

		u.sets[elem] = &set{parent: elem}
		u.count++
	}
}

// Union merges two independent sets as one. The number of sets is decreased by 1.
func (u *UnionFind) Union(x, y interface{}) {
	a := u.Find(x)
	b := u.Find(y)

	// Already connected.
	if a == b {
		return
	}

	// Weighting.
	switch {
	case u.sets[a].rank < u.sets[b].rank:
		u.sets[a].parent = b

	case u.sets[a].rank > u.sets[b].rank:
		u.sets[b].parent = a

	case u.sets[a].rank == u.sets[b].rank:
		u.sets[b].parent = a
		u.sets[a].rank++
	}

	u.count--
}

// Find returns the root element of the set. The root element is the same for
// all elements within the same set.
func (u UnionFind) Find(x interface{}) interface{} {
	if _, ok := u.sets[x]; !ok {
		panic(fmt.Sprintf("set %v hasn't been made yet with MakeSet", x))
	}

	// The root.
	if u.sets[x].parent == x {
		return x
	}

	// Path compression.
	u.sets[x].parent = u.Find(u.sets[x].parent)

	return u.sets[x].parent
}

// Exists returns true if the element belongs to any set, false otherwise.
func (u UnionFind) Exists(x interface{}) bool {
	if _, ok := u.sets[x]; ok {
		return true
	} else {
		return false
	}
}

// Connected returns true if the elements belong to the same set,
// false otherwise.
func (u UnionFind) Connected(x, y interface{}) bool {
	return u.Find(x) == u.Find(y)
}

// Count returns the number of independent sets.
func (u UnionFind) Count() int {
	return u.count
}

func (u UnionFind) prepareDump() []string {
	m := make(map[interface{}][]interface{})

	for k, v := range u.sets {
		parent := u.Find(v.parent)

		if _, ok := m[parent]; !ok {
			m[parent] = []interface{}{}
		}
		m[parent] = append(m[parent], k)
	}

	s := []string{}
	for _, e := range m {
		s = append(s, fmt.Sprintf("%v", e))
	}
	return s
}

// String returns a text representation of a UnionFind data structure.
func (u UnionFind) String() string {
	return strings.Join(u.prepareDump(), " ")
}
<|endoftext|>


<commit_before>package user

import (
	"fmt"
	"message-board/server/mysql"
	"os"
)

var (
	db    = os.Getenv("USERS_DB_NAME")
	table = "user"
)

// Gender for user.
type Gender uint

const (
	// Man Gender for man.
	Man Gender = iota
	// Woman Gender for woman.
	Woman
)

// User Basic user.
type User struct {
	ID     int64
	Name   string
	Email  string
	Pwd    string
	Gender Gender
}

// CreateUser will create a new user with name, email and password, return new user created right now.
func CreateUser(name, email, pwd string, gender Gender) *User {
	if mysql.MySQLDB == nil {
		fmt.Println("mysql is nil")
	}
	_, e := mysql.MySQLDB.Exec(fmt.Sprintf("USE %s", db))
	if e != nil {
		panic(fmt.Sprintf("CreateUser error: %s", e))
	}
	stmt, e := mysql.MySQLDB.Prepare(fmt.Sprintf("INSERT %s SET name=?,email=?,password=?,gender=?", table))
	if e != nil {
		panic(fmt.Sprintf("Prepare INSERT USER error: %s", e))
	}
	defer stmt.Close()
	res, e := stmt.Exec(name, email, pwd, gender)
	if e != nil {
		panic(fmt.Sprintf("INSERT USER error: %s", e))
	}
	id, e := res.LastInsertId()
	if e != nil {
		panic(fmt.Sprintf("INSERT USER and get last insert id error: %s", e))
	}
	return &User{
		ID:     id,
		Name:   name,
		Email:  email,
		Pwd:    pwd,
		Gender: gender,
	}
}
<commit_msg>add user table scheme instruction.<commit_after>package user

import (
	"fmt"
	"message-board/server/mysql"
	"os"
)

var (
	db    = os.Getenv("USERS_DB_NAME")
	table = "user"
)

// Gender for user.
type Gender uint

const (
	// Man Gender for man.
	Man Gender = iota
	// Woman Gender for woman.
	Woman
)

// User Basic user.
type User struct {
	ID     int64
	Name   string
	Email  string
	Pwd    string
	Gender Gender
}

// user table scheme.
// CREATE TABLE `user` (
//   `id` int(5) NOT NULL AUTO_INCREMENT,
//   `name` char(20) NOT NULL,
//   `gender` tinyint(1) NOT NULL DEFAULT '0',
//   `email` char(40) NOT NULL,
//   `password` char(50) NOT NULL,
//   PRIMARY KEY (`id`)
// )

// CreateUser will create a new user with name, email and password, return new user created right now.
func CreateUser(name, email, pwd string, gender Gender) *User {
	if mysql.MySQLDB == nil {
		fmt.Println("mysql is nil")
	}
	_, e := mysql.MySQLDB.Exec(fmt.Sprintf("USE %s", db))
	if e != nil {
		panic(fmt.Sprintf("CreateUser error: %s", e))
	}
	stmt, e := mysql.MySQLDB.Prepare(fmt.Sprintf("INSERT %s SET name=?,email=?,password=?,gender=?", table))
	if e != nil {
		panic(fmt.Sprintf("Prepare INSERT USER error: %s", e))
	}
	defer stmt.Close()
	res, e := stmt.Exec(name, email, pwd, gender)
	if e != nil {
		panic(fmt.Sprintf("INSERT USER error: %s", e))
	}
	id, e := res.LastInsertId()
	if e != nil {
		panic(fmt.Sprintf("INSERT USER and get last insert id error: %s", e))
	}
	return &User{
		ID:     id,
		Name:   name,
		Email:  email,
		Pwd:    pwd,
		Gender: gender,
	}
}
<|endoftext|>


<commit_before>package requests

import (
	"errors"
	"fmt"
	"reflect"
	"strconv"
)

// set is a simple slice of unique strings.
type set []string

// add appends a variadic amount of strings to a set, returning the
// resulting set.  Duplicates will only exist once in the resulting
// set.
func (s set) add(values ...string) set {
	for _, newValue := range values {
		exists := false
		for _, value := range s {
			if newValue == value {
				exists = true
				break
			}
		}
		if !exists {
			s = append(s, newValue)
		}
	}
	return s
}

// UnmarshalParams unmarshals a request to a struct, using field tags
// to locate corresponding values in the request and check/parse them
// before assigning them to struct fields.  It acts similar to json's
// Unmarshal when used on a struct, but works with any codec
// registered with AddCodec().  Field tags are used as follows:
//
// * All field tags are considered to be of the format
// name,option1,option2,...
// * Options will *only* be parsed from the "request" tag.
// * By default, name will only be checked in the "request" tag, but
// you can add fallback tag names using AddFallbackTag.
// * If no non-empty name is found using field tags, the lowercase
// field name will be used instead.
// * Once a name is found, if the name is "-", then the field will be
// treated as if it does not exist.
//
// For an explanation on how options work, see the documentation for
// RegisterOption.  For a list of tag options built in to this
// library, see the options package in this package.
//
// Fields which implement Receiver will have their Receive method
// called using the value from the request after calling all
// OptionFuncs matching the field's tag options.
//
// An error will be returned if the target type is not a pointer to a
// struct, or if the target implements PreUnmarshaller, Unmarshaller,
// or PostUnmarshaller and the corresponding methods fail.
//
// Any errors encountered while attempting to apply input values to
// the target's fields will be stored in an error of type InputErrors.
// At the end of the Unmarshal process, the InputErrors error will be
// returned if any errors were encountered.
//
// A simple example:
//
//     type Example struct {
//         Foo string `request:",required"`
//         Bar string `response:"baz"`
//         Baz string `response:"-"`
//         Bacon string `response:"-" request:"bacon,required"`
//     }
//
//     func CreateExample(request *http.Request) (*Example, error) {
//         target := new(Example)
//         if err := requests.New(request).Unmarshal(target); err != nil {
//             if inputErrs, ok := err.(InputErrors); ok {
//                 // inputErrs is a map of input names to error
//                 // messages, so send them to a function to turn
//                 // them into a proper user-friendly error message.
//                 return nil, userErrors(inputErrs)
//             }
//             return nil, err
//         }
//         return target, nil
//     }
//
func (request *Request) Unmarshal(target interface{}) (unmarshalErr error) {
	targetValue := reflect.ValueOf(target)
	if targetValue.Kind() != reflect.Ptr || targetValue.Elem().Kind() != reflect.Struct {
		return errors.New("The value passed to Unmarshal must be a pointer to a struct")
	}
	params, err := request.Params()
	if err != nil {
		return err
	}

	if preUnmarshaller, ok := target.(PreUnmarshaller); ok {
		if unmarshalErr = preUnmarshaller.PreUnmarshal(); unmarshalErr != nil {
			return
		}
	}
	if postUnmarshaller, ok := target.(PostUnmarshaller); ok {
		defer func() {
			if unmarshalErr == nil {
				unmarshalErr = postUnmarshaller.PostUnmarshal()
			}
		}()
	}
	if unmarshaller, ok := target.(Unmarshaller); ok {
		return unmarshaller.Unmarshal(params)
	}

	matchedFields, err := unmarshalToValue(params, targetValue)
	if err != nil {
		return err
	}

	unused := &UnusedFields{
		params:  params,
		matched: matchedFields,
	}
	if unused.HasMissing() {
		return unused
	}
	return nil
}

// unmarshalToValue is a helper for UnmarshalParams, which keeps track
// of the total number of fields matched in a request and which fields
// were missing from a request.
func unmarshalToValue(params map[string]interface{}, targetValue reflect.Value) (matchedFields set, parseErrs InputErrors) {
	matchedFields = make(set, 0, len(params))

	parseErrs = make(InputErrors)
	defer func() {
		// After parsing all input, get rid of nil errors in the input
		// error map, and set parseErrs to nil if there are no non-nil
		// errors.
		parseErrs = parseErrs.Errors()
	}()

	targetType := targetValue.Type()
	for i := 0; i < targetValue.NumField(); i++ {
		fieldValue := targetValue.Field(i)
		field := targetType.Field(i)
		if field.Anonymous {
			// Ignore non-struct anonymous fields, but treat fields in
			// struct or struct pointer anonymous fields as if they
			// were fields on the child struct.
			if fieldValue.Kind() == reflect.Ptr {
				fieldValue = fieldValue.Elem()
			}
			if fieldValue.Kind() == reflect.Struct {
				embeddedFields, newErrs := unmarshalToValue(params, fieldValue)
				if newErrs != nil {
					// Override input errors in the anonymous field
					// with input errors in the child.  Non-nil
					// errors from anonymous fields will be
					// overwritten with nil errors from overriding
					// child fields.
					parseErrs = newErrs.Merge(parseErrs)
				}
				matchedFields = matchedFields.add(embeddedFields...)
			}
			continue
		}

		// Skip unexported fields
		if field.PkgPath == "" {
			name := name(field)
			if name == "-" {
				continue
			}

			value, ok := params[name]
			if ok {
				matchedFields = matchedFields.add(name)
			} else if defaulter, ok := fieldValue.Interface().(Defaulter); ok {
				value = defaulter.DefaultValue()
			} else {
				// Here, use the current value of the field, so that
				// options like default and required won't act as if
				// the field is not set when the original value is
				// non-empty.
				value = fieldValue.Interface()
			}
			var inputErr error
			value, inputErr = ApplyOptions(field, fieldValue.Interface(), value)
			if parseErrs.Set(name, inputErr) {
				continue
			}
			parseErrs.Set(name, setValue(fieldValue, value))
		}
	}
	return
}

// setValue takes a target and a value, and updates the target to
// match the value.
func setValue(target reflect.Value, value interface{}) (parseErr error) {
	if value == nil {
		if target.Kind() != reflect.Ptr {
			return errors.New("Cannot set non-pointer value to null")
		}
		if !target.IsNil() {
			target.Set(reflect.Zero(target.Type()))
		}
		return nil
	}

	if target.Kind() == reflect.Ptr && target.IsNil() {
		target.Set(reflect.New(target.Type().Elem()))
	}

	preReceiver, hasPreReceive := target.Interface().(PreReceiver)
	receiver, hasReceive := target.Interface().(Receiver)
	postReceiver, hasPostReceive := target.Interface().(PostReceiver)
	if target.CanAddr() {
		// If interfaces weren't found, try again with the pointer
		targetPtr := target.Addr().Interface()
		if !hasPreReceive {
			preReceiver, hasPreReceive = targetPtr.(PreReceiver)
		}
		if !hasReceive {
			receiver, hasReceive = targetPtr.(Receiver)
		}
		if !hasPostReceive {
			postReceiver, hasPostReceive = targetPtr.(PostReceiver)
		}
	}

	if hasPreReceive {
		if parseErr = preReceiver.PreReceive(); parseErr != nil {
			return
		}
	}
	if hasPostReceive {
		defer func() {
			if parseErr == nil {
				parseErr = postReceiver.PostReceive()
			}
		}()
	}
	if hasReceive {
		return receiver.Receive(value)
	}

	for target.Kind() == reflect.Ptr {
		target = target.Elem()
	}
	switch target.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		parseErr = setInt(target, value)
	case reflect.Float32, reflect.Float64:
		parseErr = setFloat(target, value)
	default:
		inputType := reflect.TypeOf(value)
		if !inputType.ConvertibleTo(target.Type()) {
			return fmt.Errorf("Cannot convert value of type %s to type %s",
				inputType.Name(), target.Type().Name())
		}
		target.Set(reflect.ValueOf(value).Convert(target.Type()))
	}
	return
}

func setInt(target reflect.Value, value interface{}) error {
	switch src := value.(type) {
	case string:
		intVal, err := strconv.ParseInt(src, 10, 64)
		if err != nil {
			return err
		}
		target.SetInt(intVal)
	case int:
		target.SetInt(int64(src))
	case int8:
		target.SetInt(int64(src))
	case int16:
		target.SetInt(int64(src))
	case int32:
		target.SetInt(int64(src))
	case int64:
		target.SetInt(src)
	case float32:
		target.SetInt(int64(src))
	case float64:
		target.SetInt(int64(src))
	}
	return nil
}

func setFloat(target reflect.Value, value interface{}) error {
	switch src := value.(type) {
	case string:
		floatVal, err := strconv.ParseFloat(src, 64)
		if err != nil {
			return err
		}
		target.SetFloat(floatVal)
	case int:
		target.SetFloat(float64(src))
	case int8:
		target.SetFloat(float64(src))
	case int16:
		target.SetFloat(float64(src))
	case int32:
		target.SetFloat(float64(src))
	case int64:
		target.SetFloat(float64(src))
	case float32:
		target.SetFloat(float64(src))
	case float64:
		target.SetFloat(src)
	}
	return nil
}
<commit_msg>Documentation update, part 5<commit_after>package requests

import (
	"errors"
	"fmt"
	"reflect"
	"strconv"
)

// set is a simple slice of unique strings.
type set []string

// add appends a variadic amount of strings to a set, returning the
// resulting set.  Duplicates will only exist once in the resulting
// set.
func (s set) add(values ...string) set {
	for _, newValue := range values {
		exists := false
		for _, value := range s {
			if newValue == value {
				exists = true
				break
			}
		}
		if !exists {
			s = append(s, newValue)
		}
	}
	return s
}

// Unmarshal unmarshals a request to a struct, using field tags to
// locate corresponding values in the request and check/parse them
// before assigning them to struct fields.  It acts similar to json's
// Unmarshal when used on a struct, but works with any codec
// registered with AddCodec().  Field tags are used as follows:
//
// * All field tags are considered to be of the format
// name,option1,option2,...
// * Options will *only* be parsed from the "request" tag.
// * By default, name will only be checked in the "request" tag, but
// you can add fallback tag names using AddFallbackTag.
// * If no non-empty name is found using field tags, the lowercase
// field name will be used instead.
// * Once a name is found, if the name is "-", then the field will be
// treated as if it does not exist.
//
// For an explanation on how options work, see the documentation for
// RegisterOption.  For a list of tag options built in to this
// library, see the options package in this package.
//
// Fields which implement Receiver will have their Receive method
// called using the value from the request after calling all
// OptionFuncs matching the field's tag options.
//
// An error will be returned if the target type is not a pointer to a
// struct, or if the target implements PreUnmarshaller, Unmarshaller,
// or PostUnmarshaller and the corresponding methods fail.
//
// Any errors encountered while attempting to apply input values to
// the target's fields will be stored in an error of type InputErrors.
// At the end of the Unmarshal process, the InputErrors error will be
// returned if any errors were encountered.
//
// A simple example:
//
//     type Example struct {
//         Foo string `request:",required"`
//         Bar string `response:"baz"`
//         Baz string `response:"-"`
//         Bacon string `response:"-" request:"bacon,required"`
//     }
//
//     func CreateExample(request *http.Request) (*Example, error) {
//         target := new(Example)
//         if err := requests.New(request).Unmarshal(target); err != nil {
//             if inputErrs, ok := err.(InputErrors); ok {
//                 // inputErrs is a map of input names to error
//                 // messages, so send them to a function to turn
//                 // them into a proper user-friendly error message.
//                 return nil, userErrors(inputErrs)
//             }
//             return nil, err
//         }
//         return target, nil
//     }
//
func (request *Request) Unmarshal(target interface{}) (unmarshalErr error) {
	targetValue := reflect.ValueOf(target)
	if targetValue.Kind() != reflect.Ptr || targetValue.Elem().Kind() != reflect.Struct {
		return errors.New("The value passed to Unmarshal must be a pointer to a struct")
	}
	params, err := request.Params()
	if err != nil {
		return err
	}

	if preUnmarshaller, ok := target.(PreUnmarshaller); ok {
		if unmarshalErr = preUnmarshaller.PreUnmarshal(); unmarshalErr != nil {
			return
		}
	}
	if postUnmarshaller, ok := target.(PostUnmarshaller); ok {
		defer func() {
			if unmarshalErr == nil {
				unmarshalErr = postUnmarshaller.PostUnmarshal()
			}
		}()
	}
	if unmarshaller, ok := target.(Unmarshaller); ok {
		return unmarshaller.Unmarshal(params)
	}

	matchedFields, err := unmarshalToValue(params, targetValue)
	if err != nil {
		return err
	}

	unused := &UnusedFields{
		params:  params,
		matched: matchedFields,
	}
	if unused.HasMissing() {
		return unused
	}
	return nil
}

// unmarshalToValue is a helper for UnmarshalParams, which keeps track
// of the total number of fields matched in a request and which fields
// were missing from a request.
func unmarshalToValue(params map[string]interface{}, targetValue reflect.Value) (matchedFields set, parseErrs InputErrors) {
	matchedFields = make(set, 0, len(params))

	parseErrs = make(InputErrors)
	defer func() {
		// After parsing all input, get rid of nil errors in the input
		// error map, and set parseErrs to nil if there are no non-nil
		// errors.
		parseErrs = parseErrs.Errors()
	}()

	targetType := targetValue.Type()
	for i := 0; i < targetValue.NumField(); i++ {
		fieldValue := targetValue.Field(i)
		field := targetType.Field(i)
		if field.Anonymous {
			// Ignore non-struct anonymous fields, but treat fields in
			// struct or struct pointer anonymous fields as if they
			// were fields on the child struct.
			if fieldValue.Kind() == reflect.Ptr {
				fieldValue = fieldValue.Elem()
			}
			if fieldValue.Kind() == reflect.Struct {
				embeddedFields, newErrs := unmarshalToValue(params, fieldValue)
				if newErrs != nil {
					// Override input errors in the anonymous field
					// with input errors in the child.  Non-nil
					// errors from anonymous fields will be
					// overwritten with nil errors from overriding
					// child fields.
					parseErrs = newErrs.Merge(parseErrs)
				}
				matchedFields = matchedFields.add(embeddedFields...)
			}
			continue
		}

		// Skip unexported fields
		if field.PkgPath == "" {
			name := name(field)
			if name == "-" {
				continue
			}

			value, ok := params[name]
			if ok {
				matchedFields = matchedFields.add(name)
			} else if defaulter, ok := fieldValue.Interface().(Defaulter); ok {
				value = defaulter.DefaultValue()
			} else {
				// Here, use the current value of the field, so that
				// options like default and required won't act as if
				// the field is not set when the original value is
				// non-empty.
				value = fieldValue.Interface()
			}
			var inputErr error
			value, inputErr = ApplyOptions(field, fieldValue.Interface(), value)
			if parseErrs.Set(name, inputErr) {
				continue
			}
			parseErrs.Set(name, setValue(fieldValue, value))
		}
	}
	return
}

// setValue takes a target and a value, and updates the target to
// match the value.
func setValue(target reflect.Value, value interface{}) (parseErr error) {
	if value == nil {
		if target.Kind() != reflect.Ptr {
			return errors.New("Cannot set non-pointer value to null")
		}
		if !target.IsNil() {
			target.Set(reflect.Zero(target.Type()))
		}
		return nil
	}

	if target.Kind() == reflect.Ptr && target.IsNil() {
		target.Set(reflect.New(target.Type().Elem()))
	}

	preReceiver, hasPreReceive := target.Interface().(PreReceiver)
	receiver, hasReceive := target.Interface().(Receiver)
	postReceiver, hasPostReceive := target.Interface().(PostReceiver)
	if target.CanAddr() {
		// If interfaces weren't found, try again with the pointer
		targetPtr := target.Addr().Interface()
		if !hasPreReceive {
			preReceiver, hasPreReceive = targetPtr.(PreReceiver)
		}
		if !hasReceive {
			receiver, hasReceive = targetPtr.(Receiver)
		}
		if !hasPostReceive {
			postReceiver, hasPostReceive = targetPtr.(PostReceiver)
		}
	}

	if hasPreReceive {
		if parseErr = preReceiver.PreReceive(); parseErr != nil {
			return
		}
	}
	if hasPostReceive {
		defer func() {
			if parseErr == nil {
				parseErr = postReceiver.PostReceive()
			}
		}()
	}
	if hasReceive {
		return receiver.Receive(value)
	}

	for target.Kind() == reflect.Ptr {
		target = target.Elem()
	}
	switch target.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		parseErr = setInt(target, value)
	case reflect.Float32, reflect.Float64:
		parseErr = setFloat(target, value)
	default:
		inputType := reflect.TypeOf(value)
		if !inputType.ConvertibleTo(target.Type()) {
			return fmt.Errorf("Cannot convert value of type %s to type %s",
				inputType.Name(), target.Type().Name())
		}
		target.Set(reflect.ValueOf(value).Convert(target.Type()))
	}
	return
}

func setInt(target reflect.Value, value interface{}) error {
	switch src := value.(type) {
	case string:
		intVal, err := strconv.ParseInt(src, 10, 64)
		if err != nil {
			return err
		}
		target.SetInt(intVal)
	case int:
		target.SetInt(int64(src))
	case int8:
		target.SetInt(int64(src))
	case int16:
		target.SetInt(int64(src))
	case int32:
		target.SetInt(int64(src))
	case int64:
		target.SetInt(src)
	case float32:
		target.SetInt(int64(src))
	case float64:
		target.SetInt(int64(src))
	}
	return nil
}

func setFloat(target reflect.Value, value interface{}) error {
	switch src := value.(type) {
	case string:
		floatVal, err := strconv.ParseFloat(src, 64)
		if err != nil {
			return err
		}
		target.SetFloat(floatVal)
	case int:
		target.SetFloat(float64(src))
	case int8:
		target.SetFloat(float64(src))
	case int16:
		target.SetFloat(float64(src))
	case int32:
		target.SetFloat(float64(src))
	case int64:
		target.SetFloat(float64(src))
	case float32:
		target.SetFloat(float64(src))
	case float64:
		target.SetFloat(src)
	}
	return nil
}
<|endoftext|>