<commit_before>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom

import (
	"encoding/json"
	"fmt"
)

// FBlock represents a Factoid Block returned from factomd.
// Note: the FBlock api return does not use a "Header" field like the other
// block types do for some reason.
type FBlock struct {
	BodyMR          string `json:"bodymr"`          // Merkle root of the Factoid transactions which accompany this block.
	PrevKeyMR       string `json:"prevkeymr"`       // Key Merkle root of previous block.
	PrevLedgerKeyMR string `json:"prevledgerkeymr"` // Sha3 of the previous Factoid Block
	ExchRate        int64  `json:"exchrate"`        // Factoshis per Entry Credit
	DBHeight        int64  `json:"dbheight"`        // Directory Block height

	Transactions []Transaction `json:"transactions"`
}

func (f *FBlock) String() string {
	var s string

	s += fmt.Sprintln("BodyMR:", f.BodyMR)
	s += fmt.Sprintln("PrevKeyMR:", f.PrevKeyMR)
	s += fmt.Sprintln("PrevLedgerKeyMR:", f.PrevLedgerKeyMR)
	s += fmt.Sprintln("ExchRate:", f.ExchRate)
	s += fmt.Sprintln("DBHeight:", f.DBHeight)

	s += fmt.Sprintln("Transactions {")
	for _, t := range f.Transactions {
		s += fmt.Sprintln(t)
	}
	s += fmt.Sprintln("}")

	return s
}

// GetFblock requests a specified Factoid Block from factomd.
func GetFBlock(keymr string) (*FBlock, error) {
	params := keyMRRequest{KeyMR: keymr}
	req := NewJSON2Request("factoid-block", APICounter(), params)
	resp, err := factomdRequest(req)
	if err != nil {
		return nil, err
	}
	if resp.Error != nil {
		return nil, resp.Error
	}

	// Create temporary struct to unmarshal json object
	f := new(struct {
		FBlock *FBlock `json:"fblock"`
	})

	if err := json.Unmarshal(resp.JSONResult(), f); err != nil {
		return nil, err
	}

	return f.FBlock, nil
}
<commit_msg>rename for wrapper type<commit_after>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom

import (
	"encoding/json"
	"fmt"
)

// FBlock represents a Factoid Block returned from factomd.
// Note: the FBlock api return does not use a "Header" field like the other
// block types do for some reason.
type FBlock struct {
	BodyMR          string `json:"bodymr"`          // Merkle root of the Factoid transactions which accompany this block.
	PrevKeyMR       string `json:"prevkeymr"`       // Key Merkle root of previous block.
	PrevLedgerKeyMR string `json:"prevledgerkeymr"` // Sha3 of the previous Factoid Block
	ExchRate        int64  `json:"exchrate"`        // Factoshis per Entry Credit
	DBHeight        int64  `json:"dbheight"`        // Directory Block height

	Transactions []Transaction `json:"transactions"`
}

func (f *FBlock) String() string {
	var s string

	s += fmt.Sprintln("BodyMR:", f.BodyMR)
	s += fmt.Sprintln("PrevKeyMR:", f.PrevKeyMR)
	s += fmt.Sprintln("PrevLedgerKeyMR:", f.PrevLedgerKeyMR)
	s += fmt.Sprintln("ExchRate:", f.ExchRate)
	s += fmt.Sprintln("DBHeight:", f.DBHeight)

	s += fmt.Sprintln("Transactions {")
	for _, t := range f.Transactions {
		s += fmt.Sprintln(t)
	}
	s += fmt.Sprintln("}")

	return s
}

// GetFblock requests a specified Factoid Block from factomd.
func GetFBlock(keymr string) (*FBlock, error) {
	params := keyMRRequest{KeyMR: keymr}
	req := NewJSON2Request("factoid-block", APICounter(), params)
	resp, err := factomdRequest(req)
	if err != nil {
		return nil, err
	}
	if resp.Error != nil {
		return nil, resp.Error
	}

	// Create temporary struct to unmarshal json object
	wrap := new(struct {
		FBlock *FBlock `json:"fblock"`
	})

	if err := json.Unmarshal(resp.JSONResult(), wrap); err != nil {
		return nil, err
	}

	return wrap.FBlock, nil
}
<|endoftext|>


<commit_before>package form

// For keeping a list of enclosed functions for struct pointer fields.
type FieldFuncs map[string]func(m map[string]interface{})

// Attemp to call a function in FieldFuncs. Does not call if function does not exist.
func (fns FieldFuncs) Call(name string, m map[string]interface{}) {
	if fns[name] == nil {
		return
	}
	fns[name](m)
}

type Field struct {
	name  string
	funcs FieldFuncs
}

// Fields
type Fields struct {
	m  map[string]FieldFuncs
	n  map[string]*Field
	nm map[string]*Field
	f  []*Field
}

// Init Field
func (f *Fields) Init(fieldname string, typeCode TypeCode) FieldFuncs {
	if f.m[fieldname] != nil {
		return f.m[fieldname]
	}

	fns := FieldFuncs{
		"init": func(m map[string]interface{}) {
			*(m["type"].(*TypeCode)) = typeCode
		},
	}
	afield := &Field{fieldname, fns}
	if f.nm != nil {
		f.nm[fieldname] = afield
	}
	if f.n != nil {
		fns["set_name"] = func(m map[string]interface{}) {
			name := m["set_name"].(string)
			f.n[name] = afield
		}
	}
	f.m[fieldname] = fns
	f.f = append(f.f, afield)
	return fns
}
<commit_msg>Slight improvement<commit_after>package form

// For keeping a list of enclosed functions for struct pointer fields.
type FieldFuncs map[string]func(m map[string]interface{})

// Attemp to call a function in FieldFuncs. Does not call if function does not exist.
func (fns FieldFuncs) Call(name string, m map[string]interface{}) {
	if fns[name] == nil {
		return
	}
	fns[name](m)
}

type Field struct {
	name  string
	funcs FieldFuncs
}

// Fields
type Fields struct {
	m  map[string]FieldFuncs
	n  map[string]*Field
	nm map[string]*Field
	f  []*Field
}

// Init Field
func (f *Fields) Init(fieldname string, typeCode TypeCode) FieldFuncs {
	if f.m[fieldname] != nil {
		return f.m[fieldname]
	}

	fns := FieldFuncs{
		"init": func(m map[string]interface{}) {
			*(m["type"].(*TypeCode)) = typeCode
		},
	}
	afield := &Field{fieldname, fns}
	if f.nm != nil {
		f.nm[fieldname] = afield
	}
	if f.n != nil {
		fns["set_name"] = func(m map[string]interface{}) {
			name := m["set_name"].(string)
			f.n[name] = afield
		}
	}
	f.m[fieldname] = fns
	if f.f != nil {
		f.f = append(f.f, afield)
	}
	return fns
}
<|endoftext|>


<commit_before>package async

import (
  "reflect"
)

/*

  Filter out information from a slice in Waterfall mode.

  You must call the Done function with false as its first argument if you do
  not want the data to be present in the results. No other arguments will
  affect the performance of this function. When calling the Done function,
  an error will cause the filtering to immediately exit.

  For example, take a look at one of the tests for this function:
    func TestFilterString(t *testing.T) {
      str := []string{
        "test1",
        "test2",
        "test3",
        "test4",
        "test5",
      }

      expects := []string{
        "test1",
        "test2",
        "test4",
        "test5",
      }

      mapper := func(done Done, args ...interface{}) {
        Status("Hit string")
        Status("Args: %+v\n", args)
        if args[0] == "test3" {
          // We don't want this result in our return, so we send false back
          // as the first argument.
          done(nil, false)
          return
        }
        // We want anything else that we get, so we return true here.
        done(nil, true)
      }

      final := func(err error, results ...interface{}) {
        Status("Hit string end")
        Status("Results: %+v\n", results)
        for i := 0; i < len(results); i++ {
          if results[i] != expects[i] {
            t.Errorf("Did not filter correctly.")
            break
          }
        }
      }

      Filter(str, mapper, final)
    }

  Each Routine function will be passed the current value and its index the
  slice for its arguments.

*/
func Filter(data interface{}, routine Routine, callbacks ...Done) {
  var (
    routines []Routine
    results  []interface{}
  )

  d := reflect.ValueOf(data)

  for i := 0; i < d.Len(); i++ {
    v := d.Index(i).Interface()
    routines = append(routines, func(id int) Routine {
      return func(done Done, args ...interface{}) {
        done = func(original Done) Done {
          return func(err error, args ...interface{}) {

            if args[0] != false {
              results = append(results, v)
            }
            if id == (d.Len() - 1) {
              original(err, results...)
              return
            }
            original(err, args...)
          }
        }(done)

        routine(done, v, id)
      }
    }(i))
  }

  Waterfall(routines, callbacks...)
}

/*

  Filter out information from a slice in Parallel mode.

  You must call the Done function with false as its first argument if you do
  not want the data to be present in the results. No other arguments will
  affect the performance of this function. When calling the Done function,
  an error will cause the filtering to immediately exit.

  For example, take a look at one of the tests for this function:
    func TestFilterStringParallel(t *testing.T) {
      str := []string{
        "test1",
        "test2",
        "test3",
        "test4",
        "test5",
      }

      expects := []string{
        "test1",
        "test2",
        "test4",
        "test5",
      }

      mapper := func(done Done, args ...interface{}) {
        Status("Hit string")
        Status("Args: %+v\n", args)
        if args[0] == "test3" {
          done(nil, false)
          return
        }
        done(nil, true)
      }

      final := func(err error, results ...interface{}) {
        Status("Hit string end")
        Status("Results: %+v\n", results)
        for i := 0; i < len(results); i++ {
          if results[i] != expects[i] {
            t.Errorf("Did not filter correctly.")
            break
          }
        }
      }

      FilterParallel(str, mapper, final)
    }

  Each Routine function will be passed the current value and its index the
  slice for its arguments.

  The output of filtering in Parallel mode cannot be guaranteed to stay in the
  same order, due to the fact that it may take longer to process some things
  in your filter routine. If you need the data to stay in the order it is in,
  use Filter instead to ensure it stays in order.

*/
func FilterParallel(data interface{}, routine Routine, callbacks ...Done) {
  var routines []Routine

  d := reflect.ValueOf(data)

  for i := 0; i < d.Len(); i++ {
    v := d.Index(i).Interface()
    routines = append(routines, func(id int) Routine {
      return func(done Done, args ...interface{}) {
        done = func(original Done) Done {
          return func(err error, args ...interface{}) {
            if args[0] != false {
              original(err, v)
            }
          }
        }(done)

        routine(done, v, id)
      }
    }(i))
  }

  Parallel(routines, callbacks...)
}
<commit_msg>Ensure FilterParallel handles all data<commit_after>package async

import (
  "reflect"
)

/*

  Filter out information from a slice in Waterfall mode.

  You must call the Done function with false as its first argument if you do
  not want the data to be present in the results. No other arguments will
  affect the performance of this function. When calling the Done function,
  an error will cause the filtering to immediately exit.

  For example, take a look at one of the tests for this function:
    func TestFilterString(t *testing.T) {
      str := []string{
        "test1",
        "test2",
        "test3",
        "test4",
        "test5",
      }

      expects := []string{
        "test1",
        "test2",
        "test4",
        "test5",
      }

      mapper := func(done Done, args ...interface{}) {
        Status("Hit string")
        Status("Args: %+v\n", args)
        if args[0] == "test3" {
          // We don't want this result in our return, so we send false back
          // as the first argument.
          done(nil, false)
          return
        }
        // We want anything else that we get, so we return true here.
        done(nil, true)
      }

      final := func(err error, results ...interface{}) {
        Status("Hit string end")
        Status("Results: %+v\n", results)
        for i := 0; i < len(results); i++ {
          if results[i] != expects[i] {
            t.Errorf("Did not filter correctly.")
            break
          }
        }
      }

      Filter(str, mapper, final)
    }

  Each Routine function will be passed the current value and its index the
  slice for its arguments.

*/
func Filter(data interface{}, routine Routine, callbacks ...Done) {
  var (
    routines []Routine
    results  []interface{}
  )

  d := reflect.ValueOf(data)

  for i := 0; i < d.Len(); i++ {
    v := d.Index(i).Interface()
    routines = append(routines, func(id int) Routine {
      return func(done Done, args ...interface{}) {
        done = func(original Done) Done {
          return func(err error, args ...interface{}) {
            if args[0] != false {
              results = append(results, v)
            }
            if id == (d.Len() - 1) {
              original(err, results...)
              return
            }
            original(err, args...)
          }
        }(done)

        routine(done, v, id)
      }
    }(i))
  }

  Waterfall(routines, callbacks...)
}

