<commit_before>package proj

import (
	"fmt"
	"math"
	"strconv"
	"strings"
)

func splitWKTName(secData string) (name, data string) {
	comma := strings.Index(secData, ",")
	name = secData[0:comma]
	data = secData[comma+1 : len(secData)]
	return
}

func (sr *SR) parseWKTProjCS(secName []string, secData string) error {
	if len(secName) == 1 {
		name, data := splitWKTName(secData)
		sr.SRSCode = name
		return sr.parseWKTSection(secName, data)
	}
	switch secName[1] {
	case "GEOGCS":
		sr.parseWKTGeogCS(secName, secData)
	case "PRIMEM":
		if err := sr.parseWKTPrimeM(secName, secData); err != nil {
			return err
		}
	case "PROJECTION":
		sr.parseWKTProjection(secName, secData)
	case "PARAMETER":
		if err := sr.parseWKTParameter(secName, secData); err != nil {
			return err
		}
	case "UNIT":
		if err := sr.parseWKTUnit(secName, secData); err != nil {
			return err
		}
	case "AUTHORITY": // This holds for example the ESPG number.
	case "AXIS":
	default:
		return fmt.Errorf("proj.parseWKTProjCS: unknown WKT section %#v", secName)
	}
	return nil
}

func stringInArray(s string, a []string) bool {
	for _, aa := range a {
		if aa == s {
			return true
		}
	}
	return false
}

func (sr *SR) parseWKTGeogCS(secName []string, secData string) error {
	if secName[len(secName)-1] == "GEOGCS" {
		name, data := splitWKTName(secData)
		// Set the datum name to the GEOCS name in case we don't find a datum.
		sr.DatumCode = strings.ToLower(name)
		sr.datumRename()
		return sr.parseWKTSection(secName, data)
	} else if stringInArray("DATUM", secName) {
		return sr.parseWKTDatum(secName, secData)
	} else if secName[len(secName)-1] == "PRIMEM" {
		return sr.parseWKTPrimeM(secName, secData)
	} else if secName[len(secName)-1] == "UNIT" && sr.Name == longlat {
		return sr.parseWKTUnit(secName, secData)
	} else if secName[len(secName)-1] == "AUTHORITY" {
		return nil // Don't do anything with authority for now.
	}
	return fmt.Errorf("proj.parseWKTGeogCS: unknown WKT section %v", secName)
}

func (sr *SR) parseWKTDatum(secName []string, secData string) error {
	switch secName[len(secName)-1] {
	case "DATUM":
		name, data := splitWKTName(secData)
		sr.DatumCode = strings.ToLower(strings.Trim(name, "\" "))
		sr.datumRename()
		return sr.parseWKTSection(secName, data)
	case "SPHEROID":
		if err := sr.parseWKTSpheroid(secName, secData); err != nil {
			return err
		}
	case "TOWGS84":
		s := strings.Split(secData, ",")
		sr.DatumParams = make([]float64, len(s))
		for i, ss := range s {
			var err error
			sr.DatumParams[i], err = strconv.ParseFloat(strings.TrimSpace(ss), 64)
			if err != nil {
				return err
			}
		}
	case "AUTHORITY": // Don't do anything with this for now.
	default:
		return fmt.Errorf("proj.parseWKTDatum: unknown WKT section %v", secName)
	}
	return nil
}

func (sr *SR) datumRename() {
	if sr.DatumCode[0:2] == "d_" {
		sr.DatumCode = sr.DatumCode[2:len(sr.DatumCode)]
	}
	if sr.DatumCode == "new_zealand_geodetic_datum_1949" ||
		sr.DatumCode == "new_zealand_1949" {
		sr.DatumCode = "nzgd49"
	}
	if sr.DatumCode == "wgs_1984" {
		if sr.Name == "Mercator_Auxiliary_Sphere" {
			sr.sphere = true
		}
		sr.DatumCode = "wgs84"
	}
	if strings.HasSuffix(sr.DatumCode, "_ferro") {
		sr.DatumCode = strings.TrimSuffix(sr.DatumCode, "_ferro")
	}
	if strings.HasSuffix(sr.DatumCode, "_jakarta") {
		sr.DatumCode = strings.TrimSuffix(sr.DatumCode, "_jakarta")
	}
	if strings.Contains(sr.DatumCode, "belge") {
		sr.DatumCode = "rnb72"
	}
}

func (sr *SR) parseWKTSpheroid(secName []string, secData string) error {
	d := strings.Split(secData, ",")
	sr.Ellps = strings.Replace(strings.Trim(d[0], "\""), "_19", "", -1)
	sr.Ellps = strings.Replace(sr.Ellps, "clarke_18", "clrk", -1)
	sr.Ellps = strings.Replace(sr.Ellps, "Clarke_18", "clrk", -1)
	if len(sr.Ellps) >= 13 && strings.ToLower(sr.Ellps[0:13]) == "international" {
		sr.Ellps = "intl"
	}
	a, err := strconv.ParseFloat(d[1], 64)
	if err != nil {
		return fmt.Errorf("in proj.parseWKTSpheroid a: '%v'", err)
	}
	sr.A = a
	sr.Rf, err = strconv.ParseFloat(d[2], 64)
	if err != nil {
		return fmt.Errorf("in proj.parseWKTSpheroid rf: '%v'", err)
	}
	if strings.Contains(sr.DatumCode, "osgb_1936") {
		sr.DatumCode = "osgb36"
	}
	if math.IsInf(sr.B, 0) {
		sr.B = sr.A
	}
	return nil
}

func (sr *SR) parseWKTProjection(secName []string, secData string) {
	if strings.Contains(secData, ",") {
		// Sometimes the projection has an authority after it, which we aren't
		// currently interested in.
		sr.Name = strings.Trim(strings.Split(secData, ",")[0], "\" ")
	} else {
		sr.Name = strings.Trim(secData, "\"")
	}
}

func (sr *SR) parseWKTParameter(secName []string, secData string) error {
	v := strings.Split(secData, ",")
	name := strings.Trim(strings.ToLower(v[0]), "\"")
	val, err := strconv.ParseFloat(strings.TrimSpace(v[1]), 64)
	if err != nil {
		return fmt.Errorf("in proj.parseWKTParameter: %v", err)
	}
	switch name {
	case "standard_parallel_1":
		sr.Lat1 = val * deg2rad
	case "standard_parallel_2":
		sr.Lat2 = val * deg2rad
	case "false_easting":
		sr.X0 = val
	case "false_northing":
		sr.Y0 = val
	case "latitude_of_origin":
		sr.Lat0 = val * deg2rad
	case "central_parallel":
		sr.Lat0 = val * deg2rad
	case "scale_factor":
		sr.K0 = val
	case "latitude_of_center":
		sr.Lat0 = val * deg2rad
	case "longitude_of_center":
		sr.LongC = val * deg2rad
	case "central_meridian":
		sr.Long0 = val * deg2rad
	case "azimuth":
		sr.Alpha = val * deg2rad
	case "auxiliary_sphere_type", "rectified_grid_angle":
		// TODO: Figure out if this is important.
	default:
		return fmt.Errorf("proj.parseWKTParameter: unknown name %v", name)
	}
	return nil
}

func (sr *SR) parseWKTPrimeM(secName []string, secData string) error {
	v := strings.Split(secData, ",")
	name := strings.ToLower(strings.Trim(v[0], "\""))
	if name != "greenwich" {
		return fmt.Errorf("in proj.parseWTKPrimeM: prime meridian is %s but"+
			"only greenwich is supported", name)
	}
	return nil
}

func (sr *SR) parseWKTUnit(secName []string, secData string) error {
	v := strings.Split(secData, ",")
	sr.Units = strings.Trim(strings.ToLower(v[0]), "\"")
	if sr.Units == "metre" {
		sr.Units = "meter"
	}
	if len(v) > 1 {
		convert, err := strconv.ParseFloat(strings.TrimSpace(v[1]), 64)
		if err != nil {
			return fmt.Errorf("in proj.parseWKTUnit: %v", err)
		}
		if sr.Name == longlat {
			sr.ToMeter = convert * sr.A
		} else {
			sr.ToMeter = convert
		}
	}
	return nil
}

// wkt parses a WKT specification.
func wkt(wkt string) (*SR, error) {
	sr := NewSR()
	err := sr.parseWKTSection([]string{}, wkt)

	// Convert units to meters.
	sr.X0 *= sr.ToMeter
	sr.Y0 *= sr.ToMeter
	if math.IsNaN(sr.Lat0) {
		sr.Lat0 = sr.Lat1
	}

	return sr, err
}

// parseWKTSection is a recursive function to parse a WKT specification.
func (sr *SR) parseWKTSection(secName []string, secData string) error {
	open, close := findWKTSections(secData)
	if len(open) != len(close) {
		return fmt.Errorf("proj: malformed WKT section '%s'", secData)
	}
	for i, o := range open {
		c := close[i]
		name := strings.Trim(secData[0:o], ", ")
		if strings.Contains(name, ",") {
			comma := strings.LastIndex(name, ",")
			name = strings.TrimSpace(name[comma+1 : len(name)])
		}
		secNameO := append(secName, name)
		secDataO := secData[o+1 : c]
		var err error
		switch secNameO[0] {
		case "PROJCS":
			err = sr.parseWKTProjCS(secNameO, secDataO)
		case "GEOGCS":
			// This should only happen if there is no PROJCS.
			sr.Name = longlat
			err = sr.parseWKTGeogCS(secNameO, secDataO)
		case "LOCAL_CS":
			sr.Name = "identity"
			sr.local = true
		default:
			err = fmt.Errorf("proj: unknown WKT section name '%s'", secNameO)
		}
		if err != nil {
			return err
		}
	}
	return nil
}

// findWKTSections steps through all or part of a WKT specifications
// to find matching outermost-level brackets.
func findWKTSections(secData string) (open, close []int) {
	nest := 0
	for i := 0; i < len(secData); i++ {
		if secData[i] == '[' {
			if nest == 0 {
				open = append(open, i)
			}
			nest++
		} else if secData[i] == ']' {
			nest--
			if nest == 0 {
				close = append(close, i)
			}
		}
	}
	return
}
<commit_msg>Added GEOGCS METADATA<commit_after>package proj

import (
	"fmt"
	"math"
	"strconv"
	"strings"
)

func splitWKTName(secData string) (name, data string) {
	comma := strings.Index(secData, ",")
	name = secData[0:comma]
	data = secData[comma+1 : len(secData)]
	return
}

func (sr *SR) parseWKTProjCS(secName []string, secData string) error {
	if len(secName) == 1 {
		name, data := splitWKTName(secData)
		sr.SRSCode = name
		return sr.parseWKTSection(secName, data)
	}
	switch secName[1] {
	case "GEOGCS":
		sr.parseWKTGeogCS(secName, secData)
	case "PRIMEM":
		if err := sr.parseWKTPrimeM(secName, secData); err != nil {
			return err
		}
	case "PROJECTION":
		sr.parseWKTProjection(secName, secData)
	case "PARAMETER":
		if err := sr.parseWKTParameter(secName, secData); err != nil {
			return err
		}
	case "UNIT":
		if err := sr.parseWKTUnit(secName, secData); err != nil {
			return err
		}
	case "AUTHORITY": // This holds for example the ESPG number.
	case "AXIS":
	default:
		return fmt.Errorf("proj.parseWKTProjCS: unknown WKT section %#v", secName)
	}
	return nil
}

func stringInArray(s string, a []string) bool {
	for _, aa := range a {
		if aa == s {
			return true
		}
	}
	return false
}

