<commit_before>// Package python allows Go programs to access Python modules.
package python

/*

#cgo CFLAGS: -I/usr/include/python2.7
#cgo LDFLAGS: -lpython2.7

#include <Python.h>

#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

static void INCREF(PyObject *o) {
	Py_INCREF(o);
}

static void DECREF(PyObject *o) {
	Py_DECREF(o);
}

static void XDECREF(PyObject *o) {
	Py_XDECREF(o);
}

static void Tuple_SET_ITEM(PyObject *p, Py_ssize_t pos, PyObject *o) {
	PyTuple_SET_ITEM(p, pos, o);
}

static PyObject *NoneRef() {
	Py_INCREF(Py_None);
	return Py_None;
}

static PyObject *Long_FromInt64(int64_t v) {
	return PyLong_FromLongLong(v);
}

static PyObject *Long_FromUint64(uint64_t v) {
	return PyLong_FromUnsignedLongLong(v);
}

static bool None_Check(PyObject *o) {
	return o == Py_None;
}

static bool False_Check(PyObject *o) {
	return o == Py_False;
}

static bool True_Check(PyObject *o) {
	return o == Py_True;
}

static bool Int_Check(PyObject *o) {
	return PyInt_Check(o);
}

static bool Float_Check(PyObject *o) {
	return PyFloat_Check(o);
}

static bool Complex_Check(PyObject *o) {
	return PyComplex_Check(o);
}

static bool String_Check(PyObject *o) {
	return PyString_Check(o);
}

static PyObject *Mapping_Items(PyObject *o) {
	return PyMapping_Items(o);
}

*/
import "C"

import (
	"fmt"
	"runtime"
	"unsafe"
)

// Object wraps a Python object.
type Object interface {
	// Get an attribute of an object.
	Get(name string) (Object, error)

	// GetValue combines Get and Value methods.
	GetValue(name string) (interface{}, error)

	// Invoke a callable object.
	Invoke(args ...interface{}) (Object, error)

	// InvokeValue combines Invoke and Value methods.
	InvokeValue(args ...interface{}) (interface{}, error)

	// Call a member of an object.
	Call(name string, args ...interface{}) (Object, error)

	// CallValue combines Call and Value methods.
	CallValue(name string, args ...interface{}) (interface{}, error)

	// Value translates a Python object to a Go type (if possible).
	Value() (interface{}, error)

	// String representation of an object.  The result is an arbitrary value on
	// error.
	String() string
}

type object struct {
	pyObject *C.PyObject
}

func finalizeObject(o *object) {
	C.DECREF(o.pyObject)
}

func newObject(pyObject *C.PyObject) Object {
	o := &object{pyObject}
	runtime.SetFinalizer(o, finalizeObject)
	return o
}

func newObjectOrError(pyObject *C.PyObject) (o Object, err error) {
	if pyObject != nil {
		o = newObject(pyObject)
	} else {
		err = getError()
	}
	return
}

// Import a Python module.
func Import(name string) (Object, error) {
	cName := C.CString(name)
	defer C.free(unsafe.Pointer(cName))

	return newObjectOrError(C.PyImport_ImportModule(cName))
}

func (o *object) Get(name string) (Object, error) {
	return newObjectOrError(o.get(name))
}

func (o *object) get(name string) *C.PyObject {
	cName := C.CString(name)
	defer C.free(unsafe.Pointer(cName))

	return C.PyObject_GetAttrString(o.pyObject, cName)
}

func (o *object) GetValue(name string) (value interface{}, err error) {
	result, err := o.Get(name)
	if err != nil {
		return
	}

	return result.Value()
}

func (o *object) Invoke(args ...interface{}) (Object, error) {
	return invokeObject(o.pyObject, args)
}

func invokeObject(pyObject *C.PyObject, args []interface{}) (result Object, err error) {
	pyArgs, err := translateToPythonTuple(args)
	if err != nil {
		return
	}
	defer C.DECREF(pyArgs)

	return newObjectOrError(C.PyObject_CallObject(pyObject, pyArgs))
}

func (o *object) InvokeValue(args ...interface{}) (value interface{}, err error) {
	result, err := o.Invoke(args...)
	if err != nil {
		return
	}

	return result.Value()
}

func (o *object) Call(name string, args ...interface{}) (result Object, err error) {
	pyMember := o.get(name)
	if pyMember == nil {
		err = getError()
		return
	}
	defer C.DECREF(pyMember)

	return invokeObject(pyMember, args)
}

func (o *object) CallValue(name string, args ...interface{}) (value interface{}, err error) {
	result, err := o.Call(name, args...)
	if err != nil {
		return
	}

	return result.Value()
}

func (o *object) Value() (interface{}, error) {
	return translateFromPython(o.pyObject)
}

func (o *object) String() string {
	return objectStr(o.pyObject)
}

func objectStr(pyObject *C.PyObject) (s string) {
	if pyResult := C.PyObject_Str(pyObject); pyResult != nil {
		defer C.DECREF(pyResult)

		if cString := C.PyString_AsString(pyResult); cString != nil {
			s = C.GoString(cString)
		}
	}

	C.PyErr_Clear()
	return
}

func translateToPython(x interface{}) (pyValue *C.PyObject, err error) {
	if x == nil {
		pyValue = C.NoneRef()
		return
	}

	switch value := x.(type) {
	case bool:
		var i C.long
		if value {
			i = 1
		}
		pyValue = C.PyBool_FromLong(i)

	case byte: // alias uint8
		c := C.char(value)
		pyValue = C.PyString_FromStringAndSize(&c, 1)

	case complex64:
		pyValue = C.PyComplex_FromDoubles(C.double(real(value)), C.double(imag(value)))

	case complex128:
		pyValue = C.PyComplex_FromDoubles(C.double(real(value)), C.double(imag(value)))

	case float32:
		pyValue = C.PyFloat_FromDouble(C.double(value))

	case float64:
		pyValue = C.PyFloat_FromDouble(C.double(value))

	case int: // alias rune
		pyValue = C.PyInt_FromLong(C.long(value))

	case int8:
		pyValue = C.PyInt_FromLong(C.long(value))

	case int16:
		pyValue = C.PyInt_FromLong(C.long(value))

	case int32:
		pyValue = C.PyInt_FromLong(C.long(value))

	case int64:
		pyValue = C.Long_FromInt64(C.int64_t(value))

	case string:
		cString := C.CString(value)
		defer C.free(unsafe.Pointer(cString))
		pyValue = C.PyString_FromString(cString)

	case uint:
		pyValue = C.Long_FromUint64(C.uint64_t(value))

	case uint16:
		pyValue = C.PyInt_FromLong(C.long(value))

	case uint32:
		pyValue = C.Long_FromUint64(C.uint64_t(value))

	case uint64:
		pyValue = C.Long_FromUint64(C.uint64_t(value))

	case uintptr:
		pyValue = C.Long_FromUint64(C.uint64_t(value))

	case []interface{}:
		return translateToPythonTuple(value)

	case map[interface{}]interface{}:
		return translateToPythonDict(value)

	case *object:
		C.INCREF(value.pyObject)
		pyValue = value.pyObject

	default:
		err = fmt.Errorf("unable to translate %t to python", x)
		return
	}

	if pyValue == nil {
		err = getError()
	}
	return
}

func translateToPythonTuple(array []interface{}) (*C.PyObject, error) {
	pyTuple := C.PyTuple_New(C.Py_ssize_t(len(array)))

	for i, item := range array {
		pyItem, err := translateToPython(item)
		if err != nil {
			C.DECREF(pyTuple)
			return nil, err
		}

		C.Tuple_SET_ITEM(pyTuple, C.Py_ssize_t(i), pyItem)
	}

	return pyTuple, nil
}

func translateToPythonDict(m map[interface{}]interface{}) (*C.PyObject, error) {
	pyDict := C.PyDict_New()

	for key, value := range m {
		pyKey, err := translateToPython(key)
		if err != nil {
			C.DECREF(pyDict)
			return nil, err
		}

		pyValue, err := translateToPython(value)
		if err != nil {
			C.DECREF(pyKey)
			C.DECREF(pyDict)
			return nil, err
		}

		if C.PyDict_SetItem(pyDict, pyKey, pyValue) < 0 {
			C.DECREF(pyValue)
			C.DECREF(pyKey)
			C.DECREF(pyDict)
			return nil, getError()
		}

		C.DECREF(pyValue)
		C.DECREF(pyKey)
	}

	return pyDict, nil
}

func translateFromPython(pyValue *C.PyObject) (value interface{}, err error) {
	if C.None_Check(pyValue) {
		value = nil

	} else if C.False_Check(pyValue) {
		value = false

	} else if C.True_Check(pyValue) {
		value = true

	} else if C.Int_Check(pyValue) {
		value = int(C.PyInt_AsLong(pyValue))

	} else if C.Float_Check(pyValue) {
		value = float64(C.PyFloat_AsDouble(pyValue))

	} else if C.Complex_Check(pyValue) {
		value = complex(C.PyComplex_RealAsDouble(pyValue), C.PyComplex_ImagAsDouble(pyValue))

	} else if C.String_Check(pyValue) {
		value = C.GoString(C.PyString_AsString(pyValue))

	} else if C.PySequence_Check(pyValue) != 0 {
		return translateFromPythonSequence(pyValue)

	} else if C.PyMapping_Check(pyValue) != 0 {
		return translateFromPythonMapping(pyValue)

	} else {
		err = fmt.Errorf("unable to translate %s from python", objectStr(C.PyObject_Type(pyValue)))
		return
	}

	return
}

func translateFromPythonSequence(pySequence *C.PyObject) ([]interface{}, error) {
	length := int(C.PySequence_Size(pySequence))
	array := make([]interface{}, length)

	for i := 0; i < length; i++ {
		pyValue := C.PySequence_GetItem(pySequence, C.Py_ssize_t(i))
		if pyValue == nil {
			return nil, getError()
		}

		value, err := translateFromPython(pyValue)
		if err != nil {
			return nil, err
		}

		array[i] = value
	}

	return array, nil
}

func translateFromPythonMapping(pyMapping *C.PyObject) (map[interface{}]interface{}, error) {
	mapping := make(map[interface{}]interface{})

	pyItems := C.Mapping_Items(pyMapping)
	if pyItems == nil {
		return nil, getError()
	}

	length := int(C.PyList_Size(pyItems))

	for i := 0; i < length; i++ {
		pyPair := C.PyList_GetItem(pyItems, C.Py_ssize_t(i))

		key, err := translateFromPython(C.PyTuple_GetItem(pyPair, 0))
		if err != nil {
			return nil, err
		}

		value, err := translateFromPython(C.PyTuple_GetItem(pyPair, 1))
		if err != nil {
			return nil, err
		}

		mapping[key] = value
	}

	return mapping, nil
}

func getError() error {
	var (
		pyType  *C.PyObject
		pyValue *C.PyObject
		pyTrace *C.PyObject
	)

	C.PyErr_Fetch(&pyType, &pyValue, &pyTrace)

	defer C.DECREF(pyType)
	defer C.DECREF(pyValue)
	defer C.XDECREF(pyTrace)

	C.PyErr_Clear()

	return fmt.Errorf("Python: %s", objectStr(pyValue))
}

func init() {
	C.Py_InitializeEx(0)
}
<commit_msg>by-value helper refactoring<commit_after>// Package python allows Go programs to access Python modules.
package python

/*

#cgo CFLAGS: -I/usr/include/python2.7
#cgo LDFLAGS: -lpython2.7

#include <Python.h>

#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

static void INCREF(PyObject *o) {
	Py_INCREF(o);
}

static void DECREF(PyObject *o) {
	Py_DECREF(o);
}

static void XDECREF(PyObject *o) {
	Py_XDECREF(o);
}

static void Tuple_SET_ITEM(PyObject *p, Py_ssize_t pos, PyObject *o) {
	PyTuple_SET_ITEM(p, pos, o);
}

static PyObject *NoneRef() {
	Py_INCREF(Py_None);
	return Py_None;
}

static PyObject *Long_FromInt64(int64_t v) {
	return PyLong_FromLongLong(v);
}

static PyObject *Long_FromUint64(uint64_t v) {
	return PyLong_FromUnsignedLongLong(v);
}

static bool None_Check(PyObject *o) {
	return o == Py_None;
}

static bool False_Check(PyObject *o) {
	return o == Py_False;
}

static bool True_Check(PyObject *o) {
	return o == Py_True;
}

static bool Int_Check(PyObject *o) {
	return PyInt_Check(o);
}

static bool Float_Check(PyObject *o) {
	return PyFloat_Check(o);
}

static bool Complex_Check(PyObject *o) {
	return PyComplex_Check(o);
}

static bool String_Check(PyObject *o) {
	return PyString_Check(o);
}

static PyObject *Mapping_Items(PyObject *o) {
	return PyMapping_Items(o);
}

*/
import "C"