/*

  Filter out information from a slice in Parallel mode.

  You must call the Done function with false as its first argument if you do
  not want the data to be present in the results. No other arguments will
  affect the performance of this function. When calling the Done function,
  an error will cause the filtering to immediately exit.

  For example, take a look at one of the tests for this function:
    func TestFilterStringParallel(t *testing.T) {
      str := []string{
        "test1",
        "test2",
        "test3",
        "test4",
        "test5",
      }

      expects := []string{
        "test1",
        "test2",
        "test4",
        "test5",
      }

      mapper := func(done Done, args ...interface{}) {
        Status("Hit string")
        Status("Args: %+v\n", args)
        if args[0] == "test3" {
          done(nil, false)
          return
        }
        done(nil, true)
      }

      final := func(err error, results ...interface{}) {
        Status("Hit string end")
        Status("Results: %+v\n", results)
        for i := 0; i < len(results); i++ {
          if results[i] != expects[i] {
            t.Errorf("Did not filter correctly.")
            break
          }
        }
      }

      FilterParallel(str, mapper, final)
    }

  Each Routine function will be passed the current value and its index the
  slice for its arguments.

  The output of filtering in Parallel mode cannot be guaranteed to stay in the
  same order, due to the fact that it may take longer to process some things
  in your filter routine. If you need the data to stay in the order it is in,
  use Filter instead to ensure it stays in order.

*/
func FilterParallel(data interface{}, routine Routine, callbacks ...Done) {
  var routines []Routine

  d := reflect.ValueOf(data)

  for i := 0; i < d.Len(); i++ {
    v := d.Index(i).Interface()
    routines = append(routines, func(id int) Routine {
      return func(done Done, args ...interface{}) {
        done = func(original Done) Done {
          return func(err error, args ...interface{}) {
            if args[0] != false {
              original(err, v)
              return
            }
            original(err)
          }
        }(done)

        routine(done, v, id)
      }
    }(i))
  }

  Parallel(routines, callbacks...)
}
<|endoftext|>


<commit_before>package logrus_fluent

import (
	"github.com/Sirupsen/logrus"
	"github.com/fluent/fluent-logger-golang/fluent"
)

const (
	TagField     = "tag"
	MessageField = "message"
	DefaultTag   = "log"

	RFC3339Milli = "2006-01-02T15:04:05.999Z07:00"
)

var defaultLevels = []logrus.Level{
	logrus.PanicLevel,
	logrus.FatalLevel,
	logrus.ErrorLevel,
	logrus.WarnLevel,
	logrus.InfoLevel,
}

type fluentHook struct {
	Logger *fluent.Fluent
	levels []logrus.Level
}

func NewHook(host string, port int) (*fluentHook, error) {
	logger, err := fluent.New(fluent.Config{
		FluentHost: host,
		FluentPort: port,
	})
	if err != nil {
		return nil, err
	}
	return &fluentHook{
		Logger: logger,
		levels: defaultLevels,
	}, nil
}

func getTagAndDel(entry *logrus.Entry) string {
	var v interface{}
	var ok bool
	if v, ok = entry.Data[TagField]; !ok {
		return DefaultTag
	}

	var val string
	if val, ok = v.(string); !ok {
		return DefaultTag
	}
	delete(entry.Data, TagField)
	return val
}

func setLevelString(entry *logrus.Entry) {
	entry.Data["level"] = entry.Level.String()
}

func setMessage(entry *logrus.Entry) {
	if _, ok := entry.Data[MessageField]; !ok {
		entry.Data[MessageField] = entry.Message
	}
}

func (hook *fluentHook) Fire(entry *logrus.Entry) error {
	setLevelString(entry)
	tag := getTagAndDel(entry)
	setMessage(entry)

	data := ConvertFields(entry.Data)
	data["@timestamp"] = entry.Time.Format(RFC3339Milli)
	return hook.Logger.PostWithTime(tag, entry.Time, data)
}

func (hook *fluentHook) Levels() []logrus.Level {
	return hook.levels
}

func (hook *fluentHook) SetLevels(levels []logrus.Level) {
	hook.levels = levels
}
<commit_msg>Switch to RFC3339Nano timestamp<commit_after>package logrus_fluent

import (
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/fluent/fluent-logger-golang/fluent"
)

const (
	TagField     = "tag"
	MessageField = "message"
	DefaultTag   = "log"
)

var defaultLevels = []logrus.Level{
	logrus.PanicLevel,
	logrus.FatalLevel,
	logrus.ErrorLevel,
	logrus.WarnLevel,
	logrus.InfoLevel,
}

type fluentHook struct {
	Logger *fluent.Fluent
	levels []logrus.Level
}

func NewHook(host string, port int) (*fluentHook, error) {
	logger, err := fluent.New(fluent.Config{
		FluentHost: host,
		FluentPort: port,
	})
	if err != nil {
		return nil, err
	}
	return &fluentHook{
		Logger: logger,
		levels: defaultLevels,
	}, nil
}

func getTagAndDel(entry *logrus.Entry) string {
	var v interface{}
	var ok bool
	if v, ok = entry.Data[TagField]; !ok {
		return DefaultTag
	}

	var val string
	if val, ok = v.(string); !ok {
		return DefaultTag
	}
	delete(entry.Data, TagField)
	return val
}

func setLevelString(entry *logrus.Entry) {
	entry.Data["level"] = entry.Level.String()
}

func setMessage(entry *logrus.Entry) {
	if _, ok := entry.Data[MessageField]; !ok {
		entry.Data[MessageField] = entry.Message
	}
}

func (hook *fluentHook) Fire(entry *logrus.Entry) error {
	setLevelString(entry)
	tag := getTagAndDel(entry)
	setMessage(entry)

	data := ConvertFields(entry.Data)
	data["@timestamp"] = entry.Time.UTC().Format(time.RFC3339Nano)
	return hook.Logger.PostWithTime(tag, entry.Time, data)
}

func (hook *fluentHook) Levels() []logrus.Level {
	return hook.levels
}

func (hook *fluentHook) SetLevels(levels []logrus.Level) {
	hook.levels = levels
}
<|endoftext|>


<commit_before>// Package formam implements functions to decode values of a html form.
package formam

import (
	"encoding"
	"errors"
	"fmt"
	"net/url"
	"reflect"
	"strconv"
	"strings"
	"time"
)

const TAG_NAME = "formam"

// A pathMap holds the values of a map with its key and values correspondent
type pathMap struct {
	m reflect.Value

	key   string
	value reflect.Value

	path string
}

// a pathMaps holds the values for each key
type pathMaps []*pathMap

// find find and get the value by the given key
func (ma pathMaps) find(id reflect.Value, key string) *pathMap {
	for _, v := range ma {
		if v.m == id && v.key == key {
			return v
		}
	}
	return nil
}

// A decoder holds the values from form, the 'reflect' value of main struct
// and the 'reflect' value of current path
type decoder struct {
	main reflect.Value

	curr reflect.Value
	typ  reflect.Type

	maps pathMaps

	path   string
	field  string
	value  string
	values []string
	index  int
}

// Decode decodes the url.Values into a element that must be a pointer to a type provided by argument
func Decode(vs url.Values, dst interface{}) error {
	main := reflect.ValueOf(dst)
	if main.Kind() != reflect.Ptr {
		return fmt.Errorf("formam: the value passed for decode is not a pointer but a %v", main.Kind())
	}
	d := &decoder{main: main.Elem()}
	for k, v := range vs {
		d.path = k
		d.field = k
		d.values = v
		d.value = v[0]
		if d.value != "" {
			if err := d.begin(); err != nil {
				return err
			}
		}
	}
	for _, v := range d.maps {
		key := v.m.Type().Key()
		switch key.Kind() {
		case reflect.String:
			// the key is a string
			v.m.SetMapIndex(reflect.ValueOf(v.key), v.value)
		default:
			// must to implement the TextUnmarshaler interface for to can to decode the map's key
			var vv reflect.Value

			if key.Kind() == reflect.Ptr {
				vv = reflect.New(key.Elem())
			} else {
				vv = reflect.New(key).Elem()
			}

			d.value = v.key
			ok, err := d.unmarshalText(vv)
			if !ok {
				return fmt.Errorf("formam: the key with %s type (%v) in the path %v should implements the TextUnmarshaler interface for to can decode it", key, v.m.Type(), v.path)
			}
			if err != nil {
				return fmt.Errorf("formam: an error has occured in the UnmarshalText method for type %s: %s", key, err)
			}

			v.m.SetMapIndex(vv, v.value)
		}
	}
	d.maps = []*pathMap{}
	return nil
}

// begin prepare the current path to walk through it
func (d *decoder) begin() (err error) {
	d.curr = d.main
	fields := strings.Split(d.field, ".")
	for i, field := range fields {
		b := strings.IndexAny(field, "[")
		if b != -1 {
			// is a array
			e := strings.IndexAny(field, "]")
			if e == -1 {
				return errors.New("formam: bad syntax array")
			}
			d.field = field[:b]
			if d.index, err = strconv.Atoi(field[b+1 : e]); err != nil {
				return errors.New("formam: the index of array is not a number")
			}
			if len(fields) == i+1 {
				return d.end()
			}
			if err = d.walk(); err != nil {
				return
			}
		} else {
			// not is a array
			d.field = field
			d.index = -1
			if len(fields) == i+1 {
				return d.end()
			}
			if err = d.walk(); err != nil {
				return
			}
		}
	}
	return
}

// walk traverses the current path until to the last field
func (d *decoder) walk() error {
	// check if is a struct or map
	switch d.curr.Kind() {
	case reflect.Struct:
		if err := d.findStructField(); err != nil {
			return err
		}
	case reflect.Map:
		d.currentMap()
	}
	// check if the struct or map is a interface
	if d.curr.Kind() == reflect.Interface {
		d.curr = d.curr.Elem()
	}
	// check if the struct or map is a pointer
	if d.curr.Kind() == reflect.Ptr {
		if d.curr.IsNil() {
			d.curr.Set(reflect.New(d.curr.Type().Elem()))
		}
		d.curr = d.curr.Elem()
	}
	// finally, check if there are access to slice/array or not...
	if d.index != -1 {
		switch d.curr.Kind() {
		case reflect.Slice, reflect.Array:
			if d.curr.Len() <= d.index {
				d.expandSlice(d.index + 1)
			}
			d.curr = d.curr.Index(d.index)
		default:
			return fmt.Errorf("formam: the field \"%v\" in path \"%v\" has a index for array but it is not", d.field, d.path)
		}
	}
	return nil
}

// end finds the last field for decode its value correspondent
func (d *decoder) end() error {
	if d.curr.Kind() == reflect.Struct {
		if err := d.findStructField(); err != nil {
			return err
		}
	}
	if d.value == "" {
		return nil
	}
	return d.decode()
}

