<commit_before>package sqlite

/*
#include <sqlite3.h>
#include <stdlib.h>
#include <string.h>

#ifndef SQLITE_OPEN_READWRITE
# define SQLITE_OPEN_READWRITE 0
#endif

#ifndef SQLITE_OPEN_FULLMUTEX
# define SQLITE_OPEN_FULLMUTEX 0
#endif

static int
_sqlite3_open_v2(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs) {
#ifdef SQLITE_OPEN_URI
  return sqlite3_open_v2(filename, ppDb, flags | SQLITE_OPEN_URI, zVfs);
#else
  return sqlite3_open_v2(filename, ppDb, flags, zVfs);
#endif
}

static int
_sqlite3_bind_text(sqlite3_stmt *stmt, int n, char *p, int np) {
  return sqlite3_bind_text(stmt, n, p, np, SQLITE_TRANSIENT);
}

static int
_sqlite3_bind_blob(sqlite3_stmt *stmt, int n, void *p, int np) {
  return sqlite3_bind_blob(stmt, n, p, np, SQLITE_TRANSIENT);
}

#include <stdio.h>
#include <stdint.h>

static long
_sqlite3_last_insert_rowid(sqlite3* db) {
  return (long) sqlite3_last_insert_rowid(db);
}

static long
_sqlite3_changes(sqlite3* db) {
  return (long) sqlite3_changes(db);
}

*/
import "C"
import (
	"database/sql"
	"database/sql/driver"
	"errors"
	"io"
	"strings"
	"time"
	"unsafe"
)

// Timestamp formats understood by both this module and SQLite.
// The first format in the slice will be used when saving time values
// into the database. When parsing a string from a timestamp or
// datetime column, the formats are tried in order.
var SQLiteTimestampFormats = []string{
	"2006-01-02 15:04:05.999999999",
	"2006-01-02T15:04:05.999999999",
	"2006-01-02 15:04:05",
	"2006-01-02T15:04:05",
	"2006-01-02 15:04",
	"2006-01-02T15:04",
	"2006-01-02",
}

func init() {
	sql.Register("sqlite3", &SQLiteDriver{})
}

// Driver struct.
type SQLiteDriver struct {
}

// Conn struct.
type SQLiteConn struct {
	db *C.sqlite3
}

// Tx struct.
type SQLiteTx struct {
	c *SQLiteConn
}

// Stmt struct.
type SQLiteStmt struct {
	c      *SQLiteConn
	s      *C.sqlite3_stmt
	t      string
	closed bool
}

// Result struct.
type SQLiteResult struct {
	s *SQLiteStmt
}

// Rows struct.
type SQLiteRows struct {
	s        *SQLiteStmt
	nc       int
	cols     []string
	decltype []string
}

// Commit transaction.
func (tx *SQLiteTx) Commit() error {
	if err := tx.c.exec("COMMIT"); err != nil {
		return err
	}
	return nil
}

// Rollback transaction.
func (tx *SQLiteTx) Rollback() error {
	if err := tx.c.exec("ROLLBACK"); err != nil {
		return err
	}
	return nil
}

func (c *SQLiteConn) exec(cmd string) error {
	pcmd := C.CString(cmd)
	defer C.free(unsafe.Pointer(pcmd))
	rv := C.sqlite3_exec(c.db, pcmd, nil, nil, nil)
	if rv != C.SQLITE_OK {
		return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
	}
	return nil
}

// Begin transaction.
func (c *SQLiteConn) Begin() (driver.Tx, error) {
	if err := c.exec("BEGIN"); err != nil {
		return nil, err
	}
	return &SQLiteTx{c}, nil
}

// Open database and return a new connection.
// You can specify DSN string with URI filename.
//   test.db
//   file:test.db?cache=shared&mode=memory
//   :memory:
//   file::memory:
func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
	if C.sqlite3_threadsafe() == 0 {
		return nil, errors.New("sqlite library was not compiled for thread-safe operation")
	}

	var db *C.sqlite3
	name := C.CString(dsn)
	defer C.free(unsafe.Pointer(name))
	rv := C._sqlite3_open_v2(name, &db,
		C.SQLITE_OPEN_FULLMUTEX|
			C.SQLITE_OPEN_READWRITE|
			C.SQLITE_OPEN_CREATE,
		nil)
	if rv != 0 {
		return nil, errors.New(C.GoString(C.sqlite3_errmsg(db)))
	}
	if db == nil {
		return nil, errors.New("sqlite succeeded without returning a database")
	}

	rv = C.sqlite3_busy_timeout(db, 5000)
	if rv != C.SQLITE_OK {
		return nil, errors.New(C.GoString(C.sqlite3_errmsg(db)))
	}

	return &SQLiteConn{db}, nil
}

// Close the connection.
func (c *SQLiteConn) Close() error {
	s := C.sqlite3_next_stmt(c.db, nil)
	for s != nil {
		C.sqlite3_finalize(s)
		s = C.sqlite3_next_stmt(c.db, nil)
	}
	rv := C.sqlite3_close(c.db)
	if rv != C.SQLITE_OK {
		return errors.New("error while closing sqlite database connection")
	}
	c.db = nil
	return nil
}

// Prepare query string. Return a new statement.
func (c *SQLiteConn) Prepare(query string) (driver.Stmt, error) {
	pquery := C.CString(query)
	defer C.free(unsafe.Pointer(pquery))
	var s *C.sqlite3_stmt
	var perror *C.char
	rv := C.sqlite3_prepare_v2(c.db, pquery, -1, &s, &perror)
	if rv != C.SQLITE_OK {
		return nil, errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
	}
	var t string
	if perror != nil && C.strlen(perror) > 0 {
		t = C.GoString(perror)
	}
	return &SQLiteStmt{c: c, s: s, t: t}, nil
}

// Close the statement.
func (s *SQLiteStmt) Close() error {
	if s.closed {
		return nil
	}
	s.closed = true
	if s.c == nil || s.c.db == nil {
		return errors.New("sqlite statement with already closed database connection")
	}
	rv := C.sqlite3_finalize(s.s)
	if rv != C.SQLITE_OK {
		return errors.New(C.GoString(C.sqlite3_errmsg(s.c.db)))
	}
	return nil
}

// Return a number of parameters.
func (s *SQLiteStmt) NumInput() int {
	return int(C.sqlite3_bind_parameter_count(s.s))
}

func (s *SQLiteStmt) bind(args []driver.Value) error {
	rv := C.sqlite3_reset(s.s)
	if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
		return errors.New(C.GoString(C.sqlite3_errmsg(s.c.db)))
	}

	for i, v := range args {
		n := C.int(i + 1)
		switch v := v.(type) {
		case nil:
			rv = C.sqlite3_bind_null(s.s, n)
		case string:
			if len(v) == 0 {
				b := []byte{0}
				rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(0))
			} else {
				b := []byte(v)
				rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b)))
			}
		case int:
			rv = C.sqlite3_bind_int(s.s, n, C.int(v))
		case int64:
			rv = C.sqlite3_bind_int64(s.s, n, C.sqlite3_int64(v))
		case byte:
			rv = C.sqlite3_bind_int(s.s, n, C.int(v))
		case bool:
			if bool(v) {
				rv = C.sqlite3_bind_int(s.s, n, 1)
			} else {
				rv = C.sqlite3_bind_int(s.s, n, 0)
			}
		case float32:
			rv = C.sqlite3_bind_double(s.s, n, C.double(v))
		case float64:
			rv = C.sqlite3_bind_double(s.s, n, C.double(v))
		case []byte:
			var p *byte
			if len(v) > 0 {
				p = &v[0]
			}
			rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(p), C.int(len(v)))
		case time.Time:
			b := []byte(v.UTC().Format(SQLiteTimestampFormats[0]))
			rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b)))
		}
		if rv != C.SQLITE_OK {
			return errors.New(C.GoString(C.sqlite3_errmsg(s.c.db)))
		}
	}
	return nil
}

// Query the statment with arguments. Return records.
func (s *SQLiteStmt) Query(args []driver.Value) (driver.Rows, error) {
	if err := s.bind(args); err != nil {
		return nil, err
	}
	return &SQLiteRows{s, int(C.sqlite3_column_count(s.s)), nil, nil}, nil
}

// Return last inserted ID.
func (r *SQLiteResult) LastInsertId() (int64, error) {
	return int64(C._sqlite3_last_insert_rowid(r.s.c.db)), nil
}

// Return how many rows affected.
func (r *SQLiteResult) RowsAffected() (int64, error) {
	return int64(C._sqlite3_changes(r.s.c.db)), nil
}

// Execute the statement with arguments. Return result object.
func (s *SQLiteStmt) Exec(args []driver.Value) (driver.Result, error) {
	if err := s.bind(args); err != nil {
		return nil, err
	}
	rv := C.sqlite3_step(s.s)
	if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
		return nil, errors.New(C.GoString(C.sqlite3_errmsg(s.c.db)))
	}
	return &SQLiteResult{s}, nil
}

// Close the rows.
func (rc *SQLiteRows) Close() error {
	rv := C.sqlite3_reset(rc.s.s)
	if rv != C.SQLITE_OK {
		return errors.New(C.GoString(C.sqlite3_errmsg(rc.s.c.db)))
	}
	return nil
}

// Return column names.
func (rc *SQLiteRows) Columns() []string {
	if rc.nc != len(rc.cols) {
		rc.cols = make([]string, rc.nc)
		for i := 0; i < rc.nc; i++ {
			rc.cols[i] = C.GoString(C.sqlite3_column_name(rc.s.s, C.int(i)))
		}
	}
	return rc.cols
}

// Move cursor to next.
func (rc *SQLiteRows) Next(dest []driver.Value) error {
	rv := C.sqlite3_step(rc.s.s)
	if rv == C.SQLITE_DONE {
		return io.EOF
	}
	if rv != C.SQLITE_ROW {
		return errors.New(C.GoString(C.sqlite3_errmsg(rc.s.c.db)))
	}

	if rc.decltype == nil {
		rc.decltype = make([]string, rc.nc)
		for i := 0; i < rc.nc; i++ {
			rc.decltype[i] = strings.ToLower(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i))))
		}
	}

	for i := range dest {
		switch C.sqlite3_column_type(rc.s.s, C.int(i)) {
		case C.SQLITE_INTEGER:
			val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i)))
			switch rc.decltype[i] {
			case "timestamp", "datetime":
				dest[i] = time.Unix(val, 0)
			case "boolean":
				dest[i] = val > 0
			default:
				dest[i] = val
			}
		case C.SQLITE_FLOAT:
			dest[i] = float64(C.sqlite3_column_double(rc.s.s, C.int(i)))
		case C.SQLITE_BLOB:
			n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i)))
			p := C.sqlite3_column_blob(rc.s.s, C.int(i))
			switch dest[i].(type) {
			case sql.RawBytes:
				dest[i] = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n]
			default:
				slice := make([]byte, n)
				copy(slice[:], (*[1 << 30]byte)(unsafe.Pointer(p))[0:n])
				dest[i] = slice
			}
		case C.SQLITE_NULL:
			dest[i] = nil
		case C.SQLITE_TEXT:
			var err error
			s := C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i)))))

			switch rc.decltype[i] {
			case "timestamp", "datetime":
				for _, format := range SQLiteTimestampFormats {
					if dest[i], err = time.Parse(format, s); err == nil {
						break
					}
				}
				if err != nil {
					// The column is a time value, so return the zero time on parse failure.
					dest[i] = time.Time{}
				}
			default:
				dest[i] = s
			}

		}
	}
	return nil
}
<commit_msg>Add int32 type, close #55<commit_after>package sqlite

/*
#include <sqlite3.h>
#include <stdlib.h>
#include <string.h>

#ifndef SQLITE_OPEN_READWRITE
# define SQLITE_OPEN_READWRITE 0
#endif

#ifndef SQLITE_OPEN_FULLMUTEX
# define SQLITE_OPEN_FULLMUTEX 0
#endif

static int
_sqlite3_open_v2(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs) {
#ifdef SQLITE_OPEN_URI
  return sqlite3_open_v2(filename, ppDb, flags | SQLITE_OPEN_URI, zVfs);
#else
  return sqlite3_open_v2(filename, ppDb, flags, zVfs);
#endif
}

static int
_sqlite3_bind_text(sqlite3_stmt *stmt, int n, char *p, int np) {
  return sqlite3_bind_text(stmt, n, p, np, SQLITE_TRANSIENT);
}

static int
_sqlite3_bind_blob(sqlite3_stmt *stmt, int n, void *p, int np) {
  return sqlite3_bind_blob(stmt, n, p, np, SQLITE_TRANSIENT);
}

#include <stdio.h>
#include <stdint.h>

static long
_sqlite3_last_insert_rowid(sqlite3* db) {
  return (long) sqlite3_last_insert_rowid(db);
}

static long
_sqlite3_changes(sqlite3* db) {
  return (long) sqlite3_changes(db);
}

*/
import "C"
import (
	"database/sql"
	"database/sql/driver"
	"errors"
	"io"
	"strings"
	"time"
	"unsafe"
)

// Timestamp formats understood by both this module and SQLite.
// The first format in the slice will be used when saving time values
// into the database. When parsing a string from a timestamp or
// datetime column, the formats are tried in order.
var SQLiteTimestampFormats = []string{
	"2006-01-02 15:04:05.999999999",
	"2006-01-02T15:04:05.999999999",
	"2006-01-02 15:04:05",
	"2006-01-02T15:04:05",
	"2006-01-02 15:04",
	"2006-01-02T15:04",
	"2006-01-02",
}