import (
	"fmt"
	"runtime"
	"unsafe"
)

// Object wraps a Python object.
type Object interface {
	// Get an attribute of an object.
	Get(name string) (Object, error)

	// GetValue combines Get and Value methods.
	GetValue(name string) (interface{}, error)

	// Invoke a callable object.
	Invoke(args ...interface{}) (Object, error)

	// InvokeValue combines Invoke and Value methods.
	InvokeValue(args ...interface{}) (interface{}, error)

	// Call a member of an object.
	Call(name string, args ...interface{}) (Object, error)

	// CallValue combines Call and Value methods.
	CallValue(name string, args ...interface{}) (interface{}, error)

	// Value translates a Python object to a Go type (if possible).
	Value() (interface{}, error)

	// String representation of an object.  The result is an arbitrary value on
	// error.
	String() string
}

type object struct {
	pyObject *C.PyObject
}

func finalizeObject(o *object) {
	C.DECREF(o.pyObject)
}

func newObject(pyObject *C.PyObject) Object {
	o := &object{pyObject}
	runtime.SetFinalizer(o, finalizeObject)
	return o
}

func newObjectOrError(pyObject *C.PyObject) (o Object, err error) {
	if pyObject != nil {
		o = newObject(pyObject)
	} else {
		err = getError()
	}
	return
}

// Import a Python module.
func Import(name string) (Object, error) {
	cName := C.CString(name)
	defer C.free(unsafe.Pointer(cName))

	return newObjectOrError(C.PyImport_ImportModule(cName))
}

func (o *object) Get(name string) (Object, error) {
	return newObjectOrError(get(o.pyObject, name))
}

func (o *object) GetValue(name string) (value interface{}, err error) {
	pyResult := get(o.pyObject, name)
	if pyResult == nil {
		err = getError()
		return
	}
	defer C.DECREF(pyResult)

	return translateFromPython(pyResult)
}

func (o *object) Invoke(args ...interface{}) (Object, error) {
	return newObjectOrError(invoke(o.pyObject, args))
}

func (o *object) InvokeValue(args ...interface{}) (value interface{}, err error) {
	pyResult := invoke(o.pyObject, args)
	if pyResult == nil {
		err = getError()
		return
	}
	defer C.DECREF(pyResult)

	return translateFromPython(pyResult)
}

func (o *object) Call(name string, args ...interface{}) (Object, error) {
	return newObjectOrError(call(o.pyObject, name, args))
}

func (o *object) CallValue(name string, args ...interface{}) (value interface{}, err error) {
	pyResult := call(o.pyObject, name, args)
	if pyResult == nil {
		err = getError()
		return
	}
	defer C.DECREF(pyResult)

	return translateFromPython(pyResult)
}

func (o *object) Value() (interface{}, error) {
	return translateFromPython(o.pyObject)
}

func (o *object) String() string {
	return stringify(o.pyObject)
}

func get(pyObject *C.PyObject, name string) *C.PyObject {
	cName := C.CString(name)
	defer C.free(unsafe.Pointer(cName))

	return C.PyObject_GetAttrString(pyObject, cName)
}

func invoke(pyObject *C.PyObject, args []interface{}) (pyResult *C.PyObject) {
	pyArgs, err := translateToPythonTuple(args)
	if err != nil {
		return
	}
	defer C.DECREF(pyArgs)

	return C.PyObject_CallObject(pyObject, pyArgs)
}

func call(pyObject *C.PyObject, name string, args []interface{}) (pyResult *C.PyObject) {
	pyMember := get(pyObject, name)
	if pyMember == nil {
		return
	}
	defer C.DECREF(pyMember)

	return invoke(pyMember, args)
}

func stringify(pyObject *C.PyObject) (s string) {
	if pyResult := C.PyObject_Str(pyObject); pyResult != nil {
		defer C.DECREF(pyResult)

		if cString := C.PyString_AsString(pyResult); cString != nil {
			s = C.GoString(cString)
		}
	}

	C.PyErr_Clear()
	return
}

func translateToPython(x interface{}) (pyValue *C.PyObject, err error) {
	if x == nil {
		pyValue = C.NoneRef()
		return
	}

	switch value := x.(type) {
	case bool:
		var i C.long
		if value {
			i = 1
		}
		pyValue = C.PyBool_FromLong(i)

	case byte: // alias uint8
		c := C.char(value)
		pyValue = C.PyString_FromStringAndSize(&c, 1)

	case complex64:
		pyValue = C.PyComplex_FromDoubles(C.double(real(value)), C.double(imag(value)))

	case complex128:
		pyValue = C.PyComplex_FromDoubles(C.double(real(value)), C.double(imag(value)))

	case float32:
		pyValue = C.PyFloat_FromDouble(C.double(value))

	case float64:
		pyValue = C.PyFloat_FromDouble(C.double(value))

	case int: // alias rune
		pyValue = C.PyInt_FromLong(C.long(value))

	case int8:
		pyValue = C.PyInt_FromLong(C.long(value))

	case int16:
		pyValue = C.PyInt_FromLong(C.long(value))

	case int32:
		pyValue = C.PyInt_FromLong(C.long(value))

	case int64:
		pyValue = C.Long_FromInt64(C.int64_t(value))

	case string:
		cString := C.CString(value)
		defer C.free(unsafe.Pointer(cString))
		pyValue = C.PyString_FromString(cString)

	case uint:
		pyValue = C.Long_FromUint64(C.uint64_t(value))

	case uint16:
		pyValue = C.PyInt_FromLong(C.long(value))

	case uint32:
		pyValue = C.Long_FromUint64(C.uint64_t(value))

	case uint64:
		pyValue = C.Long_FromUint64(C.uint64_t(value))

	case uintptr:
		pyValue = C.Long_FromUint64(C.uint64_t(value))

	case []interface{}:
		return translateToPythonTuple(value)

	case map[interface{}]interface{}:
		return translateToPythonDict(value)

	case *object:
		C.INCREF(value.pyObject)
		pyValue = value.pyObject

	default:
		err = fmt.Errorf("unable to translate %t to python", x)
		return
	}

	if pyValue == nil {
		err = getError()
	}
	return
}

func translateToPythonTuple(array []interface{}) (*C.PyObject, error) {
	pyTuple := C.PyTuple_New(C.Py_ssize_t(len(array)))

	for i, item := range array {
		pyItem, err := translateToPython(item)
		if err != nil {
			C.DECREF(pyTuple)
			return nil, err
		}

		C.Tuple_SET_ITEM(pyTuple, C.Py_ssize_t(i), pyItem)
	}

	return pyTuple, nil
}

func translateToPythonDict(m map[interface{}]interface{}) (*C.PyObject, error) {
	pyDict := C.PyDict_New()

	for key, value := range m {
		pyKey, err := translateToPython(key)
		if err != nil {
			C.DECREF(pyDict)
			return nil, err
		}

		pyValue, err := translateToPython(value)
		if err != nil {
			C.DECREF(pyKey)
			C.DECREF(pyDict)
			return nil, err
		}

		if C.PyDict_SetItem(pyDict, pyKey, pyValue) < 0 {
			C.DECREF(pyValue)
			C.DECREF(pyKey)
			C.DECREF(pyDict)
			return nil, getError()
		}

		C.DECREF(pyValue)
		C.DECREF(pyKey)
	}

	return pyDict, nil
}

func translateFromPython(pyValue *C.PyObject) (value interface{}, err error) {
	if C.None_Check(pyValue) {
		value = nil

	} else if C.False_Check(pyValue) {
		value = false

	} else if C.True_Check(pyValue) {
		value = true

	} else if C.Int_Check(pyValue) {
		value = int(C.PyInt_AsLong(pyValue))

	} else if C.Float_Check(pyValue) {
		value = float64(C.PyFloat_AsDouble(pyValue))

	} else if C.Complex_Check(pyValue) {
		value = complex(C.PyComplex_RealAsDouble(pyValue), C.PyComplex_ImagAsDouble(pyValue))

	} else if C.String_Check(pyValue) {
		value = C.GoString(C.PyString_AsString(pyValue))

	} else if C.PySequence_Check(pyValue) != 0 {
		return translateFromPythonSequence(pyValue)

	} else if C.PyMapping_Check(pyValue) != 0 {
		return translateFromPythonMapping(pyValue)

	} else {
		err = fmt.Errorf("unable to translate %s from python", stringify(C.PyObject_Type(pyValue)))
		return
	}

	return
}

func translateFromPythonSequence(pySequence *C.PyObject) ([]interface{}, error) {
	length := int(C.PySequence_Size(pySequence))
	array := make([]interface{}, length)

	for i := 0; i < length; i++ {
		pyValue := C.PySequence_GetItem(pySequence, C.Py_ssize_t(i))
		if pyValue == nil {
			return nil, getError()
		}

		value, err := translateFromPython(pyValue)
		if err != nil {
			return nil, err
		}

		array[i] = value
	}

	return array, nil
}

func translateFromPythonMapping(pyMapping *C.PyObject) (map[interface{}]interface{}, error) {
	mapping := make(map[interface{}]interface{})

	pyItems := C.Mapping_Items(pyMapping)
	if pyItems == nil {
		return nil, getError()
	}

	length := int(C.PyList_Size(pyItems))

	for i := 0; i < length; i++ {
		pyPair := C.PyList_GetItem(pyItems, C.Py_ssize_t(i))

		key, err := translateFromPython(C.PyTuple_GetItem(pyPair, 0))
		if err != nil {
			return nil, err
		}

		value, err := translateFromPython(C.PyTuple_GetItem(pyPair, 1))
		if err != nil {
			return nil, err
		}

		mapping[key] = value
	}

	return mapping, nil
}

func getError() error {
	var (
		pyType  *C.PyObject
		pyValue *C.PyObject
		pyTrace *C.PyObject
	)

	C.PyErr_Fetch(&pyType, &pyValue, &pyTrace)

	defer C.DECREF(pyType)
	defer C.DECREF(pyValue)
	defer C.XDECREF(pyTrace)

	C.PyErr_Clear()

	return fmt.Errorf("Python: %s", stringify(pyValue))
}

func init() {
	C.Py_InitializeEx(0)
}
<|endoftext|>