// decode sets the value in the last field found by end function
func (d *decoder) decode() error {
	ok, err := d.unmarshalText(d.curr)
	if ok {
		return err
	} else if err != nil {
		return err
	}

	switch d.curr.Kind() {
	case reflect.Map:
		d.currentMap()
		return d.decode()
	case reflect.Slice, reflect.Array:
		if d.index == -1 {
			// not has index, so to decode all values in the slice/array
			d.expandSlice(len(d.values))
			tmp := d.curr
			for i, v := range d.values {
				d.curr = tmp.Index(i)
				d.value = v
				if err := d.decode(); err != nil {
					return err
				}
			}
			return nil
		}
		// has index, so to decode value by index indicated
		if d.curr.Len() <= d.index {
			d.expandSlice(d.index + 1)
		}
		d.curr = d.curr.Index(d.index)
		return d.decode()
	case reflect.String:
		d.curr.SetString(d.value)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if num, err := strconv.ParseInt(d.value, 10, 64); err != nil {
			return fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" should be a valid signed integer number", d.field, d.path)
		} else {
			d.curr.SetInt(num)
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		if num, err := strconv.ParseUint(d.value, 10, 64); err != nil {
			return fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" should be a valid unsigned integer number", d.field, d.path)
		} else {
			d.curr.SetUint(num)
		}
	case reflect.Float32, reflect.Float64:
		if num, err := strconv.ParseFloat(d.value, d.curr.Type().Bits()); err != nil {
			return fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" should be a valid float number", d.field, d.path)
		} else {
			d.curr.SetFloat(num)
		}
	case reflect.Bool:
		switch d.value {
		case "true", "on", "1":
			d.curr.SetBool(true)
		case "false", "off", "0":
			d.curr.SetBool(false)
		default:
			return fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" is not a valid boolean", d.field, d.path)
		}
	case reflect.Interface:
		d.curr.Set(reflect.ValueOf(d.value))
	case reflect.Ptr:
		d.curr.Set(reflect.New(d.curr.Type().Elem()))
		d.curr = d.curr.Elem()
		return d.decode()
	case reflect.Struct:
		switch d.curr.Interface().(type) {
		case time.Time:
			t, err := time.Parse("2006-01-02", d.value)
			if err != nil {
				return fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" is not a valid datetime", d.field, d.path)
			}
			d.curr.Set(reflect.ValueOf(t))
		case url.URL:
			u, err := url.Parse(d.value)
			if err != nil {
				return fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" is not a valid url", d.field, d.path)
			}
			d.curr.Set(reflect.ValueOf(*u))
		default:
			return fmt.Errorf("formam: not supported type for field \"%v\" in path \"%v\"", d.field, d.path)
		}
	default:
		return fmt.Errorf("formam: not supported type for field \"%v\" in path \"%v\"", d.field, d.path)
	}

	return nil
}

// findField finds a field by its name, if it is not found,
// then retry the search examining the tag "formam" of every field of struct
func (d *decoder) findStructField() error {
	var anon reflect.Value

	num := d.curr.NumField()
	for i := 0; i < num; i++ {
		field := d.curr.Type().Field(i)
		if field.Name == d.field {
			// check if the field's name is equal
			d.curr = d.curr.Field(i)
			return nil
		} else if field.Anonymous {
			// if the field is a anonymous struct, then iterate over its fields
			tmp := d.curr
			d.curr = d.curr.FieldByIndex(field.Index)
			if err := d.findStructField(); err != nil {
				d.curr = tmp
				continue
			}
			// field in anonymous struct is found,
			// but first it should found the field in the rest of struct
			// (a field with same name in the current struct should have preference over anonymous struct)
			anon = d.curr
			d.curr = tmp
		} else if d.field == field.Tag.Get(TAG_NAME) {
			// is not found yet, then retry by its tag name "formam"
			d.curr = d.curr.Field(i)
			return nil
		}
	}

	if anon.IsValid() {
		d.curr = anon
		return nil
	}

	return fmt.Errorf("formam: not found the field \"%v\" in the path \"%v\"", d.field, d.path)
}

// expandSlice expands the length and capacity of the current slice
func (d *decoder) expandSlice(length int) {
	sli := reflect.MakeSlice(d.curr.Type(), length, length)
	reflect.Copy(sli, d.curr)
	d.curr.Set(sli)
}

// currentMap gets in d.curr the map concrete for decode the current value
func (d *decoder) currentMap() {
	typ := d.curr.Type()
	if d.curr.IsNil() {
		d.curr.Set(reflect.MakeMap(typ))
		v := reflect.New(typ.Elem()).Elem()
		d.maps = append(d.maps, &pathMap{d.curr, d.field, v, d.path})
		d.curr = v
	} else if a := d.maps.find(d.curr, d.field); a == nil {
		v := reflect.New(typ.Elem()).Elem()
		d.maps = append(d.maps, &pathMap{d.curr, d.field, v, d.path})
		d.curr = v
	} else {
		d.curr = a.value
	}
}

var (
	timeType  = reflect.TypeOf(time.Time{})
	timePType = reflect.TypeOf(&time.Time{})
)

// unmarshalText returns a boolean and error. The boolean is true if the
// value implements TextUnmarshaler, and false if not.
func (d *decoder) unmarshalText(v reflect.Value) (bool, error) {
	// skip if the type is time.Time
	typ := v.Type()
	if typ.ConvertibleTo(timeType) || typ.ConvertibleTo(timePType) {
		return false, nil
	}
	// check if implements the interface
	t, ok := v.Interface().(encoding.TextUnmarshaler)
	canAddr := v.CanAddr()
	if !ok && !canAddr {
		return false, nil
	} else if canAddr {
		return d.unmarshalText(v.Addr())
	}
	// return result
	err := t.UnmarshalText([]byte(d.value))
	return true, err
}
<commit_msg>cleaner<commit_after>// Package formam implements functions to decode values of a html form.
package formam

import (
	"encoding"
	"errors"
	"fmt"
	"net/url"
	"reflect"
	"strconv"
	"strings"
	"time"
)

const TAG_NAME = "formam"

// A pathMap holds the values of a map with its key and values correspondent
type pathMap struct {
	m reflect.Value

	key   string
	value reflect.Value

	path string
}

// a pathMaps holds the values for each key
type pathMaps []*pathMap

// find find and get the value by the given key
func (ma pathMaps) find(id reflect.Value, key string) *pathMap {
	for _, v := range ma {
		if v.m == id && v.key == key {
			return v
		}
	}
	return nil
}

// A decoder holds the values from form, the 'reflect' value of main struct
// and the 'reflect' value of current path
type decoder struct {
	main reflect.Value

	curr   reflect.Value
	value  string
	values []string

	path  string
	field string
	index int

	maps pathMaps
}

// Decode decodes the url.Values into a element that must be a pointer to a type provided by argument
func Decode(vs url.Values, dst interface{}) error {
	main := reflect.ValueOf(dst)
	if main.Kind() != reflect.Ptr {
		return fmt.Errorf("formam: the value passed for decode is not a pointer but a %v", main.Kind())
	}

	d := &decoder{main: main.Elem()}

	// iterate over the form's values and decode it (except the maps, maps are decoded at the end)
	for k, v := range vs {
		d.path = k
		d.field = k
		d.values = v
		d.value = v[0]
		if d.value != "" {
			if err := d.begin(); err != nil {
				return err
			}
		}
	}
	// decode maps
	for _, v := range d.maps {
		key := v.m.Type().Key()
		switch key.Kind() {
		case reflect.String:
			// the key is a string
			v.m.SetMapIndex(reflect.ValueOf(v.key), v.value)
		default:
			// must to implement the TextUnmarshaler interface for to can to decode the map's key
			var vv reflect.Value

			if key.Kind() == reflect.Ptr {
				vv = reflect.New(key.Elem())
			} else {
				vv = reflect.New(key).Elem()
			}

			d.value = v.key
			if ok, err := d.unmarshalText(vv); !ok {
				return fmt.Errorf("formam: the key with %s type (%v) in the path %v should implements the TextUnmarshaler interface for to can decode it", key, v.m.Type(), v.path)
			} else if err != nil {
				return fmt.Errorf("formam: an error has occured in the UnmarshalText method for type %s: %s", key, err)
			}

			v.m.SetMapIndex(vv, v.value)
		}
	}

	d.maps = []*pathMap{}
	return nil
}

// begin prepare the current path to walk through it
func (d *decoder) begin() (err error) {
	d.curr = d.main
	fields := strings.Split(d.field, ".")
	for i, field := range fields {
		b := strings.IndexAny(field, "[")
		if b != -1 {
			// is a array
			e := strings.IndexAny(field, "]")
			if e == -1 {
				return errors.New("formam: bad syntax array")
			}
			d.field = field[:b]
			if d.index, err = strconv.Atoi(field[b+1 : e]); err != nil {
				return errors.New("formam: the index of array is not a number")
			}
			if len(fields) == i+1 {
				return d.end()
			}
			if err = d.walk(); err != nil {
				return
			}
		} else {
			// not is a array
			d.field = field
			d.index = -1
			if len(fields) == i+1 {
				return d.end()
			}
			if err = d.walk(); err != nil {
				return
			}
		}
	}
	return
}

// walk traverses the current path until to the last field
func (d *decoder) walk() error {
	// check if is a struct or map
	switch d.curr.Kind() {
	case reflect.Struct:
		if err := d.findStructField(); err != nil {
			return err
		}
	case reflect.Map:
		d.currentMap()
	}
	// check if the struct or map is a interface
	if d.curr.Kind() == reflect.Interface {
		d.curr = d.curr.Elem()
	}
	// check if the struct or map is a pointer
	if d.curr.Kind() == reflect.Ptr {
		if d.curr.IsNil() {
			d.curr.Set(reflect.New(d.curr.Type().Elem()))
		}
		d.curr = d.curr.Elem()
	}
	// finally, check if there are access to slice/array or not...
	if d.index != -1 {
		switch d.curr.Kind() {
		case reflect.Slice, reflect.Array:
			if d.curr.Len() <= d.index {
				d.expandSlice(d.index + 1)
			}
			d.curr = d.curr.Index(d.index)
		default:
			return fmt.Errorf("formam: the field \"%v\" in path \"%v\" has a index for array but it is not", d.field, d.path)
		}
	}
	return nil
}

// end finds the last field for decode its value correspondent
func (d *decoder) end() error {
	if d.curr.Kind() == reflect.Struct {
		if err := d.findStructField(); err != nil {
			return err
		}
	}
	if d.value == "" {
		return nil
	}
	return d.decode()
}

// decode sets the value in the last field found by end function
func (d *decoder) decode() error {
	if ok, err := d.unmarshalText(d.curr); !ok && err != nil {
		return err
	}

	switch d.curr.Kind() {
	case reflect.Map:
		d.currentMap()
		return d.decode()
	case reflect.Slice, reflect.Array:
		if d.index == -1 {
			// not has index, so to decode all values in the slice/array
			d.expandSlice(len(d.values))
			tmp := d.curr
			for i, v := range d.values {
				d.curr = tmp.Index(i)
				d.value = v
				if err := d.decode(); err != nil {
					return err
				}
			}
			return nil
		}
		// has index, so to decode value by index indicated
		if d.curr.Len() <= d.index {
			d.expandSlice(d.index + 1)
		}
		d.curr = d.curr.Index(d.index)
		return d.decode()
	case reflect.String:
		d.curr.SetString(d.value)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if num, err := strconv.ParseInt(d.value, 10, 64); err != nil {
			return fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" should be a valid signed integer number", d.field, d.path)
		} else {
			d.curr.SetInt(num)
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		if num, err := strconv.ParseUint(d.value, 10, 64); err != nil {
			return fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" should be a valid unsigned integer number", d.field, d.path)
		} else {
			d.curr.SetUint(num)
		}
	case reflect.Float32, reflect.Float64:
		if num, err := strconv.ParseFloat(d.value, d.curr.Type().Bits()); err != nil {
			return fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" should be a valid float number", d.field, d.path)
		} else {
			d.curr.SetFloat(num)
		}
	case reflect.Bool:
		switch d.value {
		case "true", "on", "1":
			d.curr.SetBool(true)
		case "false", "off", "0":
			d.curr.SetBool(false)
		default:
			return fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" is not a valid boolean", d.field, d.path)
		}
	case reflect.Interface:
		d.curr.Set(reflect.ValueOf(d.value))
	case reflect.Ptr:
		d.curr.Set(reflect.New(d.curr.Type().Elem()))
		d.curr = d.curr.Elem()
		return d.decode()
	case reflect.Struct:
		switch d.curr.Interface().(type) {
		case time.Time:
			t, err := time.Parse("2006-01-02", d.value)
			if err != nil {
				return fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" is not a valid datetime", d.field, d.path)
			}
			d.curr.Set(reflect.ValueOf(t))
		case url.URL:
			u, err := url.Parse(d.value)
			if err != nil {
				return fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" is not a valid url", d.field, d.path)
			}
			d.curr.Set(reflect.ValueOf(*u))
		default:
			return fmt.Errorf("formam: not supported type for field \"%v\" in path \"%v\"", d.field, d.path)
		}
	default:
		return fmt.Errorf("formam: not supported type for field \"%v\" in path \"%v\"", d.field, d.path)
	}

	return nil
}