func init() {
	sql.Register("sqlite3", &SQLiteDriver{})
}

// Driver struct.
type SQLiteDriver struct {
}

// Conn struct.
type SQLiteConn struct {
	db *C.sqlite3
}

// Tx struct.
type SQLiteTx struct {
	c *SQLiteConn
}

// Stmt struct.
type SQLiteStmt struct {
	c      *SQLiteConn
	s      *C.sqlite3_stmt
	t      string
	closed bool
}

// Result struct.
type SQLiteResult struct {
	s *SQLiteStmt
}

// Rows struct.
type SQLiteRows struct {
	s        *SQLiteStmt
	nc       int
	cols     []string
	decltype []string
}

// Commit transaction.
func (tx *SQLiteTx) Commit() error {
	if err := tx.c.exec("COMMIT"); err != nil {
		return err
	}
	return nil
}

// Rollback transaction.
func (tx *SQLiteTx) Rollback() error {
	if err := tx.c.exec("ROLLBACK"); err != nil {
		return err
	}
	return nil
}

func (c *SQLiteConn) exec(cmd string) error {
	pcmd := C.CString(cmd)
	defer C.free(unsafe.Pointer(pcmd))
	rv := C.sqlite3_exec(c.db, pcmd, nil, nil, nil)
	if rv != C.SQLITE_OK {
		return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
	}
	return nil
}

// Begin transaction.
func (c *SQLiteConn) Begin() (driver.Tx, error) {
	if err := c.exec("BEGIN"); err != nil {
		return nil, err
	}
	return &SQLiteTx{c}, nil
}

// Open database and return a new connection.
// You can specify DSN string with URI filename.
//   test.db
//   file:test.db?cache=shared&mode=memory
//   :memory:
//   file::memory:
func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
	if C.sqlite3_threadsafe() == 0 {
		return nil, errors.New("sqlite library was not compiled for thread-safe operation")
	}

	var db *C.sqlite3
	name := C.CString(dsn)
	defer C.free(unsafe.Pointer(name))
	rv := C._sqlite3_open_v2(name, &db,
		C.SQLITE_OPEN_FULLMUTEX|
			C.SQLITE_OPEN_READWRITE|
			C.SQLITE_OPEN_CREATE,
		nil)
	if rv != 0 {
		return nil, errors.New(C.GoString(C.sqlite3_errmsg(db)))
	}
	if db == nil {
		return nil, errors.New("sqlite succeeded without returning a database")
	}

	rv = C.sqlite3_busy_timeout(db, 5000)
	if rv != C.SQLITE_OK {
		return nil, errors.New(C.GoString(C.sqlite3_errmsg(db)))
	}

	return &SQLiteConn{db}, nil
}

// Close the connection.
func (c *SQLiteConn) Close() error {
	s := C.sqlite3_next_stmt(c.db, nil)
	for s != nil {
		C.sqlite3_finalize(s)
		s = C.sqlite3_next_stmt(c.db, nil)
	}
	rv := C.sqlite3_close(c.db)
	if rv != C.SQLITE_OK {
		return errors.New("error while closing sqlite database connection")
	}
	c.db = nil
	return nil
}

// Prepare query string. Return a new statement.
func (c *SQLiteConn) Prepare(query string) (driver.Stmt, error) {
	pquery := C.CString(query)
	defer C.free(unsafe.Pointer(pquery))
	var s *C.sqlite3_stmt
	var perror *C.char
	rv := C.sqlite3_prepare_v2(c.db, pquery, -1, &s, &perror)
	if rv != C.SQLITE_OK {
		return nil, errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
	}
	var t string
	if perror != nil && C.strlen(perror) > 0 {
		t = C.GoString(perror)
	}
	return &SQLiteStmt{c: c, s: s, t: t}, nil
}

// Close the statement.
func (s *SQLiteStmt) Close() error {
	if s.closed {
		return nil
	}
	s.closed = true
	if s.c == nil || s.c.db == nil {
		return errors.New("sqlite statement with already closed database connection")
	}
	rv := C.sqlite3_finalize(s.s)
	if rv != C.SQLITE_OK {
		return errors.New(C.GoString(C.sqlite3_errmsg(s.c.db)))
	}
	return nil
}

// Return a number of parameters.
func (s *SQLiteStmt) NumInput() int {
	return int(C.sqlite3_bind_parameter_count(s.s))
}

func (s *SQLiteStmt) bind(args []driver.Value) error {
	rv := C.sqlite3_reset(s.s)
	if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
		return errors.New(C.GoString(C.sqlite3_errmsg(s.c.db)))
	}

	for i, v := range args {
		n := C.int(i + 1)
		switch v := v.(type) {
		case nil:
			rv = C.sqlite3_bind_null(s.s, n)
		case string:
			if len(v) == 0 {
				b := []byte{0}
				rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(0))
			} else {
				b := []byte(v)
				rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b)))
			}
		case int:
			rv = C.sqlite3_bind_int(s.s, n, C.int(v))
		case int32:
			rv = C.sqlite3_bind_int(s.s, n, C.int(v))
		case int64:
			rv = C.sqlite3_bind_int64(s.s, n, C.sqlite3_int64(v))
		case byte:
			rv = C.sqlite3_bind_int(s.s, n, C.int(v))
		case bool:
			if bool(v) {
				rv = C.sqlite3_bind_int(s.s, n, 1)
			} else {
				rv = C.sqlite3_bind_int(s.s, n, 0)
			}
		case float32:
			rv = C.sqlite3_bind_double(s.s, n, C.double(v))
		case float64:
			rv = C.sqlite3_bind_double(s.s, n, C.double(v))
		case []byte:
			var p *byte
			if len(v) > 0 {
				p = &v[0]
			}
			rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(p), C.int(len(v)))
		case time.Time:
			b := []byte(v.UTC().Format(SQLiteTimestampFormats[0]))
			rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b)))
		}
		if rv != C.SQLITE_OK {
			return errors.New(C.GoString(C.sqlite3_errmsg(s.c.db)))
		}
	}
	return nil
}

// Query the statment with arguments. Return records.
func (s *SQLiteStmt) Query(args []driver.Value) (driver.Rows, error) {
	if err := s.bind(args); err != nil {
		return nil, err
	}
	return &SQLiteRows{s, int(C.sqlite3_column_count(s.s)), nil, nil}, nil
}

// Return last inserted ID.
func (r *SQLiteResult) LastInsertId() (int64, error) {
	return int64(C._sqlite3_last_insert_rowid(r.s.c.db)), nil
}

// Return how many rows affected.
func (r *SQLiteResult) RowsAffected() (int64, error) {
	return int64(C._sqlite3_changes(r.s.c.db)), nil
}

// Execute the statement with arguments. Return result object.
func (s *SQLiteStmt) Exec(args []driver.Value) (driver.Result, error) {
	if err := s.bind(args); err != nil {
		return nil, err
	}
	rv := C.sqlite3_step(s.s)
	if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
		return nil, errors.New(C.GoString(C.sqlite3_errmsg(s.c.db)))
	}
	return &SQLiteResult{s}, nil
}

// Close the rows.
func (rc *SQLiteRows) Close() error {
	rv := C.sqlite3_reset(rc.s.s)
	if rv != C.SQLITE_OK {
		return errors.New(C.GoString(C.sqlite3_errmsg(rc.s.c.db)))
	}
	return nil
}

// Return column names.
func (rc *SQLiteRows) Columns() []string {
	if rc.nc != len(rc.cols) {
		rc.cols = make([]string, rc.nc)
		for i := 0; i < rc.nc; i++ {
			rc.cols[i] = C.GoString(C.sqlite3_column_name(rc.s.s, C.int(i)))
		}
	}
	return rc.cols
}

// Move cursor to next.
func (rc *SQLiteRows) Next(dest []driver.Value) error {
	rv := C.sqlite3_step(rc.s.s)
	if rv == C.SQLITE_DONE {
		return io.EOF
	}
	if rv != C.SQLITE_ROW {
		return errors.New(C.GoString(C.sqlite3_errmsg(rc.s.c.db)))
	}

	if rc.decltype == nil {
		rc.decltype = make([]string, rc.nc)
		for i := 0; i < rc.nc; i++ {
			rc.decltype[i] = strings.ToLower(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i))))
		}
	}

	for i := range dest {
		switch C.sqlite3_column_type(rc.s.s, C.int(i)) {
		case C.SQLITE_INTEGER:
			val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i)))
			switch rc.decltype[i] {
			case "timestamp", "datetime":
				dest[i] = time.Unix(val, 0)
			case "boolean":
				dest[i] = val > 0
			default:
				dest[i] = val
			}
		case C.SQLITE_FLOAT:
			dest[i] = float64(C.sqlite3_column_double(rc.s.s, C.int(i)))
		case C.SQLITE_BLOB:
			n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i)))
			p := C.sqlite3_column_blob(rc.s.s, C.int(i))
			switch dest[i].(type) {
			case sql.RawBytes:
				dest[i] = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n]
			default:
				slice := make([]byte, n)
				copy(slice[:], (*[1 << 30]byte)(unsafe.Pointer(p))[0:n])
				dest[i] = slice
			}
		case C.SQLITE_NULL:
			dest[i] = nil
		case C.SQLITE_TEXT:
			var err error
			s := C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i)))))

			switch rc.decltype[i] {
			case "timestamp", "datetime":
				for _, format := range SQLiteTimestampFormats {
					if dest[i], err = time.Parse(format, s); err == nil {
						break
					}
				}
				if err != nil {
					// The column is a time value, so return the zero time on parse failure.
					dest[i] = time.Time{}
				}
			default:
				dest[i] = s
			}

		}
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import "fmt"

// Square ..
type Square struct {
	p         Point
	Cost      int64
	neighbors []*Square
}

//Neighbors .. .
func (v *Square) Neighbors() []*Square {
	return v.neighbors
}

func (v *Square) Equals(v1 *Square) bool {
	adj := v1
	return adj.p.X == v.p.X && adj.p.Y == v.p.Y
}

//CostToNeighbor ...
func (v *Square) CostToNeighbor(finding *Square) int64 {
	for _, adj := range v.Neighbors() {
		if adj == finding {
			return adj.Cost
		}
	}
	return -1
}

// BFS ...
func (v *Square) BFS(finding *Square) []*Square {
	// var cost = 0
	var Q = SquareQueue(make([]*Square, 0, 42*42))
	// var path = SquareQueue(make([]*Square, 0, 42*42))
	var D = make(map[*Square]bool)
	Q.add(v)
	D[v] = true

	for len(Q) > 0 {
		v := Q.get()
		if v == nil {
			break
		}
		for _, adj := range v.Neighbors() {
			if adj == nil {
				continue
			}
			if !D[adj] {
				if adj.Equals(finding) {
					return [](*Square){v, adj}
				}
				Q.add(adj)
				D[adj] = true
			}
		}
	}

	Q = nil
	return nil
}

func (v *Square) AStar(finding *Square) []*Square {
	var (
		closedSet = make(map[*Square]bool)
		openSet   = map[*Square]bool{v: true}
		cameFrom  = make(map[*Square]*Square)
		gScore    = map[*Square]int64{v: 0}
		fScore    = map[*Square]int64{v: (gScore[v] + v.CostToNeighbor(finding))}
	)

	for {

	}
	fmt.Println(closedSet, openSet, cameFrom, fScore)

	return nil
}

// function A*(start,goal)
//     closedset := the empty set    // The set of nodes already evaluated.
//     openset := {start}    // The set of tentative nodes to be evaluated, initially containing the start node
//     came_from := the empty map    // The map of navigated nodes.
//
//     g_score[start] := 0    // Cost from start along best known path.
//     // Estimated total cost from start to goal through y.
//     f_score[start] := g_score[start] + heuristic_cost_estimate(start, goal)
//
//     while openset is not empty
//         current := the node in openset having the lowest f_score[] value
//         if current = goal
//             return reconstruct_path(came_from, goal)
//
//         remove current from openset
//         add current to closedset
//         for each neighbor in neighbor_nodes(current)
//             if neighbor in closedset
//                 continue
//             tentative_g_score := g_score[current] + dist_between(current,neighbor)
//
//             if neighbor not in openset or tentative_g_score < g_score[neighbor]
//                 came_from[neighbor] := current
//                 g_score[neighbor] := tentative_g_score
//                 f_score[neighbor] := g_score[neighbor] + heuristic_cost_estimate(neighbor, goal)
//                 if neighbor not in openset
//                     add neighbor to openset
//
//     return failure
//
// function reconstruct_path(came_from,current)
//     total_path := [current]
//     while current in came_from:
//         current := came_from[current]
//         total_path.append(current)
//     return total_path
<commit_msg>Version incomplete of A*<commit_after>package main

import "fmt"

// Square ..
type Square struct {
	p         Point
	Cost      int64
	neighbors []*Square
}

//Neighbors .. .
func (v *Square) Neighbors() []*Square {
	return v.neighbors
}

func (v *Square) Equals(v1 *Square) bool {
	adj := v1
	return adj.p.X == v.p.X && adj.p.Y == v.p.Y
}

//CostToNeighbor ...
func (v *Square) CostToNeighbor(finding *Square) int64 {
	for _, adj := range v.Neighbors() {
		if adj == finding {
			return adj.Cost
		}
	}
	return -1
}