func (sr *SR) parseWKTGeogCS(secName []string, secData string) error {
	if secName[len(secName)-1] == "GEOGCS" {
		name, data := splitWKTName(secData)
		// Set the datum name to the GEOCS name in case we don't find a datum.
		sr.DatumCode = strings.ToLower(name)
		sr.datumRename()
		return sr.parseWKTSection(secName, data)
	} else if stringInArray("DATUM", secName) {
		return sr.parseWKTDatum(secName, secData)
	} else if secName[len(secName)-1] == "PRIMEM" {
		return sr.parseWKTPrimeM(secName, secData)
	} else if secName[len(secName)-1] == "UNIT" && sr.Name == longlat {
		return sr.parseWKTUnit(secName, secData)
	} else if secName[len(secName)-1] == "AUTHORITY" {
		return nil // Don't do anything with authority for now.
	} else if secName[len(secName)-1] == "METADATA" {
		return nil
	}
	return fmt.Errorf("proj.parseWKTGeogCS: unknown WKT section %v", secName)
}

func (sr *SR) parseWKTDatum(secName []string, secData string) error {
	switch secName[len(secName)-1] {
	case "DATUM":
		name, data := splitWKTName(secData)
		sr.DatumCode = strings.ToLower(strings.Trim(name, "\" "))
		sr.datumRename()
		return sr.parseWKTSection(secName, data)
	case "SPHEROID":
		if err := sr.parseWKTSpheroid(secName, secData); err != nil {
			return err
		}
	case "TOWGS84":
		s := strings.Split(secData, ",")
		sr.DatumParams = make([]float64, len(s))
		for i, ss := range s {
			var err error
			sr.DatumParams[i], err = strconv.ParseFloat(strings.TrimSpace(ss), 64)
			if err != nil {
				return err
			}
		}
	case "AUTHORITY": // Don't do anything with this for now.
	default:
		return fmt.Errorf("proj.parseWKTDatum: unknown WKT section %v", secName)
	}
	return nil
}

func (sr *SR) datumRename() {
	if sr.DatumCode[0:2] == "d_" {
		sr.DatumCode = sr.DatumCode[2:len(sr.DatumCode)]
	}
	if sr.DatumCode == "new_zealand_geodetic_datum_1949" ||
		sr.DatumCode == "new_zealand_1949" {
		sr.DatumCode = "nzgd49"
	}
	if sr.DatumCode == "wgs_1984" {
		if sr.Name == "Mercator_Auxiliary_Sphere" {
			sr.sphere = true
		}
		sr.DatumCode = "wgs84"
	}
	if strings.HasSuffix(sr.DatumCode, "_ferro") {
		sr.DatumCode = strings.TrimSuffix(sr.DatumCode, "_ferro")
	}
	if strings.HasSuffix(sr.DatumCode, "_jakarta") {
		sr.DatumCode = strings.TrimSuffix(sr.DatumCode, "_jakarta")
	}
	if strings.Contains(sr.DatumCode, "belge") {
		sr.DatumCode = "rnb72"
	}
}

func (sr *SR) parseWKTSpheroid(secName []string, secData string) error {
	d := strings.Split(secData, ",")
	sr.Ellps = strings.Replace(strings.Trim(d[0], "\""), "_19", "", -1)
	sr.Ellps = strings.Replace(sr.Ellps, "clarke_18", "clrk", -1)
	sr.Ellps = strings.Replace(sr.Ellps, "Clarke_18", "clrk", -1)
	if len(sr.Ellps) >= 13 && strings.ToLower(sr.Ellps[0:13]) == "international" {
		sr.Ellps = "intl"
	}
	a, err := strconv.ParseFloat(d[1], 64)
	if err != nil {
		return fmt.Errorf("in proj.parseWKTSpheroid a: '%v'", err)
	}
	sr.A = a
	sr.Rf, err = strconv.ParseFloat(d[2], 64)
	if err != nil {
		return fmt.Errorf("in proj.parseWKTSpheroid rf: '%v'", err)
	}
	if strings.Contains(sr.DatumCode, "osgb_1936") {
		sr.DatumCode = "osgb36"
	}
	if math.IsInf(sr.B, 0) {
		sr.B = sr.A
	}
	return nil
}

func (sr *SR) parseWKTProjection(secName []string, secData string) {
	if strings.Contains(secData, ",") {
		// Sometimes the projection has an authority after it, which we aren't
		// currently interested in.
		sr.Name = strings.Trim(strings.Split(secData, ",")[0], "\" ")
	} else {
		sr.Name = strings.Trim(secData, "\"")
	}
}

func (sr *SR) parseWKTParameter(secName []string, secData string) error {
	v := strings.Split(secData, ",")
	name := strings.Trim(strings.ToLower(v[0]), "\"")
	val, err := strconv.ParseFloat(strings.TrimSpace(v[1]), 64)
	if err != nil {
		return fmt.Errorf("in proj.parseWKTParameter: %v", err)
	}
	switch name {
	case "standard_parallel_1":
		sr.Lat1 = val * deg2rad
	case "standard_parallel_2":
		sr.Lat2 = val * deg2rad
	case "false_easting":
		sr.X0 = val
	case "false_northing":
		sr.Y0 = val
	case "latitude_of_origin":
		sr.Lat0 = val * deg2rad
	case "central_parallel":
		sr.Lat0 = val * deg2rad
	case "scale_factor":
		sr.K0 = val
	case "latitude_of_center":
		sr.Lat0 = val * deg2rad
	case "longitude_of_center":
		sr.LongC = val * deg2rad
	case "central_meridian":
		sr.Long0 = val * deg2rad
	case "azimuth":
		sr.Alpha = val * deg2rad
	case "auxiliary_sphere_type", "rectified_grid_angle":
		// TODO: Figure out if this is important.
	default:
		return fmt.Errorf("proj.parseWKTParameter: unknown name %v", name)
	}
	return nil
}

func (sr *SR) parseWKTPrimeM(secName []string, secData string) error {
	v := strings.Split(secData, ",")
	name := strings.ToLower(strings.Trim(v[0], "\""))
	if name != "greenwich" {
		return fmt.Errorf("in proj.parseWTKPrimeM: prime meridian is %s but"+
			"only greenwich is supported", name)
	}
	return nil
}

func (sr *SR) parseWKTUnit(secName []string, secData string) error {
	v := strings.Split(secData, ",")
	sr.Units = strings.Trim(strings.ToLower(v[0]), "\"")
	if sr.Units == "metre" {
		sr.Units = "meter"
	}
	if len(v) > 1 {
		convert, err := strconv.ParseFloat(strings.TrimSpace(v[1]), 64)
		if err != nil {
			return fmt.Errorf("in proj.parseWKTUnit: %v", err)
		}
		if sr.Name == longlat {
			sr.ToMeter = convert * sr.A
		} else {
			sr.ToMeter = convert
		}
	}
	return nil
}

// wkt parses a WKT specification.
func wkt(wkt string) (*SR, error) {
	sr := NewSR()
	err := sr.parseWKTSection([]string{}, wkt)

	// Convert units to meters.
	sr.X0 *= sr.ToMeter
	sr.Y0 *= sr.ToMeter
	if math.IsNaN(sr.Lat0) {
		sr.Lat0 = sr.Lat1
	}

	return sr, err
}

// parseWKTSection is a recursive function to parse a WKT specification.
func (sr *SR) parseWKTSection(secName []string, secData string) error {
	open, close := findWKTSections(secData)
	if len(open) != len(close) {
		return fmt.Errorf("proj: malformed WKT section '%s'", secData)
	}
	for i, o := range open {
		c := close[i]
		name := strings.Trim(secData[0:o], ", ")
		if strings.Contains(name, ",") {
			comma := strings.LastIndex(name, ",")
			name = strings.TrimSpace(name[comma+1 : len(name)])
		}
		secNameO := append(secName, name)
		secDataO := secData[o+1 : c]
		var err error
		switch secNameO[0] {
		case "PROJCS":
			err = sr.parseWKTProjCS(secNameO, secDataO)
		case "GEOGCS":
			// This should only happen if there is no PROJCS.
			sr.Name = longlat
			err = sr.parseWKTGeogCS(secNameO, secDataO)
		case "LOCAL_CS":
			sr.Name = "identity"
			sr.local = true
		default:
			err = fmt.Errorf("proj: unknown WKT section name '%s'", secNameO)
		}
		if err != nil {
			return err
		}
	}
	return nil
}

// findWKTSections steps through all or part of a WKT specifications
// to find matching outermost-level brackets.
func findWKTSections(secData string) (open, close []int) {
	nest := 0
	for i := 0; i < len(secData); i++ {
		if secData[i] == '[' {
			if nest == 0 {
				open = append(open, i)
			}
			nest++
		} else if secData[i] == ']' {
			nest--
			if nest == 0 {
				close = append(close, i)
			}
		}
	}
	return
}
<|endoftext|>


<commit_before>// Copyright (C) 2013 Miquel Sabaté Solà
// This file is licensed under the MIT license.
// See the LICENSE file.

// This package encapsulates all the methods regarding the File Cache.
package fcache

import (
    "os"
    "fmt"
    "path"
    "time"
    "errors"
    "io/ioutil"
)

// This type contains some needed info that will be used when caching.
type Cache struct {
    // The directory
    Dir string

    // The expiration time to be set for each file.
    Expiration time.Duration

    // The permissions to be set when this cache creates new files.
    Permissions os.FileMode
}

// Internal: get whether the cache file is still hot (valid) or not.
//
// mod - The last modification time of the cache file.
//
// Returns true if the cache file is still valid, false otherwise.
func (c *Cache) isHot(mod time.Time) bool {
    elapsed := time.Now().Sub(mod)
    return c.Expiration > elapsed
}

// Get a pointer to an initialized Cache structure.
//
// dir        - The path to the cache directory. If the directory does not
//              exist, it will create a new directory with permissions 0644.
// expiration - The expiration time. That is, how many nanoseconds has to pass
//              by when a cache file is no longer considered valid.
// perm       - The permissions that the cache should operate in when creating
//              new files.
//
// Returns a Cache pointer that points to an initialized Cache structure. It
// will return nil if something goes wrong.
func NewCache(dir string, expiration time.Duration, perm os.FileMode) *Cache {
    // First of all, get the directory path straight.
    if _, err := os.Stat(dir); err != nil {
        if os.IsNotExist(err) {
            if err = os.MkdirAll(dir, perm); err != nil {
                fmt.Printf("Error: %v\n", err)
                return nil
            }
        } else {
            fmt.Printf("Error: %v\n", err)
            return nil
        }
    }

    // Now it's safe to create the cache.
    cache := new(Cache)
    cache.Dir = dir
    cache.Expiration = expiration
    cache.Permissions = perm
    return cache
}

// Set the contents for a cache file. If this file doesn't exist already, it
// will be created with permissions 0644.
//
// name     - The name of the file.
// contents - The contents that the cache file has to contain after calling
//            this function.
//
// Returns nil if everything was ok. Otherwise it will return an error.
func (c *Cache) Set(name string, contents []byte) error {
    url := path.Join(c.Dir, name)
    return ioutil.WriteFile(url, contents, c.Permissions)
}

// Get the contents of a valid cache file.
//
// name - The name of the file.
//
// Returns a slice of bytes and an error. The slice of bytes contain the
// contents of the cache file. The error is set to nil if everything was fine.
func (c *Cache) Get(name string) ([]byte, error) {
    url := path.Join(c.Dir, name)
    if fi, err := os.Stat(url); err == nil {
        if c.isHot(fi.ModTime()) {
            return ioutil.ReadFile(url)
        }
        // Remove this file, its time has expired.
        os.Remove(url)
    }
    return []byte{}, errors.New("miss.")
}