// findField finds a field by its name, if it is not found,
// then retry the search examining the tag "formam" of every field of struct
func (d *decoder) findStructField() error {
	var anon reflect.Value

	num := d.curr.NumField()
	for i := 0; i < num; i++ {
		field := d.curr.Type().Field(i)
		if field.Name == d.field {
			// check if the field's name is equal
			d.curr = d.curr.Field(i)
			return nil
		} else if field.Anonymous {
			// if the field is a anonymous struct, then iterate over its fields
			tmp := d.curr
			d.curr = d.curr.FieldByIndex(field.Index)
			if err := d.findStructField(); err != nil {
				d.curr = tmp
				continue
			}
			// field in anonymous struct is found,
			// but first it should found the field in the rest of struct
			// (a field with same name in the current struct should have preference over anonymous struct)
			anon = d.curr
			d.curr = tmp
		} else if d.field == field.Tag.Get(TAG_NAME) {
			// is not found yet, then retry by its tag name "formam"
			d.curr = d.curr.Field(i)
			return nil
		}
	}

	if anon.IsValid() {
		d.curr = anon
		return nil
	}

	return fmt.Errorf("formam: not found the field \"%v\" in the path \"%v\"", d.field, d.path)
}

// expandSlice expands the length and capacity of the current slice
func (d *decoder) expandSlice(length int) {
	sli := reflect.MakeSlice(d.curr.Type(), length, length)
	reflect.Copy(sli, d.curr)
	d.curr.Set(sli)
}

// currentMap gets in d.curr the map concrete for decode the current value
func (d *decoder) currentMap() {
	typ := d.curr.Type()
	if d.curr.IsNil() {
		d.curr.Set(reflect.MakeMap(typ))
		v := reflect.New(typ.Elem()).Elem()
		d.maps = append(d.maps, &pathMap{d.curr, d.field, v, d.path})
		d.curr = v
	} else if a := d.maps.find(d.curr, d.field); a == nil {
		v := reflect.New(typ.Elem()).Elem()
		d.maps = append(d.maps, &pathMap{d.curr, d.field, v, d.path})
		d.curr = v
	} else {
		d.curr = a.value
	}
}

var (
	timeType  = reflect.TypeOf(time.Time{})
	timePType = reflect.TypeOf(&time.Time{})
)

// unmarshalText returns a boolean and error. The boolean is true if the
// value implements TextUnmarshaler, and false if not.
func (d *decoder) unmarshalText(v reflect.Value) (bool, error) {
	// skip if the type is time.Time
	typ := v.Type()
	if typ.ConvertibleTo(timeType) || typ.ConvertibleTo(timePType) {
		return false, nil
	}
	// check if implements the interface
	t, ok := v.Interface().(encoding.TextUnmarshaler)
	canAddr := v.CanAddr()
	if !ok && !canAddr {
		return false, nil
	} else if canAddr {
		return d.unmarshalText(v.Addr())
	}
	// return result
	err := t.UnmarshalText([]byte(d.value))
	return true, err
}
<|endoftext|>


<commit_before>// Copyright 2013, Örjan Persson. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package logging

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"path/filepath"
	"regexp"
	"runtime"
	"sync"
	"time"
)

// TODO see Formatter interface in fmt/print.go
// TODO try text/template, maybe it have enough performance
// TODO other template systems?
// TODO make it possible to specify formats per backend?
type fmtVerb int

const (
	fmtVerbTime fmtVerb = iota
	fmtVerbLevel
	fmtVerbId
	fmtVerbModule
	fmtVerbMessage
	fmtVerbLongfile
	fmtVerbShortfile

	// Keep last, there are no match for these below.
	fmtVerbUnknown
	fmtVerbStatic
)

var fmtVerbs = []string{
	"time",
	"level",
	"id",
	"module",
	"message",
	"longfile",
	"shortfile",
}

var defaultVerbsLayout = []string{
	"2006-01-02T15:04:05.999Z07:00",
	"s",
	"d",
	"s",
	"s",
	"s",
	"s",
}

func getFmtVerbByName(name string) fmtVerb {
	for i, verb := range fmtVerbs {
		if name == verb {
			return fmtVerb(i)
		}
	}
	return fmtVerbUnknown
}

// Formatter is the required interface for a custom log record formatter.
type Formatter interface {
	Format(calldepth int, r *Record, w io.Writer) error
}

// formatter is used by all backends unless otherwise overriden.
var formatter struct {
	sync.RWMutex
	def Formatter
}

func getFormatter() Formatter {
	formatter.RLock()
	defer formatter.RUnlock()
	return formatter.def
}

var (
	// DefaultFormatter is the default formatter used and is only the message.
	DefaultFormatter Formatter = MustStringFormatter("%{message}")

	// TODO add filename and line
	// GlogFormatter Formatter = MustStringFormatter("%{level:.1}%%{time:0102 15:04:05.99999} 0 %{file}:%{line} %{message}")
)

// SetFormatter sets the default formatter for all new backends. A backend will
// fetch this value once it is needed to format a record. Note that backends
// will cache the formatter after the first point. For now, make sure to set
// the formatter before logging.
func SetFormatter(f Formatter) {
	formatter.Lock()
	defer formatter.Unlock()
	formatter.def = f
}

// TODO use ${} instead?
var formatRe *regexp.Regexp = regexp.MustCompile(`%{([a-z]+)(?::(.*?[^\\]))?}`)

type part struct {
	verb   fmtVerb
	layout string
}

// stringFormatter contains a list of parts which explains how to build the
// formatted string passed on to the logging backend.
type stringFormatter struct {
	parts []part
}

// NewStringFormatter returns a new Formatter which outputs the log record as a
// string based on the 'verbs' specified in the format string.
//
// The verbs:
//
// General:
//     %{id}        Sequence number for log message (uint64).
//     %{time}      Time when log occurred (time.Time)
//     %{level}     Log level (Level)
//     %{module}    Module (string)
//     %{message}   Message (string)
//     %{longfile}  Full file name and line number: /a/b/c/d.go:23
//     %{shortfile} Final file name element and line number: d.go:23
//
// For normal types, the output can be customized by using the 'verbs' defined
// in the fmt package, eg. '%{id:04d}' to make the id output be '%04d' as the
// format string.
//
// For time.Time, use the same layout as time.Format to change the time format
// when output, eg "2006-01-02T15:04:05.999Z-07:00".
func NewStringFormatter(format string) (*stringFormatter, error) {
	var fmter = &stringFormatter{}

	// Find the boundaries of all %{vars}
	matches := formatRe.FindAllStringSubmatchIndex(format, -1)
	if matches == nil {
		return nil, errors.New("logger: invalid log format: " + format)
	}

	// Collect all variables and static text for the format
	prev := 0
	for _, m := range matches {
		start, end := m[0], m[1]
		if start > prev {
			fmter.add(fmtVerbStatic, format[prev:start])
		}

		name := format[m[2]:m[3]]
		verb := getFmtVerbByName(name)
		if verb == fmtVerbUnknown {
			return nil, errors.New("logger: unknown variable: " + name)
		}

		// Handle layout customizations or use the default. If this is not for the
		// time formatting, we need to prefix with %.
		layout := defaultVerbsLayout[verb]
		if m[4] != -1 {
			layout = format[m[4]:m[5]]
		}
		if verb != fmtVerbTime {
			layout = "%" + layout
		}

		fmter.add(verb, layout)
		prev = end
	}
	end := format[prev:]
	if end != "" {
		fmter.add(fmtVerbStatic, end)
	}

	// Make a test run to make sure we can format it correctly.
	t, err := time.Parse(time.RFC3339, "2010-02-04T21:00:57-08:00")
	if err != nil {
		panic(err)
	}
	r := &Record{
		Id:     12345,
		Time:   t,
		Module: "logger",
		fmt:    "hello %s",
		args:   []interface{}{"go"},
	}
	if err := fmter.Format(0, r, &bytes.Buffer{}); err != nil {
		return nil, err
	}

	formatter.def = fmter

	return fmter, nil
}

// MustStringFormatter is equivalent to NewStringFormatter with a call to panic
// on error.
func MustStringFormatter(format string) *stringFormatter {
	f, err := NewStringFormatter(format)
	if err != nil {
		panic("Failed to initialized string formatter: " + err.Error())
	}
	return f
}

func (f *stringFormatter) add(verb fmtVerb, layout string) {
	f.parts = append(f.parts, part{verb, layout})
}

func (f *stringFormatter) Format(calldepth int, r *Record, output io.Writer) error {
	// TODO collect and call fprintf once?
	for _, part := range f.parts {
		if part.verb == fmtVerbStatic {
			output.Write([]byte(part.layout))
		} else if part.verb == fmtVerbTime {
			output.Write([]byte(r.Time.Format(part.layout)))
		} else {
			var v interface{}
			switch part.verb {
			case fmtVerbLevel:
				v = r.Level
				break
			case fmtVerbId:
				v = r.Id
				break
			case fmtVerbModule:
				v = r.Module
				break
			case fmtVerbMessage:
				v = r.Message()
				break
			case fmtVerbLongfile, fmtVerbShortfile:
				_, file, line, ok := runtime.Caller(calldepth + 1)
				if !ok {
					file = "???"
					line = 0
				} else if part.verb == fmtVerbShortfile {
					file = filepath.Base(file)
				}
				v = fmt.Sprintf("%s:%d", file, line)
			default:
				panic("unhandled format part")
			}
			fmt.Fprintf(output, part.layout, v)
		}
	}
	return nil
}
<commit_msg>Added pid and program formatter options<commit_after>// Copyright 2013, Örjan Persson. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package logging

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"sync"
	"time"
)

// TODO see Formatter interface in fmt/print.go
// TODO try text/template, maybe it have enough performance
// TODO other template systems?
// TODO make it possible to specify formats per backend?
type fmtVerb int

const (
	fmtVerbTime fmtVerb = iota
	fmtVerbLevel
	fmtVerbId
	fmtVerbPid
	fmtVerbProgram
	fmtVerbModule
	fmtVerbMessage
	fmtVerbLongfile
	fmtVerbShortfile

	// Keep last, there are no match for these below.
	fmtVerbUnknown
	fmtVerbStatic
)

var fmtVerbs = []string{
	"time",
	"level",
	"id",
	"pid",
	"program",
	"module",
	"message",
	"longfile",
	"shortfile",
}

var defaultVerbsLayout = []string{
	"2006-01-02T15:04:05.999Z07:00",
	"s",
	"d",
	"d",
	"s",
	"s",
	"s",
	"s",
	"s",
}

var (
	pid     = os.Getpid()
	program = filepath.Base(os.Args[0])
)

func getFmtVerbByName(name string) fmtVerb {
	for i, verb := range fmtVerbs {
		if name == verb {
			return fmtVerb(i)
		}
	}
	return fmtVerbUnknown
}

// Formatter is the required interface for a custom log record formatter.
type Formatter interface {
	Format(calldepth int, r *Record, w io.Writer) error
}

// formatter is used by all backends unless otherwise overriden.
var formatter struct {
	sync.RWMutex
	def Formatter
}

func getFormatter() Formatter {
	formatter.RLock()
	defer formatter.RUnlock()
	return formatter.def
}

var (
	// DefaultFormatter is the default formatter used and is only the message.
	DefaultFormatter Formatter = MustStringFormatter("%{message}")

	// TODO add filename and line
	// GlogFormatter Formatter = MustStringFormatter("%{level:.1}%%{time:0102 15:04:05.99999} 0 %{file}:%{line} %{message}")
)

// SetFormatter sets the default formatter for all new backends. A backend will
// fetch this value once it is needed to format a record. Note that backends
// will cache the formatter after the first point. For now, make sure to set
// the formatter before logging.
func SetFormatter(f Formatter) {
	formatter.Lock()
	defer formatter.Unlock()
	formatter.def = f
}

// TODO use ${} instead?
var formatRe *regexp.Regexp = regexp.MustCompile(`%{([a-z]+)(?::(.*?[^\\]))?}`)

type part struct {
	verb   fmtVerb
	layout string
}

// stringFormatter contains a list of parts which explains how to build the
// formatted string passed on to the logging backend.
type stringFormatter struct {
	parts []part
}