// BFS ...
func (v *Square) BFS(finding *Square) []*Square {
	// var cost = 0
	var Q = SquareQueue(make([]*Square, 0, 42*42))
	// var path = SquareQueue(make([]*Square, 0, 42*42))
	var D = make(map[*Square]bool)
	Q.add(v)
	D[v] = true

	for len(Q) > 0 {
		v := Q.get()
		if v == nil {
			break
		}
		for _, adj := range v.Neighbors() {
			if adj == nil {
				continue
			}
			if !D[adj] {
				if adj.Equals(finding) {
					return [](*Square){v, adj}
				}
				Q.add(adj)
				D[adj] = true
			}
		}
	}

	Q = nil
	return nil
}

func (v *Square) AStar(finding *Square) []*Square {
	var (
		closedSet = make(map[*Square]bool)
		openSet   = map[*Square]bool{v: true}
		cameFrom  = make(map[*Square]*Square)
		gScore    = map[*Square]int64{v: 0}
		fScore    = map[*Square]int64{v: (gScore[v] + v.CostToNeighbor(finding))}
	)

	for {

	}

	fmt.Println(closedSet, openSet, cameFrom, fScore)

	return nil
}

// function A*(start,goal)
//     closedset := the empty set    // The set of nodes already evaluated.
//     openset := {start}    // The set of tentative nodes to be evaluated, initially containing the start node
//     came_from := the empty map    // The map of navigated nodes.
//
//     g_score[start] := 0    // Cost from start along best known path.
//     // Estimated total cost from start to goal through y.
//     f_score[start] := g_score[start] + heuristic_cost_estimate(start, goal)
//
//     while openset is not empty
//         current := the node in openset having the lowest f_score[] value
//         if current = goal
//             return reconstruct_path(came_from, goal)
//
//         remove current from openset
//         add current to closedset
//         for each neighbor in neighbor_nodes(current)
//             if neighbor in closedset
//                 continue
//             tentative_g_score := g_score[current] + dist_between(current,neighbor)
//
//             if neighbor not in openset or tentative_g_score < g_score[neighbor]
//                 came_from[neighbor] := current
//                 g_score[neighbor] := tentative_g_score
//                 f_score[neighbor] := g_score[neighbor] + heuristic_cost_estimate(neighbor, goal)
//                 if neighbor not in openset
//                     add neighbor to openset
//
//     return failure
//
// function reconstruct_path(came_from,current)
//     total_path := [current]
//     while current in came_from:
//         current := came_from[current]
//         total_path.append(current)
//     return total_path
<|endoftext|>


<commit_before>// Copyright 2018 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libdokan

import (
	"bytes"
	"context"
	"crypto/sha256"
	"fmt"
	"io"
	"os"
	"os/exec"

	"github.com/keybase/client/go/logger"
)