// Remove a cache file.
//
// name - The name of the file.
//
// Returns nil if everything was ok. Otherwise it will return an error.
func (c *Cache) Flush(name string) error {
    url := path.Join(c.Dir, name)
    return os.Remove(url)
}

// Remove all the files from the cache.
//
// Returns nil if everything was ok. Otherwise it will return an error.
func (c *Cache) FlushAll() error {
    url := path.Join(c.Dir)
    err := os.RemoveAll(url)
    if err == nil {
        err = os.MkdirAll(url, c.Permissions)
    }
    return err
}
<commit_msg>Removed the isHot function<commit_after>// Copyright (C) 2013 Miquel Sabaté Solà
// This file is licensed under the MIT license.
// See the LICENSE file.

// This package encapsulates all the methods regarding the File Cache.
package fcache

import (
    "os"
    "fmt"
    "path"
    "time"
    "errors"
    "io/ioutil"
)

// This type contains some needed info that will be used when caching.
type Cache struct {
    // The directory
    Dir string

    // The expiration time to be set for each file.
    Expiration time.Duration

    // The permissions to be set when this cache creates new files.
    Permissions os.FileMode
}

// Get a pointer to an initialized Cache structure.
//
// dir        - The path to the cache directory. If the directory does not
//              exist, it will create a new directory with permissions 0644.
// expiration - The expiration time. That is, how many nanoseconds has to pass
//              by when a cache file is no longer considered valid.
// perm       - The permissions that the cache should operate in when creating
//              new files.
//
// Returns a Cache pointer that points to an initialized Cache structure. It
// will return nil if something goes wrong.
func NewCache(dir string, expiration time.Duration, perm os.FileMode) *Cache {
    // First of all, get the directory path straight.
    if _, err := os.Stat(dir); err != nil {
        if os.IsNotExist(err) {
            if err = os.MkdirAll(dir, perm); err != nil {
                fmt.Printf("Error: %v\n", err)
                return nil
            }
        } else {
            fmt.Printf("Error: %v\n", err)
            return nil
        }
    }

    // Now it's safe to create the cache.
    cache := new(Cache)
    cache.Dir = dir
    cache.Expiration = expiration
    cache.Permissions = perm
    return cache
}

// Set the contents for a cache file. If this file doesn't exist already, it
// will be created with permissions 0644.
//
// name     - The name of the file.
// contents - The contents that the cache file has to contain after calling
//            this function.
//
// Returns nil if everything was ok. Otherwise it will return an error.
func (c *Cache) Set(name string, contents []byte) error {
    url := path.Join(c.Dir, name)
    return ioutil.WriteFile(url, contents, c.Permissions)
}

// Get the contents of a valid cache file.
//
// name - The name of the file.
//
// Returns a slice of bytes and an error. The slice of bytes contain the
// contents of the cache file. The error is set to nil if everything was fine.
func (c *Cache) Get(name string) ([]byte, error) {
    url := path.Join(c.Dir, name)
    if fi, err := os.Stat(url); err == nil {
        elapsed := time.Now().Sub(fi.ModTime())
        if c.Expiration > elapsed {
            return ioutil.ReadFile(url)
        }
        // Remove this file, its time has expired.
        os.Remove(url)
    }
    return []byte{}, errors.New("miss.")
}

// Remove a cache file.
//
// name - The name of the file.
//
// Returns nil if everything was ok. Otherwise it will return an error.
func (c *Cache) Flush(name string) error {
    url := path.Join(c.Dir, name)
    return os.Remove(url)
}

// Remove all the files from the cache.
//
// Returns nil if everything was ok. Otherwise it will return an error.
func (c *Cache) FlushAll() error {
    url := path.Join(c.Dir)
    err := os.RemoveAll(url)
    if err == nil {
        err = os.MkdirAll(url, c.Permissions)
    }
    return err
}
<|endoftext|>


<commit_before>package main

import (
	"debug/pe"
	"fmt"
	"github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
	AS "github.com/williballenthin/Lancelot/address_space"
	"github.com/williballenthin/Lancelot/artifacts"
	"github.com/williballenthin/Lancelot/config"
	peloader "github.com/williballenthin/Lancelot/loader/pe"
	"github.com/williballenthin/Lancelot/utils"
	W "github.com/williballenthin/Lancelot/workspace"
	"log"
	"os"
	"runtime"
	"strconv"
)

var inputFlag = cli.StringFlag{
	Name:  "input_file",
	Usage: "file to explore",
}

var fvaFlag = cli.StringFlag{
	Name:  "fva",
	Usage: "address of function to graph",
}