// NewStringFormatter returns a new Formatter which outputs the log record as a
// string based on the 'verbs' specified in the format string.
//
// The verbs:
//
// General:
//     %{id}        Sequence number for log message (uint64).
//     %{pid}       Process id (int)
//     %{time}      Time when log occurred (time.Time)
//     %{level}     Log level (Level)
//     %{module}    Module (string)
//     %{program}   Basename of os.Args[0] (string)
//     %{message}   Message (string)
//     %{longfile}  Full file name and line number: /a/b/c/d.go:23
//     %{shortfile} Final file name element and line number: d.go:23
//
// For normal types, the output can be customized by using the 'verbs' defined
// in the fmt package, eg. '%{id:04d}' to make the id output be '%04d' as the
// format string.
//
// For time.Time, use the same layout as time.Format to change the time format
// when output, eg "2006-01-02T15:04:05.999Z-07:00".
func NewStringFormatter(format string) (*stringFormatter, error) {
	var fmter = &stringFormatter{}

	// Find the boundaries of all %{vars}
	matches := formatRe.FindAllStringSubmatchIndex(format, -1)
	if matches == nil {
		return nil, errors.New("logger: invalid log format: " + format)
	}

	// Collect all variables and static text for the format
	prev := 0
	for _, m := range matches {
		start, end := m[0], m[1]
		if start > prev {
			fmter.add(fmtVerbStatic, format[prev:start])
		}

		name := format[m[2]:m[3]]
		verb := getFmtVerbByName(name)
		if verb == fmtVerbUnknown {
			return nil, errors.New("logger: unknown variable: " + name)
		}

		// Handle layout customizations or use the default. If this is not for the
		// time formatting, we need to prefix with %.
		layout := defaultVerbsLayout[verb]
		if m[4] != -1 {
			layout = format[m[4]:m[5]]
		}
		if verb != fmtVerbTime {
			layout = "%" + layout
		}

		fmter.add(verb, layout)
		prev = end
	}
	end := format[prev:]
	if end != "" {
		fmter.add(fmtVerbStatic, end)
	}

	// Make a test run to make sure we can format it correctly.
	t, err := time.Parse(time.RFC3339, "2010-02-04T21:00:57-08:00")
	if err != nil {
		panic(err)
	}
	r := &Record{
		Id:     12345,
		Time:   t,
		Module: "logger",
		fmt:    "hello %s",
		args:   []interface{}{"go"},
	}
	if err := fmter.Format(0, r, &bytes.Buffer{}); err != nil {
		return nil, err
	}

	formatter.def = fmter

	return fmter, nil
}

// MustStringFormatter is equivalent to NewStringFormatter with a call to panic
// on error.
func MustStringFormatter(format string) *stringFormatter {
	f, err := NewStringFormatter(format)
	if err != nil {
		panic("Failed to initialized string formatter: " + err.Error())
	}
	return f
}

func (f *stringFormatter) add(verb fmtVerb, layout string) {
	f.parts = append(f.parts, part{verb, layout})
}

func (f *stringFormatter) Format(calldepth int, r *Record, output io.Writer) error {
	// TODO collect and call fprintf once?
	for _, part := range f.parts {
		if part.verb == fmtVerbStatic {
			output.Write([]byte(part.layout))
		} else if part.verb == fmtVerbTime {
			output.Write([]byte(r.Time.Format(part.layout)))
		} else {
			var v interface{}
			switch part.verb {
			case fmtVerbLevel:
				v = r.Level
				break
			case fmtVerbId:
				v = r.Id
				break
			case fmtVerbPid:
				v = pid
				break
			case fmtVerbProgram:
				v = program
				break
			case fmtVerbModule:
				v = r.Module
				break
			case fmtVerbMessage:
				v = r.Message()
				break
			case fmtVerbLongfile, fmtVerbShortfile:
				_, file, line, ok := runtime.Caller(calldepth + 1)
				if !ok {
					file = "???"
					line = 0
				} else if part.verb == fmtVerbShortfile {
					file = filepath.Base(file)
				}
				v = fmt.Sprintf("%s:%d", file, line)
			default:
				panic("unhandled format part")
			}
			fmt.Fprintf(output, part.layout, v)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright IBM Corp 2016 All Rights Reserved.

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 main

import (
	"errors"
	"fmt"
	//"encoding/json"

	"github.com/hyperledger/fabric/core/chaincode/shim"

)

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

type Emp struct{
	empId string `json:"empId"`
	name string `json:"name"`
	title string `json:"title"`

}

func main() {
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

// Init resets all the things
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	  err := stub.PutState("table_ibminsert", []byte(args[0]))
	if err != nil {
		return nil, err
	}

	// Check if table already exists
	_,  err = stub.GetTable("EmpTable")

	if err == nil {
		// Table already exists; do not recreate
		return nil, nil
	}
     fmt.Println("ready to create the table: ")
	// Create application Table
	err = stub.CreateTable("EmpTable", []*shim.ColumnDefinition{
		&shim.ColumnDefinition{Name: "empId", Type: shim.ColumnDefinition_STRING, Key: true},
		&shim.ColumnDefinition{Name: "name", Type: shim.ColumnDefinition_STRING, Key: false},
		&shim.ColumnDefinition{Name: "title", Type: shim.ColumnDefinition_STRING, Key: false},

	})
	if err != nil {
		return nil, errors.New("Failed creating ApplicationTable.")

	}

	return nil, nil
	}

// Invoke isur entry point to invoke a chaincode function
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	if function == "init" {
		return t.Init(stub, "init", args)
	} else if function == "write" {
		return t.write(stub, args)
	}
	fmt.Println("invoke did not find func: " + function)

	if function == "submitEmp" {
		if len(args) != 3 {
			return nil, fmt.Errorf("Incorrect number of arguments. Expecting 20. Got: %d.", len(args))
		}

		empId := args[0]
		name := args[1]
		title := args[2]

		//insert a row

		ok, err := stub.InsertRow("EmpTable", shim.Row{
		Columns: []*shim.Column{
				&shim.Column{Value: &shim.Column_String_{String_: empId}},
				&shim.Column{Value: &shim.Column_String_{String_: name}},
				&shim.Column{Value: &shim.Column_String_{String_: title}},
				}})

	if !ok && err == nil {
			return nil, errors.New("Row already exists.")
		}

	}
	fmt.Println("values Inserted in the table: ")

	return nil, errors.New("Received unknown function invocation: " + function)
}

// Query is our entry point for queries
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {

	fmt.Println("query is running " + function)

	// Handle different functions
	if function == "read" { //read a variable
		return t.read(stub, args)
	}
	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query: " + function)
}

// write - invoke function to write key/value pair
func (t *SimpleChaincode) write(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	var key, value string
	var err error
	fmt.Println("running write()")

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2. name of the key and value to set")
	}

	key = args[0] //rename for funsies
	value = args[1]
	err = stub.PutState(key, []byte(value)) //write the variable into the chaincode state
	if err != nil {
		return nil, err
	}
	return nil, nil
}

// read - query function to read key/value pair
func (t *SimpleChaincode) read(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting applicationid to query")
	}

	fmt.Println("came into read func and geting empid: ")

	empId := args[0]

fmt.Println("came into read func and geting empid: "+empId)

// Get the row pertaining to this applicationId
	var columns []shim.Column
	col1 := shim.Column{Value: &shim.Column_String_{String_: empId}}
	columns = append(columns, col1)

	row, err := stub.GetRow("EmpTable", columns)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get the data for the dataaa " + empId + "\"}"
		return nil, errors.New(jsonResp)
	}

	fmt.Println("got the row from table: ")
	      var x    =     row.Columns[0].GetString_()

	fmt.Println("got the row from table: "+x)
	//res2E := Emp{}

	//res2E.empId = row.Columns[0].GetString_()
	//res2E.name = row.Columns[1].GetString_()
	//res2E.title = row.Columns[2].GetString_()

	//mapB, _ := json.Marshal(res2E)

	//fmt.Println(string(mapB))

	return nil, nil
}
<commit_msg>121121<commit_after>/*
Copyright IBM Corp 2016 All Rights Reserved.

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 main

import (
	"errors"
	"fmt"
	//"encoding/json"

	"github.com/hyperledger/fabric/core/chaincode/shim"

)

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

type Emp struct{
	empId string `json:"empId"`
	name string `json:"name"`
	title string `json:"title"`

}

func main() {
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

// Init resets all the things
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	  err := stub.PutState("table_ibminsert", []byte(args[0]))
	if err != nil {
		return nil, err
	}

	// Check if table already exists
	_,  err = stub.GetTable("EmpTable")

	if err == nil {
		// Table already exists; do not recreate
		return nil, nil
	}
     fmt.Println("ready to create the table: ")
	// Create application Table
	err = stub.CreateTable("EmpTable", []*shim.ColumnDefinition{
		&shim.ColumnDefinition{Name: "empId", Type: shim.ColumnDefinition_STRING, Key: true},
		&shim.ColumnDefinition{Name: "name", Type: shim.ColumnDefinition_STRING, Key: false},
		&shim.ColumnDefinition{Name: "title", Type: shim.ColumnDefinition_STRING, Key: false},

	})
	if err != nil {
		return nil, errors.New("Failed creating ApplicationTable.")

	}

	return nil, nil
	}

// Invoke isur entry point to invoke a chaincode function
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	if function == "init" {
		return t.Init(stub, "init", args)
	} else if function == "write" {
		return t.write(stub, args)
	}
	fmt.Println("invoke did not find func: " + function)

	if function == "submitEmp" {
		if len(args) != 3 {
			return nil, fmt.Errorf("Incorrect number of arguments. Expecting 20. Got: %d.", len(args))
		}

		empId := args[0]
		name := args[1]
		title := args[2]

		//insert a row

		ok, err := stub.InsertRow("EmpTable", shim.Row{
		Columns: []*shim.Column{
				&shim.Column{Value: &shim.Column_String_{String_: empId}},
				&shim.Column{Value: &shim.Column_String_{String_: name}},
				&shim.Column{Value: &shim.Column_String_{String_: title}},
				}})

	if !ok && err == nil {
			return nil, errors.New("Row already exists.")
		}

	}
	fmt.Println("values Inserted in the table: ")

	return nil, errors.New("Received unknown function invocation: " + function)
}

// Query is our entry point for queries
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {

	fmt.Println("query is running " + function)

	// Handle different functions
	if function == "read" { //read a variable
		return t.read(stub, args)
	}
	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query: " + function)
}

// write - invoke function to write key/value pair
func (t *SimpleChaincode) write(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	var key, value string
	var err error
	fmt.Println("running write()")

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2. name of the key and value to set")
	}

	key = args[0] //rename for funsies
	value = args[1]
	err = stub.PutState(key, []byte(value)) //write the variable into the chaincode state
	if err != nil {
		return nil, err
	}
	return nil, nil
}

// read - query function to read key/value pair
func (t *SimpleChaincode) read(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting applicationid to query")
	}

	fmt.Println("came into read func and geting empid: ")

	empId := args[0]

fmt.Println("came into read func and geting empid: "+empId)

// Get the row pertaining to this applicationId
	var columns []shim.Column
	col1 := shim.Column{Value: &shim.Column_String_{String_: empId}}
	columns = append(columns, col1)

	row, err := stub.GetRow("EmpTable", columns)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get the data for the dataaa " + empId + "\"}"
		return nil, errors.New(jsonResp)
	}

	if len(row.Columns) == 0 || row.Columns[2] == nil {
		fmt.Println("no rows returned")

		return nil, errors.New("row or column value not found")
	}

	//res2E := Emp{}

	//res2E.empId = row.Columns[0].GetString_()
	//res2E.name = row.Columns[1].GetString_()
	//res2E.title = row.Columns[2].GetString_()

	//mapB, _ := json.Marshal(res2E)

	//fmt.Println(string(mapB))

	return nil, nil
}
<|endoftext|>


<commit_before>/*
Package framed adds basic support for message framing over streams.

Messages contain an header and a body, both of which are length prefixed.

Here are the bytes (stored in little-endian byte order):

0-2: unsigned 16 bit int header length
2-4: unsinged 16 bit int body length
4+:  message content (header and body)

The use of a uint16 means that the maximum possible header and body lengths
are 65535 each.

Example:

	package main

	import (
		"github.com/oxtoacart/framed"
		"io/ioutil"
		"log"
		"net"
	)

	func main() {
		// Replace host:port with an actual TCP server, for example the echo service
		if conn, err := net.Dial("tcp", "host:port"); err == nil {
			framedConn = Framed{conn}
			if err := framedConn.WriteFrame([]byte("Header"), []byte("Hello World")); err == nil {
				if err, frame := framedConn.ReadInitial(); err == nil {
					// Note - Read is just like io.Reader.Read(), so we use ioutil.ReadAll
					if header, err := ioutil.ReadAll(framedConn.Header); err == nil {
						if body, err := ioutil.ReadAll(framedConn.Body); err == nil {
							nextFrame, err := frame.Next()
							// And so on
						}
					}
				}
			}
		}
	}
*/
package framed