const shortPath = `DOKAN1.DLL`
const syswow64 = `C:\WINDOWS\SYSWOW64\`
const system32 = `C:\WINDOWS\SYSTEM32\`

type errorPrinter struct {
	buf bytes.Buffer
}

func (ep *errorPrinter) Printf(s string, os ...interface{}) {
	fmt.Fprintf(&ep.buf, s, os...)
}

func debugFileInfo(epc *errorPrinter, path string) {
	f, err := os.Open(path)
	epc.Printf("debugFileInfo: open(%q) -> %v, %v\n", path, f, err)
	if err != nil {
		return
	}
	defer f.Close()
	fi, err := f.Stat()
	epc.Printf("debugFileInfo: stat(%q) -> %v, %v\n", path, fi, err)
	if fi != nil {
		epc.Printf("debugFileInfo: modtime is %v\n", fi.ModTime())
	}
	h := sha256.New()
	n, err := io.Copy(h, f)
	epc.Printf("debugFileInfo: read bytes -> %v, %v\n", n, err)
	if err != nil {
		return
	}
	epc.Printf("debugFileInfo: sha256 %X\n", h.Sum(nil))
}

func logDokanFilesInfo(epc *errorPrinter) {
	cwd := ``
	if d, err := os.Getwd(); err == nil {
		cwd = d + `\`
	}
	for _, d := range []string{syswow64, system32, cwd} {
		debugFileInfo(epc, d+shortPath)
	}
	for _, d := range []string{syswow64, system32} {
		debugFileInfo(epc, d+`DRIVERS\DOKAN.SYS`)
		debugFileInfo(epc, d+`DRIVERS\DOKAN1.SYS`)
		debugFileInfo(epc, d+`DRIVERS\DOKAN2.SYS`)
	}
}

func logDokanServiceInfo(epc *errorPrinter) {
	epc.Printf("Running 'sc query dokan1'")
	bs, err := exec.Command("sc", "query", "dokan1").CombinedOutput()
	if err != nil {
		epc.Printf("exec.Command error: %v\n", err)
		return
	}
	epc.Printf("%s\n", bs)
}

func logDokanInfo(ctx context.Context, log logger.Logger) {
	var epc errorPrinter
	logDokanFilesInfo(&epc)
	logDokanServiceInfo(&epc)
	log.CDebugf(ctx, "Dokan info:\n%s", epc.buf.Bytes())
}
<commit_msg>libdokan: Use %+v for error printing in dokan_info<commit_after>// Copyright 2018 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libdokan

import (
	"bytes"
	"context"
	"crypto/sha256"
	"fmt"
	"io"
	"os"
	"os/exec"

	"github.com/keybase/client/go/logger"
)

const shortPath = `DOKAN1.DLL`
const syswow64 = `C:\WINDOWS\SYSWOW64\`
const system32 = `C:\WINDOWS\SYSTEM32\`

type errorPrinter struct {
	buf bytes.Buffer
}

func (ep *errorPrinter) Printf(s string, os ...interface{}) {
	fmt.Fprintf(&ep.buf, s, os...)
}

func debugFileInfo(epc *errorPrinter, path string) {
	f, err := os.Open(path)
	epc.Printf("debugFileInfo: open(%q) -> %v, %+v\n", path, f, err)
	if err != nil {
		return
	}
	defer f.Close()
	fi, err := f.Stat()
	epc.Printf("debugFileInfo: stat(%q) -> %v, %+v\n", path, fi, err)
	if fi != nil {
		epc.Printf("debugFileInfo: modtime is %v\n", fi.ModTime())
	}
	h := sha256.New()
	n, err := io.Copy(h, f)
	epc.Printf("debugFileInfo: read bytes -> %d, %+v\n", n, err)
	if err != nil {
		return
	}
	epc.Printf("debugFileInfo: sha256 %X\n", h.Sum(nil))
}

func logDokanFilesInfo(epc *errorPrinter) {
	cwd := ``
	if d, err := os.Getwd(); err == nil {
		cwd = d + `\`
	}
	for _, d := range []string{syswow64, system32, cwd} {
		debugFileInfo(epc, d+shortPath)
	}
	for _, d := range []string{syswow64, system32} {
		debugFileInfo(epc, d+`DRIVERS\DOKAN.SYS`)
		debugFileInfo(epc, d+`DRIVERS\DOKAN1.SYS`)
		debugFileInfo(epc, d+`DRIVERS\DOKAN2.SYS`)
	}
}

func logDokanServiceInfo(epc *errorPrinter) {
	epc.Printf("Running 'sc query dokan1'")
	bs, err := exec.Command("sc", "query", "dokan1").CombinedOutput()
	if err != nil {
		epc.Printf("exec.Command error: %+v\n", err)
		return
	}
	epc.Printf("%s\n", bs)
}

func logDokanInfo(ctx context.Context, log logger.Logger) {
	var epc errorPrinter
	logDokanFilesInfo(&epc)
	logDokanServiceInfo(&epc)
	log.CDebugf(ctx, "Dokan info:\n%s", epc.buf.Bytes())
}
<|endoftext|>


<commit_before>package cc_client

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"lib/json_client"
	"net/http"
	"policy-server/models"
	"strings"

	"code.cloudfoundry.org/lager"
)

type httpClient interface {
	Do(*http.Request) (*http.Response, error)
}

type Client struct {
	BaseURL    string
	HTTPClient httpClient
	Logger     lager.Logger
	JSONClient json_client.JsonClient
}

type BadCCResponse struct {
	StatusCode     int
	CCResponseBody string
}

type AppsV3Response struct {
	Pagination struct {
		TotalPages int `json:"total_pages"`
	} `json:"pagination"`
	Resources []struct {
		GUID  string `json:"guid"`
		Links struct {
			Space struct {
				Href string `json:"href"`
			} `json:"space"`
		} `json:"links"`
	} `json:"resources"`
}

type SpaceResponse struct {
	Entity struct {
		Name             string `json:"name"`
		OrganizationGUID string `json:"organization_guid"`
	} `json:"entity"`
}

type SpacesResponse struct {
	Resources []struct {
		Metadata struct {
			GUID string `json:"guid"`
		}
		Entity struct {
			Name             string `json:"name"`
			OrganizationGUID string `json:"organization_guid"`
		} `json:"entity"`
	} `json:"resources"`
}

func (r BadCCResponse) Error() string {
	return fmt.Sprintf("bad cc response: %d: %s", r.StatusCode, r.CCResponseBody)
}

func (c *Client) GetAllAppGUIDs(token string) (map[string]interface{}, error) {
	token = fmt.Sprintf("bearer %s", token)

	var response AppsV3Response
	err := c.JSONClient.Do("GET", "/v3/apps", nil, &response, token)
	if err != nil {
		return nil, err
	}

	if response.Pagination.TotalPages > 1 {
		return nil, fmt.Errorf("pagination support not yet implemented")
	}

	ret := make(map[string]interface{})
	for _, r := range response.Resources {
		ret[r.GUID] = nil
	}

	return ret, nil
}

func (c *Client) GetSpaceGUIDs(token string, appGUIDs []string) ([]string, error) {
	mapping, err := c.GetAppSpaces(token, appGUIDs)
	if err != nil {
		return nil, err
	}

	deduplicated := map[string]struct{}{}
	for _, spaceID := range mapping {
		deduplicated[spaceID] = struct{}{}
	}

	ret := []string{}
	for spaceID, _ := range deduplicated {
		ret = append(ret, spaceID)
	}

	return ret, nil
}

func (c *Client) GetAppSpaces(token string, appGUIDs []string) (map[string]string, error) {
	if len(appGUIDs) < 1 {
		return map[string]string{}, nil
	}

	token = fmt.Sprintf("bearer %s", token)
	route := fmt.Sprintf("/v3/apps?guids=%s", strings.Join(appGUIDs, ","))

	var response AppsV3Response
	err := c.JSONClient.Do("GET", route, nil, &response, token)
	if err != nil {
		return nil, err
	}

	if response.Pagination.TotalPages > 1 {
		return nil, fmt.Errorf("pagination support not yet implemented")
	}

	set := make(map[string]string)
	for _, r := range response.Resources {
		href := r.Links.Space.Href
		parts := strings.Split(href, "/")
		appID := r.GUID
		spaceID := parts[len(parts)-1]
		set[appID] = spaceID
	}
	return set, nil
}

func (c *Client) GetSpace(token, spaceGUID string) (*models.Space, error) {
	token = fmt.Sprintf("bearer %s", token)
	route := fmt.Sprintf("/v2/spaces/%s", spaceGUID)

	var response SpaceResponse
	err := c.JSONClient.Do("GET", route, nil, &response, token)
	if err != nil {
		typedErr, ok := err.(*json_client.HttpResponseCodeError)
		if !ok {
			return nil, err
		}
		if typedErr.StatusCode == http.StatusNotFound {
			return nil, nil
		}
		return nil, err
	}

	return &models.Space{
		Name:    response.Entity.Name,
		OrgGUID: response.Entity.OrganizationGUID,
	}, nil
}

func (c *Client) GetUserSpace(token, userGUID string, space models.Space) (*models.Space, error) {
	token = fmt.Sprintf("bearer %s", token)

	route := fmt.Sprintf("/v2/spaces?q=developer_guid%%3A%s&q=name%%3A%s&q=organization_guid%%3A%s", userGUID, space.Name, space.OrgGUID)

	var response SpacesResponse
	err := c.JSONClient.Do("GET", route, nil, &response, token)
	if err != nil {
		return nil, err
	}

	numSpaces := len(response.Resources)
	if numSpaces == 0 {
		return nil, nil
	}
	if numSpaces > 1 {
		return nil, errors.New(fmt.Sprintf("found more than one matching space"))
	}

	return &models.Space{
		Name:    response.Resources[0].Entity.Name,
		OrgGUID: response.Resources[0].Entity.OrganizationGUID,
	}, nil
}

func (c *Client) GetUserSpaces(token, userGUID string) (map[string]struct{}, error) {
	reqURL := fmt.Sprintf("%s/v2/users/%s/spaces", c.BaseURL, userGUID)
	request, err := http.NewRequest("GET", reqURL, nil)
	request.Header.Set("Authorization", fmt.Sprintf("bearer %s", token))
	if err != nil {
		return nil, fmt.Errorf("create HTTP request: %s", err) // untested
	}

	c.Logger.Debug("get_user_spaces", lager.Data{"URL": request.URL})

	resp, err := c.HTTPClient.Do(request)
	if err != nil {
		return nil, fmt.Errorf("http client: %s", err)
	}
	defer resp.Body.Close()

	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("read body: %s", err)
	}

	if resp.StatusCode != 200 {
		err = BadCCResponse{
			StatusCode:     resp.StatusCode,
			CCResponseBody: string(respBytes),
		}
		return nil, err
	}

	var response SpacesResponse
	err = json.Unmarshal(respBytes, &response)
	if err != nil {
		return nil, fmt.Errorf("unmarshal json: %s", err)
	}

	userSpaces := map[string]struct{}{}
	for _, space := range response.Resources {
		spaceID := space.Metadata.GUID
		userSpaces[spaceID] = struct{}{}
	}

	return userSpaces, nil
}
<commit_msg>Refactor CC Client GetUserSpaces<commit_after>package cc_client

import (
	"errors"
	"fmt"
	"lib/json_client"
	"net/http"
	"policy-server/models"
	"strings"

	"code.cloudfoundry.org/lager"
)

type httpClient interface {
	Do(*http.Request) (*http.Response, error)
}

type Client struct {
	BaseURL    string
	HTTPClient httpClient
	Logger     lager.Logger
	JSONClient json_client.JsonClient
}

type AppsV3Response struct {
	Pagination struct {
		TotalPages int `json:"total_pages"`
	} `json:"pagination"`
	Resources []struct {
		GUID  string `json:"guid"`
		Links struct {
			Space struct {
				Href string `json:"href"`
			} `json:"space"`
		} `json:"links"`
	} `json:"resources"`
}

type SpaceResponse struct {
	Entity struct {
		Name             string `json:"name"`
		OrganizationGUID string `json:"organization_guid"`
	} `json:"entity"`
}

type SpacesResponse struct {
	Resources []struct {
		Metadata struct {
			GUID string `json:"guid"`
		}
		Entity struct {
			Name             string `json:"name"`
			OrganizationGUID string `json:"organization_guid"`
		} `json:"entity"`
	} `json:"resources"`
}

func (c *Client) GetAllAppGUIDs(token string) (map[string]interface{}, error) {
	token = fmt.Sprintf("bearer %s", token)

	var response AppsV3Response
	err := c.JSONClient.Do("GET", "/v3/apps", nil, &response, token)
	if err != nil {
		return nil, err
	}

	if response.Pagination.TotalPages > 1 {
		return nil, fmt.Errorf("pagination support not yet implemented")
	}

	ret := make(map[string]interface{})
	for _, r := range response.Resources {
		ret[r.GUID] = nil
	}

	return ret, nil
}

func (c *Client) GetSpaceGUIDs(token string, appGUIDs []string) ([]string, error) {
	mapping, err := c.GetAppSpaces(token, appGUIDs)
	if err != nil {
		return nil, err
	}

	deduplicated := map[string]struct{}{}
	for _, spaceID := range mapping {
		deduplicated[spaceID] = struct{}{}
	}

	ret := []string{}
	for spaceID, _ := range deduplicated {
		ret = append(ret, spaceID)
	}

	return ret, nil
}

func (c *Client) GetAppSpaces(token string, appGUIDs []string) (map[string]string, error) {
	if len(appGUIDs) < 1 {
		return map[string]string{}, nil
	}

	token = fmt.Sprintf("bearer %s", token)
	route := fmt.Sprintf("/v3/apps?guids=%s", strings.Join(appGUIDs, ","))

	var response AppsV3Response
	err := c.JSONClient.Do("GET", route, nil, &response, token)
	if err != nil {
		return nil, err
	}

	if response.Pagination.TotalPages > 1 {
		return nil, fmt.Errorf("pagination support not yet implemented")
	}

	set := make(map[string]string)
	for _, r := range response.Resources {
		href := r.Links.Space.Href
		parts := strings.Split(href, "/")
		appID := r.GUID
		spaceID := parts[len(parts)-1]
		set[appID] = spaceID
	}
	return set, nil
}

func (c *Client) GetSpace(token, spaceGUID string) (*models.Space, error) {
	token = fmt.Sprintf("bearer %s", token)
	route := fmt.Sprintf("/v2/spaces/%s", spaceGUID)

	var response SpaceResponse
	err := c.JSONClient.Do("GET", route, nil, &response, token)
	if err != nil {
		typedErr, ok := err.(*json_client.HttpResponseCodeError)
		if !ok {
			return nil, err
		}
		if typedErr.StatusCode == http.StatusNotFound {
			return nil, nil
		}
		return nil, err
	}

	return &models.Space{
		Name:    response.Entity.Name,
		OrgGUID: response.Entity.OrganizationGUID,
	}, nil
}

func (c *Client) GetUserSpace(token, userGUID string, space models.Space) (*models.Space, error) {
	token = fmt.Sprintf("bearer %s", token)

	route := fmt.Sprintf("/v2/spaces?q=developer_guid%%3A%s&q=name%%3A%s&q=organization_guid%%3A%s", userGUID, space.Name, space.OrgGUID)

	var response SpacesResponse
	err := c.JSONClient.Do("GET", route, nil, &response, token)
	if err != nil {
		return nil, err
	}

	numSpaces := len(response.Resources)
	if numSpaces == 0 {
		return nil, nil
	}
	if numSpaces > 1 {
		return nil, errors.New(fmt.Sprintf("found more than one matching space"))
	}

	return &models.Space{
		Name:    response.Resources[0].Entity.Name,
		OrgGUID: response.Resources[0].Entity.OrganizationGUID,
	}, nil
}

func (c *Client) GetUserSpaces(token, userGUID string) (map[string]struct{}, error) {
	token = fmt.Sprintf("bearer %s", token)

	route := fmt.Sprintf("/v2/users/%s/spaces", userGUID)

	var response SpacesResponse
	err := c.JSONClient.Do("GET", route, nil, &response, token)
	if err != nil {
		return nil, err
	}

	userSpaces := map[string]struct{}{}
	for _, space := range response.Resources {
		spaceID := space.Metadata.GUID
		userSpaces[spaceID] = struct{}{}
	}

	return userSpaces, nil
}
<|endoftext|>


<commit_before>package gobitfields

import (
	"github.com/lagarciag/bitwisebytes"
)

type MemberMetaData struct {
	Width  uint32
	Offset uint32
	Name string
}

type StructMetaData struct {
	Width      uint32
	Members    []MemberMetaData
	MembersMap map[string]*MemberMetaData
}

//GetFields returns a bitfield member as specified by the provided offset and width
func GetField(inputSlice []byte,offset int, width int) (outputSlice []byte) {
	bytesWidth := GetBytesSize(width)
	tmpField , _ := bitwisebytes.ShiftRight(inputSlice,uint(offset))
	outputSlice = tmpField[0:bytesWidth]
	maskSlice := bitwisebytes.MakeMask(uint(len(outputSlice)),uint(width),0)
	err := bitwisebytes.And(outputSlice,maskSlice)
	if err != nil {
		panic(err.Error())
	}
	return outputSlice
}

//PutField
func PutField(destSlice []byte, inputSlice []byte,offset int, width int) {
	tmpSlice := make([]byte,len(destSlice))

	for i , aByte := range inputSlice {
		tmpSlice[i] = aByte
	}

	tmpSlice2, err := bitwisebytes.ShiftLeft(tmpSlice,uint(offset))
	if err != nil {
		panic(err.Error())
	}

	bitwisebytes.Or(destSlice,tmpSlice2)
}

func PutAllFields(inputMatrix [][]byte,metadataList []MemberMetaData) (outputSlice []byte) {
	size := 0
	for _ , member := range metadataList {
		size += int(member.Width)
	}
	bytesSize := GetBytesSize(size)

	outputSlice = make([]byte,bytesSize)

	for i , field := range inputMatrix {
		PutField(outputSlice,field,int(metadataList[i].Offset),int(metadataList[i].Width))
	}

	return outputSlice
}

//GetAllFieldsList returns a slice of all the fields specified in the metadata list
func GetAllFieldsList(inputSlice []byte, metadataList []MemberMetaData) (outputMatrix [][]byte) {
	outputMatrix = make([][]byte, len(metadataList))
	for i , metadata := range metadataList {
		field := GetField(inputSlice,int(metadata.Offset),int(metadata.Width))
		outputMatrix[i] = field
	}
	return outputMatrix
}

func GetBytesSize(bitSize int) (bytesSize int) {
	bytesSize = bitSize / 8
	mod := bitSize % 8
	if mod != 0 {
		bytesSize++
	}
	return bytesSize

}

func ReverseMembers(inputBytes []byte,  metadataList []MemberMetaData) (reversed []byte) {

	fieldsMatrix := GetAllFieldsList(inputBytes, metadataList)

	reversedMetadata := ReverseMemberMetadataList(metadataList)

	reversedMatrix := reverseMembersMatrix(fieldsMatrix)
	reversed = PutAllFields(reversedMatrix,reversedMetadata)
	return reversed
}

func reverseMembersMatrix(input [][]byte) (output [][]byte) {
	length := len(input)
	output = make([][]byte, length)
	for i , data := range input {
		output[(length -1) - i] = data
	}
	return output
}

func ReverseBytes(input []byte) (output []byte) {
	length := len(input)
	output = make([]byte, length)
	for i , data := range input {
		output[(length -1) - i] = data
	}
	return output
}

func ReverseMemberMetadataList(input []MemberMetaData) (output []MemberMetaData) {
	length := len(input)
	output = make([]MemberMetaData, length)
	offset := 0
	for i , _ := range output {
		newData := MemberMetaData{}
		oldData := input[(length -1) - i]
		newData.Offset = uint32(offset)
		newData.Width = oldData.Width
		offset = offset + int(oldData.Width)
		output[i] = newData

	}
	return output
}

<commit_msg>chg: dev: Adding name in metaData<commit_after>package gobitfields

import (
	"github.com/lagarciag/bitwisebytes"
)

type MemberMetaData struct {
	Width  uint32
	Offset uint32
	Name string
}

type StructMetaData struct {
	Width      uint32
	Members    []MemberMetaData
	MembersMap map[string]*MemberMetaData
}

//GetFields returns a bitfield member as specified by the provided offset and width
func GetField(inputSlice []byte,offset int, width int) (outputSlice []byte) {
	bytesWidth := GetBytesSize(width)
	tmpField , _ := bitwisebytes.ShiftRight(inputSlice,uint(offset))
	outputSlice = tmpField[0:bytesWidth]
	maskSlice := bitwisebytes.MakeMask(uint(len(outputSlice)),uint(width),0)
	err := bitwisebytes.And(outputSlice,maskSlice)
	if err != nil {
		panic(err.Error())
	}
	return outputSlice
}

//PutField
func PutField(destSlice []byte, inputSlice []byte,offset int, width int) {
	tmpSlice := make([]byte,len(destSlice))

	for i , aByte := range inputSlice {
		tmpSlice[i] = aByte
	}

	tmpSlice2, err := bitwisebytes.ShiftLeft(tmpSlice,uint(offset))
	if err != nil {
		panic(err.Error())
	}

	bitwisebytes.Or(destSlice,tmpSlice2)
}

func PutAllFields(inputMatrix [][]byte,metadataList []MemberMetaData) (outputSlice []byte) {
	size := 0
	for _ , member := range metadataList {
		size += int(member.Width)
	}
	bytesSize := GetBytesSize(size)

	outputSlice = make([]byte,bytesSize)

	for i , field := range inputMatrix {
		PutField(outputSlice,field,int(metadataList[i].Offset),int(metadataList[i].Width))
	}

	return outputSlice
}

//GetAllFieldsList returns a slice of all the fields specified in the metadata list
func GetAllFieldsList(inputSlice []byte, metadataList []MemberMetaData) (outputMatrix [][]byte) {
	outputMatrix = make([][]byte, len(metadataList))
	for i , metadata := range metadataList {
		field := GetField(inputSlice,int(metadata.Offset),int(metadata.Width))
		outputMatrix[i] = field
	}
	return outputMatrix
}

func GetBytesSize(bitSize int) (bytesSize int) {
	bytesSize = bitSize / 8
	mod := bitSize % 8
	if mod != 0 {
		bytesSize++
	}
	return bytesSize

}

func ReverseMembers(inputBytes []byte,  metadataList []MemberMetaData) (reversed []byte) {

	fieldsMatrix := GetAllFieldsList(inputBytes, metadataList)

	reversedMetadata := ReverseMemberMetadataList(metadataList)

	reversedMatrix := reverseMembersMatrix(fieldsMatrix)
	reversed = PutAllFields(reversedMatrix,reversedMetadata)
	return reversed
}

func reverseMembersMatrix(input [][]byte) (output [][]byte) {
	length := len(input)
	output = make([][]byte, length)
	for i , data := range input {
		output[(length -1) - i] = data
	}
	return output
}

func ReverseBytes(input []byte) (output []byte) {
	length := len(input)
	output = make([]byte, length)
	for i , data := range input {
		output[(length -1) - i] = data
	}
	return output
}

func ReverseMemberMetadataList(input []MemberMetaData) (output []MemberMetaData) {
	length := len(input)
	output = make([]MemberMetaData, length)
	offset := 0
	for i , _ := range output {
		newData := MemberMetaData{}
		oldData := input[(length -1) - i]
		newData.Offset = uint32(offset)
		newData.Width = oldData.Width
		newData.Name = oldData.Name
		offset = offset + int(oldData.Width)
		output[i] = newData

	}
	return output
}

<|endoftext|>


<commit_before>package tree
/*
#cgo LDFLAGS: -lxml2
#cgo CFLAGS: -I/usr/include/libxml2
#include <libxml/tree.h>
*/
import "C"
import "unsafe"

type Element struct {
	*XmlNode
}

func (node *Element) ElementType() int {
	elem := (*C.xmlElement)(unsafe.Pointer(node.ptr()))
	return int(elem.etype)
}

func (node *Element) new(ptr *C.xmlNode) *Element {
	if ptr == nil {
		return nil
	}
	return NewNode(unsafe.Pointer(ptr), node.Doc()).(*Element)
}

func (node *Element) NextElement() *Element {
	return node.new(C.xmlNextElementSibling(node.NodePtr))
}

func (node *Element) PrevElement() *Element {
	return node.new(C.xmlPreviousElementSibling(node.NodePtr))
}

func (node *Element) FirstElement() *Element {
	return node.new(C.xmlFirstElementChild(node.NodePtr))
}

func (node *Element) LastElement() *Element {
	return node.new(C.xmlLastElementChild(node.NodePtr))
}

func (node *Element) Clear() {
	// Remember, as we delete them, the last one moves to the front
	child := node.First()
	for child != nil {
		child.Remove()
		child.Free()
		child = node.First()
	}
}

func (node *Element) Content() string {
	child := node.First()
	output := ""
	for child != nil {
		output = output + child.DumpHTML()
		child = child.Next()
	}
	return output
}

func (node *Element) SetContent(content string) {
	node.Clear()
	node.AppendContent(content)
}

func (node *Element) AppendContent(content string) {
	child := node.Doc().ParseFragment(content)
	for child != nil {
		node.AppendChildNode(child)
		child = child.Next()
	}
}

func (node *Element) PrependContent(content string) {
	child := node.Doc().ParseFragment(content).Parent().Last()
	for child != nil {
		node.PrependChildNode(child)
		child = child.Prev()
	}
}

func (node *XmlNode) AddContentAfter(content string) {
	child := node.Doc().ParseFragment(content).Parent().Last()
	for child != nil {
		node.AddNodeAfter(child)
		child = child.Prev()
	}
}
func (node *XmlNode) AddContentBefore(content string) {
	child := node.Doc().ParseFragment(content).Parent().First()
	for child != nil {
		node.AddNodeBefore(child)
		child = child.Next()
	}
}

<commit_msg>…And over zealous freeing was the reason… *sigh*. The reason is that those nodes MAY be referenced elsewhere. Aka, in the select().<commit_after>package tree
/*
#cgo LDFLAGS: -lxml2
#cgo CFLAGS: -I/usr/include/libxml2
#include <libxml/tree.h>
*/
import "C"
import "unsafe"

type Element struct {
	*XmlNode
}

func (node *Element) ElementType() int {
	elem := (*C.xmlElement)(unsafe.Pointer(node.ptr()))
	return int(elem.etype)
}

func (node *Element) new(ptr *C.xmlNode) *Element {
	if ptr == nil {
		return nil
	}
	return NewNode(unsafe.Pointer(ptr), node.Doc()).(*Element)
}

func (node *Element) NextElement() *Element {
	return node.new(C.xmlNextElementSibling(node.NodePtr))
}

func (node *Element) PrevElement() *Element {
	return node.new(C.xmlPreviousElementSibling(node.NodePtr))
}

func (node *Element) FirstElement() *Element {
	return node.new(C.xmlFirstElementChild(node.NodePtr))
}

func (node *Element) LastElement() *Element {
	return node.new(C.xmlLastElementChild(node.NodePtr))
}

func (node *Element) Clear() {
	// Remember, as we delete them, the last one moves to the front
	child := node.First()
	for child != nil {
		child.Remove()
		//child.Free()
		child = node.First()
	}
}

func (node *Element) Content() string {
	child := node.First()
	output := ""
	for child != nil {
		output = output + child.DumpHTML()
		child = child.Next()
	}
	return output
}

func (node *Element) SetContent(content string) {
	node.Clear()
	node.AppendContent(content)
}

func (node *Element) AppendContent(content string) {
	child := node.Doc().ParseFragment(content)
	for child != nil {
		node.AppendChildNode(child)
		child = child.Next()
	}
}

func (node *Element) PrependContent(content string) {
	child := node.Doc().ParseFragment(content).Parent().Last()
	for child != nil {
		node.PrependChildNode(child)
		child = child.Prev()
	}
}

func (node *XmlNode) AddContentAfter(content string) {
	child := node.Doc().ParseFragment(content).Parent().Last()
	for child != nil {
		node.AddNodeAfter(child)
		child = child.Prev()
	}
}
func (node *XmlNode) AddContentBefore(content string) {
	child := node.Doc().ParseFragment(content).Parent().First()
	for child != nil {
		node.AddNodeBefore(child)
		child = child.Next()
	}
}

<|endoftext|>


<commit_before>package link

import (
	"fmt"

	"github.com/cilium/ebpf"
	"github.com/cilium/ebpf/internal"
)

type RawTracepointOptions struct {
	// Tracepoint name.
	Name string
	// Program must be of type RawTracepoint*
	Program *ebpf.Program
}

// AttachRawTracepoint links a BPF program to a raw_tracepoint.
//
// Requires at least Linux 4.17.
func AttachRawTracepoint(opts RawTracepointOptions) (Link, error) {
	if opts.Program.FD() < 0 {
		return nil, fmt.Errorf("invalid program: %w", internal.ErrClosedFd)
	}

	fd, err := bpfRawTracepointOpen(&bpfRawTracepointOpenAttr{
		name: internal.NewStringPointer(opts.Name),
		fd:   uint32(opts.Program.FD()),
	})
	if err != nil {
		return nil, err
	}

	return &progAttachRawTracepoint{fd: fd}, nil
}

type progAttachRawTracepoint struct {
	fd *internal.FD
}

var _ Link = (*progAttachRawTracepoint)(nil)

func (rt *progAttachRawTracepoint) isLink() {}

func (rt *progAttachRawTracepoint) Close() error {
	return rt.fd.Close()
}

func (rt *progAttachRawTracepoint) Update(_ *ebpf.Program) error {
	return fmt.Errorf("can't update raw_tracepoint: %w", ErrNotSupported)
}

func (rt *progAttachRawTracepoint) Pin(_ string) error {
	return fmt.Errorf("can't pin raw_tracepoint: %w", ErrNotSupported)
}
<commit_msg>link: check program type for raw tracepoints<commit_after>package link

import (
	"fmt"

	"github.com/cilium/ebpf"
	"github.com/cilium/ebpf/internal"
)

type RawTracepointOptions struct {
	// Tracepoint name.
	Name string
	// Program must be of type RawTracepoint*
	Program *ebpf.Program
}

// AttachRawTracepoint links a BPF program to a raw_tracepoint.
//
// Requires at least Linux 4.17.
func AttachRawTracepoint(opts RawTracepointOptions) (Link, error) {
	if t := opts.Program.Type(); t != ebpf.RawTracepoint && t != ebpf.RawTracepointWritable {
		return nil, fmt.Errorf("invalid program type %s, expected RawTracepoint(Writable)", t)
	}
	if opts.Program.FD() < 0 {
		return nil, fmt.Errorf("invalid program: %w", internal.ErrClosedFd)
	}

	fd, err := bpfRawTracepointOpen(&bpfRawTracepointOpenAttr{
		name: internal.NewStringPointer(opts.Name),
		fd:   uint32(opts.Program.FD()),
	})
	if err != nil {
		return nil, err
	}

	return &progAttachRawTracepoint{fd: fd}, nil
}

type progAttachRawTracepoint struct {
	fd *internal.FD
}

var _ Link = (*progAttachRawTracepoint)(nil)

func (rt *progAttachRawTracepoint) isLink() {}

func (rt *progAttachRawTracepoint) Close() error {
	return rt.fd.Close()
}

func (rt *progAttachRawTracepoint) Update(_ *ebpf.Program) error {
	return fmt.Errorf("can't update raw_tracepoint: %w", ErrNotSupported)
}

func (rt *progAttachRawTracepoint) Pin(_ string) error {
	return fmt.Errorf("can't pin raw_tracepoint: %w", ErrNotSupported)
}
<|endoftext|>


<commit_before>package stream

import (
	"context"
	"fmt"
	"sync"

	logging "github.com/ipfs/go-log"
	tec "github.com/jbenet/go-temp-err-catcher"
	transport "github.com/libp2p/go-libp2p-transport"
	manet "github.com/multiformats/go-multiaddr-net"
)

var log = logging.Logger("stream-upgrader")

type connErr struct {
	conn transport.Conn
	err  error
}

type listener struct {
	manet.Listener

	transport transport.Transport
	upgrader  *Upgrader

	incoming chan transport.Conn
	err      error

	// Used for backpressure
	threshold *threshold

	// Canceling this context isn't sufficient to tear down the listener.
	// Call close.
	ctx    context.Context
	cancel func()
}

// Close closes the listener.
func (l *listener) Close() error {
	// Do this first to try to get any relevent errors.
	err := l.Listener.Close()

	l.cancel()
	// Drain and wait.
	for c := range l.incoming {
		c.Close()
	}
	return err
}

func (l *listener) handleIncoming() {
	var wg sync.WaitGroup
	defer func() {
		// make sure we're closed
		l.Listener.Close()
		if l.err == nil {
			l.err = fmt.Errorf("listener closed")
		}

		wg.Wait()
		close(l.incoming)
	}()

	var catcher tec.TempErrCatcher
	for {
		// no need to wait on the context.
		// Close will drain the incoming channel which will cause the
		// threshold to drop.
		l.threshold.Wait()

		maconn, err := l.Listener.Accept()
		if err != nil {
			if catcher.IsTemporary(err) {
				log.Infof("temporary accept error: %s", err)
				continue
			}
			l.err = err
			return
		}

		log.Debugf("listener %s got connection: %s <---> %s",
			l,
			maconn.LocalMultiaddr(),
			maconn.RemoteMultiaddr())

		wg.Add(1)
		go func() {
			defer wg.Done()

			ctx, cancel := context.WithTimeout(l.ctx, transport.AcceptTimeout)
			defer cancel()

			conn, err := l.upgrader.UpgradeInbound(ctx, l.transport, maconn)
			if err != nil {
				// Don't bother bubbling this up. We just failed
				// to completely negotiate the connection.
				log.Debugf("accept upgrade error: %s (%s <--> %s)",
					err,
					maconn.LocalMultiaddr(),
					maconn.RemoteMultiaddr())
				return
			}

			log.Debugf("listener %s accepted connection: %s", l, conn)

			l.threshold.Acquire()
			defer l.threshold.Release()

			select {
			case l.incoming <- conn:
			case <-ctx.Done():
				if l.ctx.Err() == nil {
					// Listener *not* closed but the accept timeout expired.
					log.Warningf("listener dropped connection due to slow accept")
				}
				// Wait on the context with a timeout. This way,
				// if we stop accepting connections for some reason,
				// we'll eventually close all the open ones
				// instead of hanging onto them.
				conn.Close()
			}
		}()
	}
}

// Accept accepts a connection.
func (l *listener) Accept() (transport.Conn, error) {
	if c, ok := <-l.incoming; ok {
		return c, nil
	}
	return nil, l.err
}

func (l *listener) String() string {
	if s, ok := l.transport.(fmt.Stringer); ok {
		return fmt.Sprintf("<stream.Listener[%s] %s>", s, l.Multiaddr())
	}
	return fmt.Sprintf("<stream.Listener %s>", l.Multiaddr())
}

var _ transport.Listener = (*listener)(nil)
<commit_msg>fix comment on why we don't need to wait on the context<commit_after>package stream

import (
	"context"
	"fmt"
	"sync"

	logging "github.com/ipfs/go-log"
	tec "github.com/jbenet/go-temp-err-catcher"
	transport "github.com/libp2p/go-libp2p-transport"
	manet "github.com/multiformats/go-multiaddr-net"
)

var log = logging.Logger("stream-upgrader")

type connErr struct {
	conn transport.Conn
	err  error
}

type listener struct {
	manet.Listener

	transport transport.Transport
	upgrader  *Upgrader

	incoming chan transport.Conn
	err      error

	// Used for backpressure
	threshold *threshold

	// Canceling this context isn't sufficient to tear down the listener.
	// Call close.
	ctx    context.Context
	cancel func()
}

// Close closes the listener.
func (l *listener) Close() error {
	// Do this first to try to get any relevent errors.
	err := l.Listener.Close()

	l.cancel()
	// Drain and wait.
	for c := range l.incoming {
		c.Close()
	}
	return err
}

func (l *listener) handleIncoming() {
	var wg sync.WaitGroup
	defer func() {
		// make sure we're closed
		l.Listener.Close()
		if l.err == nil {
			l.err = fmt.Errorf("listener closed")
		}

		wg.Wait()
		close(l.incoming)
	}()

	var catcher tec.TempErrCatcher
	for l.ctx.Err() == nil {
		maconn, err := l.Listener.Accept()
		if err != nil {
			if catcher.IsTemporary(err) {
				log.Infof("temporary accept error: %s", err)
				continue
			}
			l.err = err
			return
		}

		log.Debugf("listener %s got connection: %s <---> %s",
			l,
			maconn.LocalMultiaddr(),
			maconn.RemoteMultiaddr())

		wg.Add(1)
		go func() {
			defer wg.Done()

			ctx, cancel := context.WithTimeout(l.ctx, transport.AcceptTimeout)
			defer cancel()

			conn, err := l.upgrader.UpgradeInbound(ctx, l.transport, maconn)
			if err != nil {
				// Don't bother bubbling this up. We just failed
				// to completely negotiate the connection.
				log.Debugf("accept upgrade error: %s (%s <--> %s)",
					err,
					maconn.LocalMultiaddr(),
					maconn.RemoteMultiaddr())
				return
			}

			log.Debugf("listener %s accepted connection: %s", l, conn)

			l.threshold.Acquire()
			defer l.threshold.Release()

			select {
			case l.incoming <- conn:
			case <-ctx.Done():
				if l.ctx.Err() == nil {
					// Listener *not* closed but the accept timeout expired.
					log.Warningf("listener dropped connection due to slow accept")
				}
				// Wait on the context with a timeout. This way,
				// if we stop accepting connections for some reason,
				// we'll eventually close all the open ones
				// instead of hanging onto them.
				conn.Close()
			}
		}()

		// The go routine above calls Release when the context is
		// canceled so there's no need to wait on it here.
		l.threshold.Wait()
	}
}

// Accept accepts a connection.
func (l *listener) Accept() (transport.Conn, error) {
	if c, ok := <-l.incoming; ok {
		return c, nil
	}
	return nil, l.err
}

func (l *listener) String() string {
	if s, ok := l.transport.(fmt.Stringer); ok {
		return fmt.Sprintf("<stream.Listener[%s] %s>", s, l.Multiaddr())
	}
	return fmt.Sprintf("<stream.Listener %s>", l.Multiaddr())
}

var _ transport.Listener = (*listener)(nil)
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"encoding/base64"
	"fmt"
	"image"
	"image/color"
	"image/png"
	"io"
	"os"
	"strconv"
	"strings"
)

func main() {
	if len(os.Args) < 3 {
		fmt.Println("Usage %s: <inputPath> <output path>", os.Args[0])
		os.Exit(-1)
	}

	inputPath := string(os.Args[1])
	outputPath := string(os.Args[2])

	cDebug := false
	if os.Getenv("TXTDEBUG") == "1" {
		fmt.Println("Debug Mode..")
		cDebug = true
	}

	for {
		c, _ := os.OpenFile(inputPath, os.O_RDONLY, 0600)
		defer c.Close()

		reader := bufio.NewReader(c)
		var cfgLine []string
		var cfg = make(map[string]string, 10)
		line, err := reader.ReadString('\n')
		for err == nil {
			if !strings.HasPrefix(line, "#") {
				line = strings.TrimSpace(line)
				if len(line) > 0 {
					cfgLine = strings.Split(line, "=")
					cfg[cfgLine[0]] = cfgLine[1]
				}
			}
			line, err = reader.ReadString('\n')
		}

		if err != io.EOF {
			fmt.Println(err)
			continue
		}

		fmt.Println(cfg)

		var font FontMgr
		if cfg["font"] == "" {
			fmt.Println("No font specify")
			continue
		}

		fontImage := font.Init(cfg["font"])

		var r int = 255
		var g int = 255
		var b int = 255
		var a int = 255

		if cfg["bg_color"] == "" {
			fmt.Println("No font specify, use default [255,255,255,255]")
		} else {
			r, _ = strconv.Atoi(strings.Split(cfg["bg_color"], ",")[0])
			g, _ = strconv.Atoi(strings.Split(cfg["bg_color"], ",")[1])
			b, _ = strconv.Atoi(strings.Split(cfg["bg_color"], ",")[2])
			a, _ = strconv.Atoi(strings.Split(cfg["bg_color"], ",")[3])
		}

		// Allocate frame
		img := image.NewRGBA(image.Rect(0, 0, 39, 9))
		nm := img.Bounds()
		for y := 0; y < nm.Dy(); y++ {
			for x := 0; x < nm.Dx(); x++ {
				img.Set(x, y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)})
			}
		}

		text := "font6x7"
		if cfg["text"] == "" {
			fmt.Println("Empty text use default: font6x7")
		} else {
			text = cfg["text"]
		}

		// Fill frame
		for n, key := range text {
			outx := n * font.Width()
			wf := font.Width()
			hf := font.High()
			col := font.Col(key)
			row := font.Row(key)

			for y := 0; y < hf; y++ {
				for x := 0; x < wf; x++ {
					img.Set(x+outx, y, fontImage.At(x+wf*col, y+hf*row))
				}
			}
		}

		// Export to output file
		f, _ := os.OpenFile(outputPath, os.O_WRONLY|os.O_CREATE, 0600)
		defer f.Close()

		if cDebug {
			png.Encode(f, img)

		} else {
			buf := new(bytes.Buffer)
			png.Encode(buf, img)

			encoded := base64.StdEncoding.EncodeToString(buf.Bytes())
			fmt.Println(encoded)

			f.Write([]byte(encoded))
		}

	}
}
<commit_msg>Change defaults.<commit_after>package main

import (
	"bufio"
	"bytes"
	"encoding/base64"
	"fmt"
	"image"
	"image/color"
	"image/png"
	"io"
	"os"
	"strconv"
	"strings"
)

func main() {
	if len(os.Args) < 3 {
		fmt.Println("Usage %s: <inputPath> <output path>", os.Args[0])
		os.Exit(-1)
	}

	inputPath := string(os.Args[1])
	outputPath := string(os.Args[2])

	cDebug := false
	if os.Getenv("TXTDEBUG") == "1" {
		fmt.Println("Debug Mode..")
		cDebug = true
	}

	for {
		c, _ := os.OpenFile(inputPath, os.O_RDONLY, 0600)
		defer c.Close()

		reader := bufio.NewReader(c)
		var cfgLine []string
		var cfg = make(map[string]string, 10)
		line, err := reader.ReadString('\n')
		for err == nil {
			if !strings.HasPrefix(line, "#") {
				line = strings.TrimSpace(line)
				if len(line) > 0 {
					cfgLine = strings.Split(line, "=")
					cfg[cfgLine[0]] = cfgLine[1]
				}
			}
			line, err = reader.ReadString('\n')
		}

		if err != io.EOF {
			fmt.Println(err)
			continue
		}

		fmt.Println(cfg)

		var font FontMgr
		cfgFont := "font6x8"
		if cfg["font"] == "" {
			fmt.Println("No font specify use default..font6x8")
		} else {
			cfgFont = cfg["font"]
		}

		fontImage := font.Init(cfgFont)

		var r int = 0
		var g int = 0
		var b int = 0
		var a int = 255

		if cfg["bg_color"] == "" {
			fmt.Println("No font specify, use default [0,0,0,255]")
		} else {
			r, _ = strconv.Atoi(strings.Split(cfg["bg_color"], ",")[0])
			g, _ = strconv.Atoi(strings.Split(cfg["bg_color"], ",")[1])
			b, _ = strconv.Atoi(strings.Split(cfg["bg_color"], ",")[2])
			a, _ = strconv.Atoi(strings.Split(cfg["bg_color"], ",")[3])
		}

		// Allocate frame
		img := image.NewRGBA(image.Rect(0, 0, 39, 9))
		nm := img.Bounds()
		for y := 0; y < nm.Dy(); y++ {
			for x := 0; x < nm.Dx(); x++ {
				img.Set(x, y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)})
			}
		}

		// Fill frame
		for n, key := range cfg["text"] {
			outx := n * font.Width()
			wf := font.Width()
			hf := font.High()
			col := font.Col(key)
			row := font.Row(key)

			for y := 0; y < hf; y++ {
				for x := 0; x < wf; x++ {
					img.Set(x+outx, y, fontImage.At(x+wf*col, y+hf*row))
				}
			}
		}

		// Export to output file
		f, _ := os.OpenFile(outputPath, os.O_WRONLY|os.O_CREATE, 0600)
		defer f.Close()

		if cDebug {
			png.Encode(f, img)

		} else {
			buf := new(bytes.Buffer)
			png.Encode(buf, img)

			encoded := base64.StdEncoding.EncodeToString(buf.Bytes())
			fmt.Println(encoded)

			f.Write([]byte(encoded))
		}

	}
}
<|endoftext|>


<commit_before>/*
Copyright 2017 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package tika

import (
	"context"
	"crypto/md5"
	"fmt"
	"io"
	"net/url"
	"os"
	"os/exec"
	"time"

	"golang.org/x/net/context/ctxhttp"
)

// Server represents a Tika server. Create a new Server with NewServer,
// start it with Start, and shut it down with the close function returned
// from Start.
// There is no need to create a Server for an already running Tika Server
// since you can pass its URL directly to a Client.
type Server struct {
	jar  string
	url  string // url is derived from port.
	port string
}

// URL returns the URL of this Server.
func (s *Server) URL() string {
	return s.url
}

// NewServer creates a new Server. The default port is 9998.
func NewServer(jar, port string) (*Server, error) {
	if jar == "" {
		return nil, fmt.Errorf("no jar file specified")
	}
	if port == "" {
		port = "9998"
	}
	s := &Server{
		jar:  jar,
		port: port,
	}
	urlString := "http://localhost:" + s.port
	u, err := url.Parse(urlString)
	if err != nil {
		return nil, fmt.Errorf("invalid port %q: %v", s.port, err)
	}
	s.url = u.String()
	return s, nil
}

var commandContext = exec.CommandContext

// Start starts the given server. Start will start a new Java process. The
// caller must call cancel() to shut down the process when finished with the
// Server. The given Context is used for the Java process.
func (s *Server) Start(ctx context.Context) (cancel func(), err error) {
	ctx, cancel = context.WithCancel(ctx)
	cmd := commandContext(ctx, "java", "-jar", s.jar, "-p", s.port)

	if err := cmd.Start(); err != nil {
		cancel()
		return nil, err
	}

	if err := s.waitForStart(ctx); err != nil {
		cancel()
		out, readErr := cmd.CombinedOutput()
		if readErr != nil {
			return nil, fmt.Errorf("error reading output: %v", readErr)
		}
		// Report stderr since sometimes the server says why it failed to start.
		return nil, fmt.Errorf("error starting server: %v\nserver stderr:\n\n%s", err, out)
	}
	return cancel, nil
}

// waitForServer waits until the given Server is responding to requests or
// ctx is Done().
func (s Server) waitForStart(ctx context.Context) error {
	c := NewClient(nil, s.url)
	t := time.NewTicker(500 * time.Millisecond)
	defer t.Stop()
	for {
		select {
		case <-t.C:
			if _, err := c.Version(ctx); err == nil {
				return nil
			}
		case <-ctx.Done():
			return ctx.Err()
		}
	}
}

func md5Hash(path string) (string, error) {
	f, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer f.Close()

	h := md5.New()
	if _, err := io.Copy(h, f); err != nil {
		return "", err
	}
	return fmt.Sprintf("%x", h.Sum(nil)), nil
}

// A version represents a Tika Server version.
type version string

// Supported versions of Tika Server.
const (
	Version114 version = "1.14"
	Version115 version = "1.15"
	Version116 version = "1.16"
)

var md5s = map[version]string{
	Version114: "39055fc71358d774b9da066f80b1141c",
	Version115: "80bd3f00f05326d5190466de27d593dd",
	Version116: "6a549ce6ef6e186e019766059fd82fb2",
}

// DownloadServer downloads and validates the given server version,
// saving it at path. DownloadServer returns an error if it could
// not be downloaded/validated. Valid values for the version are 1.14.
// It is the caller's responsibility to remove the file when no longer needed.
// If the file already exists and has the correct MD5, DownloadServer will
// do nothing.
func DownloadServer(ctx context.Context, v version, path string) error {
	hash := md5s[v]
	if hash == "" {
		return fmt.Errorf("unsupported Tika version: %s", v)
	}

	if _, err := os.Stat(path); err == nil {
		if got, err := md5Hash(path); err == nil {
			if got == hash {
				return nil
			}
		}
	}
	out, err := os.Create(path)
	if err != nil {
		return fmt.Errorf("error creating file: %v", err)
	}
	defer out.Close()

	url := fmt.Sprintf("http://search.maven.org/remotecontent?filepath=org/apache/tika/tika-server/%s/tika-server-%s.jar", v, v)
	resp, err := ctxhttp.Get(ctx, nil, url)
	if err != nil {
		return fmt.Errorf("unable to download %q: %v", url, err)
	}
	defer resp.Body.Close()

	if _, err := io.Copy(out, resp.Body); err != nil {
		return fmt.Errorf("error saving download: %v", err)
	}

	h, err := md5Hash(path)

	if err != nil {
		return err
	}
	if h != hash {
		if err := os.Remove(path); err != nil {
			return fmt.Errorf("invalid md5: %s: error removing %s: %v", h, path, err)
		}
		return fmt.Errorf("invalid md5: %s", h)
	}
	return nil
}
<commit_msg>server: don't check file exists before hashing<commit_after>/*
Copyright 2017 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package tika

import (
	"context"
	"crypto/md5"
	"fmt"
	"io"
	"net/url"
	"os"
	"os/exec"
	"time"

	"golang.org/x/net/context/ctxhttp"
)

// Server represents a Tika server. Create a new Server with NewServer,
// start it with Start, and shut it down with the close function returned
// from Start.
// There is no need to create a Server for an already running Tika Server
// since you can pass its URL directly to a Client.
type Server struct {
	jar  string
	url  string // url is derived from port.
	port string
}

// URL returns the URL of this Server.
func (s *Server) URL() string {
	return s.url
}

// NewServer creates a new Server. The default port is 9998.
func NewServer(jar, port string) (*Server, error) {
	if jar == "" {
		return nil, fmt.Errorf("no jar file specified")
	}
	if port == "" {
		port = "9998"
	}
	s := &Server{
		jar:  jar,
		port: port,
	}
	urlString := "http://localhost:" + s.port
	u, err := url.Parse(urlString)
	if err != nil {
		return nil, fmt.Errorf("invalid port %q: %v", s.port, err)
	}
	s.url = u.String()
	return s, nil
}

var commandContext = exec.CommandContext

// Start starts the given server. Start will start a new Java process. The
// caller must call cancel() to shut down the process when finished with the
// Server. The given Context is used for the Java process.
func (s *Server) Start(ctx context.Context) (cancel func(), err error) {
	ctx, cancel = context.WithCancel(ctx)
	cmd := commandContext(ctx, "java", "-jar", s.jar, "-p", s.port)

	if err := cmd.Start(); err != nil {
		cancel()
		return nil, err
	}

	if err := s.waitForStart(ctx); err != nil {
		cancel()
		out, readErr := cmd.CombinedOutput()
		if readErr != nil {
			return nil, fmt.Errorf("error reading output: %v", readErr)
		}
		// Report stderr since sometimes the server says why it failed to start.
		return nil, fmt.Errorf("error starting server: %v\nserver stderr:\n\n%s", err, out)
	}
	return cancel, nil
}

// waitForServer waits until the given Server is responding to requests or
// ctx is Done().
func (s Server) waitForStart(ctx context.Context) error {
	c := NewClient(nil, s.url)
	t := time.NewTicker(500 * time.Millisecond)
	defer t.Stop()
	for {
		select {
		case <-t.C:
			if _, err := c.Version(ctx); err == nil {
				return nil
			}
		case <-ctx.Done():
			return ctx.Err()
		}
	}
}

func md5Hash(path string) (string, error) {
	f, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer f.Close()

	h := md5.New()
	if _, err := io.Copy(h, f); err != nil {
		return "", err
	}
	return fmt.Sprintf("%x", h.Sum(nil)), nil
}

// A version represents a Tika Server version.
type version string

// Supported versions of Tika Server.
const (
	Version114 version = "1.14"
	Version115 version = "1.15"
	Version116 version = "1.16"
)

var md5s = map[version]string{
	Version114: "39055fc71358d774b9da066f80b1141c",
	Version115: "80bd3f00f05326d5190466de27d593dd",
	Version116: "6a549ce6ef6e186e019766059fd82fb2",
}

// DownloadServer downloads and validates the given server version,
// saving it at path. DownloadServer returns an error if it could
// not be downloaded/validated. Valid values for the version are 1.14.
// It is the caller's responsibility to remove the file when no longer needed.
// If the file already exists and has the correct MD5, DownloadServer will
// do nothing.
func DownloadServer(ctx context.Context, v version, path string) error {
	hash := md5s[v]
	if hash == "" {
		return fmt.Errorf("unsupported Tika version: %s", v)
	}

	if got, err := md5Hash(path); err == nil {
		if got == hash {
			return nil
		}
	}
	out, err := os.Create(path)
	if err != nil {
		return fmt.Errorf("error creating file: %v", err)
	}
	defer out.Close()

	url := fmt.Sprintf("http://search.maven.org/remotecontent?filepath=org/apache/tika/tika-server/%s/tika-server-%s.jar", v, v)
	resp, err := ctxhttp.Get(ctx, nil, url)
	if err != nil {
		return fmt.Errorf("unable to download %q: %v", url, err)
	}
	defer resp.Body.Close()

	if _, err := io.Copy(out, resp.Body); err != nil {
		return fmt.Errorf("error saving download: %v", err)
	}

	h, err := md5Hash(path)

	if err != nil {
		return err
	}
	if h != hash {
		if err := os.Remove(path); err != nil {
			return fmt.Errorf("invalid md5: %s: error removing %s: %v", h, path, err)
		}
		return fmt.Errorf("invalid md5: %s", h)
	}
	return nil
}
<|endoftext|>


<commit_before>// Simple tools to read SysFS info on battery status.
package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"path/filepath"
	"strconv"
	"strings"
)

var path = "/sys/class/power_supply/BAT*/"

// readGlob reads the file contents at a glob and returns their contents.
func readGlob(glob string) ([]string, error) {
	paths, err := filepath.Glob(glob)
	if err != nil {
		return []string{}, err
	}
	result := make([]string, len(paths))
	for i, p := range paths {
		bytes, err := ioutil.ReadFile(p)
		if err != nil {
			return []string{}, err
		}
		result[i] = strings.TrimRight(string(bytes), "\n")
	}
	return result, nil
}

func getBatteries() ([]battery, error) {
	pwr, err := readGlob(path + "energy_now")
	if err != nil {
		return []battery{}, fmt.Errorf("couldn't read SysFS %s/power_now: %v\n", path, err)
	}
	status, err := readGlob(path + "status")
	if err != nil {
		return []battery{}, fmt.Errorf("couldn't read SysFS %s/status: %v\n", path, err)
	}
	full, err := readGlob(path + "energy_full")
	if err != nil {
		return []battery{}, fmt.Errorf("couldn't read SysFS %s/energy_full: %v\n", path, err)
	}
	if len(pwr) != len(status) || len(status) != len(full) {
		return []battery{}, fmt.Errorf("%d power_now files, %d status files but %d energy_full files; expected all to exist\n", len(pwr), len(status), len(full))
	}
	result := make([]battery, len(pwr))
	for i := range status {
		c, err := parseCharge(pwr[i], full[i])
		if err != nil {
			return []battery{}, fmt.Errorf("couldn't parse battery charge: %v\n", err)
		}
		result[i] = battery{current: c, status: status[i]}
	}
	return result, nil
}

// parseCharge parses the charge percentage from string values.
func parseCharge(p, f string) (float32, error) {
	pi, err := strconv.ParseInt(p, 10, 0)
	if err != nil {
		return 0.0, err
	}
	fi, err := strconv.ParseInt(f, 10, 0)
	if err != nil {
		return 0.0, err
	}
	return float32(pi) / float32(fi), nil
}

type battery struct {
	current float32
	status  string
}

func main() {
	bat, err := getBatteries()
	if err != nil {
		log.Fatalf("failed to get battery info: %v\n", err)
	}
	for i, b := range bat {
		log.Printf("[Battery %d]: %+v\n", i, b)
	}
}
<commit_msg>adds comments, fixes error msg<commit_after>// Simple tools to read SysFS info on battery status.
package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"path/filepath"
	"strconv"
	"strings"
)

// Glob for SysFS paths, within which energy_now, energy_full and status files are assumed to exist.
var path = "/sys/class/power_supply/BAT*/"

type battery struct {
	current float32 // current charge, [0.0, 1.0]
	status  string  // status of battery
}

// readGlob reads the file contents at a glob and returns their contents.
func readGlob(glob string) ([]string, error) {
	paths, err := filepath.Glob(glob)
	if err != nil {
		return []string{}, err
	}
	result := make([]string, len(paths))
	for i, p := range paths {
		bytes, err := ioutil.ReadFile(p)
		if err != nil {
			return []string{}, err
		}
		result[i] = strings.TrimRight(string(bytes), "\n")
	}
	return result, nil
}

// getBatteries reads SysFS paths to find status of batteries.
func getBatteries() ([]battery, error) {
	pwr, err := readGlob(path + "energy_now")
	if err != nil {
		return []battery{}, fmt.Errorf("couldn't read SysFS %s/energy_now: %v\n", path, err)
	}
	status, err := readGlob(path + "status")
	if err != nil {
		return []battery{}, fmt.Errorf("couldn't read SysFS %s/status: %v\n", path, err)
	}
	full, err := readGlob(path + "energy_full")
	if err != nil {
		return []battery{}, fmt.Errorf("couldn't read SysFS %s/energy_full: %v\n", path, err)
	}
	if len(pwr) != len(status) || len(status) != len(full) {
		return []battery{}, fmt.Errorf("%d power_now files, %d status files but %d energy_full files; expected all to exist\n", len(pwr), len(status), len(full))
	}
	result := make([]battery, len(pwr))
	for i := range status {
		c, err := parseCharge(pwr[i], full[i])
		if err != nil {
			return []battery{}, fmt.Errorf("couldn't parse battery charge: %v\n", err)
		}
		result[i] = battery{current: c, status: status[i]}
	}
	return result, nil
}

// parseCharge parses the charge percentage from string values.
func parseCharge(p, f string) (float32, error) {
	pi, err := strconv.ParseInt(p, 10, 0)
	if err != nil {
		return 0.0, err
	}
	fi, err := strconv.ParseInt(f, 10, 0)
	if err != nil {
		return 0.0, err
	}
	return float32(pi) / float32(fi), nil
}

func main() {
	bat, err := getBatteries()
	if err != nil {
		log.Fatalf("failed to get battery info: %v\n", err)
	}
	for i, b := range bat {
		log.Printf("[Battery %d]: %+v\n", i, b)
	}
}
<|endoftext|>


<commit_before>package tools

import (
	"encoding/json"
	"fmt"
	"github.com/Sirupsen/logrus"
	"github.com/asaskevich/govalidator"
	"github.com/kujtimiihoxha/plis/cmd"
	"github.com/kujtimiihoxha/plis/config"
	"github.com/kujtimiihoxha/plis/fs"
	"github.com/kujtimiihoxha/plis/helpers"
	"github.com/kujtimiihoxha/plis/logger"
	"github.com/kujtimiihoxha/plis/runtime"
	"github.com/kujtimiihoxha/plis/runtime/js"
	"github.com/kujtimiihoxha/plis/runtime/lua"
	"github.com/spf13/afero"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"os"
	"strings"
)

func find() (globalTools []string, projectTools []string) {
	dirs, err := afero.ReadDir(fs.GetPlisRootFs(), "tools")
	if err != nil {
		logger.GetLogger().Fatal(err)
	}
	for _, f := range dirs {
		if !strings.HasPrefix(f.Name(), ".") && strings.HasPrefix(f.Name(), "plis-") {
			globalTools = append(globalTools, strings.TrimPrefix(f.Name(), "plis-"))
		}
	}
	dirs, err = afero.ReadDir(fs.GetCurrentFs(), "plis"+afero.FilePathSeparator+"tools")
	if err != nil {
		if os.IsNotExist(err) {
			logger.GetLogger().Info("No project tools.")
		} else {
			logger.GetLogger().Fatal(err)
		}
	}
	for _, f := range dirs {
		if !strings.HasPrefix(f.Name(), ".") && strings.HasPrefix(f.Name(), "plis-") {
			projectTools = append(projectTools, strings.TrimPrefix(f.Name(), "plis-"))
		}
	}
	return
}
func Initialize() {
	globalTools, projectTools := find()
	for _, v := range globalTools {
		gFs := afero.NewBasePathFs(
			fs.GetPlisRootFs(),
			fmt.Sprintf("tools%splis-%s", afero.FilePathSeparator, v),
		)
		viper.Set(
			fmt.Sprintf("plis.tools.%s.root", v),
			fmt.Sprintf(
				"%s%stools%splis-%s",
				viper.GetString("plis.dir.root"),
				afero.FilePathSeparator,
				afero.FilePathSeparator,
				v,
			),
		)
		createToolCmd(gFs, cmd.RootCmd, v)
	}
	for _, v := range projectTools {
		if v == "get" || v == "install" {
			logger.GetLogger().Warnf("The commandd '%s' is a build in command so it can not be used", v)
			continue
		}
		toRemove := []*cobra.Command{}
		for _, gcmd := range cmd.RootCmd.Commands() {
			if gcmd.Name() == v {
				logger.GetLogger().Warnf(
					"The commandd '%s' exists as a global command it will be replaced by the project level command",
					v,
				)
				toRemove = append(toRemove, gcmd)
			}
		}
		cmd.RootCmd.RemoveCommand(toRemove...)
		gFs := afero.NewBasePathFs(fs.GetCurrentFs(), fmt.Sprintf("plis%stools%splis-%s", afero.FilePathSeparator, afero.FilePathSeparator, v))
		dr, _ := os.Getwd()
		viper.Set(
			fmt.Sprintf("plis.tools.%s.root", v),
			fmt.Sprintf(
				"%s%splis%stools%splis-%s",
				dr,
				afero.FilePathSeparator,
				afero.FilePathSeparator,
				afero.FilePathSeparator,
				v,
			),
		)
		createToolCmd(gFs, cmd.RootCmd, v)
	}
	checkIfToolProject()
}
func createToolCmd(fs afero.Fs, cmd *cobra.Command, tool string) {
	d, err := afero.ReadFile(fs, "config.json")
	if err != nil {
		logger.GetLogger().Errorf(
			"Tool `%s` has no config file and it will be ignored",
			tool,
		)
		return
	}
	c := config.ToolConfig{}
	err = json.Unmarshal(d, &c)
	if err != nil {
		logger.GetLogger().Errorf(
			"Could not read the config file of `%s` tool, this tool will be ignored",
			tool,
		)
		return
	}
	if c.Name == "" {
		c.Name = tool
	}
	addCmd(cmd, c, fs)
}
func addCmd(cmd *cobra.Command, c config.ToolConfig, gFs afero.Fs) {
	logger.GetLogger().Infof("Validating tool `%s`...", c.Name)
	if c.Validate() {
		logger.GetLogger().Info("Validation Ok")
		logger.GetLogger().Info("Validating flags...")
		flagsToKeep := []config.ToolFlag{}
		for _, v := range c.Flags {
			if v.Validate() {
				logger.GetLogger().Infof("Flag `%s` OK", v.Name)
				flagsToKeep = append(flagsToKeep, v)
			} else {
				logger.GetLogger().Warn("This flag will be ignored")
			}
		}
		c.Flags = flagsToKeep
		logger.GetLogger().Info("Validating args...")
		argsToKeep := []config.ToolArgs{}
		for _, v := range c.Args {
			if v.Validate() {
				logger.GetLogger().Infof("Argument `%s` OK", v.Name)
				argsToKeep = append(argsToKeep, v)
			} else {
				logger.GetLogger().Warn("This argument will be ignored")
			}
		}
		c.Args = argsToKeep

	} else {
		logger.GetLogger().Warn("This comand will be ignored")
		return
	}
	newC := createCommand(c, gFs)
	cmd.AddCommand(newC)
	for _, v := range c.SubCommands {
		_gFs := afero.NewBasePathFs(gFs, v)
		createToolCmd(_gFs, newC, v)
	}
	// update viper base.
}
func createCommand(c config.ToolConfig, gFs afero.Fs) *cobra.Command {
	genCmd := &cobra.Command{
		Use:     c.Name,
		Short:   c.Description,
		Long:    helpers.FromStringArrayToString(c.LongDescription),
		Aliases: c.Aliases,
	}
	addFlags(genCmd, c)
	genCmd.SetHelpTemplate(getUsageTemplate())
	switch c.ScriptType {
	case "lua":
		runtime.AddRuntime(genCmd, c, lua.NewLuaRuntime(gFs))
	case "js":
		runtime.AddRuntime(genCmd, c, js.NewJsRuntime(gFs))
	default:
		runtime.AddRuntime(genCmd, c, lua.NewLuaRuntime(gFs))
	}
	return genCmd
}
func addFlags(command *cobra.Command, c config.ToolConfig) {
	for _, v := range c.Flags {
		if v.Persistent {
			switch v.Type {
			case "string":
				command.PersistentFlags().StringP(v.Name, v.Short, v.Default.(string), v.Description)
			case "int":
				f := v.Default.(float64)
				iv := int(f)
				command.PersistentFlags().IntP(v.Name, v.Short, iv, v.Description)
			case "float":
				f := v.Default.(float64)
				command.PersistentFlags().Float64P(v.Name, v.Short, f, v.Description)
			case "bool":
				b := v.Default.(bool)
				command.PersistentFlags().BoolP(v.Name, v.Short, b, v.Description)
			}
		} else {
			switch v.Type {
			case "string":
				command.Flags().StringP(v.Name, v.Short, v.Default.(string), v.Description)
			case "int":
				f := v.Default.(float64)
				iv := int(f)
				command.Flags().IntP(v.Name, v.Short, iv, v.Description)
			case "float":
				f := v.Default.(float64)
				command.Flags().Float64P(v.Name, v.Short, f, v.Description)
			case "bool":
				b := v.Default.(bool)
				command.Flags().BoolP(v.Name, v.Short, b, v.Description)
			}
		}
	}
}
func getUsageTemplate() string {
	return `Usage:{{if .Runnable}}
  {{if .HasAvailableFlags}}{{appendIfNotPresent .UseLine "[flags]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
  {{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}}
Aliases:
  {{.NameAndAliases}}
{{end}}{{if .HasExample}}
Examples:
{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}}
Available Commands:{{range .Commands}}{{if .IsAvailableCommand}}
  {{rpad .NameAndAliases .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}}
Flags:
{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableInheritedFlags}}
Global Flags:
{{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}}
Additional help topics:{{range .Commands}}{{if .IsHelpCommand}}
  {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableSubCommands }}
Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
`
}
func checkIfToolProject() {
	logger.SetLevel(logrus.InfoLevel)
	d, err := afero.ReadFile(fs.GetCurrentFs(), ".plis-tool.json")
	if err != nil {
		return
	}
	c := config.ToolProjectConfig{}
	err = json.Unmarshal(d, &c)
	if err != nil {
		logger.GetLogger().Error(
			"Could not read the tool project config file",
			err,
		)
		return
	}
	v, _ := govalidator.ValidateStruct(c)
	if !v {
		logger.GetLogger().Error(
			"Could not calidate the tool project config file, make sure you specified all the required fields",
		)
		return
	}
	currentFs := fs.GetCurrentFs()
	fs.SetToolTestFs(afero.NewBasePathFs(currentFs, c.TestDir))
	viper.Set("plis.tool_project_name", c.ToolName)
	dr, _ := os.Getwd()
	viper.Set(
		fmt.Sprintf("plis.tools.%s.root", c.ToolName),
		fmt.Sprintf(
			dr,
		),
	)
	createToolCmd(currentFs, cmd.RootCmd, c.ToolName)

}
<commit_msg>Fix tool project command creation.<commit_after>package tools

import (
	"encoding/json"
	"fmt"
	"github.com/Sirupsen/logrus"
	"github.com/asaskevich/govalidator"
	"github.com/kujtimiihoxha/plis/cmd"
	"github.com/kujtimiihoxha/plis/config"
	"github.com/kujtimiihoxha/plis/fs"
	"github.com/kujtimiihoxha/plis/helpers"
	"github.com/kujtimiihoxha/plis/logger"
	"github.com/kujtimiihoxha/plis/runtime"
	"github.com/kujtimiihoxha/plis/runtime/js"
	"github.com/kujtimiihoxha/plis/runtime/lua"
	"github.com/spf13/afero"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"os"
	"strings"
)

func find() (globalTools []string, projectTools []string) {
	dirs, err := afero.ReadDir(fs.GetPlisRootFs(), "tools")
	if err != nil {
		logger.GetLogger().Fatal(err)
	}
	for _, f := range dirs {
		if !strings.HasPrefix(f.Name(), ".") && strings.HasPrefix(f.Name(), "plis-") {
			globalTools = append(globalTools, strings.TrimPrefix(f.Name(), "plis-"))
		}
	}
	dirs, err = afero.ReadDir(fs.GetCurrentFs(), "plis"+afero.FilePathSeparator+"tools")
	if err != nil {
		if os.IsNotExist(err) {
			logger.GetLogger().Info("No project tools.")
		} else {
			logger.GetLogger().Fatal(err)
		}
	}
	for _, f := range dirs {
		if !strings.HasPrefix(f.Name(), ".") && strings.HasPrefix(f.Name(), "plis-") {
			projectTools = append(projectTools, strings.TrimPrefix(f.Name(), "plis-"))
		}
	}
	return
}
func Initialize() {
	globalTools, projectTools := find()
	for _, v := range globalTools {
		gFs := afero.NewBasePathFs(
			fs.GetPlisRootFs(),
			fmt.Sprintf("tools%splis-%s", afero.FilePathSeparator, v),
		)
		viper.Set(
			fmt.Sprintf("plis.tools.%s.root", v),
			fmt.Sprintf(
				"%s%stools%splis-%s",
				viper.GetString("plis.dir.root"),
				afero.FilePathSeparator,
				afero.FilePathSeparator,
				v,
			),
		)
		createToolCmd(gFs, cmd.RootCmd, v)
	}
	for _, v := range projectTools {
		if v == "get" || v == "install" {
			logger.GetLogger().Warnf("The commandd '%s' is a build in command so it can not be used", v)
			continue
		}
		toRemove := []*cobra.Command{}
		for _, gcmd := range cmd.RootCmd.Commands() {
			if gcmd.Name() == v {
				logger.GetLogger().Warnf(
					"The commandd '%s' exists as a global command it will be replaced by the project level command",
					v,
				)
				toRemove = append(toRemove, gcmd)
			}
		}
		cmd.RootCmd.RemoveCommand(toRemove...)
		gFs := afero.NewBasePathFs(fs.GetCurrentFs(), fmt.Sprintf("plis%stools%splis-%s", afero.FilePathSeparator, afero.FilePathSeparator, v))
		dr, _ := os.Getwd()
		viper.Set(
			fmt.Sprintf("plis.tools.%s.root", v),
			fmt.Sprintf(
				"%s%splis%stools%splis-%s",
				dr,
				afero.FilePathSeparator,
				afero.FilePathSeparator,
				afero.FilePathSeparator,
				v,
			),
		)
		createToolCmd(gFs, cmd.RootCmd, v)
	}
	checkIfToolProject()
}
func createToolCmd(fs afero.Fs, cmd *cobra.Command, tool string) {
	d, err := afero.ReadFile(fs, "config.json")
	if err != nil {
		logger.GetLogger().Errorf(
			"Tool `%s` has no config file and it will be ignored",
			tool,
		)
		return
	}
	c := config.ToolConfig{}
	err = json.Unmarshal(d, &c)
	if err != nil {
		logger.GetLogger().Errorf(
			"Could not read the config file of `%s` tool, this tool will be ignored",
			tool,
		)
		return
	}
	if c.Name == "" {
		c.Name = tool
	}
	addCmd(cmd, c, fs)
}
func addCmd(cmd *cobra.Command, c config.ToolConfig, gFs afero.Fs) {
	logger.GetLogger().Infof("Validating tool `%s`...", c.Name)
	if c.Validate() {
		logger.GetLogger().Info("Validation Ok")
		logger.GetLogger().Info("Validating flags...")
		flagsToKeep := []config.ToolFlag{}
		for _, v := range c.Flags {
			if v.Validate() {
				logger.GetLogger().Infof("Flag `%s` OK", v.Name)
				flagsToKeep = append(flagsToKeep, v)
			} else {
				logger.GetLogger().Warn("This flag will be ignored")
			}
		}
		c.Flags = flagsToKeep
		logger.GetLogger().Info("Validating args...")
		argsToKeep := []config.ToolArgs{}
		for _, v := range c.Args {
			if v.Validate() {
				logger.GetLogger().Infof("Argument `%s` OK", v.Name)
				argsToKeep = append(argsToKeep, v)
			} else {
				logger.GetLogger().Warn("This argument will be ignored")
			}
		}
		c.Args = argsToKeep

	} else {
		logger.GetLogger().Warn("This comand will be ignored")
		return
	}
	newC := createCommand(c, gFs)
	cmd.AddCommand(newC)
	for _, v := range c.SubCommands {
		_gFs := afero.NewBasePathFs(gFs, v)
		createToolCmd(_gFs, newC, v)
	}
	// update viper base.
}
func createCommand(c config.ToolConfig, gFs afero.Fs) *cobra.Command {
	genCmd := &cobra.Command{
		Use:     c.Name,
		Short:   c.Description,
		Long:    helpers.FromStringArrayToString(c.LongDescription),
		Aliases: c.Aliases,
	}
	addFlags(genCmd, c)
	genCmd.SetHelpTemplate(getUsageTemplate())
	switch c.ScriptType {
	case "lua":
		runtime.AddRuntime(genCmd, c, lua.NewLuaRuntime(gFs))
	case "js":
		runtime.AddRuntime(genCmd, c, js.NewJsRuntime(gFs))
	default:
		runtime.AddRuntime(genCmd, c, lua.NewLuaRuntime(gFs))
	}
	return genCmd
}
func addFlags(command *cobra.Command, c config.ToolConfig) {
	for _, v := range c.Flags {
		if v.Persistent {
			switch v.Type {
			case "string":
				command.PersistentFlags().StringP(v.Name, v.Short, v.Default.(string), v.Description)
			case "int":
				f := v.Default.(float64)
				iv := int(f)
				command.PersistentFlags().IntP(v.Name, v.Short, iv, v.Description)
			case "float":
				f := v.Default.(float64)
				command.PersistentFlags().Float64P(v.Name, v.Short, f, v.Description)
			case "bool":
				b := v.Default.(bool)
				command.PersistentFlags().BoolP(v.Name, v.Short, b, v.Description)
			}
		} else {
			switch v.Type {
			case "string":
				command.Flags().StringP(v.Name, v.Short, v.Default.(string), v.Description)
			case "int":
				f := v.Default.(float64)
				iv := int(f)
				command.Flags().IntP(v.Name, v.Short, iv, v.Description)
			case "float":
				f := v.Default.(float64)
				command.Flags().Float64P(v.Name, v.Short, f, v.Description)
			case "bool":
				b := v.Default.(bool)
				command.Flags().BoolP(v.Name, v.Short, b, v.Description)
			}
		}
	}
}
func getUsageTemplate() string {
	return `Usage:{{if .Runnable}}
  {{if .HasAvailableFlags}}{{appendIfNotPresent .UseLine "[flags]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
  {{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}}
Aliases:
  {{.NameAndAliases}}
{{end}}{{if .HasExample}}
Examples:
{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}}
Available Commands:{{range .Commands}}{{if .IsAvailableCommand}}
  {{rpad .NameAndAliases .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}}
Flags:
{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableInheritedFlags}}
Global Flags:
{{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}}
Additional help topics:{{range .Commands}}{{if .IsHelpCommand}}
  {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableSubCommands }}
Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
`
}
func checkIfToolProject() {
	logger.SetLevel(logrus.InfoLevel)
	d, err := afero.ReadFile(fs.GetCurrentFs(), ".plis-tool.json")
	if err != nil {
		return
	}
	c := config.ToolProjectConfig{}
	err = json.Unmarshal(d, &c)
	if err != nil {
		logger.GetLogger().Error(
			"Could not read the tool project config file",
			err,
		)
		return
	}
	v, _ := govalidator.ValidateStruct(c)
	if !v {
		logger.GetLogger().Error(
			"Could not calidate the tool project config file, make sure you specified all the required fields",
		)
		return
	}
	currentFs := fs.GetCurrentFs()
	fs.SetToolTestFs(afero.NewBasePathFs(currentFs, c.TestDir))
	viper.Set("plis.tool_project_name", c.ToolName)
	dr, _ := os.Getwd()
	viper.Set(
		fmt.Sprintf("plis.tools.%s.root", c.ToolName),
		fmt.Sprintf(
			dr,
		),
	)
	toRemove := []*cobra.Command{}
	for _, gcmd := range cmd.RootCmd.Commands() {
		if gcmd.Name() == c.ToolName {
			logger.GetLogger().Warnf(
				"The commandd '%s' exists as a global command it will be replaced by the project level command",
				c.ToolName,
			)
			toRemove = append(toRemove, gcmd)
		}
	}
	cmd.RootCmd.RemoveCommand(toRemove...)
	createToolCmd(currentFs, cmd.RootCmd, c.ToolName)

}
<|endoftext|>