var verboseFlag = cli.BoolFlag{
	Name:  "verbose",
	Usage: "print debugging output",
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func doit(path string, fva AS.VA) error {
	runtime.LockOSThread()
	logrus.SetLevel(logrus.DebugLevel)

	exe, e := pe.Open(path)
	check(e)

	persis, e := config.MakeDefaultPersistence()
	check(e)

	ws, e := W.New(W.ARCH_X86, W.MODE_32, persis)
	check(e)

	dis, e := ws.GetDisassembler()
	check(e)

	loader, e := peloader.New(path, exe)
	check(e)

	_, e = loader.Load(ws)
	check(e)

	check(config.RegisterDefaultAnalyzers(ws))

	check(ws.MakeFunction(fva))

	f, e := ws.Artifacts.GetFunction(fva)
	check(e)

	fmt.Printf("digraph asm {\n")
	fmt.Printf(" node [shape=plain, style=\"rounded\", fontname=\"courier\"]\n")

	var exploreBBs func(bb *artifacts.BasicBlock) error
	exploreBBs = func(bb *artifacts.BasicBlock) error {
		fmt.Printf("bb_%s [label=<\n", bb.Start)
		fmt.Printf("
\n")

		insns, e := bb.GetInstructions(dis, ws)
		check(e)
		for _, insn := range insns {
			fmt.Printf("
\n")
			fmt.Printf("    \n")
			fmt.Printf("      %s\n", AS.VA(insn.Address))
			fmt.Printf("    	\n")
			fmt.Printf("    \n")
			fmt.Printf("      %s\n", insn.Mnemonic)
			fmt.Printf("    	\n")
			fmt.Printf("    \n")
			fmt.Printf("      %s\n", insn.OpStr)
			fmt.Printf("    	\n")
			fmt.Printf("
\n")
		}
		fmt.Printf("
\n")
		fmt.Printf(">];\n")

		nextBBs, e := bb.GetNextBasicBlocks()
		check(e)

		for _, nextBB := range nextBBs {
			exploreBBs(nextBB)
		}

		for _, nextBB := range nextBBs {
			fmt.Printf("bb_%s -> bb_%s;\n", bb.Start, nextBB.Start)
		}

		return nil
	}

	firstBB, e := f.GetFirstBasicBlock()
	check(e)

	exploreBBs(firstBB)
	defer fmt.Printf("}")

	runtime.UnlockOSThread()
	return nil
}

func main() {
	app := cli.NewApp()
	app.Version = "0.1"
	app.Name = "run_linear_disassembler"
	app.Usage = "Invoke linear disassembler."
	app.Flags = []cli.Flag{inputFlag, fvaFlag}
	app.Action = func(c *cli.Context) {
		if utils.CheckRequiredArgs(c, []cli.StringFlag{inputFlag, fvaFlag}) != nil {
			return
		}

		inputFile := c.String("input_file")
		if !utils.DoesPathExist(inputFile) {
			log.Printf("Error: file %s must exist", inputFile)
			return
		}

		fva, e := strconv.ParseUint(c.String("fva"), 0x10, 64)
		check(e)

		check(doit(inputFile, AS.VA(fva)))
	}
	app.Run(os.Args)
}
<commit_msg>graph: add byte hexdump<commit_after>package main

import (
	"debug/pe"
	"fmt"
	"github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
	AS "github.com/williballenthin/Lancelot/address_space"
	"github.com/williballenthin/Lancelot/artifacts"
	"github.com/williballenthin/Lancelot/config"
	peloader "github.com/williballenthin/Lancelot/loader/pe"
	"github.com/williballenthin/Lancelot/utils"
	W "github.com/williballenthin/Lancelot/workspace"
	"log"
	"os"
	"runtime"
	"strconv"
	"strings"
)

var inputFlag = cli.StringFlag{
	Name:  "input_file",
	Usage: "file to explore",
}

var fvaFlag = cli.StringFlag{
	Name:  "fva",
	Usage: "address of function to graph",
}

var verboseFlag = cli.BoolFlag{
	Name:  "verbose",
	Usage: "print debugging output",
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func doit(path string, fva AS.VA) error {
	runtime.LockOSThread()
	logrus.SetLevel(logrus.DebugLevel)

	exe, e := pe.Open(path)
	check(e)

	persis, e := config.MakeDefaultPersistence()
	check(e)

	ws, e := W.New(W.ARCH_X86, W.MODE_32, persis)
	check(e)

	dis, e := ws.GetDisassembler()
	check(e)

	loader, e := peloader.New(path, exe)
	check(e)

	_, e = loader.Load(ws)
	check(e)

	check(config.RegisterDefaultAnalyzers(ws))

	check(ws.MakeFunction(fva))

	f, e := ws.Artifacts.GetFunction(fva)
	check(e)

	fmt.Printf("digraph asm {\n")
	fmt.Printf(" node [shape=plain, style=\"rounded\", fontname=\"courier\"]\n")

	var exploreBBs func(bb *artifacts.BasicBlock) error
	exploreBBs = func(bb *artifacts.BasicBlock) error {
		fmt.Printf("bb_%s [label=<\n", bb.Start)
		fmt.Printf("
\n")

		insns, e := bb.GetInstructions(dis, ws)
		check(e)
		for _, insn := range insns {

			d, e := ws.MemRead(AS.VA(insn.Address), uint64(insn.Size))
			check(e)

			// format each of those as hex
			var bytesPrefix []string
			for _, b := range d {
				bytesPrefix = append(bytesPrefix, fmt.Sprintf("%02X", b))
			}
			prefix := strings.Join(bytesPrefix, " ")

			fmt.Printf("
\n")
			fmt.Printf("    \n")
			fmt.Printf("      %s\n", AS.VA(insn.Address))
			fmt.Printf("    	\n")
			fmt.Printf("    \n")
			fmt.Printf("      %s\n", prefix)
			fmt.Printf("    	\n")
			fmt.Printf("    \n")
			fmt.Printf("      %s\n", insn.Mnemonic)
			fmt.Printf("    	\n")
			fmt.Printf("    \n")
			fmt.Printf("      %s\n", insn.OpStr)
			fmt.Printf("    	\n")
			fmt.Printf("
\n")
		}
		fmt.Printf("
\n")
		fmt.Printf(">];\n")

		nextBBs, e := bb.GetNextBasicBlocks()
		check(e)

		for _, nextBB := range nextBBs {
			exploreBBs(nextBB)
		}

		for _, nextBB := range nextBBs {
			fmt.Printf("bb_%s -> bb_%s;\n", bb.Start, nextBB.Start)
		}

		return nil
	}

	firstBB, e := f.GetFirstBasicBlock()
	check(e)

	exploreBBs(firstBB)
	defer fmt.Printf("}")

	runtime.UnlockOSThread()
	return nil
}

func main() {
	app := cli.NewApp()
	app.Version = "0.1"
	app.Name = "run_linear_disassembler"
	app.Usage = "Invoke linear disassembler."
	app.Flags = []cli.Flag{inputFlag, fvaFlag}
	app.Action = func(c *cli.Context) {
		if utils.CheckRequiredArgs(c, []cli.StringFlag{inputFlag, fvaFlag}) != nil {
			return
		}

		inputFile := c.String("input_file")
		if !utils.DoesPathExist(inputFile) {
			log.Printf("Error: file %s must exist", inputFile)
			return
		}

		fva, e := strconv.ParseUint(c.String("fva"), 0x10, 64)
		check(e)

		check(doit(inputFile, AS.VA(fva)))
	}
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package index

import (
	"fmt"
	ta "github.com/balzaczyy/golucene/core/analysis/tokenattributes"
	. "github.com/balzaczyy/golucene/core/index/model"
	"github.com/balzaczyy/golucene/core/util"
)

// index/InvertedDocConsumerPerField.java

// type InvertedDocConsumerPerField interface {
// 	// Called once per field, and is given all IndexableField
// 	// occurrences for this field in the document. Return true if you
// 	// wish to see inverted tokens for these fields:
// 	start([]IndexableField, int) (bool, error)
// 	// Called before a field instance is being processed
// 	startField(IndexableField)
// 	// Called once per inverted token
// 	add() error
// 	// Called once per field per document, after all IndexableFields
// 	// are inverted
// 	finish() error
// 	// Called on hitting an aborting error
// 	abort()
// }

const HASH_INIT_SIZE = 4

type TermsHashPerField interface {
	next() TermsHashPerField
	reset()
	addFrom(int) error
	add() error
	finish() error
	start(IndexableField, bool) bool
}

type TermsHashPerFieldSPI interface {
	// Called when a term is seen for the first time.
	newTerm(int) error
	// Called when postings array is initialized or resized.
	newPostingsArray()
	// Creates a new postings array of the specified size.
	createPostingsArray(int) *ParallelPostingsArray
}

type TermsHashPerFieldImpl struct {
	spi TermsHashPerFieldSPI

	termsHash TermsHash

	nextPerField TermsHashPerField
	docState     *docState
	fieldState   *FieldInvertState
	termAtt      ta.TermToBytesRefAttribute
	termBytesRef *util.BytesRef

	// Copied from our perThread
	intPool      *util.IntBlockPool
	bytePool     *util.ByteBlockPool
	termBytePool *util.ByteBlockPool

	streamCount   int
	numPostingInt int

	fieldInfo *FieldInfo

	bytesHash *util.BytesRefHash

	postingsArray *ParallelPostingsArray
	bytesUsed     util.Counter

	doNextCall bool

	intUptos     []int
	intUptoStart int
}

/*
streamCount: how many streams this field stores per term. E.g.
doc(+freq) is 1 stream, prox+offset is a second.

NOTE: due to Go's embedded inheritance, it has to be invoked after it
is initialized and embedded by child class.
*/
func (h *TermsHashPerFieldImpl) _constructor(spi TermsHashPerFieldSPI,
	streamCount int, fieldState *FieldInvertState,
	termsHash TermsHash, nextPerField TermsHashPerField,
	fieldInfo *FieldInfo) {

	termsHashImpl := termsHash.fields()

	h.spi = spi
	h.intPool = termsHashImpl.intPool
	h.bytePool = termsHashImpl.bytePool
	h.termBytePool = termsHashImpl.termBytePool
	h.docState = termsHashImpl.docState
	h.termsHash = termsHash
	h.bytesUsed = termsHashImpl.bytesUsed
	h.fieldState = fieldState
	h.streamCount = streamCount
	h.numPostingInt = 2 * streamCount
	h.fieldInfo = fieldInfo
	h.nextPerField = nextPerField
	byteStarts := newPostingsBytesStartArray(h, h.bytesUsed)
	h.bytesHash = util.NewBytesRefHash(termsHashImpl.termBytePool, HASH_INIT_SIZE, byteStarts)
}

func (h *TermsHashPerFieldImpl) next() TermsHashPerField {
	return h.nextPerField
}

func (h *TermsHashPerFieldImpl) reset() {
	h.bytesHash.Clear(false)
	if h.nextPerField != nil {
		h.nextPerField.reset()
	}
}

// func (h *TermsHashPerField) abort() {
// 	h.reset()
// 	if h.nextPerField != nil {
// 		h.nextPerField.abort()
// 	}
// }

func (h *TermsHashPerFieldImpl) initReader(reader *ByteSliceReader, termId, stream int) {
	assert(stream < h.streamCount)
	intStart := h.postingsArray.intStarts[termId]
	ints := h.intPool.Buffers[intStart>>util.INT_BLOCK_SHIFT]
	upto := intStart & util.INT_BLOCK_MASK
	reader.init(h.bytePool,
		h.postingsArray.byteStarts[termId]+stream*util.FIRST_LEVEL_SIZE,
		ints[upto+stream])
}

/* Collapse the hash table & sort in-place; also sets sortedTermIDs to the results */
func (h *TermsHashPerFieldImpl) sortPostings(termComp func(a, b []byte) bool) []int {
	return h.bytesHash.Sort(termComp)
}

// func (h *TermsHashPerField) startField(f IndexableField) {
// 	h.termAtt = h.fieldState.attributeSource.Get("TermToBytesRefAttribute").(ta.TermToBytesRefAttribute)
// 	h.termBytesRef = h.termAtt.BytesRef()
// 	assert(h.termBytesRef != nil)
// 	h.consumer.startField(f)
// 	if h.nextPerField != nil {
// 		h.nextPerField.startField(f)
// 	}
// }

// func (h *TermsHashPerField) start(fields []IndexableField, count int) (bool, error) {
// 	var err error
// 	h.doCall, err = h.consumer.start(fields, count)
// 	if err != nil {
// 		return false, err
// 	}
// 	h.bytesHash.Reinit()
// 	if h.nextPerField != nil {
// 		h.doNextCall, err = h.nextPerField.start(fields, count)
// 		if err != nil {
// 			return false, err
// 		}
// 	}
// 	return h.doCall || h.doNextCall, nil
// }

/*
Secondary entry point (for 2nd & subsequent TermsHash), because token
text has already be "interned" into textStart, so we hash by textStart
*/
func (h *TermsHashPerFieldImpl) addFrom(textStart int) error {
	panic("not implemented yet")
}

// Simpler version of Lucene's own method
func utf8ToString(iso8859_1_buf []byte) string {
	buf := make([]rune, len(iso8859_1_buf))
	for i, b := range iso8859_1_buf {
		buf[i] = rune(b)
	}
	return string(buf)
}

/*
Called once per inverted token. This is the primary entry point (for
first TermsHash); postings use this API.
*/
func (h *TermsHashPerFieldImpl) add() (err error) {
	h.termAtt.FillBytesRef()

	// We are first in the chain so we must "intern" the term text into
	// textStart address. Get the text & hash of this term.
	var termId int
	if termId, err = h.bytesHash.Add(h.termBytesRef.Value); err != nil {
		return
	}

	fmt.Printf("add term=%v doc=%v termId=%v\n",
		utf8ToString(h.termBytesRef.Value), h.docState.docID, termId)

	if termId >= 0 { // new posting
		h.bytesHash.ByteStart(termId)
		// init stream slices
		if h.numPostingInt+h.intPool.IntUpto > util.INT_BLOCK_SIZE {
			h.intPool.NextBuffer()
		}

		if util.BYTE_BLOCK_SIZE-h.bytePool.ByteUpto < h.numPostingInt*util.FIRST_LEVEL_SIZE {
			panic("not implemented yet")
		}

		h.intUptos = h.intPool.Buffer
		h.intUptoStart = h.intPool.IntUpto
		h.intPool.IntUpto += h.streamCount

		h.postingsArray.intStarts[termId] = h.intUptoStart + h.intPool.IntOffset

		for i := 0; i < h.streamCount; i++ {
			upto := h.bytePool.NewSlice(util.FIRST_LEVEL_SIZE)
			h.intUptos[h.intUptoStart+i] = upto + h.bytePool.ByteOffset
		}
		h.postingsArray.byteStarts[termId] = h.intUptos[h.intUptoStart]

		if err = h.spi.newTerm(termId); err != nil {
			return
		}
	} else {
		panic("not implemented yet")
	}

	if h.doNextCall {
		return h.nextPerField.addFrom(h.postingsArray.textStarts[termId])
	}
	return nil
}

func (h *TermsHashPerFieldImpl) writeByte(stream int, b byte) {
	upto := h.intUptos[h.intUptoStart+stream]
	bytes := h.bytePool.Buffers[upto>>util.BYTE_BLOCK_SHIFT]
	assert(bytes != nil)
	offset := upto & util.BYTE_BLOCK_MASK
	if bytes[offset] != 0 {
		// end of slice; allocate a new one
		panic("not implemented yet")
	}
	bytes[offset] = b
	h.intUptos[h.intUptoStart+stream]++
}

func (h *TermsHashPerFieldImpl) writeVInt(stream, i int) {
	assert(stream < h.streamCount)
	for (i & ^0x7F) != 0 {
		h.writeByte(stream, byte((i&0x7F)|0x80))
	}
	h.writeByte(stream, byte(i))
}

func (h *TermsHashPerFieldImpl) finish() error {
	if h.nextPerField != nil {
		return h.nextPerField.finish()
	}
	return nil
}

/*
Start adding a new field instance; first is true if this is the first
time this field name was seen in the document.
*/
func (h *TermsHashPerFieldImpl) start(field IndexableField, first bool) bool {
	if h.termAtt = h.fieldState.termAttribute; h.termAtt != nil {
		// EmptyTokenStream can have nil term att
		h.termBytesRef = h.termAtt.BytesRef()
	}
	if h.nextPerField != nil {
		h.doNextCall = h.nextPerField.start(field, first)
	}
	return true
}

type PostingsBytesStartArray struct {
	perField  *TermsHashPerFieldImpl
	bytesUsed util.Counter
}

func newPostingsBytesStartArray(perField *TermsHashPerFieldImpl,
	bytesUsed util.Counter) *PostingsBytesStartArray {
	return &PostingsBytesStartArray{perField, bytesUsed}
}

func (ss *PostingsBytesStartArray) Init() []int {
	if ss.perField.postingsArray == nil {
		arr := ss.perField.spi.createPostingsArray(2)
		ss.perField.postingsArray = arr
		ss.perField.spi.newPostingsArray()
		ss.bytesUsed.AddAndGet(int64(arr.size * arr.bytesPerPosting()))
	}
	return ss.perField.postingsArray.textStarts
}

func (ss *PostingsBytesStartArray) Grow() []int {
	panic("not implemented yet")
}

func (ss *PostingsBytesStartArray) Clear() []int {
	if arr := ss.perField.postingsArray; arr != nil {
		ss.bytesUsed.AddAndGet(-int64(arr.size * arr.bytesPerPosting()))
		ss.perField.postingsArray = nil
		ss.perField.spi.newPostingsArray()
	}
	return nil
}

func (ss *PostingsBytesStartArray) BytesUsed() util.Counter {
	return ss.bytesUsed
}

// index/ParallelPostingsArray.java

const BYTES_PER_POSTING = 3 * util.NUM_BYTES_INT

type PostingsArray interface {
	bytesPerPosting() int
	newInstance(size int) PostingsArray
	copyTo(toArray PostingsArray, numToCopy int)
}

type ParallelPostingsArray struct {
	PostingsArray
	size       int
	textStarts []int
	intStarts  []int
	byteStarts []int
}

func newParallelPostingsArray(spi PostingsArray, size int) *ParallelPostingsArray {
	return &ParallelPostingsArray{
		PostingsArray: spi,
		size:          size,
		textStarts:    make([]int, size),
		intStarts:     make([]int, size),
		byteStarts:    make([]int, size),
	}
}

func (arr *ParallelPostingsArray) grow() *ParallelPostingsArray {
	panic("not implemented yet")
}
<commit_msg>implement PostingsBytesStartArray.grow()<commit_after>package index

import (
	"fmt"
	ta "github.com/balzaczyy/golucene/core/analysis/tokenattributes"
	. "github.com/balzaczyy/golucene/core/index/model"
	"github.com/balzaczyy/golucene/core/util"
)

// index/InvertedDocConsumerPerField.java

// type InvertedDocConsumerPerField interface {
// 	// Called once per field, and is given all IndexableField
// 	// occurrences for this field in the document. Return true if you
// 	// wish to see inverted tokens for these fields:
// 	start([]IndexableField, int) (bool, error)
// 	// Called before a field instance is being processed
// 	startField(IndexableField)
// 	// Called once per inverted token
// 	add() error
// 	// Called once per field per document, after all IndexableFields
// 	// are inverted
// 	finish() error
// 	// Called on hitting an aborting error
// 	abort()
// }

const HASH_INIT_SIZE = 4

type TermsHashPerField interface {
	next() TermsHashPerField
	reset()
	addFrom(int) error
	add() error
	finish() error
	start(IndexableField, bool) bool
}

type TermsHashPerFieldSPI interface {
	// Called when a term is seen for the first time.
	newTerm(int) error
	// Called when postings array is initialized or resized.
	newPostingsArray()
	// Creates a new postings array of the specified size.
	createPostingsArray(int) *ParallelPostingsArray
}

type TermsHashPerFieldImpl struct {
	spi TermsHashPerFieldSPI

	termsHash TermsHash

	nextPerField TermsHashPerField
	docState     *docState
	fieldState   *FieldInvertState
	termAtt      ta.TermToBytesRefAttribute
	termBytesRef *util.BytesRef

	// Copied from our perThread
	intPool      *util.IntBlockPool
	bytePool     *util.ByteBlockPool
	termBytePool *util.ByteBlockPool

	streamCount   int
	numPostingInt int

	fieldInfo *FieldInfo

	bytesHash *util.BytesRefHash

	postingsArray *ParallelPostingsArray
	bytesUsed     util.Counter

	doNextCall bool

	intUptos     []int
	intUptoStart int
}

/*
streamCount: how many streams this field stores per term. E.g.
doc(+freq) is 1 stream, prox+offset is a second.

NOTE: due to Go's embedded inheritance, it has to be invoked after it
is initialized and embedded by child class.
*/
func (h *TermsHashPerFieldImpl) _constructor(spi TermsHashPerFieldSPI,
	streamCount int, fieldState *FieldInvertState,
	termsHash TermsHash, nextPerField TermsHashPerField,
	fieldInfo *FieldInfo) {

	termsHashImpl := termsHash.fields()

	h.spi = spi
	h.intPool = termsHashImpl.intPool
	h.bytePool = termsHashImpl.bytePool
	h.termBytePool = termsHashImpl.termBytePool
	h.docState = termsHashImpl.docState
	h.termsHash = termsHash
	h.bytesUsed = termsHashImpl.bytesUsed
	h.fieldState = fieldState
	h.streamCount = streamCount
	h.numPostingInt = 2 * streamCount
	h.fieldInfo = fieldInfo
	h.nextPerField = nextPerField
	byteStarts := newPostingsBytesStartArray(h, h.bytesUsed)
	h.bytesHash = util.NewBytesRefHash(termsHashImpl.termBytePool, HASH_INIT_SIZE, byteStarts)
}

func (h *TermsHashPerFieldImpl) next() TermsHashPerField {
	return h.nextPerField
}

func (h *TermsHashPerFieldImpl) reset() {
	h.bytesHash.Clear(false)
	if h.nextPerField != nil {
		h.nextPerField.reset()
	}
}

// func (h *TermsHashPerField) abort() {
// 	h.reset()
// 	if h.nextPerField != nil {
// 		h.nextPerField.abort()
// 	}
// }

func (h *TermsHashPerFieldImpl) initReader(reader *ByteSliceReader, termId, stream int) {
	assert(stream < h.streamCount)
	intStart := h.postingsArray.intStarts[termId]
	ints := h.intPool.Buffers[intStart>>util.INT_BLOCK_SHIFT]
	upto := intStart & util.INT_BLOCK_MASK
	reader.init(h.bytePool,
		h.postingsArray.byteStarts[termId]+stream*util.FIRST_LEVEL_SIZE,
		ints[upto+stream])
}

/* Collapse the hash table & sort in-place; also sets sortedTermIDs to the results */
func (h *TermsHashPerFieldImpl) sortPostings(termComp func(a, b []byte) bool) []int {
	return h.bytesHash.Sort(termComp)
}

// func (h *TermsHashPerField) startField(f IndexableField) {
// 	h.termAtt = h.fieldState.attributeSource.Get("TermToBytesRefAttribute").(ta.TermToBytesRefAttribute)
// 	h.termBytesRef = h.termAtt.BytesRef()
// 	assert(h.termBytesRef != nil)
// 	h.consumer.startField(f)
// 	if h.nextPerField != nil {
// 		h.nextPerField.startField(f)
// 	}
// }

// func (h *TermsHashPerField) start(fields []IndexableField, count int) (bool, error) {
// 	var err error
// 	h.doCall, err = h.consumer.start(fields, count)
// 	if err != nil {
// 		return false, err
// 	}
// 	h.bytesHash.Reinit()
// 	if h.nextPerField != nil {
// 		h.doNextCall, err = h.nextPerField.start(fields, count)
// 		if err != nil {
// 			return false, err
// 		}
// 	}
// 	return h.doCall || h.doNextCall, nil
// }

/*
Secondary entry point (for 2nd & subsequent TermsHash), because token
text has already be "interned" into textStart, so we hash by textStart
*/
func (h *TermsHashPerFieldImpl) addFrom(textStart int) error {
	panic("not implemented yet")
}

// Simpler version of Lucene's own method
func utf8ToString(iso8859_1_buf []byte) string {
	buf := make([]rune, len(iso8859_1_buf))
	for i, b := range iso8859_1_buf {
		buf[i] = rune(b)
	}
	return string(buf)
}

/*
Called once per inverted token. This is the primary entry point (for
first TermsHash); postings use this API.
*/
func (h *TermsHashPerFieldImpl) add() (err error) {
	h.termAtt.FillBytesRef()

	// We are first in the chain so we must "intern" the term text into
	// textStart address. Get the text & hash of this term.
	var termId int
	if termId, err = h.bytesHash.Add(h.termBytesRef.Value); err != nil {
		return
	}

	fmt.Printf("add term=%v doc=%v termId=%v\n",
		utf8ToString(h.termBytesRef.Value), h.docState.docID, termId)

	if termId >= 0 { // new posting
		h.bytesHash.ByteStart(termId)
		// init stream slices
		if h.numPostingInt+h.intPool.IntUpto > util.INT_BLOCK_SIZE {
			h.intPool.NextBuffer()
		}

		if util.BYTE_BLOCK_SIZE-h.bytePool.ByteUpto < h.numPostingInt*util.FIRST_LEVEL_SIZE {
			panic("not implemented yet")
		}

		h.intUptos = h.intPool.Buffer
		h.intUptoStart = h.intPool.IntUpto
		h.intPool.IntUpto += h.streamCount

		h.postingsArray.intStarts[termId] = h.intUptoStart + h.intPool.IntOffset

		for i := 0; i < h.streamCount; i++ {
			upto := h.bytePool.NewSlice(util.FIRST_LEVEL_SIZE)
			h.intUptos[h.intUptoStart+i] = upto + h.bytePool.ByteOffset
		}
		h.postingsArray.byteStarts[termId] = h.intUptos[h.intUptoStart]

		if err = h.spi.newTerm(termId); err != nil {
			return
		}
	} else {
		panic("not implemented yet")
	}

	if h.doNextCall {
		return h.nextPerField.addFrom(h.postingsArray.textStarts[termId])
	}
	return nil
}

func (h *TermsHashPerFieldImpl) writeByte(stream int, b byte) {
	upto := h.intUptos[h.intUptoStart+stream]
	bytes := h.bytePool.Buffers[upto>>util.BYTE_BLOCK_SHIFT]
	assert(bytes != nil)
	offset := upto & util.BYTE_BLOCK_MASK
	if bytes[offset] != 0 {
		// end of slice; allocate a new one
		panic("not implemented yet")
	}
	bytes[offset] = b
	h.intUptos[h.intUptoStart+stream]++
}

func (h *TermsHashPerFieldImpl) writeVInt(stream, i int) {
	assert(stream < h.streamCount)
	for (i & ^0x7F) != 0 {
		h.writeByte(stream, byte((i&0x7F)|0x80))
	}
	h.writeByte(stream, byte(i))
}

func (h *TermsHashPerFieldImpl) finish() error {
	if h.nextPerField != nil {
		return h.nextPerField.finish()
	}
	return nil
}

/*
Start adding a new field instance; first is true if this is the first
time this field name was seen in the document.
*/
func (h *TermsHashPerFieldImpl) start(field IndexableField, first bool) bool {
	if h.termAtt = h.fieldState.termAttribute; h.termAtt != nil {
		// EmptyTokenStream can have nil term att
		h.termBytesRef = h.termAtt.BytesRef()
	}
	if h.nextPerField != nil {
		h.doNextCall = h.nextPerField.start(field, first)
	}
	return true
}

type PostingsBytesStartArray struct {
	perField  *TermsHashPerFieldImpl
	bytesUsed util.Counter
}

func newPostingsBytesStartArray(perField *TermsHashPerFieldImpl,
	bytesUsed util.Counter) *PostingsBytesStartArray {
	return &PostingsBytesStartArray{perField, bytesUsed}
}

func (ss *PostingsBytesStartArray) Init() []int {
	if ss.perField.postingsArray == nil {
		arr := ss.perField.spi.createPostingsArray(2)
		ss.perField.postingsArray = arr
		ss.perField.spi.newPostingsArray()
		ss.bytesUsed.AddAndGet(int64(arr.size * arr.bytesPerPosting()))
	}
	return ss.perField.postingsArray.textStarts
}

func (ss *PostingsBytesStartArray) Grow() []int {
	postingsArray := ss.perField.postingsArray
	oldSize := postingsArray.size
	postingsArray = postingsArray.grow()
	ss.perField.postingsArray = postingsArray
	ss.perField.spi.newPostingsArray()
	ss.bytesUsed.AddAndGet(int64(postingsArray.bytesPerPosting() * (postingsArray.size - oldSize)))
	return postingsArray.textStarts
}

func (ss *PostingsBytesStartArray) Clear() []int {
	if arr := ss.perField.postingsArray; arr != nil {
		ss.bytesUsed.AddAndGet(-int64(arr.size * arr.bytesPerPosting()))
		ss.perField.postingsArray = nil
		ss.perField.spi.newPostingsArray()
	}
	return nil
}

func (ss *PostingsBytesStartArray) BytesUsed() util.Counter {
	return ss.bytesUsed
}

// index/ParallelPostingsArray.java

const BYTES_PER_POSTING = 3 * util.NUM_BYTES_INT

type PostingsArray interface {
	bytesPerPosting() int
	newInstance(size int) PostingsArray
	copyTo(toArray PostingsArray, numToCopy int)
}

type ParallelPostingsArray struct {
	PostingsArray
	size       int
	textStarts []int
	intStarts  []int
	byteStarts []int
}

func newParallelPostingsArray(spi PostingsArray, size int) *ParallelPostingsArray {
	return &ParallelPostingsArray{
		PostingsArray: spi,
		size:          size,
		textStarts:    make([]int, size),
		intStarts:     make([]int, size),
		byteStarts:    make([]int, size),
	}
}

func (arr *ParallelPostingsArray) grow() *ParallelPostingsArray {
	panic("not implemented yet")
}
<|endoftext|>


<commit_before>package state

import (
	"encoding/gob"
	"fmt"
	"log"
	"math"
	"math/rand"
	"os"
	"os/signal"
	"time"
)

func (g *Game) write(fn string) {
	g.Lock()
	defer g.Unlock()

	new := fn + ".new"
	old := fn + ".old"
	f, err := os.OpenFile(fn+".new", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		log.Fatal(err)
	}
	err = gob.NewEncoder(f).Encode(&g.g)
	if err != nil {
		log.Fatal(err)
	}
	f.Sync()
	f.Close()

	os.Rename(fn, old)
	err = os.Rename(new, fn)
	if err != nil {
		log.Fatal(err)
	}
	os.Remove(old)
}

func nextTurn() <-chan time.Time {
	now := time.Now().UTC()
	tomorrow := now.Add(time.Hour * 23)
	for tomorrow.Day() == now.Day() {
		tomorrow = tomorrow.Add(time.Hour)
	}
	next := time.Date(tomorrow.Year(), tomorrow.Month(), tomorrow.Day(), 0, 0, 0, 0, time.UTC)
	return time.After(next.Sub(now))
}

func (g *Game) newDay() {
	const rounds = 15
	const (
		up = iota
		down
		dividend
	)

	before := g.g.Stock
	var divpaid [stockTypes]uint64
	news := make([]string, 0, stockTypes)

	for i := 0; i < rounds; i++ {
		adjust := uint64(math.Pow(rand.Float64()*.8+1.2, 5.0))
		stock := rand.Intn(stockTypes)
		switch rand.Intn(3) {
		case up:
			g.g.Stock[stock].Value += adjust
			if g.g.Stock[stock].Value >= splitValue {
				news = append(news, g.g.Stock[stock].Name+" split 2 for 1")
				g.g.Stock[stock].Value = (g.g.Stock[stock].Value + 1) / 2
				before[stock].Value = (before[stock].Value + 1) / 2
				for _, p := range g.g.Player {
					p.Shares[stock] *= 2
				}
			}
		case down:
			if g.g.Stock[stock].Value <= adjust {
				news = append(news, g.g.Stock[stock].Name+" went bankrupt, and was removed from the market")
				for _, p := range g.g.Player {
					p.Shares[stock] = 0
				}
				g.g.Stock[stock].Value = startingValue
				before[stock].Value = startingValue
				newname := g.g.pickName()
				news = append(news, newname+" was added to the market")
				g.g.Stock[stock].Name = newname
			} else {
				g.g.Stock[stock].Value -= adjust
			}
		case dividend:
			if g.g.Stock[stock].Value >= startingValue {
				divpaid[stock] += adjust
				for _, p := range g.g.Player {
					p.Cash += adjust * p.Shares[stock]
				}
			}
		}
	}

	for k, v := range g.g.Stock {
		var item string
		switch {
		case v.Value == before[k].Value:
			item = v.Name + " did not change price"
		case v.Value < before[k].Value:
			item = fmt.Sprintf("%s fell %.1f%%", v.Name, float64(before[k].Value-v.Value)/float64(before[k].Value)*100)
		default: // case v.Value > before[k].Value:
			item = fmt.Sprintf("%s rose %.1f%%", v.Name, float64(v.Value-before[k].Value)/float64(before[k].Value)*100)
		}
		if divpaid[k] > 0 {
			item = fmt.Sprintf("%s, and paid $%d in dividends", item, divpaid[k])
		}
		news = append(news, item)
	}
	g.g.News = news
}

func watcher(g *Game, filename string, changed chan struct{}) {
	var tick <-chan time.Time
	tock := nextTurn()

	sigint := make(chan os.Signal, 1)
	signal.Notify(sigint, os.Interrupt, os.Kill)

	for {
		select {
		case <-changed:
			if tick == nil {
				tick = time.After(5 * time.Minute)
			}
		case <-tick:
			tick = nil
			g.write(filename)
		case <-tock:
			g.newDay()
			g.write(filename)
			tock = nextTurn()
		case <-sigint:
			if tick != nil {
				g.write(filename)
			}
			log.Println("Exiting")
			os.Exit(0)
		}
	}
}
<commit_msg>Take lock when updating stock values<commit_after>package state

import (
	"encoding/gob"
	"fmt"
	"log"
	"math"
	"math/rand"
	"os"
	"os/signal"
	"time"
)

func (g *Game) write(fn string) {
	g.Lock()
	defer g.Unlock()

	new := fn + ".new"
	old := fn + ".old"
	f, err := os.OpenFile(fn+".new", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		log.Fatal(err)
	}
	err = gob.NewEncoder(f).Encode(&g.g)
	if err != nil {
		log.Fatal(err)
	}
	f.Sync()
	f.Close()

	os.Rename(fn, old)
	err = os.Rename(new, fn)
	if err != nil {
		log.Fatal(err)
	}
	os.Remove(old)
}

func nextTurn() <-chan time.Time {
	now := time.Now().UTC()
	tomorrow := now.Add(time.Hour * 23)
	for tomorrow.Day() == now.Day() {
		tomorrow = tomorrow.Add(time.Hour)
	}
	next := time.Date(tomorrow.Year(), tomorrow.Month(), tomorrow.Day(), 0, 0, 0, 0, time.UTC)
	return time.After(next.Sub(now))
}

func (g *Game) newDay() {
	const rounds = 15
	const (
		up = iota
		down
		dividend
	)

	g.Lock()
	defer g.Unlock()

	before := g.g.Stock
	var divpaid [stockTypes]uint64
	news := make([]string, 0, stockTypes)

	for i := 0; i < rounds; i++ {
		adjust := uint64(math.Pow(rand.Float64()*.8+1.2, 5.0))
		stock := rand.Intn(stockTypes)
		switch rand.Intn(3) {
		case up:
			g.g.Stock[stock].Value += adjust
			if g.g.Stock[stock].Value >= splitValue {
				news = append(news, g.g.Stock[stock].Name+" split 2 for 1")
				g.g.Stock[stock].Value = (g.g.Stock[stock].Value + 1) / 2
				before[stock].Value = (before[stock].Value + 1) / 2
				for _, p := range g.g.Player {
					p.Shares[stock] *= 2
				}
			}
		case down:
			if g.g.Stock[stock].Value <= adjust {
				news = append(news, g.g.Stock[stock].Name+" went bankrupt, and was removed from the market")
				for _, p := range g.g.Player {
					p.Shares[stock] = 0
				}
				g.g.Stock[stock].Value = startingValue
				before[stock].Value = startingValue
				newname := g.g.pickName()
				news = append(news, newname+" was added to the market")
				g.g.Stock[stock].Name = newname
			} else {
				g.g.Stock[stock].Value -= adjust
			}
		case dividend:
			if g.g.Stock[stock].Value >= startingValue {
				divpaid[stock] += adjust
				for _, p := range g.g.Player {
					p.Cash += adjust * p.Shares[stock]
				}
			}
		}
	}

	for k, v := range g.g.Stock {
		var item string
		switch {
		case v.Value == before[k].Value:
			item = v.Name + " did not change price"
		case v.Value < before[k].Value:
			item = fmt.Sprintf("%s fell %.1f%%", v.Name, float64(before[k].Value-v.Value)/float64(before[k].Value)*100)
		default: // case v.Value > before[k].Value:
			item = fmt.Sprintf("%s rose %.1f%%", v.Name, float64(v.Value-before[k].Value)/float64(before[k].Value)*100)
		}
		if divpaid[k] > 0 {
			item = fmt.Sprintf("%s, and paid $%d in dividends", item, divpaid[k])
		}
		news = append(news, item)
	}
	g.g.News = news
}

func watcher(g *Game, filename string, changed chan struct{}) {
	var tick <-chan time.Time
	tock := nextTurn()

	sigint := make(chan os.Signal, 1)
	signal.Notify(sigint, os.Interrupt, os.Kill)

	for {
		select {
		case <-changed:
			if tick == nil {
				tick = time.After(5 * time.Minute)
			}
		case <-tick:
			tick = nil
			g.write(filename)
		case <-tock:
			g.newDay()
			g.write(filename)
			tock = nextTurn()
		case <-sigint:
			if tick != nil {
				g.write(filename)
			}
			log.Println("Exiting")
			os.Exit(0)
		}
	}
}
<|endoftext|>


<commit_before>package rizo

import (
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/http/httptest"
	"strconv"
	"sync"
	"time"
)

func check(err error) {
	if err != nil {
		panic(err)
	}
}

//RecordedRequest ...
type RecordedRequest struct {
	Request *http.Request
	body    string
}

//HTTPRequestPredicate ...
type HTTPRequestPredicate func(request RecordedRequest) bool

//HTTPResponseFactory ...
type HTTPResponseFactory func(writer http.ResponseWriter)

//UseWithPredicates ...
type UseWithPredicates struct {
	ResponseFactory   HTTPResponseFactory
	RequestPredicates []HTTPRequestPredicate
}

//RequestRecordingServer ...
type RequestRecordingServer struct {
	Requests []RecordedRequest
	port     int
	server   *httptest.Server
	use      []UseWithPredicates
	lock     *sync.Mutex
}

//CreateRequestRecordingServer ...
func CreateRequestRecordingServer(port int) *RequestRecordingServer {
	return &RequestRecordingServer{
		Requests: []RecordedRequest{},
		port:     port,
		use:      []UseWithPredicates{},
		lock:     &sync.Mutex{},
	}
}

//CreateURL ...
func (instance *RequestRecordingServer) CreateURL(path string) string {
	return fmt.Sprintf("http://localhost:%d%s", instance.port, path)
}

func (instance *RequestRecordingServer) evaluatePredicates(recordedRequest RecordedRequest, w http.ResponseWriter) {
	for _, item := range instance.use {
		if item.RequestPredicates != nil {
			result := instance.Evaluate(recordedRequest, item.RequestPredicates...)
			if result {
				item.ResponseFactory(w)
				return
			}
		} else {
			item.ResponseFactory(w)
			return
		}
	}
	w.WriteHeader(http.StatusOK)
}

//Start ...
func (instance *RequestRecordingServer) Start() {
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		body, err := ioutil.ReadAll(r.Body)
		check(err)
		recordedRequest := RecordedRequest{
			Request: r,
			body:    string(body),
		}
		instance.lock.Lock()
		instance.Requests = append(instance.Requests, recordedRequest)
		instance.lock.Unlock()
		if instance.use != nil {
			instance.evaluatePredicates(recordedRequest, w)
		} else {
			w.WriteHeader(http.StatusOK)
		}
	})
	instance.server = httptest.NewUnstartedServer(handler)
	listener, err := net.Listen("tcp", ":"+strconv.Itoa(instance.port))
	if err != nil {
		panic(err)
	}
	instance.server.Listener = listener
	instance.server.Start()
}

//Stop ...
func (instance *RequestRecordingServer) Stop() {
	if instance.server != nil {
		instance.server.Close()
		time.Sleep(1 * time.Millisecond)
	}
}

//Clear ...
func (instance *RequestRecordingServer) Clear() {
	instance.Requests = []RecordedRequest{}
	instance.use = []UseWithPredicates{}
}

//Evaluate ...
func (instance *RequestRecordingServer) Evaluate(request RecordedRequest, predicates ...HTTPRequestPredicate) bool {
	results := make([]bool, len(predicates))
	for index, predicate := range predicates {
		results[index] = predicate(request)
	}
	thing := true
	for _, result := range results {
		if !result {
			thing = false
			break
		}
	}
	return thing
}

//Find ...
func (instance *RequestRecordingServer) Find(predicates ...HTTPRequestPredicate) bool {
	for _, request := range instance.Requests {
		if instance.Evaluate(request) {
			return true
		}
	}
	return false
}

//Use ...
func (instance *RequestRecordingServer) Use(factory HTTPResponseFactory) *RequestRecordingServer {
	instance.use = append(instance.use, UseWithPredicates{
		ResponseFactory:   factory,
		RequestPredicates: []HTTPRequestPredicate{},
	})
	return instance
}

//For ...
func (instance *RequestRecordingServer) For(predicates ...HTTPRequestPredicate) {
	index := len(instance.use) - 1
	for _, item := range predicates {
		instance.use[index].RequestPredicates = append(instance.use[index].RequestPredicates, item)
	}
}

//RequestWithPath ...
func RequestWithPath(path string) HTTPRequestPredicate {
	return HTTPRequestPredicate(func(r RecordedRequest) bool {
		result := r.Request.URL.Path == path
		if !result {
			log.Println(fmt.Sprintf("path does not equal %s it equals %s", path, r.Request.URL.Path))
		}
		return result
	})
}

//RequestWithMethod ...
func RequestWithMethod(method string) HTTPRequestPredicate {
	return HTTPRequestPredicate(func(r RecordedRequest) bool {
		result := r.Request.Method == method
		if !result {
			log.Println("request method does not equal " + method)
		}
		return result
	})
}

//RequestWithHeader ...
func RequestWithHeader(key string, value string) HTTPRequestPredicate {
	return HTTPRequestPredicate(func(r RecordedRequest) bool {
		result := r.Request.Header.Get(key) == value
		if !result {
			log.Println(fmt.Sprintf("request method does not contain header with key %s and value %s actual %s", key, value, r.Request.Header.Get(key)))
		}
		return result
	})
}

//RequestWithBody ...
func RequestWithBody(value string) HTTPRequestPredicate {
	return HTTPRequestPredicate(func(r RecordedRequest) bool {
		result := string(r.body) == value
		if !result {
			log.Println(fmt.Sprintf("request body does not equal %s it equals %s", value, r.body))
		}
		return result
	})
}

//RequestWithQuerystring ...
func RequestWithQuerystring(value string) HTTPRequestPredicate {
	return HTTPRequestPredicate(func(r RecordedRequest) bool {
		result := r.Request.URL.RawQuery == value
		if !result {
			log.Println("request query does not equal " + value + " | it equals " + r.Request.URL.RawQuery)
		}
		return result
	})
}
<commit_msg>Removed logging<commit_after>package rizo

import (
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httptest"
	"strconv"
	"sync"
	"time"
)

func check(err error) {
	if err != nil {
		panic(err)
	}
}

//RecordedRequest ...
type RecordedRequest struct {
	Request *http.Request
	body    string
}

//HTTPRequestPredicate ...
type HTTPRequestPredicate func(request RecordedRequest) bool

//HTTPResponseFactory ...
type HTTPResponseFactory func(writer http.ResponseWriter)

//UseWithPredicates ...
type UseWithPredicates struct {
	ResponseFactory   HTTPResponseFactory
	RequestPredicates []HTTPRequestPredicate
}

//RequestRecordingServer ...
type RequestRecordingServer struct {
	Requests []RecordedRequest
	port     int
	server   *httptest.Server
	use      []UseWithPredicates
	lock     *sync.Mutex
}

//CreateRequestRecordingServer ...
func CreateRequestRecordingServer(port int) *RequestRecordingServer {
	return &RequestRecordingServer{
		Requests: []RecordedRequest{},
		port:     port,
		use:      []UseWithPredicates{},
		lock:     &sync.Mutex{},
	}
}

//CreateURL ...
func (instance *RequestRecordingServer) CreateURL(path string) string {
	return fmt.Sprintf("http://localhost:%d%s", instance.port, path)
}

func (instance *RequestRecordingServer) evaluatePredicates(recordedRequest RecordedRequest, w http.ResponseWriter) {
	for _, item := range instance.use {
		if item.RequestPredicates != nil {
			result := instance.Evaluate(recordedRequest, item.RequestPredicates...)
			if result {
				item.ResponseFactory(w)
				return
			}
		} else {
			item.ResponseFactory(w)
			return
		}
	}
	w.WriteHeader(http.StatusOK)
}

//Start ...
func (instance *RequestRecordingServer) Start() {
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		body, err := ioutil.ReadAll(r.Body)
		check(err)
		recordedRequest := RecordedRequest{
			Request: r,
			body:    string(body),
		}
		instance.lock.Lock()
		instance.Requests = append(instance.Requests, recordedRequest)
		instance.lock.Unlock()
		if instance.use != nil {
			instance.evaluatePredicates(recordedRequest, w)
		} else {
			w.WriteHeader(http.StatusOK)
		}
	})
	instance.server = httptest.NewUnstartedServer(handler)
	listener, err := net.Listen("tcp", ":"+strconv.Itoa(instance.port))
	if err != nil {
		panic(err)
	}
	instance.server.Listener = listener
	instance.server.Start()
}

//Stop ...
func (instance *RequestRecordingServer) Stop() {
	if instance.server != nil {
		instance.server.Close()
		time.Sleep(1 * time.Millisecond)
	}
}

//Clear ...
func (instance *RequestRecordingServer) Clear() {
	instance.Requests = []RecordedRequest{}
	instance.use = []UseWithPredicates{}
}

//Evaluate ...
func (instance *RequestRecordingServer) Evaluate(request RecordedRequest, predicates ...HTTPRequestPredicate) bool {
	results := make([]bool, len(predicates))
	for index, predicate := range predicates {
		results[index] = predicate(request)
	}
	thing := true
	for _, result := range results {
		if !result {
			thing = false
			break
		}
	}
	return thing
}

//Find ...
func (instance *RequestRecordingServer) Find(predicates ...HTTPRequestPredicate) bool {
	for _, request := range instance.Requests {
		if instance.Evaluate(request) {
			return true
		}
	}
	return false
}

//Use ...
func (instance *RequestRecordingServer) Use(factory HTTPResponseFactory) *RequestRecordingServer {
	instance.use = append(instance.use, UseWithPredicates{
		ResponseFactory:   factory,
		RequestPredicates: []HTTPRequestPredicate{},
	})
	return instance
}

//For ...
func (instance *RequestRecordingServer) For(predicates ...HTTPRequestPredicate) {
	index := len(instance.use) - 1
	for _, item := range predicates {
		instance.use[index].RequestPredicates = append(instance.use[index].RequestPredicates, item)
	}
}

//RequestWithPath ...
func RequestWithPath(path string) HTTPRequestPredicate {
	return HTTPRequestPredicate(func(r RecordedRequest) bool {
		result := r.Request.URL.Path == path
		return result
	})
}

//RequestWithMethod ...
func RequestWithMethod(method string) HTTPRequestPredicate {
	return HTTPRequestPredicate(func(r RecordedRequest) bool {
		result := r.Request.Method == method
		return result
	})
}

//RequestWithHeader ...
func RequestWithHeader(key string, value string) HTTPRequestPredicate {
	return HTTPRequestPredicate(func(r RecordedRequest) bool {
		result := r.Request.Header.Get(key) == value
		return result
	})
}

//RequestWithBody ...
func RequestWithBody(value string) HTTPRequestPredicate {
	return HTTPRequestPredicate(func(r RecordedRequest) bool {
		result := string(r.body) == value
		return result
	})
}

//RequestWithQuerystring ...
func RequestWithQuerystring(value string) HTTPRequestPredicate {
	return HTTPRequestPredicate(func(r RecordedRequest) bool {
		result := r.Request.URL.RawQuery == value
		return result
	})
}
<|endoftext|>


<commit_before>package flow

// Message represents a single FBP protocol message
type Message struct {
	// Protocol is NoFlo protocol identifier:
	// "runtime", "component", "graph" or "network"
	Protocol string `json:"protocol"`
	// Command is a command to be executed within the protocol
	Command string `json:"command"`
	// Payload is JSON-encoded body of the message
	Payload interface{} `json:"payload"`
}

// runtimeInfo message contains response to runtime.getruntime request
type runtimeInfo struct {
	Type         string   `json:"type"`
	Version      string   `json:"version"`
	Capabilities []string `json:"capabilities"`
	Id           string   `json:"id"`
}

type runtimeMessage struct {
	Protocol string      `json:"protocol"`
	Command  string      `json:"command"`
	Payload  runtimeInfo `json:"payload"`
}

// clearGraph message is sent by client to create a new empty graph
type clearGraph struct {
	Id          string
	Name        string `json:",omitempty"` // ignored
	Library     string `json:",omitempty"` // ignored
	Main        bool   `json:",omitempty"`
	Icon        string `json:",omitempty"`
	Description string `json:",omitempty"`
}

// addNode message is sent by client to add a node to a graph
type addNode struct {
	Id        string
	Component string
	Graph     string
	Metadata  map[string]interface{} `json:",omitempty"` // ignored
}

// removeNode is a client message to remove a node from a graph
type removeNode struct {
	Id    string
	Graph string
}

// renameNode is a client message to rename a node in a graph
type renameNode struct {
	From  string
	To    string
	Graph string
}

// changeNode is a client message to change the metadata
// associated to a node in the graph
type changeNode struct { // ignored
	Id       string
	Graph    string
	Metadata map[string]interface{}
}

// addEdge is a client message to create a connection in a graph
type addEdge struct {
	Src struct {
		Node  string
		Port  string
		Index int `json:",omitempty"` // ignored
	}
	Tgt struct {
		Node  string
		Port  string
		Index int `json:",omitempty"` // ignored
	}
	Graph    string
	Metadata map[string]interface{} `json:",omitempty"` // ignored
}

// removeEdge is a client message to delete a connection from a graph
type removeEdge struct {
	Src struct {
		Node string
		Port string
	}
	Tgt struct {
		Node string
		Port string
	}
	Graph string
}

// changeEdge is a client message to change connection metadata
type changeEdge struct { // ignored
	Src struct {
		Node  string
		Port  string
		Index int `json:",omitempty"`
	}
	Tgt struct {
		Node  string
		Port  string
		Index int `json:",omitempty"`
	}
	Graph    string
	Metadata map[string]interface{}
}

// addInitial is a client message to add an IIP to a graph
type addInitial struct {
	Src struct {
		Data interface{}
	}
	Tgt struct {
		Node  string
		Port  string
		Index int `json:",omitempty"` // ignored
	}
	Graph    string
	Metadata map[string]interface{} `json:",omitempty"` // ignored
}

// removeInitial is a client message to remove an IIP from a graph
type removeInitial struct {
	Tgt struct {
		Node  string
		Port  string
		Index int `json:",omitempty"` // ignored
	}
	Graph string
}

// addPort is a client message to add an exported inport/outport to the graph
type addPort struct {
	Public   string
	Node     string
	Port     string
	Graph    string
	Metadata map[string]interface{} `json:",omitempty"` // ignored
}

// removePort is a client message to remove an exported inport/outport from the graph
type removePort struct {
	Public string
	Graph  string
}

// renamePort is a client message to rename a port of a graph
type renamePort struct {
	From  string
	To    string
	Graph string
}

// PortInfo represents a port to a runtime client
type PortInfo struct {
	Id          string        `json:"id"`
	Type        string        `json:"type"`
	Description string        `json:"description"`
	Addressable bool          `json:"addressable"` // ignored
	Required    bool          `json:"required"`
	Values      []interface{} `json:"values"`  // ignored
	Default     interface{}   `json:"default"` // ignored
}

// ComponentInfo represents a component to a protocol client
type ComponentInfo struct {
	Name        string     `json:"name"`
	Description string     `json:"description"`
	Icon        string     `json:"icon"`
	Subgraph    bool       `json:"subgraph"`
	InPorts     []PortInfo `json:"inPorts"`
	OutPorts    []PortInfo `json:"outPorts"`
}

type componentMessage struct {
	Protocol string        `json:"protocol"`
	Command  string        `json:"command"`
	Payload  ComponentInfo `json:"payload"`
}
<commit_msg>Fix linter errors in protocol.go<commit_after>package flow

// Message represents a single FBP protocol message
type Message struct {
	// Protocol is NoFlo protocol identifier:
	// "runtime", "component", "graph" or "network"
	Protocol string `json:"protocol"`
	// Command is a command to be executed within the protocol
	Command string `json:"command"`
	// Payload is JSON-encoded body of the message
	Payload interface{} `json:"payload"`
}

// runtimeInfo message contains response to runtime.getruntime request
type runtimeInfo struct {
	Type         string   `json:"type"`
	Version      string   `json:"version"`
	Capabilities []string `json:"capabilities"`
	ID           string   `json:"id"`
}

type runtimeMessage struct {
	Protocol string      `json:"protocol"`
	Command  string      `json:"command"`
	Payload  runtimeInfo `json:"payload"`
}

// clearGraph message is sent by client to create a new empty graph
type clearGraph struct {
	ID          string
	Name        string `json:",omitempty"` // ignored
	Library     string `json:",omitempty"` // ignored
	Main        bool   `json:",omitempty"`
	Icon        string `json:",omitempty"`
	Description string `json:",omitempty"`
}

// addNode message is sent by client to add a node to a graph
type addNode struct {
	ID        string
	Component string
	Graph     string
	Metadata  map[string]interface{} `json:",omitempty"` // ignored
}

// removeNode is a client message to remove a node from a graph
type removeNode struct {
	ID    string
	Graph string
}

// renameNode is a client message to rename a node in a graph
type renameNode struct {
	From  string
	To    string
	Graph string
}

// changeNode is a client message to change the metadata
// associated to a node in the graph
type changeNode struct { // ignored
	ID       string
	Graph    string
	Metadata map[string]interface{}
}

// addEdge is a client message to create a connection in a graph
type addEdge struct {
	Src struct {
		Node  string
		Port  string
		Index int `json:",omitempty"` // ignored
	}
	Tgt struct {
		Node  string
		Port  string
		Index int `json:",omitempty"` // ignored
	}
	Graph    string
	Metadata map[string]interface{} `json:",omitempty"` // ignored
}

// removeEdge is a client message to delete a connection from a graph
type removeEdge struct {
	Src struct {
		Node string
		Port string
	}
	Tgt struct {
		Node string
		Port string
	}
	Graph string
}

// changeEdge is a client message to change connection metadata
type changeEdge struct { // ignored
	Src struct {
		Node  string
		Port  string
		Index int `json:",omitempty"`
	}
	Tgt struct {
		Node  string
		Port  string
		Index int `json:",omitempty"`
	}
	Graph    string
	Metadata map[string]interface{}
}

// addInitial is a client message to add an IIP to a graph
type addInitial struct {
	Src struct {
		Data interface{}
	}
	Tgt struct {
		Node  string
		Port  string
		Index int `json:",omitempty"` // ignored
	}
	Graph    string
	Metadata map[string]interface{} `json:",omitempty"` // ignored
}

// removeInitial is a client message to remove an IIP from a graph
type removeInitial struct {
	Tgt struct {
		Node  string
		Port  string
		Index int `json:",omitempty"` // ignored
	}
	Graph string
}

// addPort is a client message to add an exported inport/outport to the graph
type addPort struct {
	Public   string
	Node     string
	Port     string
	Graph    string
	Metadata map[string]interface{} `json:",omitempty"` // ignored
}

// removePort is a client message to remove an exported inport/outport from the graph
type removePort struct {
	Public string
	Graph  string
}

// renamePort is a client message to rename a port of a graph
type renamePort struct {
	From  string
	To    string
	Graph string
}

// PortInfo represents a port to a runtime client
type PortInfo struct {
	ID          string        `json:"id"`
	Type        string        `json:"type"`
	Description string        `json:"description"`
	Addressable bool          `json:"addressable"` // ignored
	Required    bool          `json:"required"`
	Values      []interface{} `json:"values"`  // ignored
	Default     interface{}   `json:"default"` // ignored
}

// ComponentInfo represents a component to a protocol client
type ComponentInfo struct {
	Name        string     `json:"name"`
	Description string     `json:"description"`
	Icon        string     `json:"icon"`
	Subgraph    bool       `json:"subgraph"`
	InPorts     []PortInfo `json:"inPorts"`
	OutPorts    []PortInfo `json:"outPorts"`
}

type componentMessage struct {
	Protocol string        `json:"protocol"`
	Command  string        `json:"command"`
	Payload  ComponentInfo `json:"payload"`
}
<|endoftext|>


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

package utl

import "github.com/cpmech/gosl/io"

// MatToArray converts a matrix into a column-major array
func MatToArray(a [][]float64) (v []float64) {
	m, n, k := len(a), len(a[0]), 0
	v = make([]float64, m*n)
	for j := 0; j < n; j++ {
		for i := 0; i < m; i++ {
			v[k] = a[i][j]
			k += 1
		}
	}
	return
}

// ArrayToMat converts a column-major array to a matrix
func ArrayToMat(v []float64, m, n int) (a [][]float64) {
	a = make([][]float64, m)
	for i := 0; i < m; i++ {
		a[i] = make([]float64, n)
	}
	for k := 0; k < m*n; k++ {
		i, j := k%m, k/m
		a[i][j] = v[k]
	}
	return
}

// Deep3Serialize serializes an array of array of array in column-compressed format
//  Example:
//
func Deep3Serialize(A [][][]float64) (I, P []int, S []float64) {
	i, p := 0, 0
	for _, a := range A {
		for _, b := range a {
			i += 1
			p += len(b)
		}
	}
	I = make([]int, i)
	P = make([]int, i+1)
	S = make([]float64, p)
	i, p, k := 0, 0, 0
	for j, a := range A {
		for _, b := range a {
			I[i] = j
			i += 1
			p += len(b)
			P[i] = p
			for _, v := range b {
				S[k] = v
				k += 1
			}
		}
	}
	return
}

// Deep3GetInfo returns information of serialized array of array of array
//  Example:
func Deep3GetInfo(I, P []int, S []float64, verbose bool) (nitems, nrows, ncols_tot int, ncols []int) {
	if verbose {
		io.Pf("I = %v\n", I)
		io.Pf("P = %v\n", P)
		io.Pf("S = %v\n", S)
	}
	nitems = P[len(P)-1]
	nrows = I[len(I)-1] + 1
	ncols = make([]int, nrows)
	for _, j := range I {
		ncols_tot += 1
		ncols[j] += 1
	}
	if verbose {
		io.Pf("nitems    = %v\n", nitems)
		io.Pf("nrows     = %v\n", nrows)
		io.Pf("ncols_tot = %v\n", ncols_tot)
		io.Pf("ncols     = %v\n", ncols)
	}
	return
}

// Deep3Deserialize deserializes an array of array of array in column-compressed format
//  Example:
func Deep3Deserialize(I, P []int, S []float64, debug bool) (A [][][]float64) {
	_, nrows, _, ncols := Deep3GetInfo(I, P, S, false)
	A = make([][][]float64, nrows)
	for i := 0; i < nrows; i++ {
		A[i] = make([][]float64, ncols[i])
	}
	iprev := 0 // previous i
	j := 0     // column index
	for l, i := range I {
		nitems := P[l+1] - P[l]
		if i != iprev { // jumped to new column
			j = 0
		}
		if debug {
			io.Pf("l=%v  i=%v  nitems=%v  j=%v\n", l, i, nitems, j)
		}
		for k, p := 0, P[l]; p < P[l+1]; k, p = k+1, p+1 {
			if debug {
				io.Pf("  k=%v  p=%v  s=%v\n", k, p, S[p])
			}
			if k == 0 {
				A[i][j] = make([]float64, nitems)
			}
			A[i][j][k] = S[p]
		}
		iprev = i
		j += 1
	}
	return
}
<commit_msg>Replace increment method<commit_after>// Copyright 2016 The Gosl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package utl

import "github.com/cpmech/gosl/io"

// MatToArray converts a matrix into a column-major array
func MatToArray(a [][]float64) (v []float64) {
	m, n, k := len(a), len(a[0]), 0
	v = make([]float64, m*n)
	for j := 0; j < n; j++ {
		for i := 0; i < m; i++ {
			v[k] = a[i][j]
			k++
		}
	}
	return
}

// ArrayToMat converts a column-major array to a matrix
func ArrayToMat(v []float64, m, n int) (a [][]float64) {
	a = make([][]float64, m)
	for i := 0; i < m; i++ {
		a[i] = make([]float64, n)
	}
	for k := 0; k < m*n; k++ {
		i, j := k%m, k/m
		a[i][j] = v[k]
	}
	return
}

// Deep3Serialize serializes an array of array of array in column-compressed format
//  Example:
//
func Deep3Serialize(A [][][]float64) (I, P []int, S []float64) {
	i, p := 0, 0
	for _, a := range A {
		for _, b := range a {
			i++
			p += len(b)
		}
	}
	I = make([]int, i)
	P = make([]int, i+1)
	S = make([]float64, p)
	i, p, k := 0, 0, 0
	for j, a := range A {
		for _, b := range a {
			I[i] = j
			i++
			p += len(b)
			P[i] = p
			for _, v := range b {
				S[k] = v
				k++
			}
		}
	}
	return
}

// Deep3GetInfo returns information of serialized array of array of array
//  Example:
func Deep3GetInfo(I, P []int, S []float64, verbose bool) (nitems, nrows, ncols_tot int, ncols []int) {
	if verbose {
		io.Pf("I = %v\n", I)
		io.Pf("P = %v\n", P)
		io.Pf("S = %v\n", S)
	}
	nitems = P[len(P)-1]
	nrows = I[len(I)-1] + 1
	ncols = make([]int, nrows)
	for _, j := range I {
		ncols_tot++
		ncols[j]++
	}
	if verbose {
		io.Pf("nitems    = %v\n", nitems)
		io.Pf("nrows     = %v\n", nrows)
		io.Pf("ncols_tot = %v\n", ncols_tot)
		io.Pf("ncols     = %v\n", ncols)
	}
	return
}

// Deep3Deserialize deserializes an array of array of array in column-compressed format
//  Example:
func Deep3Deserialize(I, P []int, S []float64, debug bool) (A [][][]float64) {
	_, nrows, _, ncols := Deep3GetInfo(I, P, S, false)
	A = make([][][]float64, nrows)
	for i := 0; i < nrows; i++ {
		A[i] = make([][]float64, ncols[i])
	}
	iprev := 0 // previous i
	j := 0     // column index
	for l, i := range I {
		nitems := P[l+1] - P[l]
		if i != iprev { // jumped to new column
			j = 0
		}
		if debug {
			io.Pf("l=%v  i=%v  nitems=%v  j=%v\n", l, i, nitems, j)
		}
		for k, p := 0, P[l]; p < P[l+1]; k, p = k+1, p+1 {
			if debug {
				io.Pf("  k=%v  p=%v  s=%v\n", k, p, S[p])
			}
			if k == 0 {
				A[i][j] = make([]float64, nitems)
			}
			A[i][j][k] = S[p]
		}
		iprev = i
		j++
	}
	return
}
<|endoftext|>