import (
	"encoding/binary"
	"io"
	"io/ioutil"
)

var endianness = binary.LittleEndian

/*
A Framed enhances an io.ReadWriteCloser to provide methods that allow writing
and reading frames.

Although the underlying ReadWriteCloser may be safe to use from multiple
goroutines, a Framed is not.
*/
type Framed struct {
	io.ReadWriteCloser // the raw underlying connection
	hasReadInitial     bool
}

// AlreadyReadError is returned when someone has already read from a Frame
type AlreadyReadError string

func (err AlreadyReadError) Error() string {
	return string(err)
}

// Frame encapsulates a frame from a Framed
type Frame struct {
	framed         *Framed
	headerLength   uint16
	bodyLength     uint16
	header         *FrameSection
	body           *FrameSection
	completelyRead chan bool
}

// FrameSection encapsulates a section of a frame (header or body)
type FrameSection struct {
	frame          *Frame
	init           func() error
	finish         func()
	bytesRemaining int
	startedReading bool
}

// NewFramed creates a new Framed on top of the given readWriteCloser
func NewFramed(readWriteCloser io.ReadWriteCloser) *Framed {
	return &Framed{readWriteCloser, false}
}

/*
ReadInitial reads the initial frame from the framed.  It returns an
AlreadyReadError if the initial frame has already been read previously.
*/
func (framed *Framed) ReadInitial() (frame *Frame, err error) {
	if framed.hasReadInitial {
		return nil, AlreadyReadError("Initial Frame already read")
	}
	frame, err = framed.nextFrame()
	framed.hasReadInitial = true
	return
}

/*
Next returns the next frame from the Framed underlying the frame on which
it is called.  This method blocks until the previous frame has been consumed.
If there are no more frames, it returns io.EOF as an error.
*/
func (frame *Frame) Next() (nextFrame *Frame, err error) {
	<-frame.completelyRead
	return frame.framed.nextFrame()
}

/*
WriteFrame writes the given header and body to the Framed.
Either or both can be nil.
*/
func (framed *Framed) WriteFrame(header []byte, body []byte) (err error) {
	headerLength := 0
	bodyLength := 0
	if header != nil {
		headerLength = len(header)
	}
	if body != nil {
		bodyLength = len(body)
	}

	if err = framed.WriteHeader(uint16(headerLength), uint16(bodyLength)); err != nil {
		return err
	}

	if header != nil {
		if _, err = framed.Write(header); err != nil {
			return err
		}
	}

	if body != nil {
		_, err = framed.Write(body)
	}

	return
}

// WriteHeader writes a frame header with the given lengths to the Framed.
func (framed *Framed) WriteHeader(headerLength uint16, bodyLength uint16) (err error) {
	return writeHeaderTo(framed, headerLength, bodyLength)
}

/*
CopyTo copies the given Frame to the given Writer.  If reading of the Frame
has already started before CopyTo is called, CopyTo returns an
AlreadyReadError.
*/
func (frame *Frame) CopyTo(out io.Writer) (err error) {
	if frame.header.startedReading || frame.body.startedReading {
		return AlreadyReadError("Already read from frame, cannot copy")
	}
	if err = writeHeaderTo(out, frame.headerLength, frame.bodyLength); err != nil {
		return
	}
	_, err = io.CopyN(out, frame.framed, int64(frame.headerLength+frame.bodyLength))
	frame.completelyRead <- true
	return
}

/*
Read implements io.Reader.Read for a FrameSection.  Just like the usual Read(),
this one may read incompletely, so make sure to call it until it returns EOF.
*/
func (section *FrameSection) Read(p []byte) (n int, err error) {
	if section.bytesRemaining == 0 {
		return 0, err
	}
	if section.init != nil {
		if err = section.init(); err != nil {
			return 0, err
		}
	}
	section.startedReading = true
	if len(p) > section.bytesRemaining {
		p = p[0:section.bytesRemaining]
	}
	n, err = section.frame.framed.Read(p)
	if n > 0 {
		section.bytesRemaining -= n
	}
	if section.bytesRemaining == 0 {
		err = io.EOF
	}
	return
}

func (section *FrameSection) Drain() (err error) {
	if section.bytesRemaining > 0 {
		_, err = io.Copy(ioutil.Discard, section)
	}
	return
}

func (frame *Frame) HeaderLength() uint16 {
	return frame.headerLength
}

func (frame *Frame) BodyLength() uint16 {
	return frame.bodyLength
}

func (frame *Frame) Header() io.Reader {
	return frame.header
}

func (frame *Frame) Body() io.Reader {
	return frame.body
}

func (framed *Framed) nextFrame() (frame *Frame, err error) {
	frame = &Frame{framed: framed, completelyRead: make(chan bool, 10)}
	frame.header = &FrameSection{frame: frame}
	frame.body = &FrameSection{frame: frame, init: frame.header.Drain, finish: frame.done}
	if err = frame.readLengths(); err != nil {
		return
	}
	return
}

func (frame *Frame) readLengths() (err error) {
	if err = binary.Read(frame.framed, endianness, &frame.headerLength); err != nil {
		return
	}
	if err = binary.Read(frame.framed, endianness, &frame.bodyLength); err != nil {
		return
	}
	frame.header.bytesRemaining = int(frame.headerLength)
	frame.body.bytesRemaining = int(frame.bodyLength)
	return
}

func (frame *Frame) done() {
	frame.completelyRead <- true
}

func writeHeaderTo(out io.Writer, headerLength uint16, bodyLength uint16) (err error) {
	if err = binary.Write(out, endianness, headerLength); err != nil {
		return
	}
	err = binary.Write(out, endianness, bodyLength)
	return
}
<commit_msg>Drain/Next improvements<commit_after>/*
Package framed adds basic support for message framing over streams.

Messages contain an header and a body, both of which are length prefixed.

Here are the bytes (stored in little-endian byte order):

0-2: unsigned 16 bit int header length
2-4: unsinged 16 bit int body length
4+:  message content (header and body)

The use of a uint16 means that the maximum possible header and body lengths
are 65535 each.

Example:

	package main

	import (
		"github.com/oxtoacart/framed"
		"io/ioutil"
		"log"
		"net"
	)

	func main() {
		// Replace host:port with an actual TCP server, for example the echo service
		if conn, err := net.Dial("tcp", "host:port"); err == nil {
			framedConn = Framed{conn}
			if err := framedConn.WriteFrame([]byte("Header"), []byte("Hello World")); err == nil {
				if err, frame := framedConn.ReadInitial(); err == nil {
					// Note - Read is just like io.Reader.Read(), so we use ioutil.ReadAll
					if header, err := ioutil.ReadAll(framedConn.Header); err == nil {
						if body, err := ioutil.ReadAll(framedConn.Body); err == nil {
							nextFrame, err := frame.Next()
							// And so on
						}
					}
				}
			}
		}
	}
*/
package framed

import (
	"encoding/binary"
	"io"
	"io/ioutil"
)

var endianness = binary.LittleEndian

/*
A Framed enhances an io.ReadWriteCloser to provide methods that allow writing
and reading frames.

Although the underlying ReadWriteCloser may be safe to use from multiple
goroutines, a Framed is not.
*/
type Framed struct {
	io.ReadWriteCloser // the raw underlying connection
	hasReadInitial     bool
}

// AlreadyReadError is returned when someone has already read from a Frame
type AlreadyReadError string

func (err AlreadyReadError) Error() string {
	return string(err)
}

// Frame encapsulates a frame from a Framed
type Frame struct {
	framed         *Framed
	headerLength   uint16
	bodyLength     uint16
	header         *FrameSection
	body           *FrameSection
	completelyRead chan bool
}

// FrameSection encapsulates a section of a frame (header or body)
type FrameSection struct {
	frame          *Frame
	init           func() error
	finish         func()
	bytesRemaining int
	startedReading bool
}

// NewFramed creates a new Framed on top of the given readWriteCloser
func NewFramed(readWriteCloser io.ReadWriteCloser) *Framed {
	return &Framed{readWriteCloser, false}
}

/*
ReadInitial reads the initial frame from the framed.  It returns an
AlreadyReadError if the initial frame has already been read previously.
*/
func (framed *Framed) ReadInitial() (frame *Frame, err error) {
	if framed.hasReadInitial {
		return nil, AlreadyReadError("Initial Frame already read")
	}
	frame, err = framed.nextFrame()
	framed.hasReadInitial = true
	return
}

/*
Next returns the next frame from the Framed underlying the frame on which
it is called.  This method blocks until the previous frame has been consumed.
If there are no more frames, it returns io.EOF as an error.
*/
func (frame *Frame) Next() (nextFrame *Frame, err error) {
	<-frame.completelyRead
	return frame.framed.nextFrame()
}

/*
WriteFrame writes the given header and body to the Framed.
Either or both can be nil.
*/
func (framed *Framed) WriteFrame(header []byte, body []byte) (err error) {
	headerLength := 0
	bodyLength := 0
	if header != nil {
		headerLength = len(header)
	}
	if body != nil {
		bodyLength = len(body)
	}

	if err = framed.WriteHeader(uint16(headerLength), uint16(bodyLength)); err != nil {
		return err
	}

	if header != nil {
		if _, err = framed.Write(header); err != nil {
			return err
		}
	}

	if body != nil {
		_, err = framed.Write(body)
	}

	return
}

// WriteHeader writes a frame header with the given lengths to the Framed.
func (framed *Framed) WriteHeader(headerLength uint16, bodyLength uint16) (err error) {
	return writeHeaderTo(framed, headerLength, bodyLength)
}

/*
CopyTo copies the given Frame to the given Writer.  If reading of the Frame
has already started before CopyTo is called, CopyTo returns an
AlreadyReadError.
*/
func (frame *Frame) CopyTo(out io.Writer) (err error) {
	if frame.header.startedReading || frame.body.startedReading {
		return AlreadyReadError("Already read from frame, cannot copy")
	}
	if err = writeHeaderTo(out, frame.headerLength, frame.bodyLength); err != nil {
		return
	}
	_, err = io.CopyN(out, frame.framed, int64(frame.headerLength+frame.bodyLength))
	frame.completelyRead <- true
	return
}

/*
Read implements io.Reader.Read for a FrameSection.  Just like the usual Read(),
this one may read incompletely, so make sure to call it until it returns EOF.
*/
func (section *FrameSection) Read(p []byte) (n int, err error) {
	if section.bytesRemaining == 0 {
		return 0, err
	}
	if section.init != nil {
		if err = section.init(); err != nil {
			return 0, err
		}
	}
	section.startedReading = true
	if len(p) > section.bytesRemaining {
		p = p[0:section.bytesRemaining]
	}
	n, err = section.frame.framed.Read(p)
	if n > 0 {
		section.bytesRemaining -= n
	}
	if section.bytesRemaining == 0 {
		err = io.EOF
	}
	return
}

func (section *FrameSection) Drain() (err error) {
	if section.bytesRemaining > 0 {
		_, err = io.Copy(ioutil.Discard, section)
	}
	return
}

func (frame *Frame) HeaderLength() uint16 {
	return frame.headerLength
}

func (frame *Frame) BodyLength() uint16 {
	return frame.bodyLength
}

func (frame *Frame) Header() io.Reader {
	return frame.header
}

func (frame *Frame) Body() io.Reader {
	return frame.body
}

func (framed *Framed) nextFrame() (frame *Frame, err error) {
	frame = &Frame{framed: framed, completelyRead: make(chan bool, 1)}
	frame.header = &FrameSection{frame: frame}
	frame.body = &FrameSection{frame: frame, init: frame.header.Drain, finish: frame.done}
	if err = frame.readLengths(); err != nil {
		return
	}
	return
}