<commit_before>package main
import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"os"
)
//string slicing
func getFromTo(text string, from string,to string) string {
	i1 := strings.Index(text, from)
	i2 := strings.Index(text, to)
	sub := text[i1:i2]
	return sub
}
func getFromToStartingFrom(text string, from string,to string,) string {
	i1 := strings.Index(text, from)
	i2 := strings.Index(text[i1:], to) + i1
	sub := text[i1:i2]
	return sub
}
//modify answer section
func prepareAnswer(ans string) string {
	r := strings.Replace(ans, "", "\nCODE---------------------------------------\n", -1)
	r = strings.Replace(r, "", "\nENDCODE------------------------------------\n", -1)
	r = strings.Replace(r, "
", "", -1)
	r = strings.Replace(r, "
", "", -1)
	r = strings.Replace(r, "
", "", -1)
	r = strings.Replace(r, "
", "", -1)
	return r
}
func main() {
	//Get args
    args := os.Args[1:]
    searchQuery := strings.Replace(strings.Join(args[:]," "), " ", "+", -1)
  	//
    fmt.Println("Searching for: "+searchQuery)
    //Find top stackoverflow result
	url :="https://search.yahoo.com/search?p="+searchQuery
	resp, err := http.Get(url)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
	byteArray, err := ioutil.ReadAll(resp.Body)
	html := string(byteArray[:])
	stackUrl := getFromToStartingFrom(html,"http://stackoverflow.com","\"")
	//
	fmt.Println("Source: "+stackUrl)
	//Get stackoverflow page from to result url
	url = stackUrl
	resp, err = http.Get(url)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
	byteArray, err = ioutil.ReadAll(resp.Body)
	html = string(byteArray[:])
	//Slice and display results
	fmt.Println("ANSWER##################################################")
	fmt.Println("########################################################")
	sub := getFromToStartingFrom(html,"class=\"answercell\"","class=\"fw\"")
	answer := getFromTo(sub, "" ,  "")
	fmt.Println(question[27:])
}
<commit_msg>cleaned code<commit_after>package main
import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"os"
)
//string slicing
func getFromTo(text string, from string,to string) string {
	i1 := strings.Index(text, from)
	i2 := strings.Index(text, to)
	sub := text[i1:i2]
	return sub
}
func getFromToStartingFrom(text string, from string,to string,) string {
	i1 := strings.Index(text, from)
	i2 := strings.Index(text[i1:], to) + i1
	sub := text[i1:i2]
	return sub
}
//modify answer section
func prepareAnswer(ans string) string {
	r := strings.Replace(ans, "", "\nCODE---------------------------------------\n", -1)
	r = strings.Replace(r, "", "\nENDCODE------------------------------------\n", -1)
	r = strings.Replace(r, "
", "", -1)
	r = strings.Replace(r, "
", "", -1)
	r = strings.Replace(r, "
", "", -1)
	r = strings.Replace(r, "
", "", -1)
	return r
}
func main() {
	//Get args
    args := os.Args[1:]
    searchQuery := "stackoverflow+"
    searchQuery += strings.Replace(strings.Join(args[:]," "), " ", "+", -1)
    if len(args) == 0 {
    	fmt.Println("Please include search term. Example: qstack css add font")
    	return
    }
  	//
    fmt.Println("Searching for: "+searchQuery)
    //Find top stackoverflow result
	url :="https://search.yahoo.com/search?p="+searchQuery
	resp, err := http.Get(url)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
	byteArray, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	html := string(byteArray[:])
	stackUrl := getFromToStartingFrom(html,"http://stackoverflow.com","\"")
	//
	fmt.Println("Source: "+stackUrl)
	//Get stackoverflow page from to result url
	url = stackUrl
	resp, err = http.Get(url)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
	byteArray, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	html = string(byteArray[:])
	//Slice and display results
	fmt.Println("ANSWER##################################################")
	fmt.Println("########################################################")
	sub := getFromToStartingFrom(html,"class=\"answercell\"","class=\"fw\"")
	answer := getFromTo(sub, "" ,  "")
	fmt.Println(question[27:])
}
<|endoftext|>


<commit_before>package quandl

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

// APIKey is used to set your api key before you make any call
var APIKey = ""

// LastURL will hold the last requested URL after each call
var LastURL = ""

// CacheHandler is a reference to a struct that implements the Cacher interface.
// If set, it will use it to get documents from the cache or set to it.
var CacheHandler Cacher

var urlTemplates = map[string]string{
	"symbol": "https://www.quandl.com/api/v3/datasets/%s.%s?%s",
	"search": "https://www.quandl.com/api/v3/datasets.%s?%s",
	"list":   "https://www.quandl.com/api/v3/datasets.%s?%s",
	// "favs":    "https://www.quandl.com/api/v1/current_user/collections/datasets/favourites.%s?auth_token=%s",
}

// Options is used to send additional parameters in the Quandl request
type Options url.Values

// Set registers a key=value pair to be sent in the Quandl request
func (o Options) Set(key, value string) {
	o[key] = []string{value}
}

// Cacher defines the interface for a custom cache handler
type Cacher interface {
	Get(key string) []byte
	Set(key string, data []byte) error
}

// NewOptions accepts any even number of arguments and returns an
// Options object. The odd arguments are the keys, the even arguments
// are the values.
func NewOptions(s ...string) Options {
	o := Options{}
	for i := 0; i < len(s); i += 2 {
		o.Set(s[i], s[i+1])
	}
	return o
}

// GetSymbol returns data for a given symbol
func GetSymbol(symbol string, params Options) (*SymbolResponse, error) {
	raw, err := GetSymbolRaw(symbol, "json", params)
	var response struct {
		Dataset SymbolResponse
	}
	if err != nil {
		return &response.Dataset, err
	}

	err = json.Unmarshal(raw, &response)
	if err != nil {
		return &response.Dataset, marshallerError(raw, err)
	}
	return &response.Dataset, nil
}

// GetList returns a list of symbols for a source
func GetList(source string, page int, perPage int) (*ListResponse, error) {
	raw, err := GetListRaw(source, "json", page, perPage)
	var response ListResponse
	if err != nil {
		return &response, err
	}

	err = json.Unmarshal(raw, &response)
	if err != nil {
		return &response, marshallerError(raw, err)
	}
	return &response, nil
}

// GetSearch returns search results
func GetSearch(query string, page int, perPage int) (*SearchResponse, error) {
	raw, err := GetSearchRaw(query, "json", page, perPage)
	var response SearchResponse
	if err != nil {
		return &response, err
	}

	err = json.Unmarshal(raw, &response)
	if err != nil {
		return &response, marshallerError(raw, err)
	}
	return &response, nil
}

// GetSymbolRaw returns CSV, JSON or XML data for a given symbol
func GetSymbolRaw(symbol string, format string, params Options) ([]byte, error) {
	url := getURL("symbol", symbol, format, arrangeParams(params))
	return getData(url)
}

// GetListRaw returns a list of symbols for a source as CSV, JSON or XML
func GetListRaw(source string, format string, page int, perPage int) ([]byte, error) {
	params := Options{}

	params.Set("query", "*")
	params.Set("database_code", source)
	params.Set("per_page", strconv.Itoa(perPage))
	params.Set("page", strconv.Itoa(page))

	url := getURL("list", format, arrangeParams(params))
	return getData(url)
}

// GetSearchRaw returns search results as JSON or XML
func GetSearchRaw(query string, format string, page int, perPage int) ([]byte, error) {
	params := Options{}

	// TODO: Remove when Quandl fixes this bug
	if format == "csv" {
		format = "json"
	}

	params.Set("query", query)
	params.Set("per_page", strconv.Itoa(perPage))
	params.Set("page", strconv.Itoa(page))

	url := getURL("search", format, arrangeParams(params))
	return getData(url)
}

// ToColumns converts a rows array to a columns array
func ToColumns(src [][]interface{}) (out [][]interface{}) {
	out = make([][]interface{}, len(src[0]))
	for _, row := range src {
		for j, cell := range row {
			out[j] = append(out[j], cell)
		}
	}
	return
}

// ToNamedColumns converts a rows array to a columns map
func ToNamedColumns(src [][]interface{}, keys []string) (out map[string][]interface{}) {
	out = make(map[string][]interface{})
	for _, row := range src {
		for j, cell := range row {
			out[keys[j]] = append(out[keys[j]], cell)
		}
	}
	return
}

// FloatColumn converts a column of interface{} to a column of floats
func FloatColumn(s []interface{}) []float64 {
	r := make([]float64, len(s))
	for i := range s {
		r[i] = s[i].(float64)
	}
	return r
}

// TimeColumn converts a column of interface{} to a column of time
func TimeColumn(s []interface{}) []time.Time {
	r := make([]time.Time, len(s))
	for i := range s {
		r[i], _ = time.Parse("2006-01-02", s[i].(string))
	}
	return r
}

// StringColumn converts a column of interface{} to a column of string
func StringColumn(s []interface{}) []string {
	r := make([]string, len(s))
	for i := range s {
		r[i] = s[i].(string)
	}
	return r
}

// getData requests a URL from Quandl and returns the raw response string
func getData(url string) ([]byte, error) {
	if CacheHandler != nil {
		if response := CacheHandler.Get(url); response != nil {
			return response, nil
		}
	}

	response, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	contents, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	if CacheHandler != nil {
		if err := CacheHandler.Set(url, contents); err != nil {
			return nil, err
		}
	}

	return contents, nil
}

// getURL receives a kind that points to a URL template and
// a variable number of strings, which will be replaced
// in the template.
func getURL(kind string, args ...interface{}) string {
	template := urlTemplates[kind]
	LastURL = strings.Trim(fmt.Sprintf(template, args...), "&?")
	return LastURL
}

// arrangeParams takes an Options map and converts it to
// a query string. It will also append the api key as needed.
func arrangeParams(qs Options) string {
	if qs == nil {
		if APIKey == "" {
			return ""
		}
		qs = Options{}
	}
	if APIKey != "" {
		qs.Set("api_key", APIKey)
	}
	return url.Values(qs).Encode()
}

// marshallerError returns a formatted error that includes the response
func marshallerError(response []byte, err error) error {
	return errors.New("JSON Marshaller Error:\nRESPONSE:\n" + string(response) + "\n\nERROR:\n" + err.Error())
}
<commit_msg>remove old favs endpoint comment<commit_after>package quandl

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

// APIKey is used to set your api key before you make any call
var APIKey = ""

// LastURL will hold the last requested URL after each call
var LastURL = ""

// CacheHandler is a reference to a struct that implements the Cacher interface.
// If set, it will use it to get documents from the cache or set to it.
var CacheHandler Cacher

var urlTemplates = map[string]string{
	"symbol": "https://www.quandl.com/api/v3/datasets/%s.%s?%s",
	"search": "https://www.quandl.com/api/v3/datasets.%s?%s",
	"list":   "https://www.quandl.com/api/v3/datasets.%s?%s",
}

// Options is used to send additional parameters in the Quandl request
type Options url.Values

// Set registers a key=value pair to be sent in the Quandl request
func (o Options) Set(key, value string) {
	o[key] = []string{value}
}

// Cacher defines the interface for a custom cache handler
type Cacher interface {
	Get(key string) []byte
	Set(key string, data []byte) error
}

// NewOptions accepts any even number of arguments and returns an
// Options object. The odd arguments are the keys, the even arguments
// are the values.
func NewOptions(s ...string) Options {
	o := Options{}
	for i := 0; i < len(s); i += 2 {
		o.Set(s[i], s[i+1])
	}
	return o
}

// GetSymbol returns data for a given symbol
func GetSymbol(symbol string, params Options) (*SymbolResponse, error) {
	raw, err := GetSymbolRaw(symbol, "json", params)
	var response struct {
		Dataset SymbolResponse
	}
	if err != nil {
		return &response.Dataset, err
	}

	err = json.Unmarshal(raw, &response)
	if err != nil {
		return &response.Dataset, marshallerError(raw, err)
	}
	return &response.Dataset, nil
}

// GetList returns a list of symbols for a source
func GetList(source string, page int, perPage int) (*ListResponse, error) {
	raw, err := GetListRaw(source, "json", page, perPage)
	var response ListResponse
	if err != nil {
		return &response, err
	}

	err = json.Unmarshal(raw, &response)
	if err != nil {
		return &response, marshallerError(raw, err)
	}
	return &response, nil
}

// GetSearch returns search results
func GetSearch(query string, page int, perPage int) (*SearchResponse, error) {
	raw, err := GetSearchRaw(query, "json", page, perPage)
	var response SearchResponse
	if err != nil {
		return &response, err
	}

	err = json.Unmarshal(raw, &response)
	if err != nil {
		return &response, marshallerError(raw, err)
	}
	return &response, nil
}

// GetSymbolRaw returns CSV, JSON or XML data for a given symbol
func GetSymbolRaw(symbol string, format string, params Options) ([]byte, error) {
	url := getURL("symbol", symbol, format, arrangeParams(params))
	return getData(url)
}

// GetListRaw returns a list of symbols for a source as CSV, JSON or XML
func GetListRaw(source string, format string, page int, perPage int) ([]byte, error) {
	params := Options{}

	params.Set("query", "*")
	params.Set("database_code", source)
	params.Set("per_page", strconv.Itoa(perPage))
	params.Set("page", strconv.Itoa(page))

	url := getURL("list", format, arrangeParams(params))
	return getData(url)
}

// GetSearchRaw returns search results as JSON or XML
func GetSearchRaw(query string, format string, page int, perPage int) ([]byte, error) {
	params := Options{}

	// TODO: Remove when Quandl fixes this bug
	if format == "csv" {
		format = "json"
	}

	params.Set("query", query)
	params.Set("per_page", strconv.Itoa(perPage))
	params.Set("page", strconv.Itoa(page))

	url := getURL("search", format, arrangeParams(params))
	return getData(url)
}

// ToColumns converts a rows array to a columns array
func ToColumns(src [][]interface{}) (out [][]interface{}) {
	out = make([][]interface{}, len(src[0]))
	for _, row := range src {
		for j, cell := range row {
			out[j] = append(out[j], cell)
		}
	}
	return
}

// ToNamedColumns converts a rows array to a columns map
func ToNamedColumns(src [][]interface{}, keys []string) (out map[string][]interface{}) {
	out = make(map[string][]interface{})
	for _, row := range src {
		for j, cell := range row {
			out[keys[j]] = append(out[keys[j]], cell)
		}
	}
	return
}

// FloatColumn converts a column of interface{} to a column of floats
func FloatColumn(s []interface{}) []float64 {
	r := make([]float64, len(s))
	for i := range s {
		r[i] = s[i].(float64)
	}
	return r
}

// TimeColumn converts a column of interface{} to a column of time
func TimeColumn(s []interface{}) []time.Time {
	r := make([]time.Time, len(s))
	for i := range s {
		r[i], _ = time.Parse("2006-01-02", s[i].(string))
	}
	return r
}

// StringColumn converts a column of interface{} to a column of string
func StringColumn(s []interface{}) []string {
	r := make([]string, len(s))
	for i := range s {
		r[i] = s[i].(string)
	}
	return r
}

// getData requests a URL from Quandl and returns the raw response string
func getData(url string) ([]byte, error) {
	if CacheHandler != nil {
		if response := CacheHandler.Get(url); response != nil {
			return response, nil
		}
	}

	response, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	contents, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	if CacheHandler != nil {
		if err := CacheHandler.Set(url, contents); err != nil {
			return nil, err
		}
	}

	return contents, nil
}

// getURL receives a kind that points to a URL template and
// a variable number of strings, which will be replaced
// in the template.
func getURL(kind string, args ...interface{}) string {
	template := urlTemplates[kind]
	LastURL = strings.Trim(fmt.Sprintf(template, args...), "&?")
	return LastURL
}

// arrangeParams takes an Options map and converts it to
// a query string. It will also append the api key as needed.
func arrangeParams(qs Options) string {
	if qs == nil {
		if APIKey == "" {
			return ""
		}
		qs = Options{}
	}
	if APIKey != "" {
		qs.Set("api_key", APIKey)
	}
	return url.Values(qs).Encode()
}

// marshallerError returns a formatted error that includes the response
func marshallerError(response []byte, err error) error {
	return errors.New("JSON Marshaller Error:\nRESPONSE:\n" + string(response) + "\n\nERROR:\n" + err.Error())
}
<|endoftext|>


<commit_before>package rabbus

import (
	"sync"
	"time"

	"github.com/rafaeljesus/retry-go"
	"github.com/sony/gobreaker"
	"github.com/streadway/amqp"
)

const (
	// Transient means higher throughput but messages will not be restored on broker restart.
	Transient uint8 = 1
	// Persistent messages will be restored to durable queues and lost on non-durable queues during server restart.
	Persistent uint8 = 2
	// ContentTypeJSON define json content type
	ContentTypeJSON string = "application/json"
	// ContentTypePlain define plain text content type
	ContentTypePlain string = "plain/text"
)

// Rabbus exposes a interface for emitting and listening for messages.
type Rabbus interface {
	// EmitAsync emits a message to RabbitMQ, but does not wait for the response from broker.
	EmitAsync() chan<- Message
	// EmitErr returns an error if encoding payload fails, or if after circuit breaker is open or retries attempts exceed.
	EmitErr() <-chan error
	// EmitOk returns true when the message was sent.
	EmitOk() <-chan struct{}
	// Listen to a message from RabbitMQ, returns
	// an error if exchange, queue name and function handler not passed or if an error occurred while creating
	// amqp consumer.
	Listen(ListenConfig) (chan ConsumerMessage, error)
	// Close attempt to close channel and connection.
	Close()
}

// Config carries the variables to tune a newly started rabbus.
type Config struct {
	// Dsn is the amqp url address.
	Dsn string
	// Durable indicates of the queue will survive broker restarts. Default to true.
	Durable bool
	// Attempts is the max number of retries on broker outages.
	Attempts int
	// Sleep is the sleep time of the retry mechanism.
	Sleep time.Duration
	// Interval is the cyclic period of the closed state for CircuitBreaker to clear the internal counts,
	// If Interval is 0, CircuitBreaker doesn't clear the internal counts during the closed state.
	Interval time.Duration
	// Timeout is the period of the open state, after which the state of CircuitBreaker becomes half-open.
	// If Timeout is 0, the timeout value of CircuitBreaker is set to 60 seconds.
	Timeout time.Duration
	// Threshold when a threshold of failures has been reached, future calls to the broker will not run.
	// During this state, the circuit breaker will periodically allow the calls to run and, if it is successful,
	// will start running the function again. Default value is 5.
	Threshold uint32
	// OnStateChange is called whenever the state of CircuitBreaker changes.
	OnStateChange func(name, from, to string)
}

// Message carries fields for sending messages.
type Message struct {
	// Exchange the exchange name.
	Exchange string
	// Kind the exchange type.
	Kind string
	// Key the routing key name.
	Key string
	// Payload the message payload.
	Payload []byte
	// DeliveryMode indicates if the is Persistent or Transient.
	DeliveryMode uint8
	// ContentType the message content-type.
	ContentType string
	// Headers the message application headers
	Headers map[string]interface{}
}

// ListenConfig carries fields for listening messages.
type ListenConfig struct {
	// Exchange the exchange name.
	Exchange string
	// Kind the exchange type.
	Kind string
	// Key the routing key name.
	Key string
	// Queue the queue name
	Queue string
}

// Delivery wraps amqp.Delivery struct
type Delivery struct {
	amqp.Delivery
}

type rabbus struct {
	sync.RWMutex
	conn       *amqp.Connection
	ch         *amqp.Channel
	breaker    *gobreaker.CircuitBreaker
	emit       chan Message
	emitErr    chan error
	emitOk     chan struct{}
	config     Config
	exDeclared map[string]struct{}
}

// NewRabbus returns a new Rabbus configured with the
// variables from the config parameter, or returning an non-nil err
// if an error occurred while creating connection and channel.
func NewRabbus(c Config) (Rabbus, error) {
	conn, err := amqp.Dial(c.Dsn)
	if err != nil {
		return nil, err
	}

	ch, err := conn.Channel()
	if err != nil {
		return nil, err
	}

	if c.Threshold == 0 {
		c.Threshold = 5
	}

	st := gobreaker.Settings{
		Name:     "Rabbus",
		Interval: c.Interval,
		Timeout:  c.Timeout,
		ReadyToTrip: func(counts gobreaker.Counts) bool {
			return counts.ConsecutiveFailures > c.Threshold
		},
		OnStateChange: func(name string, from gobreaker.State, to gobreaker.State) {
			c.OnStateChange(name, from.String(), to.String())
		},
	}

	r := &rabbus{
		conn:       conn,
		ch:         ch,
		breaker:    gobreaker.NewCircuitBreaker(st),
		emit:       make(chan Message),
		emitErr:    make(chan error),
		emitOk:     make(chan struct{}),
		config:     c,
		exDeclared: make(map[string]struct{}),
	}

	go r.register()
	go notifyClose(c.Dsn, r)

	rab := r

	return rab, nil
}

// EmitAsync emits a message to RabbitMQ, but does not wait for the response from broker.
func (r *rabbus) EmitAsync() chan<- Message {
	return r.emit
}

// EmitErr returns an error if encoding payload fails, or if after circuit breaker is open or retries attempts exceed.
func (r *rabbus) EmitErr() <-chan error {
	return r.emitErr
}

// EmitOk returns true when the message was sent.
func (r *rabbus) EmitOk() <-chan struct{} {
	return r.emitOk
}

// Listen to a message from RabbitMQ, returns
// an error if exchange, queue name and function handler not passed or if an error occurred while creating
// amqp consumer.
func (r *rabbus) Listen(c ListenConfig) (chan ConsumerMessage, error) {
	if c.Exchange == "" {
		return nil, ErrMissingExchange
	}

	if c.Kind == "" {
		return nil, ErrMissingKind
	}

	if c.Queue == "" {
		return nil, ErrMissingQueue
	}

	if err := r.ch.ExchangeDeclare(c.Exchange, c.Kind, r.config.Durable, false, false, false, nil); err != nil {
		return nil, err
	}

	q, err := r.ch.QueueDeclare(c.Queue, r.config.Durable, false, false, false, nil)
	if err != nil {
		return nil, err
	}

	if err := r.ch.QueueBind(q.Name, c.Key, c.Exchange, false, nil); err != nil {
		return nil, err
	}

	msgs, err := r.ch.Consume(q.Name, "", false, false, false, false, nil)
	if err != nil {
		return nil, err
	}

	messages := make(chan ConsumerMessage, 256)
	go func(msgs <-chan amqp.Delivery, messages chan ConsumerMessage) {
		for m := range msgs {
			messages <- newConsumerMessage(m)
		}
	}(msgs, messages)

	return messages, nil
}

// Close attempt to close channel and connection.
func (r *rabbus) Close() {
	r.ch.Close()
	r.conn.Close()
}

func (r *rabbus) register() {
	for m := range r.emit {
		r.produce(m)
	}
}

func (r *rabbus) produce(m Message) {
	if _, ok := r.exDeclared[m.Exchange]; !ok {
		if err := r.ch.ExchangeDeclare(m.Exchange, m.Kind, r.config.Durable, false, false, false, nil); err != nil {
			r.emitErr <- err
			return
		}
		r.exDeclared[m.Exchange] = struct{}{}
	}

	if m.ContentType == "" {
		m.ContentType = ContentTypeJSON
	}

	if m.DeliveryMode == 0 {
		m.DeliveryMode = Persistent
	}

	if _, err := r.breaker.Execute(func() (interface{}, error) {
		return nil, retry.Do(func() error {
			return r.ch.Publish(m.Exchange, m.Key, false, false, amqp.Publishing{
				Headers:         amqp.Table(m.Headers),
				ContentType:     m.ContentType,
				ContentEncoding: "UTF-8",
				DeliveryMode:    m.DeliveryMode,
				Timestamp:       time.Now(),
				Body:            m.Payload,
			})
		}, r.config.Attempts, r.config.Sleep)
	}); err != nil {
		r.emitErr <- err
		return
	}

	r.emitOk <- struct{}{}
}

func notifyClose(dsn string, r *rabbus) {
	err := <-r.conn.NotifyClose(make(chan *amqp.Error))
	if err != nil {
		for {
			time.Sleep(time.Second * 2)
			conn, err := amqp.Dial(dsn)
			if err != nil {
				continue
			}

			ch, err := conn.Channel()
			if err != nil {
				continue
			}

			r.Lock()
			defer r.Unlock()
			r.conn = conn
			r.ch = ch

			go notifyClose(dsn, r)

			break
		}
	}
}
<commit_msg>Add Qos on the channel connection<commit_after>package rabbus

import (
	"sync"
	"time"

	"github.com/rafaeljesus/retry-go"
	"github.com/sony/gobreaker"
	"github.com/streadway/amqp"
)

const (
	// Transient means higher throughput but messages will not be restored on broker restart.
	Transient uint8 = 1
	// Persistent messages will be restored to durable queues and lost on non-durable queues during server restart.
	Persistent uint8 = 2
	// ContentTypeJSON define json content type
	ContentTypeJSON string = "application/json"
	// ContentTypePlain define plain text content type
	ContentTypePlain string = "plain/text"
)

// Rabbus exposes a interface for emitting and listening for messages.
type Rabbus interface {
	// EmitAsync emits a message to RabbitMQ, but does not wait for the response from broker.
	EmitAsync() chan<- Message
	// EmitErr returns an error if encoding payload fails, or if after circuit breaker is open or retries attempts exceed.
	EmitErr() <-chan error
	// EmitOk returns true when the message was sent.
	EmitOk() <-chan struct{}
	// Listen to a message from RabbitMQ, returns
	// an error if exchange, queue name and function handler not passed or if an error occurred while creating
	// amqp consumer.
	Listen(ListenConfig) (chan ConsumerMessage, error)
	// Close attempt to close channel and connection.
	Close()
}

// Config carries the variables to tune a newly started rabbus.
type Config struct {
	// Dsn is the amqp url address.
	Dsn string
	// Durable indicates of the queue will survive broker restarts. Default to true.
	Durable bool
	// Attempts is the max number of retries on broker outages.
	Attempts int
	// Sleep is the sleep time of the retry mechanism.
	Sleep time.Duration
	// Interval is the cyclic period of the closed state for CircuitBreaker to clear the internal counts,
	// If Interval is 0, CircuitBreaker doesn't clear the internal counts during the closed state.
	Interval time.Duration
	// Timeout is the period of the open state, after which the state of CircuitBreaker becomes half-open.
	// If Timeout is 0, the timeout value of CircuitBreaker is set to 60 seconds.
	Timeout time.Duration
	// Threshold when a threshold of failures has been reached, future calls to the broker will not run.
	// During this state, the circuit breaker will periodically allow the calls to run and, if it is successful,
	// will start running the function again. Default value is 5.
	Threshold uint32
	// OnStateChange is called whenever the state of CircuitBreaker changes.
	OnStateChange func(name, from, to string)
	// Qos controls how many messages or how many bytes will be consumed before receiving delivery acks
	Qos Qos
}

// Qos controls how many messages or how many bytes the server will try to keep on the network for consumers before receiving delivery acks.
type Qos struct {
	PrefetchCount int
	PrefetchSize  int
	Global        bool
}

// Message carries fields for sending messages.
type Message struct {
	// Exchange the exchange name.
	Exchange string
	// Kind the exchange type.
	Kind string
	// Key the routing key name.
	Key string
	// Payload the message payload.
	Payload []byte
	// DeliveryMode indicates if the is Persistent or Transient.
	DeliveryMode uint8
	// ContentType the message content-type.
	ContentType string
	// Headers the message application headers
	Headers map[string]interface{}
}

// ListenConfig carries fields for listening messages.
type ListenConfig struct {
	// Exchange the exchange name.
	Exchange string
	// Kind the exchange type.
	Kind string
	// Key the routing key name.
	Key string
	// Queue the queue name
	Queue string
}

// Delivery wraps amqp.Delivery struct
type Delivery struct {
	amqp.Delivery
}

type rabbus struct {
	sync.RWMutex
	conn       *amqp.Connection
	ch         *amqp.Channel
	breaker    *gobreaker.CircuitBreaker
	emit       chan Message
	emitErr    chan error
	emitOk     chan struct{}
	config     Config
	exDeclared map[string]struct{}
}

// NewRabbus returns a new Rabbus configured with the
// variables from the config parameter, or returning an non-nil err
// if an error occurred while creating connection and channel.
func NewRabbus(c Config) (Rabbus, error) {
	conn, err := amqp.Dial(c.Dsn)
	if err != nil {
		return nil, err
	}

	ch, err := conn.Channel()
	if err != nil {
		return nil, err
	}

	err = ch.Qos(c.Qos.PrefetchCount, c.Qos.PrefetchSize, c.Qos.Global)
	if err != nil {
		return nil, err
	}

	if c.Threshold == 0 {
		c.Threshold = 5
	}

	st := gobreaker.Settings{
		Name:     "Rabbus",
		Interval: c.Interval,
		Timeout:  c.Timeout,
		ReadyToTrip: func(counts gobreaker.Counts) bool {
			return counts.ConsecutiveFailures > c.Threshold
		},
		OnStateChange: func(name string, from gobreaker.State, to gobreaker.State) {
			c.OnStateChange(name, from.String(), to.String())
		},
	}

	r := &rabbus{
		conn:       conn,
		ch:         ch,
		breaker:    gobreaker.NewCircuitBreaker(st),
		emit:       make(chan Message),
		emitErr:    make(chan error),
		emitOk:     make(chan struct{}),
		config:     c,
		exDeclared: make(map[string]struct{}),
	}

	go r.register()
	go notifyClose(c.Dsn, r)

	rab := r

	return rab, nil
}

// EmitAsync emits a message to RabbitMQ, but does not wait for the response from broker.
func (r *rabbus) EmitAsync() chan<- Message {
	return r.emit
}

// EmitErr returns an error if encoding payload fails, or if after circuit breaker is open or retries attempts exceed.
func (r *rabbus) EmitErr() <-chan error {
	return r.emitErr
}

// EmitOk returns true when the message was sent.
func (r *rabbus) EmitOk() <-chan struct{} {
	return r.emitOk
}

// Listen to a message from RabbitMQ, returns
// an error if exchange, queue name and function handler not passed or if an error occurred while creating
// amqp consumer.
func (r *rabbus) Listen(c ListenConfig) (chan ConsumerMessage, error) {
	if c.Exchange == "" {
		return nil, ErrMissingExchange
	}

	if c.Kind == "" {
		return nil, ErrMissingKind
	}

	if c.Queue == "" {
		return nil, ErrMissingQueue
	}

	if err := r.ch.ExchangeDeclare(c.Exchange, c.Kind, r.config.Durable, false, false, false, nil); err != nil {
		return nil, err
	}

	q, err := r.ch.QueueDeclare(c.Queue, r.config.Durable, false, false, false, nil)
	if err != nil {
		return nil, err
	}

	if err := r.ch.QueueBind(q.Name, c.Key, c.Exchange, false, nil); err != nil {
		return nil, err
	}

	msgs, err := r.ch.Consume(q.Name, "", false, false, false, false, nil)
	if err != nil {
		return nil, err
	}

	messages := make(chan ConsumerMessage, 256)
	go func(msgs <-chan amqp.Delivery, messages chan ConsumerMessage) {
		for m := range msgs {
			messages <- newConsumerMessage(m)
		}
	}(msgs, messages)

	return messages, nil
}

// Close attempt to close channel and connection.
func (r *rabbus) Close() {
	r.ch.Close()
	r.conn.Close()
}

func (r *rabbus) register() {
	for m := range r.emit {
		r.produce(m)
	}
}

func (r *rabbus) produce(m Message) {
	if _, ok := r.exDeclared[m.Exchange]; !ok {
		if err := r.ch.ExchangeDeclare(m.Exchange, m.Kind, r.config.Durable, false, false, false, nil); err != nil {
			r.emitErr <- err
			return
		}
		r.exDeclared[m.Exchange] = struct{}{}
	}

	if m.ContentType == "" {
		m.ContentType = ContentTypeJSON
	}

	if m.DeliveryMode == 0 {
		m.DeliveryMode = Persistent
	}

	if _, err := r.breaker.Execute(func() (interface{}, error) {
		return nil, retry.Do(func() error {
			return r.ch.Publish(m.Exchange, m.Key, false, false, amqp.Publishing{
				Headers:         amqp.Table(m.Headers),
				ContentType:     m.ContentType,
				ContentEncoding: "UTF-8",
				DeliveryMode:    m.DeliveryMode,
				Timestamp:       time.Now(),
				Body:            m.Payload,
			})
		}, r.config.Attempts, r.config.Sleep)
	}); err != nil {
		r.emitErr <- err
		return
	}

	r.emitOk <- struct{}{}
}

func notifyClose(dsn string, r *rabbus) {
	err := <-r.conn.NotifyClose(make(chan *amqp.Error))
	if err != nil {
		for {
			time.Sleep(time.Second * 2)
			conn, err := amqp.Dial(dsn)
			if err != nil {
				continue
			}

			ch, err := conn.Channel()
			if err != nil {
				continue
			}

			r.Lock()
			defer r.Unlock()
			r.conn = conn
			r.ch = ch

			go notifyClose(dsn, r)

			break
		}
	}
}
<|endoftext|>


<commit_before>// Copyright  The Shinichi Nakagawa. All rights reserved.
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"net/http"
	"os"
	"io/ioutil"
	"path"
	"flag"
)

func IsExist(filename string) bool {
    _, err := os.Stat(filename)
    return err == nil
}

func MakeWorkDirectory(dirname string) {
	if IsExist(dirname) {
		fmt.Println("Directory delete")
		if err := os.RemoveAll(dirname); err != nil {
			fmt.Println(err)
		}
	}
	os.MkdirAll(dirname, 0777)
}

func DownloadArchives(url string, dirname string) {
	// get archives
	fmt.Println(fmt.Sprintf("download: %s", url))
	response, err := http.Get(url)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	fmt.Println(fmt.Sprintf("status: %s", response.Status))

	// download
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	_, filename := path.Split(url)
	fmt.Println(filename)
	file, err := os.OpenFile(fmt.Sprintf("%s/%s", dirname, filename), os.O_CREATE|os.O_WRONLY, 0777)
	if err != nil {
		fmt.Println(err)
	}
	defer func() {
		file.Close()
	}()

	file.Write(body)
}

func GetEventsFile(year int, dirname string) {
	var url string = fmt.Sprintf("http://www.retrosheet.org/events/%deve.zip", year)
	// file Download
	DownloadArchives(url, dirname)
	return
}

func GetGameLogs(year int, dirname string) {
	var url string = fmt.Sprintf("http://www.retrosheet.org/gamelogs/gl%d.zip", year)
	// file Download
	DownloadArchives(url, dirname)
	return
}

func main() {
	// Commandline Options
	var fromYear = flag.Int("f", 2010, "Season Year(From)")
	var toYear = flag.Int("t", 2014, "Season Year(To)")
	flag.Parse()

	// make dir
	var dirname string = "files"
	MakeWorkDirectory(dirname)

	// Events/Game Log download
	for year := *fromYear; year < *toYear + 1; year++ {
		fmt.Println(fmt.Sprintf("Get Retrosheet Archives(%d Season)", year))
		GetEventsFile(year, dirname)
		GetGameLogs(year, dirname)
	}

}
<commit_msg>multithreading for download task<commit_after>// Copyright  The Shinichi Nakagawa. All rights reserved.
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"net/http"
	"os"
	"io/ioutil"
	"path"
	"flag"
	"sync"
)

func IsExist(filename string) bool {
    _, err := os.Stat(filename)
    return err == nil
}

func MakeWorkDirectory(dirname string) {
	if IsExist(dirname) {
		return
	}
	os.MkdirAll(dirname, 0777)
}

func DownloadArchives(url string, dirname string) {
	// get archives
	fmt.Println(fmt.Sprintf("download: %s", url))
	response, err := http.Get(url)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	fmt.Println(fmt.Sprintf("status: %s", response.Status))

	// download
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	_, filename := path.Split(url)
	fmt.Println(filename)
	file, err := os.OpenFile(fmt.Sprintf("%s/%s", dirname, filename), os.O_CREATE|os.O_WRONLY, 0777)
	if err != nil {
		fmt.Println(err)
	}
	defer func() {
		file.Close()
	}()

	file.Write(body)
}

func GetEventsFileUrl(year int) string {
	return fmt.Sprintf("http://www.retrosheet.org/events/%deve.zip", year)
}

func GetGameLogsUrl(year int) string {
	return fmt.Sprintf("http://www.retrosheet.org/gamelogs/gl%d.zip", year)
}

func main() {
	// Commandline Options
	var fromYear = flag.Int("f", 2010, "Season Year(From)")
	var toYear = flag.Int("t", 2014, "Season Year(To)")
	flag.Parse()

	// make dir
	var dirname string = "files"
	MakeWorkDirectory(dirname)

	wait := new(sync.WaitGroup)
	// Generate URL
	urls := []string{}
	for year := *fromYear; year < *toYear + 1; year++ {
		urls = append(urls, GetEventsFileUrl(year))
		wait.Add(1)
		urls = append(urls, GetGameLogsUrl(year))
		wait.Add(1)
	}

	// Download files
	for _, url := range urls {
		go func(url string) {
			DownloadArchives(url, dirname)
			wait.Done()
		}(url)
	}
	wait.Wait()

}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"

	"github.com/justone/pmb/api"
)

type DumpRawCommand struct {
	Pretty bool `short:"p" long:"pretty" description:"Pretty print message contents."`
}

var dumpRawCommand DumpRawCommand

func (x *DumpRawCommand) Execute(args []string) error {
	bus := pmb.GetPMB(globalOptions.Primary)

	id := pmb.GenerateRandomID("dumpRaw")

	conn, err := bus.ConnectClient(id, !globalOptions.TrustKey)
	if err != nil {
		return err
	}

	return runDumpRaw(conn)
}

func init() {
	parser.AddCommand("dump-raw",
		"Print out each raw JSON message as it comes through. (low level)",
		"",
		&dumpRawCommand)
}

func runDumpRaw(conn *pmb.Connection) error {

	for {
		message := <-conn.In

		if dumpRawCommand.Pretty {
			var out bytes.Buffer
			err := json.Indent(&out, []byte(message.Raw), "", "  ")

			if err != nil {
				fmt.Println(err)
			} else {
				fmt.Printf("%s\n", out.Bytes())
			}
		} else {
			fmt.Printf("%s\n", message.Raw)
		}
	}

	return nil
}
<commit_msg>add ability to ignore certain message types in dump-raw<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"

	"github.com/Sirupsen/logrus"
	"github.com/justone/pmb/api"
)

type DumpRawCommand struct {
	Pretty bool     `short:"p" long:"pretty" description:"Pretty print message contents."`
	Ignore []string `short:"i" long:"ignore" description:"Message types to ignore."`
}

var dumpRawCommand DumpRawCommand

func (x *DumpRawCommand) Execute(args []string) error {
	bus := pmb.GetPMB(globalOptions.Primary)

	id := pmb.GenerateRandomID("dumpRaw")

	conn, err := bus.ConnectClient(id, !globalOptions.TrustKey)
	if err != nil {
		return err
	}

	return runDumpRaw(conn)
}

func init() {
	parser.AddCommand("dump-raw",
		"Print out each raw JSON message as it comes through. (low level)",
		"",
		&dumpRawCommand)
}

func runDumpRaw(conn *pmb.Connection) error {
	ignoreTypes := make(map[string]bool)

	for _, ign := range dumpRawCommand.Ignore {
		ignoreTypes[ign] = true
	}

	for {
		message := <-conn.In

		if _, ok := ignoreTypes[message.Contents["type"].(string)]; ok {
			logrus.Debugf("ignoring message of type %s", message.Contents["type"].(string))
			continue
		}

		if dumpRawCommand.Pretty {
			var out bytes.Buffer
			err := json.Indent(&out, []byte(message.Raw), "", "  ")

			if err != nil {
				fmt.Println(err)
			} else {
				fmt.Printf("%s\n", out.Bytes())
			}
		} else {
			fmt.Printf("%s\n", message.Raw)
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package shredis

// All replies are build of the types:
//   - string
//   - int
//   - error
//   - interface{} arrays of the above types

import (
	"bufio"
	"errors"
	"io"
)

var (
	// ErrProtocolError is returned on unexpected replies.
	ErrProtocolError = errors.New("shredis: protocol error")
)

type replyReader struct {
	buf     *bufio.Reader
	scratch []byte
}

func newReplyReader(r io.Reader) *replyReader {
	return &replyReader{
		buf: bufio.NewReader(r),
	}
}

func (r *replyReader) Next() (interface{}, error) {
	c, err := r.buf.ReadByte()
	if err != nil {
		return nil, err
	}
	switch c {
	case '+':
		return r.simpleString()
	case ':':
		return r.integer()
	case '$':
		return r.bulk()
	case '-':
		return r.error()
	case '*':
		return r.array()
	default:
		return nil, ErrProtocolError
	}
}

func (r *replyReader) readString() (string, error) {
	p, err := r.buf.ReadSlice('\n')
	if err != nil {
		return "", err
	}
	return string(p[:len(p)-2]), nil
}

func (r *replyReader) readInt() (int, error) {
	p, err := r.buf.ReadSlice('\n')
	if err != nil {
		return 0, err
	}
	negate := false
	n := 0
	for i, c := range p[:len(p)-2] {
		switch {
		case c >= '0' && c <= '9':
			n *= 10
			n += int(c - '0')
		case i == 0 && c == '-':
			negate = true
		default:
			return 0, ErrProtocolError
		}
	}
	if negate {
		n *= -1
	}
	return n, nil
}

func (r *replyReader) simpleString() (string, error) {
	return r.readString()
}

func (r *replyReader) integer() (int, error) {
	return r.readInt()
}

func (r *replyReader) error() (error, error) {
	s, err := r.readString()
	if err != nil {
		return nil, err
	}
	return errors.New(s), nil
}

func (r *replyReader) bulk() (interface{}, error) {
	n, err := r.readInt()
	if err != nil || n < 0 {
		return nil, err
	}

	if len(r.scratch) < n+2 {
		r.scratch = make([]byte, n+2)
	}
	_, err = io.ReadFull(r.buf, r.scratch[:n+2])
	if err != nil {
		return nil, err
	}
	return string(r.scratch[:n]), nil
}

func (r *replyReader) array() (interface{}, error) {
	n, err := r.readInt()
	if err != nil || n < 0 {
		return nil, err
	}
	res := make([]interface{}, n)
	for i := range res {
		res[i], err = r.Next()
		if err != nil {
			return nil, err
		}
	}
	return res, nil
}
<commit_msg>integer read cleanup<commit_after>package shredis

// All replies are build of the types:
//   - string
//   - int
//   - error
//   - interface{} arrays of the above types

import (
	"bufio"
	"errors"
	"io"
)

var (
	// ErrProtocolError is returned on unexpected replies.
	ErrProtocolError = errors.New("shredis: protocol error")
)

type replyReader struct {
	buf     *bufio.Reader
	scratch []byte
}

func newReplyReader(r io.Reader) *replyReader {
	return &replyReader{
		buf: bufio.NewReader(r),
	}
}

func (r *replyReader) Next() (interface{}, error) {
	c, err := r.buf.ReadByte()
	if err != nil {
		return nil, err
	}
	switch c {
	case '+':
		return r.simpleString()
	case ':':
		return r.integer()
	case '$':
		return r.bulk()
	case '-':
		return r.error()
	case '*':
		return r.array()
	default:
		return nil, ErrProtocolError
	}
}

func (r *replyReader) readString() (string, error) {
	p, err := r.buf.ReadSlice('\n')
	if err != nil {
		return "", err
	}
	return string(p[:len(p)-2]), nil
}

func (r *replyReader) readInt() (int, error) {
	var (
		negate = false
		n      = 0
	)
loop:
	for i := 0; ; i++ {
		c, err := r.buf.ReadByte()
		if err != nil {
			return 0, err
		}
		switch {
		case c >= '0' && c <= '9':
			n = n*10 + int(c-'0')
		case i == 0 && c == '-':
			negate = true
		case c == '\r':
			break loop
		default:
			return 0, ErrProtocolError
		}
	}
	r.buf.ReadByte() // flush the \n

	if negate {
		n *= -1
	}
	return n, nil
}

func (r *replyReader) simpleString() (string, error) {
	return r.readString()
}

func (r *replyReader) integer() (int, error) {
	return r.readInt()
}

func (r *replyReader) error() (error, error) {
	s, err := r.readString()
	if err != nil {
		return nil, err
	}
	return errors.New(s), nil
}

func (r *replyReader) bulk() (interface{}, error) {
	n, err := r.readInt()
	if err != nil || n < 0 {
		return nil, err
	}

	if len(r.scratch) < n+2 {
		r.scratch = make([]byte, n+2)
	}
	_, err = io.ReadFull(r.buf, r.scratch[:n+2])
	if err != nil {
		return nil, err
	}
	return string(r.scratch[:n]), nil
}

func (r *replyReader) array() (interface{}, error) {
	n, err := r.readInt()
	if err != nil || n < 0 {
		return nil, err
	}
	res := make([]interface{}, n)
	for i := range res {
		res[i], err = r.Next()
		if err != nil {
			return nil, err
		}
	}
	return res, nil
}
<|endoftext|>


<commit_before>package rardecode

import (
	"bytes"
	"errors"
	"io"
	"io/ioutil"
	"time"
)

// FileHeader HostOS types
const (
	HostOSUnknown = 0
	HostOSMSDOS   = 1
	HostOSOS2     = 2
	HostOSWindows = 3
	HostOSUnix    = 4
	HostOSMacOS   = 5
	HostOSBeOS    = 6
)

const (
	maxPassword = 128
)

var (
	errShortFile        = errors.New("rardecode: decoded file too short")
	errInvalidFileBlock = errors.New("rardecode: invalid file block")
	errUnexpectedArcEnd = errors.New("rardecode: unexpected end of archive")
	errBadFileChecksum  = errors.New("rardecode: bad file checksum")
)

type limitedReader struct {
	r        io.Reader
	n        int64 // bytes remaining
	shortErr error // error returned when r returns io.EOF with n > 0
}

func (l *limitedReader) Read(p []byte) (int, error) {
	if l.n <= 0 {
		return 0, io.EOF
	}
	if int64(len(p)) > l.n {
		p = p[0:l.n]
	}
	n, err := l.r.Read(p)
	l.n -= int64(n)
	if err == io.EOF && l.n > 0 {
		return n, l.shortErr
	}
	return n, err
}

// limitReader returns an io.Reader that reads from r and stops with
// io.EOF after n bytes.
// If r returns an io.EOF before reading n bytes, err is returned.
func limitReader(r io.Reader, n int64, err error) io.Reader {
	return &limitedReader{r, n, err}
}

// fileChecksum allows file checksum validations to be performed.
// File contents must first be written to fileChecksum. Then valid is
// called to perform the file checksum calculation to determine
// if the file contents are valid or not.
type fileChecksum interface {
	io.Writer
	valid() bool
}

// FileHeader represents a single file in a RAR archive.
type FileHeader struct {
	Name             string    // file name using '/' as the directory separator
	IsDir            bool      // is a directory
	HostOS           byte      // Host OS the archive was created on
	Attributes       int64     // file attributes
	PackedSize       int64     // packed file size (or first block if the file spans volumes)
	UnPackedSize     int64     // unpacked file size
	UnKnownSize      bool      // unpacked file size is not known
	ModificationTime time.Time // modification time (non-zero if set)
	CreationTime     time.Time // creation time (non-zero if set)
	AccessTime       time.Time // access time (non-zero if set)
	Version          int       // file version
}

// fileBlockHeader represents a file block in a RAR archive.
// Files may comprise one or more file blocks.
// Solid files retain decode tables and dictionary from previous solid files in the archive.
type fileBlockHeader struct {
	first   bool         // first block in file
	last    bool         // last block in file
	solid   bool         // file is solid
	winSize uint         // log base 2 of decode window size
	cksum   fileChecksum // file checksum
	decoder decoder      // decoder to use for file
	key     []byte       // key for AES, non-empty if file encrypted
	iv      []byte       // iv for AES, non-empty if file encrypted
	FileHeader
}

// fileBlockReader provides sequential access to file blocks in a RAR archive.
type fileBlockReader interface {
	io.Reader                        // Read's read data from the current file block
	next() (*fileBlockHeader, error) // advances to the next file block
	reset(r io.Reader)               // resets for new volume file
	version() int                    // returns current archive format version
}

// packedFileReader provides sequential access to packed files in a RAR archive.
type packedFileReader struct {
	r fileBlockReader
	h *fileBlockHeader // current file header
}

// nextBlockInFile advances to the next file block in the current file, or returns
// an error if there is a problem.
// It is invalid to call this when already at the last block in the current file.
func (f *packedFileReader) nextBlockInFile() error {
	h, err := f.r.next()
	if err != nil {
		if err == io.EOF {
			// archive ended, but file hasn't
			return errUnexpectedArcEnd
		}
		return err
	}
	if h.first || h.Name != f.h.Name {
		return errInvalidFileBlock
	}
	f.h = h
	return nil
}

// next advances to the next packed file in the RAR archive.
func (f *packedFileReader) next() (*fileBlockHeader, error) {
	if f.h != nil {
		// skip to last block in current file
		for !f.h.last {
			if err := f.nextBlockInFile(); err != nil {
				return nil, err
			}
		}
	}
	var err error
	f.h, err = f.r.next() // get next file block
	if err != nil {
		return nil, err
	}
	if !f.h.first {
		return nil, errInvalidFileBlock
	}
	return f.h, nil
}

// Read reads the packed data for the current file into p.
func (f *packedFileReader) Read(p []byte) (int, error) {
	n, err := f.r.Read(p) // read current block data
	for err == io.EOF {   // current block empty
		if n > 0 {
			return n, nil
		}
		if f.h == nil || f.h.last {
			return 0, io.EOF // last block so end of file
		}
		if err := f.nextBlockInFile(); err != nil {
			return 0, err
		}
		n, err = f.r.Read(p) // read new block data
	}
	return n, err
}

// Reader provides sequential access to files in a RAR archive.
type Reader struct {
	r     io.Reader        // reader for current unpacked file
	pr    packedFileReader // reader for current packed file
	dr    decodeReader     // reader for decoding and filters if file is compressed
	cksum fileChecksum     // current file checksum
	solid bool             // file is solid
}

// Read reads from the current file in the RAR archive.
func (r *Reader) Read(p []byte) (int, error) {
	n, err := r.r.Read(p)
	if err == io.EOF && r.cksum != nil && !r.cksum.valid() {
		return n, errBadFileChecksum
	}
	return n, err
}

// Next advances to the next file in the archive.
func (r *Reader) Next() (*FileHeader, error) {
	if r.solid {
		// solid files must be read fully to update decode tables and window
		if _, err := io.Copy(ioutil.Discard, r.r); err != nil {
			return nil, err
		}
	}

	h, err := r.pr.next() // skip to next file
	if err != nil {
		return nil, err
	}
	r.solid = h.solid

	r.r = io.Reader(&r.pr) // start with packed file reader

	// check for encryption
	if len(h.key) > 0 && len(h.iv) > 0 {
		r.r = newAesDecryptReader(r.r, h.key, h.iv) // decrypt
	}
	// check for compression
	if h.decoder != nil {
		err = r.dr.init(r.r, h.decoder, h.winSize, !h.solid)
		if err != nil {
			return nil, err
		}
		r.r = &r.dr
	}
	if h.UnPackedSize >= 0 && !h.UnKnownSize {
		// Limit reading to UnPackedSize as there may be padding
		r.r = limitReader(r.r, h.UnPackedSize, errShortFile)
	}
	r.cksum = h.cksum
	if r.cksum != nil {
		r.r = io.TeeReader(r.r, h.cksum) // write file data to checksum as it is read
	}
	fh := new(FileHeader)
	*fh = h.FileHeader
	return fh, nil
}

func newReader(fbr fileBlockReader) *Reader {
	r := new(Reader)
	r.r = bytes.NewReader(nil) // initial reads will always return EOF
	r.pr.r = fbr
	return r
}

// NewReader creates a Reader reading from r.
func NewReader(r io.Reader, password string) (*Reader, error) {
	fbr, err := newFileBlockReader(r, password)
	if err != nil {
		return nil, err
	}
	return newReader(fbr), nil
}

// OpenReader opens a RAR archive specified by the name and returns a Reader.
func OpenReader(name, password string) (*Reader, error) {
	v, err := openVolume(name, password)
	if err != nil {
		return nil, err
	}
	return newReader(v), nil
}
<commit_msg>return a ReadCloser from OpenReader so the opened file can be closed.<commit_after>package rardecode

import (
	"bytes"
	"errors"
	"io"
	"io/ioutil"
	"time"
)

// FileHeader HostOS types
const (
	HostOSUnknown = 0
	HostOSMSDOS   = 1
	HostOSOS2     = 2
	HostOSWindows = 3
	HostOSUnix    = 4
	HostOSMacOS   = 5
	HostOSBeOS    = 6
)

const (
	maxPassword = 128
)

var (
	errShortFile        = errors.New("rardecode: decoded file too short")
	errInvalidFileBlock = errors.New("rardecode: invalid file block")
	errUnexpectedArcEnd = errors.New("rardecode: unexpected end of archive")
	errBadFileChecksum  = errors.New("rardecode: bad file checksum")
)

type limitedReader struct {
	r        io.Reader
	n        int64 // bytes remaining
	shortErr error // error returned when r returns io.EOF with n > 0
}

func (l *limitedReader) Read(p []byte) (int, error) {
	if l.n <= 0 {
		return 0, io.EOF
	}
	if int64(len(p)) > l.n {
		p = p[0:l.n]
	}
	n, err := l.r.Read(p)
	l.n -= int64(n)
	if err == io.EOF && l.n > 0 {
		return n, l.shortErr
	}
	return n, err
}

// limitReader returns an io.Reader that reads from r and stops with
// io.EOF after n bytes.
// If r returns an io.EOF before reading n bytes, err is returned.
func limitReader(r io.Reader, n int64, err error) io.Reader {
	return &limitedReader{r, n, err}
}

// fileChecksum allows file checksum validations to be performed.
// File contents must first be written to fileChecksum. Then valid is
// called to perform the file checksum calculation to determine
// if the file contents are valid or not.
type fileChecksum interface {
	io.Writer
	valid() bool
}

// FileHeader represents a single file in a RAR archive.
type FileHeader struct {
	Name             string    // file name using '/' as the directory separator
	IsDir            bool      // is a directory
	HostOS           byte      // Host OS the archive was created on
	Attributes       int64     // file attributes
	PackedSize       int64     // packed file size (or first block if the file spans volumes)
	UnPackedSize     int64     // unpacked file size
	UnKnownSize      bool      // unpacked file size is not known
	ModificationTime time.Time // modification time (non-zero if set)
	CreationTime     time.Time // creation time (non-zero if set)
	AccessTime       time.Time // access time (non-zero if set)
	Version          int       // file version
}

// fileBlockHeader represents a file block in a RAR archive.
// Files may comprise one or more file blocks.
// Solid files retain decode tables and dictionary from previous solid files in the archive.
type fileBlockHeader struct {
	first   bool         // first block in file
	last    bool         // last block in file
	solid   bool         // file is solid
	winSize uint         // log base 2 of decode window size
	cksum   fileChecksum // file checksum
	decoder decoder      // decoder to use for file
	key     []byte       // key for AES, non-empty if file encrypted
	iv      []byte       // iv for AES, non-empty if file encrypted
	FileHeader
}

// fileBlockReader provides sequential access to file blocks in a RAR archive.
type fileBlockReader interface {
	io.Reader                        // Read's read data from the current file block
	next() (*fileBlockHeader, error) // advances to the next file block
	reset(r io.Reader)               // resets for new volume file
	version() int                    // returns current archive format version
}

// packedFileReader provides sequential access to packed files in a RAR archive.
type packedFileReader struct {
	r fileBlockReader
	h *fileBlockHeader // current file header
}

// nextBlockInFile advances to the next file block in the current file, or returns
// an error if there is a problem.
// It is invalid to call this when already at the last block in the current file.
func (f *packedFileReader) nextBlockInFile() error {
	h, err := f.r.next()
	if err != nil {
		if err == io.EOF {
			// archive ended, but file hasn't
			return errUnexpectedArcEnd
		}
		return err
	}
	if h.first || h.Name != f.h.Name {
		return errInvalidFileBlock
	}
	f.h = h
	return nil
}

// next advances to the next packed file in the RAR archive.
func (f *packedFileReader) next() (*fileBlockHeader, error) {
	if f.h != nil {
		// skip to last block in current file
		for !f.h.last {
			if err := f.nextBlockInFile(); err != nil {
				return nil, err
			}
		}
	}
	var err error
	f.h, err = f.r.next() // get next file block
	if err != nil {
		return nil, err
	}
	if !f.h.first {
		return nil, errInvalidFileBlock
	}
	return f.h, nil
}

// Read reads the packed data for the current file into p.
func (f *packedFileReader) Read(p []byte) (int, error) {
	n, err := f.r.Read(p) // read current block data
	for err == io.EOF {   // current block empty
		if n > 0 {
			return n, nil
		}
		if f.h == nil || f.h.last {
			return 0, io.EOF // last block so end of file
		}
		if err := f.nextBlockInFile(); err != nil {
			return 0, err
		}
		n, err = f.r.Read(p) // read new block data
	}
	return n, err
}

// Reader provides sequential access to files in a RAR archive.
type Reader struct {
	r     io.Reader        // reader for current unpacked file
	pr    packedFileReader // reader for current packed file
	dr    decodeReader     // reader for decoding and filters if file is compressed
	cksum fileChecksum     // current file checksum
	solid bool             // file is solid
}

// Read reads from the current file in the RAR archive.
func (r *Reader) Read(p []byte) (int, error) {
	n, err := r.r.Read(p)
	if err == io.EOF && r.cksum != nil && !r.cksum.valid() {
		return n, errBadFileChecksum
	}
	return n, err
}

// Next advances to the next file in the archive.
func (r *Reader) Next() (*FileHeader, error) {
	if r.solid {
		// solid files must be read fully to update decode tables and window
		if _, err := io.Copy(ioutil.Discard, r.r); err != nil {
			return nil, err
		}
	}

	h, err := r.pr.next() // skip to next file
	if err != nil {
		return nil, err
	}
	r.solid = h.solid

	r.r = io.Reader(&r.pr) // start with packed file reader

	// check for encryption
	if len(h.key) > 0 && len(h.iv) > 0 {
		r.r = newAesDecryptReader(r.r, h.key, h.iv) // decrypt
	}
	// check for compression
	if h.decoder != nil {
		err = r.dr.init(r.r, h.decoder, h.winSize, !h.solid)
		if err != nil {
			return nil, err
		}
		r.r = &r.dr
	}
	if h.UnPackedSize >= 0 && !h.UnKnownSize {
		// Limit reading to UnPackedSize as there may be padding
		r.r = limitReader(r.r, h.UnPackedSize, errShortFile)
	}
	r.cksum = h.cksum
	if r.cksum != nil {
		r.r = io.TeeReader(r.r, h.cksum) // write file data to checksum as it is read
	}
	fh := new(FileHeader)
	*fh = h.FileHeader
	return fh, nil
}

func (r *Reader) init(fbr fileBlockReader) {
	r.r = bytes.NewReader(nil) // initial reads will always return EOF
	r.pr.r = fbr
}

// NewReader creates a Reader reading from r.
func NewReader(r io.Reader, password string) (*Reader, error) {
	fbr, err := newFileBlockReader(r, password)
	if err != nil {
		return nil, err
	}
	rr := new(Reader)
	rr.init(fbr)
	return rr, nil
}

type ReadCloser struct {
	v *volume
	Reader
}

// Close closes the rar file.
func (rc *ReadCloser) Close() error {
	return rc.v.Close()
}

// OpenReader opens a RAR archive specified by the name and returns a ReadCloser.
func OpenReader(name, password string) (*ReadCloser, error) {
	v, err := openVolume(name, password)
	if err != nil {
		return nil, err
	}
	rc := new(ReadCloser)
	rc.v = v
	rc.Reader.init(v)
	return rc, nil
}
<|endoftext|>


<commit_before>package cpio

import (
	"io"
	"io/ioutil"
)

// A Reader provides sequential access to the contents of a CPIO archive. A CPIO
// archive consists of a sequence of files. The Next method advances to the next
// file in the archive (including the first), and then it can be treated as an
// io.Reader to access the file's data.
type Reader struct {
	r   io.Reader // underlying file reader
	hdr *Header   // current Header
	eof int64     // bytes until the end of the current file
}

// NewReader creates a new Reader reading from r.
func NewReader(r io.Reader) *Reader {
	return &Reader{
		r: r,
	}
}

// Read reads from the current entry in the CPIO archive. It returns 0, io.EOF
// when it reaches the end of that entry, until Next is called to advance to the
// next entry.
func (r *Reader) Read(p []byte) (n int, err error) {
	if r.hdr == nil || r.eof == 0 {
		return 0, io.EOF
	}

	rn := len(p)
	if r.eof < int64(rn) {
		rn = int(r.eof)
	}

	n, err = r.r.Read(p[0:rn])
	r.eof -= int64(n)
	return
}

// Next advances to the next entry in the CPIO archive.
// io.EOF is returned at the end of the input.
func (r *Reader) Next() (*Header, error) {
	if r.hdr == nil {
		return r.next()
	}

	// skip ahead
	// TODO: padding is version specific. Should be determined from header
	skp := r.eof + r.hdr.pad
	if skp > 0 {
		_, err := io.CopyN(ioutil.Discard, r.r, skp)
		if err != nil {
			return nil, err
		}
	}

	return r.next()
}

func (r *Reader) next() (*Header, error) {
	var err error
	r.eof = 0
	r.hdr, err = readHeader(r.r)
	if err == nil {
		r.eof = r.hdr.Size
	}
	return r.hdr, err
}
<commit_msg>Fixed bad hdr state on failed reader<commit_after>package cpio

import (
	"io"
	"io/ioutil"
)

// A Reader provides sequential access to the contents of a CPIO archive. A CPIO
// archive consists of a sequence of files. The Next method advances to the next
// file in the archive (including the first), and then it can be treated as an
// io.Reader to access the file's data.
type Reader struct {
	r   io.Reader // underlying file reader
	hdr *Header   // current Header
	eof int64     // bytes until the end of the current file
}

// NewReader creates a new Reader reading from r.
func NewReader(r io.Reader) *Reader {
	return &Reader{
		r: r,
	}
}

// Read reads from the current entry in the CPIO archive. It returns 0, io.EOF
// when it reaches the end of that entry, until Next is called to advance to the
// next entry.
func (r *Reader) Read(p []byte) (n int, err error) {
	if r.hdr == nil || r.eof == 0 {
		return 0, io.EOF
	}
	rn := len(p)
	if r.eof < int64(rn) {
		rn = int(r.eof)
	}
	n, err = r.r.Read(p[0:rn])
	r.eof -= int64(n)
	return
}

// Next advances to the next entry in the CPIO archive.
// io.EOF is returned at the end of the input.
func (r *Reader) Next() (*Header, error) {
	if r.hdr == nil {
		return r.next()
	}
	skp := r.eof + r.hdr.pad
	if skp > 0 {
		_, err := io.CopyN(ioutil.Discard, r.r, skp)
		if err != nil {
			return nil, err
		}
	}
	return r.next()
}

func (r *Reader) next() (*Header, error) {
	r.eof = 0
	hdr, err := readHeader(r.r)
	if err != nil {
		return nil, err
	}
	r.hdr = hdr
	r.eof = r.hdr.Size
	return hdr, nil
}
<|endoftext|>


<commit_before>package shp

import (
	"encoding/binary"
	"log"
	"math"
	"os"
	"strings"
)

// Reader provides a interface for reading Shapefiles. Calls
// to the Next method will iterate through the objects in the
// Shapefile. After a call to Next the object will be available
// through the Shape method.
type Reader struct {
	GeometryType ShapeType
	bbox         Box

	shp        *os.File
	shape      Shape
	num        int32
	filename   string
	filelength int64

	dbf             *os.File
	dbfFields       []Field
	dbfNumRecords   int32
	dbfHeaderLength int16
	dbfRecordLength int16
}

// Open opens a Shapefile for reading.
func Open(filename string) (*Reader, error) {
	filename = filename[0 : len(filename)-3]
	shp, err := os.Open(filename + "shp")
	if err != nil {
		return nil, err
	}
	s := &Reader{filename: filename, shp: shp}
	s.readHeaders()
	return s, nil
}

func (r *Reader) BBox() Box {
	return r.bbox
}

// Read and parse headers in the Shapefile. This will
// fill out GeometryType, filelength and bbox.
func (r *Reader) readHeaders() {
	// don't trust the the filelength in the header
	r.filelength, _ = r.shp.Seek(0, os.SEEK_END)

	var filelength int32
	r.shp.Seek(24, 0)
	// file length
	binary.Read(r.shp, binary.BigEndian, &filelength)
	r.shp.Seek(32, 0)
	binary.Read(r.shp, binary.LittleEndian, &r.GeometryType)
	r.bbox.MinX = r.readFloat64()
	r.bbox.MinY = r.readFloat64()
	r.bbox.MaxX = r.readFloat64()
	r.bbox.MaxY = r.readFloat64()
	r.shp.Seek(100, 0)
}

func (r *Reader) readFloat64() float64 {
	var bits uint64
	binary.Read(r.shp, binary.LittleEndian, &bits)
	return math.Float64frombits(bits)
}

// Close closes the Shapefile.
func (r *Reader) Close() error {
	err := r.shp.Close()
	if r.dbf != nil {
		r.dbf.Close()
	}
	return err
}

// Shape returns the most recent feature that was read by
// a call to Next. It returns two values, the int is the
// object index starting from zero in the shapefile which
// can be used as row in ReadAttribute, and the Shape is the object.
func (r *Reader) Shape() (int, Shape) {
	return int(r.num) - 1, r.shape
}

// Next reads in the next Shape in the Shapefile, which
// will then be available through the Shape method. It
// returns false when the reader has reached the end of the
// file.
func (r *Reader) Next() bool {
	cur, _ := r.shp.Seek(0, os.SEEK_CUR)
	if cur >= r.filelength {
		return false
	}

	var size int32
	var shapetype ShapeType
	binary.Read(r.shp, binary.BigEndian, &r.num)
	binary.Read(r.shp, binary.BigEndian, &size)
	binary.Read(r.shp, binary.LittleEndian, &shapetype)

	switch shapetype {
	case NULL:
		r.shape = new(Null)
	case POINT:
		r.shape = new(Point)
	case POLYLINE:
		r.shape = new(PolyLine)
	case POLYGON:
		r.shape = new(Polygon)
	case MULTIPOINT:
		r.shape = new(MultiPoint)
	case POINTZ:
		r.shape = new(PointZ)
	case POLYLINEZ:
		r.shape = new(PolyLineZ)
	case POLYGONZ:
		r.shape = new(PolygonZ)
	case MULTIPOINTZ:
		r.shape = new(MultiPointZ)
	case POINTM:
		r.shape = new(PointM)
	case POLYLINEM:
		r.shape = new(PolyLineM)
	case POLYGONM:
		r.shape = new(PolygonM)
	case MULTIPOINTM:
		r.shape = new(MultiPointM)
	case MULTIPATCH:
		r.shape = new(MultiPatch)
	default:
		log.Fatal("Unsupported shape type:", shapetype)
	}
	r.shape.read(r.shp)

	// move to next object
	r.shp.Seek(int64(size)*2+cur+8, 0)
	return true
}

// Opens DBF file using r.filename + "dbf". This method
// will parse the header and fill out all dbf* values int
// the f object.
func (r *Reader) openDbf() (err error) {
	if r.dbf != nil {
		return
	}

	r.dbf, err = os.Open(r.filename + "dbf")
	if err != nil {
		return
	}

	// read header
	r.dbf.Seek(4, os.SEEK_SET)
	binary.Read(r.dbf, binary.LittleEndian, &r.dbfNumRecords)
	binary.Read(r.dbf, binary.LittleEndian, &r.dbfHeaderLength)
	binary.Read(r.dbf, binary.LittleEndian, &r.dbfRecordLength)

	r.dbf.Seek(20, os.SEEK_CUR) // skip padding
	numFields := int(math.Floor(float64(r.dbfHeaderLength-33) / 32.0))
	r.dbfFields = make([]Field, numFields)
	binary.Read(r.dbf, binary.LittleEndian, &r.dbfFields)

	return
}

// Fields returns a slice of Fields that are present in the
// DBF table.
func (r *Reader) Fields() []Field {
	r.openDbf() // make sure we have dbf file to read from
	return r.dbfFields
}

// AttributeCount returns number of records in the DBF table.
func (r *Reader) AttributeCount() int {
	r.openDbf() // make sure we have a dbf file to read from
	return int(r.dbfNumRecords)
}

// ReadAttribute returns the attribute value at row for field in
// the DBF table as a string. Both values starts at 0.
func (r *Reader) ReadAttribute(row int, field int) string {
	r.openDbf() // make sure we have a dbf file to read from
	seekTo := 1 + int64(r.dbfHeaderLength) + (int64(row) * int64(r.dbfRecordLength))
	for n := 0; n < field; n++ {
		seekTo += int64(r.dbfFields[n].Size)
	}
	r.dbf.Seek(seekTo, os.SEEK_SET)
	buf := make([]byte, r.dbfFields[field].Size)
	r.dbf.Read(buf)
	return strings.Trim(string(buf[:]), " ")
}
<commit_msg>refactored unexported Reader.readFloat method into a more generic function<commit_after>package shp

import (
	"encoding/binary"
	"io"
	"log"
	"math"
	"os"
	"strings"
)

// Reader provides a interface for reading Shapefiles. Calls
// to the Next method will iterate through the objects in the
// Shapefile. After a call to Next the object will be available
// through the Shape method.
type Reader struct {
	GeometryType ShapeType
	bbox         Box

	shp        *os.File
	shape      Shape
	num        int32
	filename   string
	filelength int64

	dbf             *os.File
	dbfFields       []Field
	dbfNumRecords   int32
	dbfHeaderLength int16
	dbfRecordLength int16
}

// Open opens a Shapefile for reading.
func Open(filename string) (*Reader, error) {
	filename = filename[0 : len(filename)-3]
	shp, err := os.Open(filename + "shp")
	if err != nil {
		return nil, err
	}
	s := &Reader{filename: filename, shp: shp}
	s.readHeaders()
	return s, nil
}

func (r *Reader) BBox() Box {
	return r.bbox
}

// Read and parse headers in the Shapefile. This will
// fill out GeometryType, filelength and bbox.
func (r *Reader) readHeaders() {
	// don't trust the the filelength in the header
	r.filelength, _ = r.shp.Seek(0, os.SEEK_END)

	var filelength int32
	r.shp.Seek(24, 0)
	// file length
	binary.Read(r.shp, binary.BigEndian, &filelength)
	r.shp.Seek(32, 0)
	binary.Read(r.shp, binary.LittleEndian, &r.GeometryType)
	r.bbox.MinX = readFloat64(r.shp)
	r.bbox.MinY = readFloat64(r.shp)
	r.bbox.MaxX = readFloat64(r.shp)
	r.bbox.MaxY = readFloat64(r.shp)
	r.shp.Seek(100, 0)
}

func readFloat64(r io.Reader) float64 {
	var bits uint64
	binary.Read(r, binary.LittleEndian, &bits)
	return math.Float64frombits(bits)
}

// Close closes the Shapefile.
func (r *Reader) Close() error {
	err := r.shp.Close()
	if r.dbf != nil {
		r.dbf.Close()
	}
	return err
}

// Shape returns the most recent feature that was read by
// a call to Next. It returns two values, the int is the
// object index starting from zero in the shapefile which
// can be used as row in ReadAttribute, and the Shape is the object.
func (r *Reader) Shape() (int, Shape) {
	return int(r.num) - 1, r.shape
}

// Next reads in the next Shape in the Shapefile, which
// will then be available through the Shape method. It
// returns false when the reader has reached the end of the
// file.
func (r *Reader) Next() bool {
	cur, _ := r.shp.Seek(0, os.SEEK_CUR)
	if cur >= r.filelength {
		return false
	}

	var size int32
	var shapetype ShapeType
	binary.Read(r.shp, binary.BigEndian, &r.num)
	binary.Read(r.shp, binary.BigEndian, &size)
	binary.Read(r.shp, binary.LittleEndian, &shapetype)

	switch shapetype {
	case NULL:
		r.shape = new(Null)
	case POINT:
		r.shape = new(Point)
	case POLYLINE:
		r.shape = new(PolyLine)
	case POLYGON:
		r.shape = new(Polygon)
	case MULTIPOINT:
		r.shape = new(MultiPoint)
	case POINTZ:
		r.shape = new(PointZ)
	case POLYLINEZ:
		r.shape = new(PolyLineZ)
	case POLYGONZ:
		r.shape = new(PolygonZ)
	case MULTIPOINTZ:
		r.shape = new(MultiPointZ)
	case POINTM:
		r.shape = new(PointM)
	case POLYLINEM:
		r.shape = new(PolyLineM)
	case POLYGONM:
		r.shape = new(PolygonM)
	case MULTIPOINTM:
		r.shape = new(MultiPointM)
	case MULTIPATCH:
		r.shape = new(MultiPatch)
	default:
		log.Fatal("Unsupported shape type:", shapetype)
	}
	r.shape.read(r.shp)

	// move to next object
	r.shp.Seek(int64(size)*2+cur+8, 0)
	return true
}

// Opens DBF file using r.filename + "dbf". This method
// will parse the header and fill out all dbf* values int
// the f object.
func (r *Reader) openDbf() (err error) {
	if r.dbf != nil {
		return
	}

	r.dbf, err = os.Open(r.filename + "dbf")
	if err != nil {
		return
	}

	// read header
	r.dbf.Seek(4, os.SEEK_SET)
	binary.Read(r.dbf, binary.LittleEndian, &r.dbfNumRecords)
	binary.Read(r.dbf, binary.LittleEndian, &r.dbfHeaderLength)
	binary.Read(r.dbf, binary.LittleEndian, &r.dbfRecordLength)

	r.dbf.Seek(20, os.SEEK_CUR) // skip padding
	numFields := int(math.Floor(float64(r.dbfHeaderLength-33) / 32.0))
	r.dbfFields = make([]Field, numFields)
	binary.Read(r.dbf, binary.LittleEndian, &r.dbfFields)

	return
}

// Fields returns a slice of Fields that are present in the
// DBF table.
func (r *Reader) Fields() []Field {
	r.openDbf() // make sure we have dbf file to read from
	return r.dbfFields
}

// AttributeCount returns number of records in the DBF table.
func (r *Reader) AttributeCount() int {
	r.openDbf() // make sure we have a dbf file to read from
	return int(r.dbfNumRecords)
}

// ReadAttribute returns the attribute value at row for field in
// the DBF table as a string. Both values starts at 0.
func (r *Reader) ReadAttribute(row int, field int) string {
	r.openDbf() // make sure we have a dbf file to read from
	seekTo := 1 + int64(r.dbfHeaderLength) + (int64(row) * int64(r.dbfRecordLength))
	for n := 0; n < field; n++ {
		seekTo += int64(r.dbfFields[n].Size)
	}
	r.dbf.Seek(seekTo, os.SEEK_SET)
	buf := make([]byte, r.dbfFields[field].Size)
	r.dbf.Read(buf)
	return strings.Trim(string(buf[:]), " ")
}
<|endoftext|>