func (frame *Frame) readLengths() (err error) {
	if err = binary.Read(frame.framed, endianness, &frame.headerLength); err != nil {
		return
	}
	if err = binary.Read(frame.framed, endianness, &frame.bodyLength); err != nil {
		return
	}
	frame.header.bytesRemaining = int(frame.headerLength)
	frame.body.bytesRemaining = int(frame.bodyLength)
	return
}

func (frame *Frame) done() {
	frame.completelyRead <- true
}

func writeHeaderTo(out io.Writer, headerLength uint16, bodyLength uint16) (err error) {
	if err = binary.Write(out, endianness, headerLength); err != nil {
		return
	}
	err = binary.Write(out, endianness, bodyLength)
	return
}
<|endoftext|>


<commit_before>/*
Package framed provides an implementations of io.Writer and io.Reader that write
and read whole frames only.

Frames are length-prefixed.  The first two bytes are an unsigned 16 bit int
stored in little-endian byte order indicating the length of the content.  The
remaining bytes are the actual content of the frame.

The use of a uint16 means that the maximum possible frame size (MaxFrameSize)
is 65535.

The frame size can be increased to 4294967295 bytes by calling EnableBigFrames()
on the corresponding Reader and Writer.
*/
package framed

import (
	"bufio"
	"encoding/binary"
	"fmt"
	"io"
	"sync"

	"github.com/oxtoacart/bpool"
)

var endianness = binary.LittleEndian

const (
	// FrameHeaderBits is the size of the frame header in bits
	FrameHeaderBits = 16

	// FrameHeaderBitsBig is the size of the frame header in bits when big frames are enabled
	FrameHeaderBitsBig = 32

	// FrameHeaderLength is the size of the frame header in bytes
	FrameHeaderLength = FrameHeaderBits / 8

	// FrameHeaderLengthBig is the size of the frame header in bytes when big frames are enabled
	FrameHeaderLengthBig = FrameHeaderBitsBig / 8

	// MaxFrameLength is the maximum possible size of a frame (not including the
	// length prefix)
	MaxFrameLength = 1<<FrameHeaderBits - 1

	// MaxFrameLengthBigFrames is the maximum possible size of a frame (not
	// including the length prefix) when big frames are enabled.
	MaxFrameLengthBigFrames = 1<<FrameHeaderBitsBig - 1

	tooLongError = "Attempted to write frame of length %d which is longer than maximum allowed length of %d"
)

// Framed is the common interface for framed Readers and Writers
type Framed interface {
	// EnableBigFrames enables support for frames up to 4294967295 bytes in length
	// by using BigEndian byte order for the frame size and supporting expansion of
	// the size header from 2 to 4 bytes.
	EnableBigFrames(framed interface{})

	// DisableThreadSafety disables thread safety on reading and writing.
	DisableThreadSafety()
}

type framed struct {
	bigFramesEnabled     bool
	headerLength         int
	maxFrameLength       int64
	threadSafetyDisabled bool
	mutex                sync.Mutex
}

func newFramed() framed {
	return framed{
		headerLength:   FrameHeaderLength,
		maxFrameLength: MaxFrameLength,
	}
}

func (fr *framed) EnableBigFrames() {
	fr.mutex.Lock()
	fr.bigFramesEnabled = true
	fr.headerLength = FrameHeaderLengthBig
	fr.maxFrameLength = MaxFrameLengthBigFrames
	fr.mutex.Unlock()
}

func (fr *framed) DisableThreadSafety() {
	fr.threadSafetyDisabled = true
}

/*
A Reader enhances an io.ReadCloser to read data in contiguous frames. It
implements the io.Reader interface, but unlike typical io.Readers it only
returns whole frames.

A Reader also supports the ability to read frames using dynamically allocated
buffers via the ReadFrame method.
*/
type Reader struct {
	Stream io.Reader // the raw underlying connection
	framed
	lb []byte
}

/*
A Writer enhances an io.WriteCloser to write data in contiguous frames. It
implements the io.Writer interface, but unlike typical io.Writers, it includes
information that allows a corresponding Reader to read whole frames without them
being fragmented.

A Writer also supports a method that writes multiple buffers to the underlying
stream as a single frame.
*/
type Writer struct {
	Stream io.Writer // the raw underlying connection
	framed
}

/*
ReadWriteCloser combines a Reader and a Writer on top of an underlying
ReadWriteCloser.
*/
type ReadWriteCloser struct {
	Reader
	Writer
	io.Closer
}

func NewReader(r io.Reader) *Reader {
	return &Reader{
		Stream: r,
		framed: newFramed(),
		lb:     make([]byte, 2),
	}
}

func (fr *Reader) EnableBigFrames() {
	fr.framed.EnableBigFrames()
	fr.lb = make([]byte, 4)
}

func NewWriter(w io.Writer) *Writer {
	return &Writer{Stream: w, framed: newFramed()}
}

func NewReadWriteCloser(rwc io.ReadWriteCloser) *ReadWriteCloser {
	return &ReadWriteCloser{
		*NewReader(rwc),
		*NewWriter(rwc),
		rwc,
	}
}

func (fr *ReadWriteCloser) EnableBigFrames() {
	fr.Reader.EnableBigFrames()
	fr.Writer.EnableBigFrames()
}

func (fr *ReadWriteCloser) DisableThreadSafety() {
	fr.Reader.DisableThreadSafety()
	fr.Writer.DisableThreadSafety()
}

// EnableBuffering enables buffering of read data
func (fr *Reader) EnableBuffering(size int) {
	fr.mutex.Lock()
	fr.Stream = bufio.NewReaderSize(fr.Stream, size+fr.headerLength)
	fr.mutex.Unlock()
}

/*
Read implements the function from io.Reader.  Unlike io.Reader.Read,
frame.Read only returns full frames of data (assuming that the data was written
by a fr.Writer).
*/
func (fr *Reader) Read(buffer []byte) (n int, err error) {
	if !fr.threadSafetyDisabled {
		fr.mutex.Lock()
		defer fr.mutex.Unlock()
	}

	n, err = fr.readLength()
	if err != nil {
		return
	}

	bufferSize := len(buffer)
	if n > bufferSize {
		return 0, fmt.Errorf("Buffer of size %d is too small to hold frame of size %d", bufferSize, n)
	}

	// Read into buffer
	n, err = io.ReadFull(fr.Stream, buffer[:n])
	return
}

// ReadFrame reads the next frame, using a new buffer sized to hold the frame.
func (fr *Reader) ReadFrame() (frame []byte, err error) {
	if !fr.threadSafetyDisabled {
		fr.mutex.Lock()
		defer fr.mutex.Unlock()
	}

	var n int
	n, err = fr.readLength()
	if err != nil {
		return
	}

	frame = make([]byte, n)

	// Read into buffer
	_, err = io.ReadFull(fr.Stream, frame)
	return
}

func (fr *Reader) readLength() (int, error) {
	_, err := io.ReadFull(fr.Stream, fr.lb)
	if err != nil {
		return 0, err
	}
	if fr.bigFramesEnabled {
		return int(endianness.Uint32(fr.lb)), nil
	}
	return int(endianness.Uint16(fr.lb)), nil
}

/*
Write implements the Write method from io.Writer.  It prepends a frame length
header that allows the fr.Reader on the other end to read the whole frame.
*/
func (fr *Writer) Write(frame []byte) (n int, err error) {
	if !fr.threadSafetyDisabled {
		fr.mutex.Lock()
		defer fr.mutex.Unlock()
	}

	n = len(frame)
	if n, err = fr.writeHeaderLength(n); err != nil {
		return
	}

	// Write the data
	var written int
	if written, err = fr.Stream.Write(frame); err != nil {
		return
	}
	if written != n {
		err = fmt.Errorf("%d bytes written, expected to write %d", written, n)
	}
	return
}

// WriteAtomic writes a the frame and its length header in a single write. This requires
// that the frame was read into a buffer obtained from a pool created with
// NewHeaderPreservingBufferPool().
func (fr *Writer) WriteAtomic(frame bpool.ByteSlice) (n int, err error) {
	if !fr.threadSafetyDisabled {
		fr.mutex.Lock()
		defer fr.mutex.Unlock()
	}

	n = len(frame.Bytes())
	_frame := frame.BytesWithHeader()

	switch fr.bigFramesEnabled {
	case true:
		endianness.PutUint32(_frame, uint32(n))
	default:
		endianness.PutUint16(_frame, uint16(n))
	}

	// Write frame and data atomically
	_, err = fr.Stream.Write(_frame)
	if err != nil {
		n = 0
	}
	return
}

func (fr *Writer) WritePieces(pieces ...[]byte) (n int, err error) {
	if !fr.threadSafetyDisabled {
		fr.mutex.Lock()
		defer fr.mutex.Unlock()
	}

	for _, piece := range pieces {
		n = n + len(piece)
	}

	if n, err = fr.writeHeaderLength(n); err != nil {
		return
	}

	// Write the data
	var written int
	for _, piece := range pieces {
		var nw int
		if nw, err = fr.Stream.Write(piece); err != nil {
			return
		}
		written = written + nw
	}
	if written != n {
		err = fmt.Errorf("%d bytes written, expected to write %d", written, n)
	}
	return
}

func (fr *Writer) writeHeaderLength(n int) (int, error) {
	if int64(n) > fr.maxFrameLength {
		return 0, fmt.Errorf(tooLongError, n, MaxFrameLength)
	}

	if fr.bigFramesEnabled {
		return n, binary.Write(fr.Stream, endianness, uint32(n))
	}
	return n, binary.Write(fr.Stream, endianness, uint16(n))
}

// NewHeaderPreservingBufferPool creates a BufferPool that leaves room at the beginning
// of buffers for the framed header. This allows use of the WriteAtomic() capability.
func NewHeaderPreservingBufferPool(maxSize int, width int, enableBigFrames bool) bpool.ByteSlicePool {
	headerLength := FrameHeaderLength
	if enableBigFrames {
		headerLength = FrameHeaderLengthBig
	}
	return bpool.NewHeaderPreservingByteSlicePool(maxSize, width, headerLength)
}
<commit_msg>Sizing buffer pool in bytes rather than frames<commit_after>/*
Package framed provides an implementations of io.Writer and io.Reader that write
and read whole frames only.

Frames are length-prefixed.  The first two bytes are an unsigned 16 bit int
stored in little-endian byte order indicating the length of the content.  The
remaining bytes are the actual content of the frame.

The use of a uint16 means that the maximum possible frame size (MaxFrameSize)
is 65535.

The frame size can be increased to 4294967295 bytes by calling EnableBigFrames()
on the corresponding Reader and Writer.
*/
package framed

import (
	"bufio"
	"encoding/binary"
	"fmt"
	"io"
	"sync"

	"github.com/oxtoacart/bpool"
)

var endianness = binary.LittleEndian

const (
	// FrameHeaderBits is the size of the frame header in bits
	FrameHeaderBits = 16

	// FrameHeaderBitsBig is the size of the frame header in bits when big frames are enabled
	FrameHeaderBitsBig = 32

	// FrameHeaderLength is the size of the frame header in bytes
	FrameHeaderLength = FrameHeaderBits / 8

	// FrameHeaderLengthBig is the size of the frame header in bytes when big frames are enabled
	FrameHeaderLengthBig = FrameHeaderBitsBig / 8

	// MaxFrameLength is the maximum possible size of a frame (not including the
	// length prefix)
	MaxFrameLength = 1<<FrameHeaderBits - 1

	// MaxFrameLengthBigFrames is the maximum possible size of a frame (not
	// including the length prefix) when big frames are enabled.
	MaxFrameLengthBigFrames = 1<<FrameHeaderBitsBig - 1

	tooLongError = "Attempted to write frame of length %d which is longer than maximum allowed length of %d"
)

// Framed is the common interface for framed Readers and Writers
type Framed interface {
	// EnableBigFrames enables support for frames up to 4294967295 bytes in length
	// by using BigEndian byte order for the frame size and supporting expansion of
	// the size header from 2 to 4 bytes.
	EnableBigFrames(framed interface{})

	// DisableThreadSafety disables thread safety on reading and writing.
	DisableThreadSafety()
}

type framed struct {
	bigFramesEnabled     bool
	headerLength         int
	maxFrameLength       int64
	threadSafetyDisabled bool
	mutex                sync.Mutex
}

func newFramed() framed {
	return framed{
		headerLength:   FrameHeaderLength,
		maxFrameLength: MaxFrameLength,
	}
}

func (fr *framed) EnableBigFrames() {
	fr.mutex.Lock()
	fr.bigFramesEnabled = true
	fr.headerLength = FrameHeaderLengthBig
	fr.maxFrameLength = MaxFrameLengthBigFrames
	fr.mutex.Unlock()
}

func (fr *framed) DisableThreadSafety() {
	fr.threadSafetyDisabled = true
}

/*
A Reader enhances an io.ReadCloser to read data in contiguous frames. It
implements the io.Reader interface, but unlike typical io.Readers it only
returns whole frames.

A Reader also supports the ability to read frames using dynamically allocated
buffers via the ReadFrame method.
*/
type Reader struct {
	Stream io.Reader // the raw underlying connection
	framed
	lb []byte
}

/*
A Writer enhances an io.WriteCloser to write data in contiguous frames. It
implements the io.Writer interface, but unlike typical io.Writers, it includes
information that allows a corresponding Reader to read whole frames without them
being fragmented.

A Writer also supports a method that writes multiple buffers to the underlying
stream as a single frame.
*/
type Writer struct {
	Stream io.Writer // the raw underlying connection
	framed
}

/*
ReadWriteCloser combines a Reader and a Writer on top of an underlying
ReadWriteCloser.
*/
type ReadWriteCloser struct {
	Reader
	Writer
	io.Closer
}

func NewReader(r io.Reader) *Reader {
	return &Reader{
		Stream: r,
		framed: newFramed(),
		lb:     make([]byte, 2),
	}
}

func (fr *Reader) EnableBigFrames() {
	fr.framed.EnableBigFrames()
	fr.lb = make([]byte, 4)
}

func NewWriter(w io.Writer) *Writer {
	return &Writer{Stream: w, framed: newFramed()}
}

func NewReadWriteCloser(rwc io.ReadWriteCloser) *ReadWriteCloser {
	return &ReadWriteCloser{
		*NewReader(rwc),
		*NewWriter(rwc),
		rwc,
	}
}

func (fr *ReadWriteCloser) EnableBigFrames() {
	fr.Reader.EnableBigFrames()
	fr.Writer.EnableBigFrames()
}

func (fr *ReadWriteCloser) DisableThreadSafety() {
	fr.Reader.DisableThreadSafety()
	fr.Writer.DisableThreadSafety()
}

// EnableBuffering enables buffering of read data
func (fr *Reader) EnableBuffering(size int) {
	fr.mutex.Lock()
	fr.Stream = bufio.NewReaderSize(fr.Stream, size+fr.headerLength)
	fr.mutex.Unlock()
}

/*
Read implements the function from io.Reader.  Unlike io.Reader.Read,
frame.Read only returns full frames of data (assuming that the data was written
by a fr.Writer).
*/
func (fr *Reader) Read(buffer []byte) (n int, err error) {
	if !fr.threadSafetyDisabled {
		fr.mutex.Lock()
		defer fr.mutex.Unlock()
	}

	n, err = fr.readLength()
	if err != nil {
		return
	}

	bufferSize := len(buffer)
	if n > bufferSize {
		return 0, fmt.Errorf("Buffer of size %d is too small to hold frame of size %d", bufferSize, n)
	}

	// Read into buffer
	n, err = io.ReadFull(fr.Stream, buffer[:n])
	return
}

// ReadFrame reads the next frame, using a new buffer sized to hold the frame.
func (fr *Reader) ReadFrame() (frame []byte, err error) {
	if !fr.threadSafetyDisabled {
		fr.mutex.Lock()
		defer fr.mutex.Unlock()
	}

	var n int
	n, err = fr.readLength()
	if err != nil {
		return
	}

	frame = make([]byte, n)

	// Read into buffer
	_, err = io.ReadFull(fr.Stream, frame)
	return
}

func (fr *Reader) readLength() (int, error) {
	_, err := io.ReadFull(fr.Stream, fr.lb)
	if err != nil {
		return 0, err
	}
	if fr.bigFramesEnabled {
		return int(endianness.Uint32(fr.lb)), nil
	}
	return int(endianness.Uint16(fr.lb)), nil
}

/*
Write implements the Write method from io.Writer.  It prepends a frame length
header that allows the fr.Reader on the other end to read the whole frame.
*/
func (fr *Writer) Write(frame []byte) (n int, err error) {
	if !fr.threadSafetyDisabled {
		fr.mutex.Lock()
		defer fr.mutex.Unlock()
	}

	n = len(frame)
	if n, err = fr.writeHeaderLength(n); err != nil {
		return
	}

	// Write the data
	var written int
	if written, err = fr.Stream.Write(frame); err != nil {
		return
	}
	if written != n {
		err = fmt.Errorf("%d bytes written, expected to write %d", written, n)
	}
	return
}

// WriteAtomic writes a the frame and its length header in a single write. This requires
// that the frame was read into a buffer obtained from a pool created with
// NewHeaderPreservingBufferPool().
func (fr *Writer) WriteAtomic(frame bpool.ByteSlice) (n int, err error) {
	if !fr.threadSafetyDisabled {
		fr.mutex.Lock()
		defer fr.mutex.Unlock()
	}

	n = len(frame.Bytes())
	_frame := frame.BytesWithHeader()

	switch fr.bigFramesEnabled {
	case true:
		endianness.PutUint32(_frame, uint32(n))
	default:
		endianness.PutUint16(_frame, uint16(n))
	}

	// Write frame and data atomically
	_, err = fr.Stream.Write(_frame)
	if err != nil {
		n = 0
	}
	return
}

func (fr *Writer) WritePieces(pieces ...[]byte) (n int, err error) {
	if !fr.threadSafetyDisabled {
		fr.mutex.Lock()
		defer fr.mutex.Unlock()
	}

	for _, piece := range pieces {
		n = n + len(piece)
	}

	if n, err = fr.writeHeaderLength(n); err != nil {
		return
	}

	// Write the data
	var written int
	for _, piece := range pieces {
		var nw int
		if nw, err = fr.Stream.Write(piece); err != nil {
			return
		}
		written = written + nw
	}
	if written != n {
		err = fmt.Errorf("%d bytes written, expected to write %d", written, n)
	}
	return
}

func (fr *Writer) writeHeaderLength(n int) (int, error) {
	if int64(n) > fr.maxFrameLength {
		return 0, fmt.Errorf(tooLongError, n, MaxFrameLength)
	}

	if fr.bigFramesEnabled {
		return n, binary.Write(fr.Stream, endianness, uint32(n))
	}
	return n, binary.Write(fr.Stream, endianness, uint16(n))
}

// NewHeaderPreservingBufferPool creates a BufferPool that leaves room at the beginning
// of buffers for the framed header. This allows use of the WriteAtomic() capability.
func NewHeaderPreservingBufferPool(maxSize int, width int, enableBigFrames bool) bpool.ByteSlicePool {
	headerLength := FrameHeaderLength
	if enableBigFrames {
		headerLength = FrameHeaderLengthBig
	}
	return bpool.NewHeaderPreservingByteSlicePool(maxSize/(width+headerLength), width, headerLength)
}
<|endoftext|>


<commit_before>package main

import (
    "net/http"
    "os"
    "io"
    "time"
    "io/ioutil"
    "fmt"
    fp "path/filepath"
)

func handler(w http.ResponseWriter, r *http.Request, add, isFile bool) {
  // after 200000 bytes of file parts stored in memory
  // the remainder are persisted to disk in temporary files
  err := r.ParseMultipartForm(200000)
  if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
  }

  formData := r.MultipartForm
  relPath := formData.Value["path"][0]

  baseDir := os.Getenv("APP_SRC_DIR")
  if len(baseDir) == 0 {
    baseDir = "/app/"
  }

  filepath := fp.Join(baseDir, relPath)

  if add {

    dir := filepath
    if isFile {
      dir = fp.Dir(filepath)
    }

    err = os.MkdirAll(dir, 0777)
    if err != nil {
      http.Error(w, "Unable to create the folder for writing. Check your write access privilege", http.StatusInternalServerError)
      return
    }

    if isFile {
      file := formData.File["file"][0]

      f, err := file.Open()
      defer f.Close()
      if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
      }

      dest, err := os.Create(filepath)
      defer dest.Close()
      if err != nil {
        http.Error(w, "Unable to create the file for writing. Check your write access privilege", http.StatusInternalServerError)
        return
      }

      _, err = io.Copy(dest, f)
      if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
      }
    }

  } else {

    err = os.RemoveAll(filepath)
    if err != nil {
      http.Error(w, "Unable to delete the file/folder. Check your write access privilege", http.StatusInternalServerError)
      return
    }
  }

  os.Chtimes(fp.Join(baseDir, ".hotrod-update"), time.Now(), time.Now())

}

func addBaseHandler(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "Hello, server running.")
}

func addFileHandler(w http.ResponseWriter, r *http.Request) {
  handler(w, r, true, true)
}

func addFolderHandler(w http.ResponseWriter, r *http.Request) {
  handler(w, r, true, false)
}

func removeHandler(w http.ResponseWriter, r *http.Request) {
  handler(w, r, false, false)
}

func main() {

    baseDir := os.Getenv("APP_SRC_DIR")
    if len(baseDir) == 0 {
      baseDir = "/app/"
    }

    ioutil.WriteFile(fp.Join(baseDir, ".hotrod-update"), []byte(""), 0777)

    http.HandleFunc("/", addBaseHandler)
    http.HandleFunc("/addFile", addFileHandler)
    http.HandleFunc("/addFolder", addFolderHandler)
    http.HandleFunc("/remove", removeHandler)
    http.ListenAndServe(":8888", nil)
}
<commit_msg>add const paths<commit_after>package main

import (
    "net/http"
    "os"
    "io"
    "time"
    "io/ioutil"
    "fmt"
    fp "path/filepath"
)

const (
  UPDATE_FILE = ".hotrod-update"
  BASE_DIR = "/app/"
)

func handler(w http.ResponseWriter, r *http.Request, add, isFile bool) {
  // after 200000 bytes of file parts stored in memory
  // the remainder are persisted to disk in temporary files
  err := r.ParseMultipartForm(200000)
  if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
  }

  formData := r.MultipartForm
  relPath := formData.Value["path"][0]

  filepath := fp.Join(BASE_DIR, relPath)

  if add {

    dir := filepath
    if isFile {
      dir = fp.Dir(filepath)
    }

    err = os.MkdirAll(dir, 0777)
    if err != nil {
      http.Error(w, "Unable to create the folder for writing. Check your write access privilege", http.StatusInternalServerError)
      return
    }

    if isFile {
      file := formData.File["file"][0]

      f, err := file.Open()
      defer f.Close()
      if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
      }

      dest, err := os.Create(filepath)
      defer dest.Close()
      if err != nil {
        http.Error(w, "Unable to create the file for writing. Check your write access privilege", http.StatusInternalServerError)
        return
      }

      _, err = io.Copy(dest, f)
      if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
      }
    }

  } else {

    err = os.RemoveAll(filepath)
    if err != nil {
      http.Error(w, "Unable to delete the file/folder. Check your write access privilege", http.StatusInternalServerError)
      return
    }
  }

  os.Chtimes(fp.Join(BASE_DIR, UPDATE_FILE), time.Now(), time.Now())
}

func addBaseHandler(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "Hello, server running.")
}

func addFileHandler(w http.ResponseWriter, r *http.Request) {
  handler(w, r, true, true)
}

func addFolderHandler(w http.ResponseWriter, r *http.Request) {
  handler(w, r, true, false)
}

func removeHandler(w http.ResponseWriter, r *http.Request) {
  handler(w, r, false, false)
}

func main() {
    ioutil.WriteFile(fp.Join(BASE_DIR, UPDATE_FILE), []byte(""), 0777)

    http.HandleFunc("/", addBaseHandler)
    http.HandleFunc("/addFile", addFileHandler)
    http.HandleFunc("/addFolder", addFolderHandler)
    http.HandleFunc("/remove", removeHandler)
    http.ListenAndServe(":8888", nil)
}
<|endoftext|>