<commit_before>package clw11

/*
#define CL_USE_DEPRECATED_OPENCL_1_1_APIS
#ifdef __APPLE__
#include "OpenCL/opencl.h"
#else
#include "CL/opencl.h"
#endif
*/
import "C"
import "unsafe"

type (
	MemObjectType C.cl_mem_object_type
	ImageFormat   C.cl_image_format
	ImageInfo     C.cl_image_info
	ChannelOrder  C.cl_channel_order
	ChannelType   C.cl_channel_type
)

const (
	MemObjectBuffer  MemObjectType = C.CL_MEM_OBJECT_BUFFER
	MemObjectImage2D MemObjectType = C.CL_MEM_OBJECT_IMAGE2D
	MemObjectImage3D MemObjectType = C.CL_MEM_OBJECT_IMAGE3D
)

const (
	R         ChannelOrder = C.CL_R
	A         ChannelOrder = C.CL_A
	RG        ChannelOrder = C.CL_RG
	RA        ChannelOrder = C.CL_RA
	RGB       ChannelOrder = C.CL_RGB
	RGBA      ChannelOrder = C.CL_RGBA
	BGRA      ChannelOrder = C.CL_BGRA
	ARGB      ChannelOrder = C.CL_ARGB
	Intensity ChannelOrder = C.CL_INTENSITY
	Luminance ChannelOrder = C.CL_LUMINANCE
	Rx        ChannelOrder = C.CL_Rx
	RGx       ChannelOrder = C.CL_RGx
	RGBx      ChannelOrder = C.CL_RGBx
)

const (
	SnormInt8      ChannelType = C.CL_SNORM_INT8
	SnormInt16     ChannelType = C.CL_SNORM_INT16
	UnormInt8      ChannelType = C.CL_UNORM_INT8
	UnormInt16     ChannelType = C.CL_UNORM_INT16
	UnormShort565  ChannelType = C.CL_UNORM_SHORT_565
	UnormShort555  ChannelType = C.CL_UNORM_SHORT_555
	UnormInt101010 ChannelType = C.CL_UNORM_INT_101010
	SignedInt8     ChannelType = C.CL_SIGNED_INT8
	SignedInt16    ChannelType = C.CL_SIGNED_INT16
	SignedInt32    ChannelType = C.CL_SIGNED_INT32
	UnsignedInt8   ChannelType = C.CL_UNSIGNED_INT8
	UnsignedInt16  ChannelType = C.CL_UNSIGNED_INT16
	UnsignedInt32  ChannelType = C.CL_UNSIGNED_INT32
	HalfFloat      ChannelType = C.CL_HALF_FLOAT
	Float          ChannelType = C.CL_FLOAT
)

const (
	ImageFormatInfo  ImageInfo = C.CL_IMAGE_FORMAT // Appended "Info" due to conflict with type.
	ImageElementSize ImageInfo = C.CL_IMAGE_ELEMENT_SIZE
	ImageRowPitch    ImageInfo = C.CL_IMAGE_ROW_PITCH
	ImageSlicePitch  ImageInfo = C.CL_IMAGE_SLICE_PITCH
	ImageWidth       ImageInfo = C.CL_IMAGE_WIDTH
	ImageHeight      ImageInfo = C.CL_IMAGE_HEIGHT
	ImageDepth       ImageInfo = C.CL_IMAGE_DEPTH
)

func CreateImageFormat(co ChannelOrder, ct ChannelType) ImageFormat {
	return ImageFormat{C.cl_channel_order(co), C.cl_channel_type(ct)}
}

func (f *ImageFormat) ChannelOrder() ChannelOrder {
	return ChannelOrder(f.image_channel_order)
}

func (f *ImageFormat) ChannelType() ChannelType {
	return ChannelType(f.image_channel_data_type)
}

// Creates a 2D image object.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clCreateImage2D.html
func CreateImage2D(context Context, flags MemFlags, image_format ImageFormat, image_width, image_height,
	image_row_pitch Size, host_ptr unsafe.Pointer) (Mem, error) {

	var err C.cl_int
	mem := C.clCreateImage2D(context, C.cl_mem_flags(flags), (*C.cl_image_format)(&image_format), C.size_t(image_width),
		C.size_t(image_height), C.size_t(image_row_pitch), host_ptr, &err)

	return Mem(mem), toError(err)
}

// Creates a 3D image object.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clCreateImage3D.html
func CreateImage3D(context Context, flags MemFlags, image_format ImageFormat, image_width, image_height, image_depth,
	image_row_pitch, image_slice_pitch Size, host_ptr unsafe.Pointer) (Mem, error) {

	var err C.cl_int
	mem := C.clCreateImage3D(context, C.cl_mem_flags(flags), (*C.cl_image_format)(&image_format), C.size_t(image_width),
		C.size_t(image_height), C.size_t(image_depth), C.size_t(image_row_pitch), C.size_t(image_slice_pitch), host_ptr,
		&err)

	return Mem(mem), toError(err)
}

// Get information specific to an image object.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clGetImageInfo.html
func GetImageInfo(image Mem, param_name ImageInfo, param_value_size Size, param_value unsafe.Pointer,
	param_value_size_ret *Size) error {

	return toError(C.clGetImageInfo(image, C.cl_image_info(param_name), C.size_t(param_value_size), param_value,
		(*C.size_t)(param_value_size_ret)))
}

// Get the list of image formats supported by an OpenCL implementation.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clGetSupportedImageFormats.html
func GetSupportedImageFormats(context Context, flags MemFlags, image_type MemObjectType, num_entries Uint,
	image_formats *ImageFormat, num_image_formats *Uint) error {

	return toError(C.clGetSupportedImageFormats(context, C.cl_mem_flags(flags), C.cl_mem_object_type(image_type),
		C.cl_uint(num_entries), (*C.cl_image_format)(image_formats), (*C.cl_uint)(num_image_formats)))
}
<commit_msg>Ensuring all public functions are documented.<commit_after>package clw11

/*
#define CL_USE_DEPRECATED_OPENCL_1_1_APIS
#ifdef __APPLE__
#include "OpenCL/opencl.h"
#else
#include "CL/opencl.h"
#endif
*/
import "C"
import "unsafe"

type (
	MemObjectType C.cl_mem_object_type
	ImageFormat   C.cl_image_format
	ImageInfo     C.cl_image_info
	ChannelOrder  C.cl_channel_order
	ChannelType   C.cl_channel_type
)

const (
	MemObjectBuffer  MemObjectType = C.CL_MEM_OBJECT_BUFFER
	MemObjectImage2D MemObjectType = C.CL_MEM_OBJECT_IMAGE2D
	MemObjectImage3D MemObjectType = C.CL_MEM_OBJECT_IMAGE3D
)

const (
	R         ChannelOrder = C.CL_R
	A         ChannelOrder = C.CL_A
	RG        ChannelOrder = C.CL_RG
	RA        ChannelOrder = C.CL_RA
	RGB       ChannelOrder = C.CL_RGB
	RGBA      ChannelOrder = C.CL_RGBA
	BGRA      ChannelOrder = C.CL_BGRA
	ARGB      ChannelOrder = C.CL_ARGB
	Intensity ChannelOrder = C.CL_INTENSITY
	Luminance ChannelOrder = C.CL_LUMINANCE
	Rx        ChannelOrder = C.CL_Rx
	RGx       ChannelOrder = C.CL_RGx
	RGBx      ChannelOrder = C.CL_RGBx
)

const (
	SnormInt8      ChannelType = C.CL_SNORM_INT8
	SnormInt16     ChannelType = C.CL_SNORM_INT16
	UnormInt8      ChannelType = C.CL_UNORM_INT8
	UnormInt16     ChannelType = C.CL_UNORM_INT16
	UnormShort565  ChannelType = C.CL_UNORM_SHORT_565
	UnormShort555  ChannelType = C.CL_UNORM_SHORT_555
	UnormInt101010 ChannelType = C.CL_UNORM_INT_101010
	SignedInt8     ChannelType = C.CL_SIGNED_INT8
	SignedInt16    ChannelType = C.CL_SIGNED_INT16
	SignedInt32    ChannelType = C.CL_SIGNED_INT32
	UnsignedInt8   ChannelType = C.CL_UNSIGNED_INT8
	UnsignedInt16  ChannelType = C.CL_UNSIGNED_INT16
	UnsignedInt32  ChannelType = C.CL_UNSIGNED_INT32
	HalfFloat      ChannelType = C.CL_HALF_FLOAT
	Float          ChannelType = C.CL_FLOAT
)

const (
	ImageFormatInfo  ImageInfo = C.CL_IMAGE_FORMAT // Appended "Info" due to conflict with type.
	ImageElementSize ImageInfo = C.CL_IMAGE_ELEMENT_SIZE
	ImageRowPitch    ImageInfo = C.CL_IMAGE_ROW_PITCH
	ImageSlicePitch  ImageInfo = C.CL_IMAGE_SLICE_PITCH
	ImageWidth       ImageInfo = C.CL_IMAGE_WIDTH
	ImageHeight      ImageInfo = C.CL_IMAGE_HEIGHT
	ImageDepth       ImageInfo = C.CL_IMAGE_DEPTH
)

// Create an image format descriptor.
func CreateImageFormat(co ChannelOrder, ct ChannelType) ImageFormat {
	return ImageFormat{C.cl_channel_order(co), C.cl_channel_type(ct)}
}

// Retruns the number of channels and the channel layout.
func (f *ImageFormat) ChannelOrder() ChannelOrder {
	return ChannelOrder(f.image_channel_order)
}

// Returns the size of the channel data type.
func (f *ImageFormat) ChannelType() ChannelType {
	return ChannelType(f.image_channel_data_type)
}

// Creates a 2D image object.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clCreateImage2D.html
func CreateImage2D(context Context, flags MemFlags, image_format ImageFormat, image_width, image_height,
	image_row_pitch Size, host_ptr unsafe.Pointer) (Mem, error) {

	var err C.cl_int
	mem := C.clCreateImage2D(context, C.cl_mem_flags(flags), (*C.cl_image_format)(&image_format), C.size_t(image_width),
		C.size_t(image_height), C.size_t(image_row_pitch), host_ptr, &err)

	return Mem(mem), toError(err)
}

// Creates a 3D image object.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clCreateImage3D.html
func CreateImage3D(context Context, flags MemFlags, image_format ImageFormat, image_width, image_height, image_depth,
	image_row_pitch, image_slice_pitch Size, host_ptr unsafe.Pointer) (Mem, error) {

	var err C.cl_int
	mem := C.clCreateImage3D(context, C.cl_mem_flags(flags), (*C.cl_image_format)(&image_format), C.size_t(image_width),
		C.size_t(image_height), C.size_t(image_depth), C.size_t(image_row_pitch), C.size_t(image_slice_pitch), host_ptr,
		&err)

	return Mem(mem), toError(err)
}

// Get information specific to an image object.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clGetImageInfo.html
func GetImageInfo(image Mem, param_name ImageInfo, param_value_size Size, param_value unsafe.Pointer,
	param_value_size_ret *Size) error {

	return toError(C.clGetImageInfo(image, C.cl_image_info(param_name), C.size_t(param_value_size), param_value,
		(*C.size_t)(param_value_size_ret)))
}

// Get the list of image formats supported by an OpenCL implementation.
// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clGetSupportedImageFormats.html
func GetSupportedImageFormats(context Context, flags MemFlags, image_type MemObjectType, num_entries Uint,
	image_formats *ImageFormat, num_image_formats *Uint) error {

	return toError(C.clGetSupportedImageFormats(context, C.cl_mem_flags(flags), C.cl_mem_object_type(image_type),
		C.cl_uint(num_entries), (*C.cl_image_format)(image_formats), (*C.cl_uint)(num_image_formats)))
}
<|endoftext|>


<commit_before>package mvm

import (
	"fmt"
	"io/ioutil"
	"os"
)

func SetupDefault() {
	welcome := MakeBlueprint("welcome")
	TheVM.active = MakeObject(welcome, nil, nil)
}

var FileName string = "mvm.img"

func LoadImage() error {
	byte_slice, err := ioutil.ReadFile(FileName)
	if err != nil {
		fmt.Printf("'%s' not found - loading the default VM image\n", FileName)
		SetupDefault()
		return nil
	}
	ble, err := Unflatten(byte_slice)
	if err != nil {
		return err
	}
	TheVM = ble.(*VM)
	return nil
}

func SaveImage() error {
	bytes, err := Flatten(TheVM)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(FileName, bytes, os.ModePerm)
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>Initialize default blueprint<commit_after>package mvm

import (
	"fmt"
	"io/ioutil"
	"os"
)

func SetupDefault() {
	welcome := MakeBlueprint("welcome")
	TheVM.active = MakeObject(welcome, nil, nil)
	welcome.Instantiate(TheVM.active)
}

var FileName string = "mvm.img"

func LoadImage() error {
	byte_slice, err := ioutil.ReadFile(FileName)
	if err != nil {
		fmt.Printf("'%s' not found - loading the default VM image\n", FileName)
		SetupDefault()
		return nil
	}
	ble, err := Unflatten(byte_slice)
	if err != nil {
		return err
	}
	TheVM = ble.(*VM)
	return nil
}

func SaveImage() error {
	bytes, err := Flatten(TheVM)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(FileName, bytes, os.ModePerm)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package platformvm

import (
	"errors"
	"fmt"

	"github.com/ava-labs/avalanchego/ids"
	"github.com/ava-labs/avalanchego/snow/choices"
)

var (
	errConflictingParentTxs = errors.New("block contains a transaction that conflicts with a transaction in a parent block")

	_ Block    = &AtomicBlock{}
	_ decision = &AtomicBlock{}
)

// AtomicBlock being accepted results in the atomic transaction contained in the
// block to be accepted and committed to the chain.
type AtomicBlock struct {
	CommonDecisionBlock `serialize:"true"`

	Tx Tx `serialize:"true" json:"tx"`

	// inputs are the atomic inputs that are consumed by this block's atomic
	// transaction
	inputs ids.Set
}

func (ab *AtomicBlock) initialize(vm *VM, bytes []byte, status choices.Status, self Block) error {
	if err := ab.CommonDecisionBlock.initialize(vm, bytes, status, self); err != nil {
		return fmt.Errorf("failed to initialize: %w", err)
	}
	unsignedBytes, err := vm.codec.Marshal(codecVersion, &ab.Tx.UnsignedTx)
	if err != nil {
		return fmt.Errorf("failed to marshal unsigned tx: %w", err)
	}
	signedBytes, err := ab.vm.codec.Marshal(codecVersion, &ab.Tx)
	if err != nil {
		return fmt.Errorf("failed to marshal tx: %w", err)
	}
	ab.Tx.Initialize(unsignedBytes, signedBytes)
	return nil
}

// conflicts checks to see if the provided input set contains any conflicts with
// any of this block's non-accepted ancestors or itself.
func (ab *AtomicBlock) conflicts(s ids.Set) (bool, error) {
	if ab.Status() == choices.Accepted {
		return false, nil
	}
	if ab.inputs.Overlaps(s) {
		return true, nil
	}
	parent, err := ab.parentBlock()
	if err != nil {
		return false, err
	}
	return parent.conflicts(s)
}

// Verify this block performs a valid state transition.
//
// The parent block must be a decision block
//
// This function also sets onAcceptDB database if the verification passes.
func (ab *AtomicBlock) Verify() error {
	blkID := ab.ID()

	if err := ab.CommonDecisionBlock.Verify(); err != nil {
		ab.vm.ctx.Log.Trace("rejecting block %s due to a failed verification: %s", blkID, err)
		if err := ab.Reject(); err != nil {
			ab.vm.ctx.Log.Error(
				"failed to reject atomic block %s due to %s",
				blkID,
				err,
			)
		}
		return err
	}

	tx, ok := ab.Tx.UnsignedTx.(UnsignedAtomicTx)
	if !ok {
		return errWrongTxType
	}
	ab.inputs = tx.InputUTXOs()

	parentIntf, err := ab.parentBlock()
	if err != nil {
		return err
	}

	conflicts, err := parentIntf.conflicts(ab.inputs)
	if err != nil {
		return err
	}
	if conflicts {
		return errConflictingParentTxs
	}

	// AtomicBlock is not a modifier on a proposal block, so its parent must be
	// a decision.
	parent, ok := parentIntf.(decision)
	if !ok {
		return errInvalidBlockType
	}

	parentState := parent.onAccept()
	onAccept, err := tx.SemanticVerify(ab.vm, parentState, &ab.Tx)
	if err != nil {
		txID := tx.ID()
		ab.vm.droppedTxCache.Put(txID, err.Error()) // cache tx as dropped
		return fmt.Errorf("tx %s failed semantic verification: %w", txID, err)
	}
	onAccept.AddTx(&ab.Tx, Committed)

	ab.timestamp = onAccept.GetTimestamp()
	ab.onAcceptState = onAccept

	ab.vm.currentBlocks[blkID] = ab
	parentIntf.addChild(ab)
	return nil
}

func (ab *AtomicBlock) Accept() error {
	blkID := ab.ID()
	ab.vm.ctx.Log.Verbo(
		"Accepting Atomic Block %s at height %d with parent %s",
		blkID,
		ab.Height(),
		ab.Parent(),
	)

	if err := ab.CommonBlock.Accept(); err != nil {
		return fmt.Errorf("failed to accept CommonBlock of %s: %w", blkID, err)
	}

	tx, ok := ab.Tx.UnsignedTx.(UnsignedAtomicTx)
	if !ok {
		return errWrongTxType
	}

	// Update the state of the chain in the database
	ab.onAcceptState.Apply(ab.vm.internalState)

	defer ab.vm.internalState.Abort()
	batch, err := ab.vm.internalState.CommitBatch()
	if err != nil {
		return fmt.Errorf(
			"failed to commit VM's database for block %s: %w",
			blkID,
			err,
		)
	}
	if err := tx.Accept(ab.vm.ctx, batch); err != nil {
		return fmt.Errorf(
			"failed to atomically accept tx %s in block %s: %w",
			tx.ID(),
			blkID,
			err,
		)
	}

	for _, child := range ab.children {
		child.setBaseState()
	}
	if ab.onAcceptFunc != nil {
		if err := ab.onAcceptFunc(); err != nil {
			return fmt.Errorf(
				"failed to execute onAcceptFunc of %s: %w",
				blkID,
				err,
			)
		}
	}

	ab.free()
	return nil
}

func (ab *AtomicBlock) Reject() error {
	ab.vm.ctx.Log.Verbo(
		"Rejecting Atomic Block %s at height %d with parent %s",
		ab.ID(),
		ab.Height(),
		ab.Parent(),
	)

	if err := ab.vm.mempool.IssueTx(&ab.Tx); err != nil {
		ab.vm.ctx.Log.Debug(
			"failed to reissue tx %q due to: %s",
			ab.Tx.ID(),
			err,
		)
	}
	return ab.CommonDecisionBlock.Reject()
}

// newAtomicBlock returns a new *AtomicBlock where the block's parent, a
// decision block, has ID [parentID].
func (vm *VM) newAtomicBlock(parentID ids.ID, height uint64, tx Tx) (*AtomicBlock, error) {
	ab := &AtomicBlock{
		CommonDecisionBlock: CommonDecisionBlock{
			CommonBlock: CommonBlock{
				PrntID: parentID,
				Hght:   height,
			},
		},
		Tx: tx,
	}

	// We serialize this block as a Block so that it can be deserialized into a
	// Block
	blk := Block(ab)
	bytes, err := Codec.Marshal(codecVersion, &blk)
	if err != nil {
		return nil, fmt.Errorf("failed to marshal block: %w", err)
	}
	return ab, ab.CommonDecisionBlock.initialize(vm, bytes, choices.Processing, ab)
}
<commit_msg>be consistent in the timestamp setting order<commit_after>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package platformvm

import (
	"errors"
	"fmt"

	"github.com/ava-labs/avalanchego/ids"
	"github.com/ava-labs/avalanchego/snow/choices"
)

var (
	errConflictingParentTxs = errors.New("block contains a transaction that conflicts with a transaction in a parent block")

	_ Block    = &AtomicBlock{}
	_ decision = &AtomicBlock{}
)

// AtomicBlock being accepted results in the atomic transaction contained in the
// block to be accepted and committed to the chain.
type AtomicBlock struct {
	CommonDecisionBlock `serialize:"true"`

	Tx Tx `serialize:"true" json:"tx"`

	// inputs are the atomic inputs that are consumed by this block's atomic
	// transaction
	inputs ids.Set
}

func (ab *AtomicBlock) initialize(vm *VM, bytes []byte, status choices.Status, self Block) error {
	if err := ab.CommonDecisionBlock.initialize(vm, bytes, status, self); err != nil {
		return fmt.Errorf("failed to initialize: %w", err)
	}
	unsignedBytes, err := vm.codec.Marshal(codecVersion, &ab.Tx.UnsignedTx)
	if err != nil {
		return fmt.Errorf("failed to marshal unsigned tx: %w", err)
	}
	signedBytes, err := ab.vm.codec.Marshal(codecVersion, &ab.Tx)
	if err != nil {
		return fmt.Errorf("failed to marshal tx: %w", err)
	}
	ab.Tx.Initialize(unsignedBytes, signedBytes)
	return nil
}

// conflicts checks to see if the provided input set contains any conflicts with
// any of this block's non-accepted ancestors or itself.
func (ab *AtomicBlock) conflicts(s ids.Set) (bool, error) {
	if ab.Status() == choices.Accepted {
		return false, nil
	}
	if ab.inputs.Overlaps(s) {
		return true, nil
	}
	parent, err := ab.parentBlock()
	if err != nil {
		return false, err
	}
	return parent.conflicts(s)
}

// Verify this block performs a valid state transition.
//
// The parent block must be a decision block
//
// This function also sets onAcceptDB database if the verification passes.
func (ab *AtomicBlock) Verify() error {
	blkID := ab.ID()

	if err := ab.CommonDecisionBlock.Verify(); err != nil {
		ab.vm.ctx.Log.Trace("rejecting block %s due to a failed verification: %s", blkID, err)
		if err := ab.Reject(); err != nil {
			ab.vm.ctx.Log.Error(
				"failed to reject atomic block %s due to %s",
				blkID,
				err,
			)
		}
		return err
	}

	tx, ok := ab.Tx.UnsignedTx.(UnsignedAtomicTx)
	if !ok {
		return errWrongTxType
	}
	ab.inputs = tx.InputUTXOs()

	parentIntf, err := ab.parentBlock()
	if err != nil {
		return err
	}

	conflicts, err := parentIntf.conflicts(ab.inputs)
	if err != nil {
		return err
	}
	if conflicts {
		return errConflictingParentTxs
	}

	// AtomicBlock is not a modifier on a proposal block, so its parent must be
	// a decision.
	parent, ok := parentIntf.(decision)
	if !ok {
		return errInvalidBlockType
	}

	parentState := parent.onAccept()
	onAccept, err := tx.SemanticVerify(ab.vm, parentState, &ab.Tx)
	if err != nil {
		txID := tx.ID()
		ab.vm.droppedTxCache.Put(txID, err.Error()) // cache tx as dropped
		return fmt.Errorf("tx %s failed semantic verification: %w", txID, err)
	}
	onAccept.AddTx(&ab.Tx, Committed)

	ab.onAcceptState = onAccept
	ab.timestamp = onAccept.GetTimestamp()

	ab.vm.currentBlocks[blkID] = ab
	parentIntf.addChild(ab)
	return nil
}

func (ab *AtomicBlock) Accept() error {
	blkID := ab.ID()
	ab.vm.ctx.Log.Verbo(
		"Accepting Atomic Block %s at height %d with parent %s",
		blkID,
		ab.Height(),
		ab.Parent(),
	)

	if err := ab.CommonBlock.Accept(); err != nil {
		return fmt.Errorf("failed to accept CommonBlock of %s: %w", blkID, err)
	}

	tx, ok := ab.Tx.UnsignedTx.(UnsignedAtomicTx)
	if !ok {
		return errWrongTxType
	}

	// Update the state of the chain in the database
	ab.onAcceptState.Apply(ab.vm.internalState)

	defer ab.vm.internalState.Abort()
	batch, err := ab.vm.internalState.CommitBatch()
	if err != nil {
		return fmt.Errorf(
			"failed to commit VM's database for block %s: %w",
			blkID,
			err,
		)
	}
	if err := tx.Accept(ab.vm.ctx, batch); err != nil {
		return fmt.Errorf(
			"failed to atomically accept tx %s in block %s: %w",
			tx.ID(),
			blkID,
			err,
		)
	}

	for _, child := range ab.children {
		child.setBaseState()
	}
	if ab.onAcceptFunc != nil {
		if err := ab.onAcceptFunc(); err != nil {
			return fmt.Errorf(
				"failed to execute onAcceptFunc of %s: %w",
				blkID,
				err,
			)
		}
	}

	ab.free()
	return nil
}

func (ab *AtomicBlock) Reject() error {
	ab.vm.ctx.Log.Verbo(
		"Rejecting Atomic Block %s at height %d with parent %s",
		ab.ID(),
		ab.Height(),
		ab.Parent(),
	)

	if err := ab.vm.mempool.IssueTx(&ab.Tx); err != nil {
		ab.vm.ctx.Log.Debug(
			"failed to reissue tx %q due to: %s",
			ab.Tx.ID(),
			err,
		)
	}
	return ab.CommonDecisionBlock.Reject()
}

// newAtomicBlock returns a new *AtomicBlock where the block's parent, a
// decision block, has ID [parentID].
func (vm *VM) newAtomicBlock(parentID ids.ID, height uint64, tx Tx) (*AtomicBlock, error) {
	ab := &AtomicBlock{
		CommonDecisionBlock: CommonDecisionBlock{
			CommonBlock: CommonBlock{
				PrntID: parentID,
				Hght:   height,
			},
		},
		Tx: tx,
	}

	// We serialize this block as a Block so that it can be deserialized into a
	// Block
	blk := Block(ab)
	bytes, err := Codec.Marshal(codecVersion, &blk)
	if err != nil {
		return nil, fmt.Errorf("failed to marshal block: %w", err)
	}
	return ab, ab.CommonDecisionBlock.initialize(vm, bytes, choices.Processing, ab)
}
<|endoftext|>


<commit_before>package check

// errcheck is the check for the errcheck command
type Errcheck struct {
	Dir       string
	Filenames []string
}

// Name returns the name of the display name of the command
func (e Errcheck) Name() string {
	return "errcheck"
}

// Weight returns the weight this check has in the overall average
func (e Errcheck) Weight() float64 {
	return .10
}

// Percentage returns the percentage of .go files that pass errcheck
func (e Errcheck) Percentage() (float64, []FileSummary, error) {
	return GoTool(e.Dir, e.Filenames, []string{"gometalinter", "--deadline=180s", "--disable-all", "--enable=errcheck", "--min-confidence=0.85"})
}

// Description returns the description of errcheck
func (e Errcheck) Description() string {
	return `errcheck checks that you checked errors.`
}
<commit_msg>Fix typo in errcheck comment<commit_after>package check

// Errcheck is the check for the errcheck command
type Errcheck struct {
	Dir       string
	Filenames []string
}

// Name returns the name of the display name of the command
func (e Errcheck) Name() string {
	return "errcheck"
}

// Weight returns the weight this check has in the overall average
func (e Errcheck) Weight() float64 {
	return .10
}

// Percentage returns the percentage of .go files that pass errcheck
func (e Errcheck) Percentage() (float64, []FileSummary, error) {
	return GoTool(e.Dir, e.Filenames, []string{"gometalinter", "--deadline=180s", "--disable-all", "--enable=errcheck", "--min-confidence=0.85"})
}

// Description returns the description of errcheck
func (e Errcheck) Description() string {
	return `errcheck checks that you checked errors.`
}
<|endoftext|>


<commit_before>package vcs

import (
	"bytes"
	"encoding/hex"
	"errors"
	"fmt"
	"net/mail"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/knieriem/hgo"
	hg_changelog "github.com/knieriem/hgo/changelog"
	hg_revlog "github.com/knieriem/hgo/revlog"
	hg_store "github.com/knieriem/hgo/store"
)

type HgRepositoryNative struct {
	dir         string
	u           *hgo.Repository
	st          *hg_store.Store
	cl          *hg_revlog.Index
	allTags     *hgo.Tags
	branchHeads *hgo.BranchHeads
}

func OpenHgRepositoryNative(dir string) (*HgRepositoryNative, error) {
	r, err := hgo.OpenRepository(dir)
	if err != nil {
		return nil, err
	}

	st := r.NewStore()
	cl, err := st.OpenChangeLog()
	if err != nil {
		return nil, err
	}

	globalTags, allTags := r.Tags()
	globalTags.Sort()
	allTags.Sort()
	allTags.Add("tip", cl.Tip().Id().Node())

	bh, err := r.BranchHeads()
	if err != nil {
		return nil, err
	}

	return &HgRepositoryNative{dir, r, st, cl, allTags, bh}, nil
}

func (r *HgRepositoryNative) ResolveRevision(spec string) (CommitID, error) {
	if id, err := r.ResolveBranch(spec); err == nil {
		return id, nil
	}
	if id, err := r.ResolveTag(spec); err == nil {
		return id, nil
	}

	rec, err := r.parseRevisionSpec(spec).Lookup(r.cl)
	if err != nil {
		return "", err
	}
	return CommitID(hex.EncodeToString(rec.Id())), nil
}

func (r *HgRepositoryNative) ResolveTag(name string) (CommitID, error) {
	if id, ok := r.allTags.IdByName[name]; ok {
		return CommitID(id), nil
	}
	return "", ErrTagNotFound
}

func (r *HgRepositoryNative) ResolveBranch(name string) (CommitID, error) {
	if id, ok := r.branchHeads.IdByName[name]; ok {
		return CommitID(id), nil
	}
	return "", ErrBranchNotFound
}

func (r *HgRepositoryNative) GetCommit(id CommitID) (*Commit, error) {
	rec, err := hg_revlog.NodeIdRevSpec(id).Lookup(r.cl)
	if err != nil {
		return nil, err
	}

	return r.makeCommit(rec)
}

func (r *HgRepositoryNative) CommitLog(to CommitID) ([]*Commit, error) {
	rec, err := hg_revlog.NodeIdRevSpec(to).Lookup(r.cl)
	if err != nil {
		return nil, err
	}

	var commits []*Commit
	for ; ; rec = rec.Prev() {
		c, err := r.makeCommit(rec)
		if err != nil {
			return nil, err
		}

		commits = append(commits, c)

		if rec.IsStartOfBranch() {
			break
		}
	}
	return commits, nil
}

func (r *HgRepositoryNative) makeCommit(rec *hg_revlog.Rec) (*Commit, error) {
	fb := hg_revlog.NewFileBuilder()
	ce, err := hg_changelog.BuildEntry(rec, fb)
	if err != nil {
		return nil, err
	}

	addr, err := mail.ParseAddress(ce.Committer)
	if err != nil {
		return nil, err
	}

	var parents []CommitID
	if !rec.IsStartOfBranch() {
		if p := rec.Parent(); p != nil {
			parents = append(parents, CommitID(hex.EncodeToString(rec.Parent().Id())))
		}
		if rec.Parent2Present() {
			parents = append(parents, CommitID(hex.EncodeToString(rec.Parent2().Id())))
		}
	}

	return &Commit{
		ID:      CommitID(ce.Id),
		Author:  Signature{addr.Name, addr.Address, ce.Date},
		Message: ce.Comment,
		Parents: parents,
	}, nil
}

func (r *HgRepositoryNative) FileSystem(at CommitID) (FileSystem, error) {
	rec, err := hg_revlog.NodeIdRevSpec(at).Lookup(r.cl)
	if err != nil {
		return nil, err
	}

	return &hgFSNative{
		dir:  r.dir,
		at:   hg_revlog.FileRevSpec(rec.FileRev()),
		repo: r.u,
		st:   r.st,
		cl:   r.cl,
		fb:   hg_revlog.NewFileBuilder(),
	}, nil
}

func (r *HgRepositoryNative) parseRevisionSpec(s string) hg_revlog.RevisionSpec {
	if s == "" {
		s = "tip"
		// TODO(sqs): determine per-repository default branch name (not always "default"?)
	}
	if s == "tip" {
		return hg_revlog.TipRevSpec{}
	}
	if s == "null" {
		return hg_revlog.NullRevSpec{}
	}
	if id, ok := r.allTags.IdByName[s]; ok {
		s = id
	} else if i, err := strconv.Atoi(s); err == nil {
		return hg_revlog.FileRevSpec(i)
	}

	return hg_revlog.NodeIdRevSpec(s)
}

type hgFSNative struct {
	dir  string
	at   hg_revlog.FileRevSpec
	repo *hgo.Repository
	st   *hg_store.Store
	cl   *hg_revlog.Index
	fb   *hg_revlog.FileBuilder
}

func (fs *hgFSNative) manifestEntry(chgId hg_revlog.FileRevSpec, fileName string) (me *hg_store.ManifestEnt, err error) {
	m, err := fs.getManifest(chgId)
	if err != nil {
		return
	}
	me = m.Map()[fileName]
	if me == nil {
		err = errors.New("file does not exist in given revision")
	}
	return
}

func (fs *hgFSNative) getManifest(chgId hg_revlog.FileRevSpec) (m hg_store.Manifest, err error) {
	rec, err := chgId.Lookup(fs.cl)
	if err != nil {
		return
	}
	c, err := hg_changelog.BuildEntry(rec, fs.fb)
	if err != nil {
		return
	}

	// st := fs.repo.NewStore()
	mlog, err := fs.st.OpenManifests()
	if err != nil {
		return nil, err
	}

	rec2, err := mlog.LookupRevision(int(c.Linkrev), c.ManifestNode)
	if err != nil {
		return nil, err
	}

	return hg_store.BuildManifest(rec2, fs.fb)
}

func (fs *hgFSNative) getEntry(path string) (*hg_revlog.Rec, *hg_store.ManifestEnt, error) {
	fileLog, err := fs.st.OpenRevlog(path)
	if err != nil {
		return nil, nil, err
	}

	rec, err := hg_revlog.LinkRevSpec{Rev: int(fs.at)}.Lookup(fileLog)
	if err != nil {
		return nil, nil, err
	}
	if rec.FileRev() == -1 {
		return nil, nil, hg_revlog.ErrRevisionNotFound
	}

	// Check for the file's existence using the manifest.
	ent, err := fs.manifestEntry(fs.at, path)
	if err != nil {
		return nil, nil, err
	}

	// compare hashes
	wantId, err := ent.Id()
	if err != nil {
		return nil, nil, err
	}
	if !wantId.Eq(rec.Id()) {
		return nil, nil, errors.New("manifest node id does not match file id")
	}

	if int(rec.Linkrev) == int(fs.at) {
		// The requested revision matches this record, which can be
		// used as a sign that the file exists. (TODO(sqs): original comments
		// say maybe this means the file is NOT existent yet? the word "not" is
		// not there but that seems to be a mistake.)
		return rec, ent, nil
	}

	if !rec.IsLeaf() {
		// There are other records that have the current record as a parent.
		// This means, the file was existent, no need to check the manifest.
		return rec, ent, nil
	}

	return rec, ent, nil
}

func (fs *hgFSNative) Open(name string) (ReadSeekCloser, error) {
	rec, _, err := fs.getEntry(name)
	if err != nil {
		return nil, standardizeHgError(err)
	}

	data, err := fs.readFile(rec)
	if err != nil {
		return nil, err
	}
	return nopCloser{bytes.NewReader(data)}, nil
}

func (fs *hgFSNative) readFile(rec *hg_revlog.Rec) ([]byte, error) {
	fb := hg_revlog.NewFileBuilder()
	return fb.Build(rec)
}

func (fs *hgFSNative) Lstat(path string) (os.FileInfo, error) {
	fi, _, err := fs.lstat(path)
	return fi, err
}

func (fs *hgFSNative) lstat(path string) (os.FileInfo, []byte, error) {
	path = filepath.Clean(path)

	rec, ent, err := fs.getEntry(path)
	if os.IsNotExist(err) {
		// check if path is a dir (dirs are not in hg's manifest, so we need to
		// hack around to get them).
		fi, err := fs.dirStat(path)
		return fi, nil, err
	}
	if err != nil {
		return nil, nil, standardizeHgError(err)
	}

	fi := fs.fileInfo(ent)

	// read data to determine file size
	data, err := fs.readFile(rec)
	if err != nil {
		return nil, nil, err
	}
	fi.size = int64(len(data))

	return fi, data, nil
}

func (fs *hgFSNative) Stat(path string) (os.FileInfo, error) {
	fi, data, err := fs.lstat(path)
	if err != nil {
		return nil, err
	}

	if fi.Mode()&os.ModeSymlink != 0 {
		// derefence symlink
		derefPath := string(data)
		fi, err := fs.Lstat(derefPath)
		if err != nil {
			return nil, err
		}

		fi.(*fileInfo).name = filepath.Base(path)
		return fi, nil
	}

	return fi, nil
}

// dirStat determines whether a directory exists at path by listing files
// underneath it. If it has files, then it's a directory. We must do it this way
// because hg doesn't track directories in the manifest.
func (fs *hgFSNative) dirStat(path string) (os.FileInfo, error) {
	if path == "." {
		return &fileInfo{
			name: ".",
			mode: os.ModeDir,
		}, nil
	}

	m, err := fs.getManifest(fs.at)
	if err != nil {
		return nil, err
	}

	dirPrefix := filepath.Clean(path) + "/"
	for _, e := range m {
		if strings.HasPrefix(e.FileName, dirPrefix) {
			return &fileInfo{
				name: filepath.Base(path),
				mode: os.ModeDir,
			}, nil
		}
	}

	return nil, os.ErrNotExist
}

func (fs *hgFSNative) fileInfo(ent *hg_store.ManifestEnt) *fileInfo {
	var mode os.FileMode
	if ent.IsExecutable() {
		mode |= 0111 // +x
	}
	if ent.IsLink() {
		mode |= os.ModeSymlink
	}

	return &fileInfo{
		name: filepath.Base(ent.FileName),
		mode: mode,
	}
}

func (fs *hgFSNative) ReadDir(path string) ([]os.FileInfo, error) {
	m, err := fs.getManifest(fs.at)
	if err != nil {
		return nil, err
	}

	var fis []os.FileInfo
	subdirs := make(map[string]struct{})

	var dirPrefix string
	if path := filepath.Clean(path); path == "." {
		dirPrefix = ""
	} else {
		dirPrefix = path + "/"
	}
	for _, e := range m {
		if !strings.HasPrefix(e.FileName, dirPrefix) {
			continue
		}
		name := strings.TrimPrefix(e.FileName, dirPrefix)
		dir := filepath.Dir(name)
		if dir == "." {
			fis = append(fis, fs.fileInfo(&e))
		} else {
			subdir := strings.SplitN(dir, "/", 2)[0]
			if _, seen := subdirs[subdir]; !seen {
				fis = append(fis, &fileInfo{name: subdir, mode: os.ModeDir})
				subdirs[subdir] = struct{}{}
			}
		}
	}
	return fis, nil
}

func (fs *hgFSNative) String() string {
	return fmt.Sprintf("hg repository %s commit %s (native)", fs.dir, fs.at)
}

func standardizeHgError(err error) error {
	if err == hg_revlog.ErrRevisionNotFound {
		return os.ErrNotExist
	}
	return err
}

type fileInfo struct {
	name  string
	mode  os.FileMode
	size  int64
	mtime time.Time
}

func (fi *fileInfo) Name() string       { return fi.name }
func (fi *fileInfo) Size() int64        { return fi.size }
func (fi *fileInfo) Mode() os.FileMode  { return fi.mode }
func (fi *fileInfo) ModTime() time.Time { return fi.mtime }
func (fi *fileInfo) IsDir() bool        { return fi.Mode().IsDir() }
func (fi *fileInfo) Sys() interface{}   { return nil }
<commit_msg>find revlog entry by the nodeid in the manifest<commit_after>package vcs

import (
	"bytes"
	"encoding/hex"
	"errors"
	"fmt"
	"net/mail"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/knieriem/hgo"
	hg_changelog "github.com/knieriem/hgo/changelog"
	hg_revlog "github.com/knieriem/hgo/revlog"
	hg_store "github.com/knieriem/hgo/store"
)

type HgRepositoryNative struct {
	dir         string
	u           *hgo.Repository
	st          *hg_store.Store
	cl          *hg_revlog.Index
	allTags     *hgo.Tags
	branchHeads *hgo.BranchHeads
}

func OpenHgRepositoryNative(dir string) (*HgRepositoryNative, error) {
	r, err := hgo.OpenRepository(dir)
	if err != nil {
		return nil, err
	}

	st := r.NewStore()
	cl, err := st.OpenChangeLog()
	if err != nil {
		return nil, err
	}

	globalTags, allTags := r.Tags()
	globalTags.Sort()
	allTags.Sort()
	allTags.Add("tip", cl.Tip().Id().Node())

	bh, err := r.BranchHeads()
	if err != nil {
		return nil, err
	}

	return &HgRepositoryNative{dir, r, st, cl, allTags, bh}, nil
}

func (r *HgRepositoryNative) ResolveRevision(spec string) (CommitID, error) {
	if id, err := r.ResolveBranch(spec); err == nil {
		return id, nil
	}
	if id, err := r.ResolveTag(spec); err == nil {
		return id, nil
	}

	rec, err := r.parseRevisionSpec(spec).Lookup(r.cl)
	if err != nil {
		return "", err
	}
	return CommitID(hex.EncodeToString(rec.Id())), nil
}

func (r *HgRepositoryNative) ResolveTag(name string) (CommitID, error) {
	if id, ok := r.allTags.IdByName[name]; ok {
		return CommitID(id), nil
	}
	return "", ErrTagNotFound
}

func (r *HgRepositoryNative) ResolveBranch(name string) (CommitID, error) {
	if id, ok := r.branchHeads.IdByName[name]; ok {
		return CommitID(id), nil
	}
	return "", ErrBranchNotFound
}

func (r *HgRepositoryNative) GetCommit(id CommitID) (*Commit, error) {
	rec, err := hg_revlog.NodeIdRevSpec(id).Lookup(r.cl)
	if err != nil {
		return nil, err
	}

	return r.makeCommit(rec)
}

func (r *HgRepositoryNative) CommitLog(to CommitID) ([]*Commit, error) {
	rec, err := hg_revlog.NodeIdRevSpec(to).Lookup(r.cl)
	if err != nil {
		return nil, err
	}

	var commits []*Commit
	for ; ; rec = rec.Prev() {
		c, err := r.makeCommit(rec)
		if err != nil {
			return nil, err
		}

		commits = append(commits, c)

		if rec.IsStartOfBranch() {
			break
		}
	}
	return commits, nil
}

func (r *HgRepositoryNative) makeCommit(rec *hg_revlog.Rec) (*Commit, error) {
	fb := hg_revlog.NewFileBuilder()
	ce, err := hg_changelog.BuildEntry(rec, fb)
	if err != nil {
		return nil, err
	}

	addr, err := mail.ParseAddress(ce.Committer)
	if err != nil {
		return nil, err
	}

	var parents []CommitID
	if !rec.IsStartOfBranch() {
		if p := rec.Parent(); p != nil {
			parents = append(parents, CommitID(hex.EncodeToString(rec.Parent().Id())))
		}
		if rec.Parent2Present() {
			parents = append(parents, CommitID(hex.EncodeToString(rec.Parent2().Id())))
		}
	}

	return &Commit{
		ID:      CommitID(ce.Id),
		Author:  Signature{addr.Name, addr.Address, ce.Date},
		Message: ce.Comment,
		Parents: parents,
	}, nil
}

func (r *HgRepositoryNative) FileSystem(at CommitID) (FileSystem, error) {
	rec, err := hg_revlog.NodeIdRevSpec(at).Lookup(r.cl)
	if err != nil {
		return nil, err
	}

	return &hgFSNative{
		dir:  r.dir,
		at:   hg_revlog.FileRevSpec(rec.FileRev()),
		repo: r.u,
		st:   r.st,
		cl:   r.cl,
		fb:   hg_revlog.NewFileBuilder(),
	}, nil
}

func (r *HgRepositoryNative) parseRevisionSpec(s string) hg_revlog.RevisionSpec {
	if s == "" {
		s = "tip"
		// TODO(sqs): determine per-repository default branch name (not always "default"?)
	}
	if s == "tip" {
		return hg_revlog.TipRevSpec{}
	}
	if s == "null" {
		return hg_revlog.NullRevSpec{}
	}
	if id, ok := r.allTags.IdByName[s]; ok {
		s = id
	} else if i, err := strconv.Atoi(s); err == nil {
		return hg_revlog.FileRevSpec(i)
	}

	return hg_revlog.NodeIdRevSpec(s)
}

type hgFSNative struct {
	dir  string
	at   hg_revlog.FileRevSpec
	repo *hgo.Repository
	st   *hg_store.Store
	cl   *hg_revlog.Index
	fb   *hg_revlog.FileBuilder
}

func (fs *hgFSNative) manifestEntry(chgId hg_revlog.FileRevSpec, fileName string) (me *hg_store.ManifestEnt, err error) {
	m, err := fs.getManifest(chgId)
	if err != nil {
		return
	}
	me = m.Map()[fileName]
	if me == nil {
		err = errors.New("file does not exist in given revision")
	}
	return
}

func (fs *hgFSNative) getManifest(chgId hg_revlog.FileRevSpec) (m hg_store.Manifest, err error) {
	rec, err := chgId.Lookup(fs.cl)
	if err != nil {
		return
	}
	c, err := hg_changelog.BuildEntry(rec, fs.fb)
	if err != nil {
		return
	}

	// st := fs.repo.NewStore()
	mlog, err := fs.st.OpenManifests()
	if err != nil {
		return nil, err
	}

	rec2, err := mlog.LookupRevision(int(c.Linkrev), c.ManifestNode)
	if err != nil {
		return nil, err
	}

	return hg_store.BuildManifest(rec2, fs.fb)
}

func (fs *hgFSNative) getEntry(path string) (*hg_revlog.Rec, *hg_store.ManifestEnt, error) {
	fileLog, err := fs.st.OpenRevlog(path)
	if err != nil {
		return nil, nil, err
	}

	// Get file entry from manifest (so we can look up the correct record in the file revlog)
	ent, err := fs.manifestEntry(fs.at, path)
	if err != nil {
		return nil, nil, err
	}

	// Lookup record in revlog
	entId, err := ent.Id()
	if err != nil {
		return nil, nil, err
	}
	linkRevSpec := hg_revlog.LinkRevSpec{
		Rev: int(fs.at),
		FindPresent: func(maybeAncestors []*hg_revlog.Rec) (index int, err error) {
			// Find the present file record by matching against the manifest entry.
			//
			// Note: this is necessary due to some edge case where the returned file record nodeid does not match the
			// entry in the manifest. So far, have not been able to repro this outside the Python standard library (try
			// Stat() on the README)
			for a, anc := range maybeAncestors {
				if anc.Id().Eq(entId) {
					return a, nil
				}
			}

			ancIds := make([]hg_revlog.NodeId, len(maybeAncestors))
			for a, anc := range maybeAncestors {
				ancIds[a] = anc.Id()
			}
			return 0, fmt.Errorf("failed to find file record with nodeid matching manifest entry nodeid %v, candidates were %v",
				entId, ancIds)
		},
	}
	rec, err := linkRevSpec.Lookup(fileLog)
	if err != nil {
		return nil, nil, err
	}
	if rec.FileRev() == -1 {
		return nil, nil, hg_revlog.ErrRevisionNotFound
	}

	if int(rec.Linkrev) == int(fs.at) {
		// The requested revision matches this record, which can be
		// used as a sign that the file exists. (TODO(sqs): original comments
		// say maybe this means the file is NOT existent yet? the word "not" is
		// not there but that seems to be a mistake.)
		return rec, ent, nil
	}

	if !rec.IsLeaf() {
		// There are other records that have the current record as a parent.
		// This means, the file was existent, no need to check the manifest.
		return rec, ent, nil
	}

	return rec, ent, nil
}

func (fs *hgFSNative) Open(name string) (ReadSeekCloser, error) {
	rec, _, err := fs.getEntry(name)
	if err != nil {
		return nil, standardizeHgError(err)
	}

	data, err := fs.readFile(rec)
	if err != nil {
		return nil, err
	}
	return nopCloser{bytes.NewReader(data)}, nil
}

func (fs *hgFSNative) readFile(rec *hg_revlog.Rec) ([]byte, error) {
	fb := hg_revlog.NewFileBuilder()
	return fb.Build(rec)
}

func (fs *hgFSNative) Lstat(path string) (os.FileInfo, error) {
	fi, _, err := fs.lstat(path)
	return fi, err
}

func (fs *hgFSNative) lstat(path string) (os.FileInfo, []byte, error) {
	path = filepath.Clean(path)

	rec, ent, err := fs.getEntry(path)
	if os.IsNotExist(err) {
		// check if path is a dir (dirs are not in hg's manifest, so we need to
		// hack around to get them).
		fi, err := fs.dirStat(path)
		return fi, nil, err
	}
	if err != nil {
		return nil, nil, standardizeHgError(err)
	}

	fi := fs.fileInfo(ent)

	// read data to determine file size
	data, err := fs.readFile(rec)
	if err != nil {
		return nil, nil, err
	}
	fi.size = int64(len(data))

	return fi, data, nil
}

func (fs *hgFSNative) Stat(path string) (os.FileInfo, error) {
	fi, data, err := fs.lstat(path)
	if err != nil {
		return nil, err
	}

	if fi.Mode()&os.ModeSymlink != 0 {
		// derefence symlink
		derefPath := string(data)
		fi, err := fs.Lstat(derefPath)
		if err != nil {
			return nil, err
		}

		fi.(*fileInfo).name = filepath.Base(path)
		return fi, nil
	}

	return fi, nil
}

// dirStat determines whether a directory exists at path by listing files
// underneath it. If it has files, then it's a directory. We must do it this way
// because hg doesn't track directories in the manifest.
func (fs *hgFSNative) dirStat(path string) (os.FileInfo, error) {
	if path == "." {
		return &fileInfo{
			name: ".",
			mode: os.ModeDir,
		}, nil
	}

	m, err := fs.getManifest(fs.at)
	if err != nil {
		return nil, err
	}

	dirPrefix := filepath.Clean(path) + "/"
	for _, e := range m {
		if strings.HasPrefix(e.FileName, dirPrefix) {
			return &fileInfo{
				name: filepath.Base(path),
				mode: os.ModeDir,
			}, nil
		}
	}

	return nil, os.ErrNotExist
}

func (fs *hgFSNative) fileInfo(ent *hg_store.ManifestEnt) *fileInfo {
	var mode os.FileMode
	if ent.IsExecutable() {
		mode |= 0111 // +x
	}
	if ent.IsLink() {
		mode |= os.ModeSymlink
	}

	return &fileInfo{
		name: filepath.Base(ent.FileName),
		mode: mode,
	}
}

func (fs *hgFSNative) ReadDir(path string) ([]os.FileInfo, error) {
	m, err := fs.getManifest(fs.at)
	if err != nil {
		return nil, err
	}

	var fis []os.FileInfo
	subdirs := make(map[string]struct{})

	var dirPrefix string
	if path := filepath.Clean(path); path == "." {
		dirPrefix = ""
	} else {
		dirPrefix = path + "/"
	}
	for _, e := range m {
		if !strings.HasPrefix(e.FileName, dirPrefix) {
			continue
		}
		name := strings.TrimPrefix(e.FileName, dirPrefix)
		dir := filepath.Dir(name)
		if dir == "." {
			fis = append(fis, fs.fileInfo(&e))
		} else {
			subdir := strings.SplitN(dir, "/", 2)[0]
			if _, seen := subdirs[subdir]; !seen {
				fis = append(fis, &fileInfo{name: subdir, mode: os.ModeDir})
				subdirs[subdir] = struct{}{}
			}
		}
	}
	return fis, nil
}

func (fs *hgFSNative) String() string {
	return fmt.Sprintf("hg repository %s commit %s (native)", fs.dir, fs.at)
}

func standardizeHgError(err error) error {
	if err == hg_revlog.ErrRevisionNotFound {
		return os.ErrNotExist
	}
	return err
}

type fileInfo struct {
	name  string
	mode  os.FileMode
	size  int64
	mtime time.Time
}

func (fi *fileInfo) Name() string       { return fi.name }
func (fi *fileInfo) Size() int64        { return fi.size }
func (fi *fileInfo) Mode() os.FileMode  { return fi.mode }
func (fi *fileInfo) ModTime() time.Time { return fi.mtime }
func (fi *fileInfo) IsDir() bool        { return fi.Mode().IsDir() }
func (fi *fileInfo) Sys() interface{}   { return nil }
<|endoftext|>


<commit_before>// Copyright 2015 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 verify

import (
	"fmt"
	"strings"
	"time"

	"github.com/jacobsa/comeback/blob"
)

const (
	filePrefix = "f:"
	dirPrefix  = "d:"
)

// A record certifying that a node was verified at a particular time.
type Record struct {
	Time time.Time

	// The node that was verified.
	//
	// For directory nodes, the record certifies that at Time we verified that a
	// piece of content with the given score was parseable as a directory listing
	// that referred to the given scores for its direct children.
	//
	// For file nodes, the record certifies that at Time we verified that a piece
	// of content with the given score was parseable as a piece of a file or
	// symlink. File nodes never have children.
	Node Node

	// Child nodes, present only for directories. See notes on Node above.
	Children []Node
}

// A node in the DAG of blobs in the supplied bucket.
type Node struct {
	Score blob.Score

	// If true, this node represents a directory listing that has zero or more
	// children. Otherwise, this is a file or a symlink.
	Dir bool
}

// Format the node as a standardized name that is guaranteed to be stable
// across invocations of the process.
func (n *Node) String() (s string) {
	if n.Dir {
		s = dirPrefix + n.Score.Hex()
	} else {
		s = filePrefix + n.Score.Hex()
	}

	return
}

// Parse a node name previously generated by Node.String.
func ParseNode(s string) (n Node, err error) {
	var hexScore string

	switch {
	case strings.HasPrefix(s, filePrefix):
		hexScore = strings.TrimPrefix(s, filePrefix)

	case strings.HasPrefix(s, dirPrefix):
		n.Dir = true
		hexScore = strings.TrimPrefix(s, dirPrefix)

	default:
		err = fmt.Errorf("Unknown prefix")
		return
	}

	n.Score, err = blob.ParseHexScore(hexScore)
	if err != nil {
		err = fmt.Errorf("ParseHexScore: %v", err)
		return
	}

	return
}
<commit_msg>Record.String<commit_after>// Copyright 2015 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 verify

import (
	"fmt"
	"strings"
	"time"

	"github.com/jacobsa/comeback/blob"
)

const (
	filePrefix = "f:"
	dirPrefix  = "d:"
)

// A record certifying that a node was verified at a particular time.
type Record struct {
	Time time.Time

	// The node that was verified.
	//
	// For directory nodes, the record certifies that at Time we verified that a
	// piece of content with the given score was parseable as a directory listing
	// that referred to the given scores for its direct children.
	//
	// For file nodes, the record certifies that at Time we verified that a piece
	// of content with the given score was parseable as a piece of a file or
	// symlink. File nodes never have children.
	Node Node

	// Child nodes, present only for directories. See notes on Node above.
	Children []Node
}

// Format the record in a manner that can later be parsed with ParseRecord.
func (r *Record) String() (s string) {
	s = fmt.Sprintf(
		"%s %s",
		r.Time.Format(time.RFC3339),
		r.Node)

	for _, child := range r.Children {
		s += fmt.Sprintf(" %s", child.String())
	}

	return
}

// A node in the DAG of blobs in the supplied bucket.
type Node struct {
	Score blob.Score

	// If true, this node represents a directory listing that has zero or more
	// children. Otherwise, this is a file or a symlink.
	Dir bool
}

// Format the node as a standardized name that is guaranteed to be stable
// across invocations of the process.
func (n *Node) String() (s string) {
	if n.Dir {
		s = dirPrefix + n.Score.Hex()
	} else {
		s = filePrefix + n.Score.Hex()
	}

	return
}

// Parse a node name previously generated by Node.String.
func ParseNode(s string) (n Node, err error) {
	var hexScore string

	switch {
	case strings.HasPrefix(s, filePrefix):
		hexScore = strings.TrimPrefix(s, filePrefix)

	case strings.HasPrefix(s, dirPrefix):
		n.Dir = true
		hexScore = strings.TrimPrefix(s, dirPrefix)

	default:
		err = fmt.Errorf("Unknown prefix")
		return
	}

	n.Score, err = blob.ParseHexScore(hexScore)
	if err != nil {
		err = fmt.Errorf("ParseHexScore: %v", err)
		return
	}

	return
}
<|endoftext|>


<commit_before>//: ----------------------------------------------------------------------------
//: Copyright (C) 2017 Verizon.  All Rights Reserved.
//: All Rights Reserved
//:
//: file:    options.go
//: details: TODO
//: author:  Mehrdad Arshad Rad
//: date:    02/01/2017
//:
//: 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 (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"gopkg.in/yaml.v2"
)

// Options represents options
type Options struct {
	// global options
	Verbose bool   `yaml:"verbose"`
	LogFile string `yaml:"log-file"`
	PIDFile string `yaml:"pid-file"`
	Logger  *log.Logger

	// stats options
	StatsEnabled  bool   `yaml:"stats-enabled"`
	StatsHTTPAddr string `yaml:"stats-http-addr"`
	StatsHTTPPort string `yaml:"stats-http-port"`

	// sFlow options
	SFlowEnabled bool `yaml:"sflow-enabled"`
	SFlowPort    int  `yaml:"sflow-port"`
	SFlowUDPSize int  `yaml:"sflow-udp-size"`
	SFlowWorkers int  `yaml:"sflow-workers"`

	// IPFIX options
	IPFIXEnabled       bool   `yaml:"ipfix-enabled"`
	IPFIXRPCEnabled    bool   `yaml:"ipfix-rpc-enabled"`
	IPFIXPort          int    `yaml:"ipfix-port"`
	IPFIXUDPSize       int    `yaml:"ipfix-udp-size"`
	IPFIXWorkers       int    `yaml:"ipfix-workers"`
	IPFIXMirrorAddr    string `yaml:"ipfix-mirror-addr"`
	IPFIXMirrorPort    int    `yaml:"ipfix-mirror-port"`
	IPFIXMirrorWorkers int    `yaml:"ipfix-mirror-workers"`
	IPFIXTplCacheFile  string `yaml:"ipfix-tpl-cache-file"`

	// producer
	MQName       string `yaml:"mq-name"`
	MQConfigFile string `yaml:"mq-config-file"`
}

// NewOptions constructs new options
func NewOptions() *Options {
	return &Options{
		Verbose: false,
		PIDFile: "/var/run/vflow.pid",
		Logger:  log.New(os.Stderr, "[vflow] ", log.Ldate|log.Ltime),

		StatsEnabled:  true,
		StatsHTTPPort: "8081",
		StatsHTTPAddr: "",

		SFlowEnabled: true,
		SFlowPort:    6343,
		SFlowUDPSize: 1500,
		SFlowWorkers: 200,

		IPFIXEnabled:       true,
		IPFIXRPCEnabled:    true,
		IPFIXPort:          4739,
		IPFIXUDPSize:       1500,
		IPFIXWorkers:       200,
		IPFIXMirrorAddr:    "",
		IPFIXMirrorPort:    4172,
		IPFIXMirrorWorkers: 5,
		IPFIXTplCacheFile:  "/tmp/vflow.templates",

		MQName:       "kafka",
		MQConfigFile: "/usr/local/vflow/etc/kafka.conf",
	}
}

// GetOptions gets options through cmd and file
func GetOptions() *Options {
	opts := NewOptions()

	opts.vFlowFlagSet()

	if opts.LogFile != "" {
		f, err := os.OpenFile(opts.LogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			opts.Logger.Println(err)
		} else {
			opts.Logger.SetOutput(f)
		}
	}

	opts.vFlowPIDWrite()

	return opts
}

func (opts Options) vFlowPIDWrite() {
	f, err := os.OpenFile(opts.PIDFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		opts.Logger.Println(err)
		return
	}

	_, err = fmt.Fprintf(f, "%d", os.Getpid())
	if err != nil {
		opts.Logger.Println(err)
	}
}

func (opts *Options) vFlowFlagSet() {

	var config string

	flag.StringVar(&config, "config", "/usr/local/vflow/etc/vflow.conf", "path to config file")

	vFlowLoadCfg(config, opts)

	// global options
	flag.BoolVar(&opts.Verbose, "verbose", opts.Verbose, "enable verbose logging")
	flag.StringVar(&opts.LogFile, "log-file", opts.LogFile, "log file name")
	flag.StringVar(&opts.PIDFile, "pid-file", opts.PIDFile, "pid file name")

	// stats options
	flag.BoolVar(&opts.StatsEnabled, "stats-enabled", opts.StatsEnabled, "enable stats listener")
	flag.StringVar(&opts.StatsHTTPPort, "stats-http-port", opts.StatsHTTPPort, "stats port listener")
	flag.StringVar(&opts.StatsHTTPAddr, "stats-http-addr", opts.StatsHTTPAddr, "stats bind address listener")

	// sflow options
	flag.BoolVar(&opts.SFlowEnabled, "sflow-enabled", opts.SFlowEnabled, "enable sflow listener")
	flag.IntVar(&opts.SFlowPort, "sflow-port", opts.SFlowPort, "sflow port number")
	flag.IntVar(&opts.SFlowUDPSize, "sflow-max-udp-size", opts.SFlowUDPSize, "sflow maximum UDP size")
	flag.IntVar(&opts.SFlowWorkers, "sflow-workers", opts.SFlowWorkers, "sflow workers number")

	// ipfix options
	flag.BoolVar(&opts.IPFIXEnabled, "ipfix-enabled", opts.IPFIXEnabled, "enable IPFIX listener")
	flag.BoolVar(&opts.IPFIXRPCEnabled, "ipfix-rpc-enabled", opts.IPFIXRPCEnabled, "enable RPC IPFIX")
	flag.IntVar(&opts.IPFIXPort, "ipfix-port", opts.IPFIXPort, "IPFIX port number")
	flag.IntVar(&opts.IPFIXUDPSize, "ipfix-max-udp-size", opts.IPFIXUDPSize, "IPFIX maximum UDP size")
	flag.IntVar(&opts.IPFIXWorkers, "ipfix-workers", opts.IPFIXWorkers, "IPFIX workers number")
	flag.StringVar(&opts.IPFIXTplCacheFile, "ipfix-tpl-cache-file", opts.IPFIXTplCacheFile, "IPFIX template cache file")
	flag.StringVar(&opts.IPFIXMirrorAddr, "ipfix-mirror-addr", opts.IPFIXMirrorAddr, "IPFIX mirror destination address")
	flag.IntVar(&opts.IPFIXMirrorPort, "ipfix-mirror-port", opts.IPFIXMirrorPort, "IPFIX mirror destination port number")
	flag.IntVar(&opts.IPFIXMirrorWorkers, "ipfix-mirror-workers", opts.IPFIXMirrorWorkers, "IPFIX mirror workers number")

	// producer options
	flag.StringVar(&opts.MQName, "mqueue", opts.MQName, "producer message queue name")
	flag.StringVar(&opts.MQConfigFile, "mqueue-conf", opts.MQConfigFile, "producer message queue configuration file")

	flag.Parse()
}

func vFlowLoadCfg(f string, opts *Options) {
	b, err := ioutil.ReadFile(f)
	if err != nil {
		opts.Logger.Println(err)
		return
	}
	err = yaml.Unmarshal(b, opts)
	if err != nil {
		opts.Logger.Println(err)
	}
}
<commit_msg>fix pid file write<commit_after>//: ----------------------------------------------------------------------------
//: Copyright (C) 2017 Verizon.  All Rights Reserved.
//: All Rights Reserved
//:
//: file:    options.go
//: details: TODO
//: author:  Mehrdad Arshad Rad
//: date:    02/01/2017
//:
//: 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 (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"gopkg.in/yaml.v2"
)

// Options represents options
type Options struct {
	// global options
	Verbose bool   `yaml:"verbose"`
	LogFile string `yaml:"log-file"`
	PIDFile string `yaml:"pid-file"`
	Logger  *log.Logger

	// stats options
	StatsEnabled  bool   `yaml:"stats-enabled"`
	StatsHTTPAddr string `yaml:"stats-http-addr"`
	StatsHTTPPort string `yaml:"stats-http-port"`

	// sFlow options
	SFlowEnabled bool `yaml:"sflow-enabled"`
	SFlowPort    int  `yaml:"sflow-port"`
	SFlowUDPSize int  `yaml:"sflow-udp-size"`
	SFlowWorkers int  `yaml:"sflow-workers"`

	// IPFIX options
	IPFIXEnabled       bool   `yaml:"ipfix-enabled"`
	IPFIXRPCEnabled    bool   `yaml:"ipfix-rpc-enabled"`
	IPFIXPort          int    `yaml:"ipfix-port"`
	IPFIXUDPSize       int    `yaml:"ipfix-udp-size"`
	IPFIXWorkers       int    `yaml:"ipfix-workers"`
	IPFIXMirrorAddr    string `yaml:"ipfix-mirror-addr"`
	IPFIXMirrorPort    int    `yaml:"ipfix-mirror-port"`
	IPFIXMirrorWorkers int    `yaml:"ipfix-mirror-workers"`
	IPFIXTplCacheFile  string `yaml:"ipfix-tpl-cache-file"`

	// producer
	MQName       string `yaml:"mq-name"`
	MQConfigFile string `yaml:"mq-config-file"`
}

// NewOptions constructs new options
func NewOptions() *Options {
	return &Options{
		Verbose: false,
		PIDFile: "/var/run/vflow.pid",
		Logger:  log.New(os.Stderr, "[vflow] ", log.Ldate|log.Ltime),

		StatsEnabled:  true,
		StatsHTTPPort: "8081",
		StatsHTTPAddr: "",

		SFlowEnabled: true,
		SFlowPort:    6343,
		SFlowUDPSize: 1500,
		SFlowWorkers: 200,

		IPFIXEnabled:       true,
		IPFIXRPCEnabled:    true,
		IPFIXPort:          4739,
		IPFIXUDPSize:       1500,
		IPFIXWorkers:       200,
		IPFIXMirrorAddr:    "",
		IPFIXMirrorPort:    4172,
		IPFIXMirrorWorkers: 5,
		IPFIXTplCacheFile:  "/tmp/vflow.templates",

		MQName:       "kafka",
		MQConfigFile: "/usr/local/vflow/etc/kafka.conf",
	}
}

// GetOptions gets options through cmd and file
func GetOptions() *Options {
	opts := NewOptions()

	opts.vFlowFlagSet()

	if opts.LogFile != "" {
		f, err := os.OpenFile(opts.LogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			opts.Logger.Println(err)
		} else {
			opts.Logger.SetOutput(f)
		}
	}

	opts.vFlowPIDWrite()

	return opts
}

func (opts Options) vFlowPIDWrite() {
	f, err := os.OpenFile(opts.PIDFile, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		opts.Logger.Println(err)
		return
	}

	_, err = fmt.Fprintf(f, "%d", os.Getpid())
	if err != nil {
		opts.Logger.Println(err)
	}
}

func (opts *Options) vFlowFlagSet() {

	var config string

	flag.StringVar(&config, "config", "/usr/local/vflow/etc/vflow.conf", "path to config file")

	vFlowLoadCfg(config, opts)

	// global options
	flag.BoolVar(&opts.Verbose, "verbose", opts.Verbose, "enable verbose logging")
	flag.StringVar(&opts.LogFile, "log-file", opts.LogFile, "log file name")
	flag.StringVar(&opts.PIDFile, "pid-file", opts.PIDFile, "pid file name")

	// stats options
	flag.BoolVar(&opts.StatsEnabled, "stats-enabled", opts.StatsEnabled, "enable stats listener")
	flag.StringVar(&opts.StatsHTTPPort, "stats-http-port", opts.StatsHTTPPort, "stats port listener")
	flag.StringVar(&opts.StatsHTTPAddr, "stats-http-addr", opts.StatsHTTPAddr, "stats bind address listener")

	// sflow options
	flag.BoolVar(&opts.SFlowEnabled, "sflow-enabled", opts.SFlowEnabled, "enable sflow listener")
	flag.IntVar(&opts.SFlowPort, "sflow-port", opts.SFlowPort, "sflow port number")
	flag.IntVar(&opts.SFlowUDPSize, "sflow-max-udp-size", opts.SFlowUDPSize, "sflow maximum UDP size")
	flag.IntVar(&opts.SFlowWorkers, "sflow-workers", opts.SFlowWorkers, "sflow workers number")

	// ipfix options
	flag.BoolVar(&opts.IPFIXEnabled, "ipfix-enabled", opts.IPFIXEnabled, "enable IPFIX listener")
	flag.BoolVar(&opts.IPFIXRPCEnabled, "ipfix-rpc-enabled", opts.IPFIXRPCEnabled, "enable RPC IPFIX")
	flag.IntVar(&opts.IPFIXPort, "ipfix-port", opts.IPFIXPort, "IPFIX port number")
	flag.IntVar(&opts.IPFIXUDPSize, "ipfix-max-udp-size", opts.IPFIXUDPSize, "IPFIX maximum UDP size")
	flag.IntVar(&opts.IPFIXWorkers, "ipfix-workers", opts.IPFIXWorkers, "IPFIX workers number")
	flag.StringVar(&opts.IPFIXTplCacheFile, "ipfix-tpl-cache-file", opts.IPFIXTplCacheFile, "IPFIX template cache file")
	flag.StringVar(&opts.IPFIXMirrorAddr, "ipfix-mirror-addr", opts.IPFIXMirrorAddr, "IPFIX mirror destination address")
	flag.IntVar(&opts.IPFIXMirrorPort, "ipfix-mirror-port", opts.IPFIXMirrorPort, "IPFIX mirror destination port number")
	flag.IntVar(&opts.IPFIXMirrorWorkers, "ipfix-mirror-workers", opts.IPFIXMirrorWorkers, "IPFIX mirror workers number")

	// producer options
	flag.StringVar(&opts.MQName, "mqueue", opts.MQName, "producer message queue name")
	flag.StringVar(&opts.MQConfigFile, "mqueue-conf", opts.MQConfigFile, "producer message queue configuration file")

	flag.Parse()
}

func vFlowLoadCfg(f string, opts *Options) {
	b, err := ioutil.ReadFile(f)
	if err != nil {
		opts.Logger.Println(err)
		return
	}
	err = yaml.Unmarshal(b, opts)
	if err != nil {
		opts.Logger.Println(err)
	}
}
<|endoftext|>


<commit_before>//: ----------------------------------------------------------------------------
//: Copyright (C) 2017 Verizon.  All Rights Reserved.
//: All Rights Reserved
//:
//: file:    options.go
//: details: TODO
//: author:  Mehrdad Arshad Rad
//: date:    02/01/2017
//:
//: 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 (
	"flag"
	"io/ioutil"
	"log"
	"os"

	"gopkg.in/yaml.v2"
)

// Options represents options
type Options struct {
	// global options
	Verbose bool   `yaml:"verbose"`
	Logfile string `yaml:"log-file"`
	Logger  *log.Logger

	// stats options
	StatsEnabled  bool   `yaml:"stats-enabled"`
	StatsHTTPAddr string `yaml:"stats-http-addr"`
	StatsHTTPPort string `yaml:"stats-http-port"`

	// sFlow options
	SFlowEnabled bool `yaml:"sflow-enabled"`
	SFlowPort    int  `yaml:"sflow-port"`
	SFlowUDPSize int  `yaml:"sflow-udp-size"`
	SFlowWorkers int  `yaml:"sflow-workers"`

	// IPFIX options
	IPFIXEnabled       bool   `yaml:"ipfix-enabled"`
	IPFIXRPCEnabled    bool   `yaml:"ipfix-rpc-enabled"`
	IPFIXPort          int    `yaml:"ipfix-port"`
	IPFIXUDPSize       int    `yaml:"ipfix-udp-size"`
	IPFIXWorkers       int    `yaml:"ipfix-workers"`
	IPFIXMirrorAddr    string `yaml:"ipfix-mirror-addr"`
	IPFIXMirrorPort    int    `yaml:"ipfix-mirror-port"`
	IPFIXMirrorWorkers int    `yaml:"ipfix-mirror-workers"`
	IPFIXTplCacheFile  string `yaml:"ipfix-tpl-cache-file"`

	// producer
	MQName       string `yaml:"mq-name"`
	MQConfigFile string `yaml:"mq-config-file"`
}

// NewOptions constructs new options
func NewOptions() *Options {
	return &Options{
		Verbose: false,
		Logger:  log.New(os.Stderr, "[vflow] ", log.Ldate|log.Ltime),

		StatsEnabled:  true,
		StatsHTTPPort: "8080",
		StatsHTTPAddr: "",

		SFlowEnabled: true,
		SFlowPort:    6343,
		SFlowUDPSize: 1500,
		SFlowWorkers: 10,

		IPFIXEnabled:       true,
		IPFIXRPCEnabled:    true,
		IPFIXPort:          4739,
		IPFIXUDPSize:       1500,
		IPFIXWorkers:       10,
		IPFIXMirrorAddr:    "",
		IPFIXMirrorPort:    4172,
		IPFIXMirrorWorkers: 5,
		IPFIXTplCacheFile:  "/tmp/vflow.templates",

		MQName:       "kafka",
		MQConfigFile: "/usr/local/vflow/etc/kafka.conf",
	}
}

// GetOptions gets options through cmd and file
func GetOptions() *Options {
	opts := NewOptions()
	vFlowFlagSet(opts)

	if opts.Logfile != "" {
		f, err := os.OpenFile(opts.Logfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			opts.Logger.Println(err)
		}

		opts.Logger.SetOutput(f)
	}

	return opts
}

func vFlowFlagSet(opts *Options) {

	var config string

	flag.StringVar(&config, "config", "/usr/local/vflow/etc/vflow.conf", "path to config file")

	vFlowLoadCfg(config, opts)

	// global options
	flag.BoolVar(&opts.Verbose, "verbose", opts.Verbose, "enable verbose logging")
	flag.StringVar(&opts.Logfile, "log-file", opts.Logfile, "log file name")

	// stats options
	flag.BoolVar(&opts.StatsEnabled, "stats-enabled", opts.StatsEnabled, "enable stats listener")
	flag.StringVar(&opts.StatsHTTPPort, "stats-http-port", opts.StatsHTTPPort, "stats port listener")
	flag.StringVar(&opts.StatsHTTPAddr, "stats-http-addr", opts.StatsHTTPAddr, "stats bind address listener")

	// sflow options
	flag.BoolVar(&opts.SFlowEnabled, "sflow-enabled", opts.SFlowEnabled, "enable sflow listener")
	flag.IntVar(&opts.SFlowPort, "sflow-port", opts.SFlowPort, "sflow port number")
	flag.IntVar(&opts.SFlowUDPSize, "sflow-max-udp-size", opts.SFlowUDPSize, "sflow maximum UDP size")
	flag.IntVar(&opts.SFlowWorkers, "sflow-workers", opts.SFlowWorkers, "sflow workers number")

	// ipfix options
	flag.BoolVar(&opts.IPFIXEnabled, "ipfix-enabled", opts.IPFIXEnabled, "enable IPFIX listener")
	flag.BoolVar(&opts.IPFIXRPCEnabled, "ipfix-rpc-enabled", opts.IPFIXRPCEnabled, "enable RPC IPFIX")
	flag.IntVar(&opts.IPFIXPort, "ipfix-port", opts.IPFIXPort, "IPFIX port number")
	flag.IntVar(&opts.IPFIXUDPSize, "ipfix-max-udp-size", opts.IPFIXUDPSize, "IPFIX maximum UDP size")
	flag.IntVar(&opts.IPFIXWorkers, "ipfix-workers", opts.IPFIXWorkers, "IPFIX workers number")
	flag.StringVar(&opts.IPFIXTplCacheFile, "ipfix-tpl-cache-file", opts.IPFIXTplCacheFile, "IPFIX template cache file")
	flag.StringVar(&opts.IPFIXMirrorAddr, "ipfix-mirror-addr", opts.IPFIXMirrorAddr, "IPFIX mirror destination address")
	flag.IntVar(&opts.IPFIXMirrorPort, "ipfix-mirror-port", opts.IPFIXMirrorPort, "IPFIX mirror destination port number")
	flag.IntVar(&opts.IPFIXMirrorWorkers, "ipfix-mirror-workers", opts.IPFIXMirrorWorkers, "IPFIX mirror workers number")

	// producer options
	flag.StringVar(&opts.MQName, "mqueue", opts.MQName, "producer message queue name")
	flag.StringVar(&opts.MQConfigFile, "mqueue-conf", opts.MQConfigFile, "producer message queue configuration file")

	flag.Parse()
}

func vFlowLoadCfg(f string, opts *Options) {
	b, err := ioutil.ReadFile(f)
	if err != nil {
		opts.Logger.Println(err)
		return
	}
	err = yaml.Unmarshal(b, opts)
	if err != nil {
		opts.Logger.Println(err)
	}
}
<commit_msg>fix set output once there is err<commit_after>//: ----------------------------------------------------------------------------
//: Copyright (C) 2017 Verizon.  All Rights Reserved.
//: All Rights Reserved
//:
//: file:    options.go
//: details: TODO
//: author:  Mehrdad Arshad Rad
//: date:    02/01/2017
//:
//: 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 (
	"flag"
	"io/ioutil"
	"log"
	"os"

	"gopkg.in/yaml.v2"
)

// Options represents options
type Options struct {
	// global options
	Verbose bool   `yaml:"verbose"`
	Logfile string `yaml:"log-file"`
	Logger  *log.Logger

	// stats options
	StatsEnabled  bool   `yaml:"stats-enabled"`
	StatsHTTPAddr string `yaml:"stats-http-addr"`
	StatsHTTPPort string `yaml:"stats-http-port"`

	// sFlow options
	SFlowEnabled bool `yaml:"sflow-enabled"`
	SFlowPort    int  `yaml:"sflow-port"`
	SFlowUDPSize int  `yaml:"sflow-udp-size"`
	SFlowWorkers int  `yaml:"sflow-workers"`

	// IPFIX options
	IPFIXEnabled       bool   `yaml:"ipfix-enabled"`
	IPFIXRPCEnabled    bool   `yaml:"ipfix-rpc-enabled"`
	IPFIXPort          int    `yaml:"ipfix-port"`
	IPFIXUDPSize       int    `yaml:"ipfix-udp-size"`
	IPFIXWorkers       int    `yaml:"ipfix-workers"`
	IPFIXMirrorAddr    string `yaml:"ipfix-mirror-addr"`
	IPFIXMirrorPort    int    `yaml:"ipfix-mirror-port"`
	IPFIXMirrorWorkers int    `yaml:"ipfix-mirror-workers"`
	IPFIXTplCacheFile  string `yaml:"ipfix-tpl-cache-file"`

	// producer
	MQName       string `yaml:"mq-name"`
	MQConfigFile string `yaml:"mq-config-file"`
}

// NewOptions constructs new options
func NewOptions() *Options {
	return &Options{
		Verbose: false,
		Logger:  log.New(os.Stderr, "[vflow] ", log.Ldate|log.Ltime),

		StatsEnabled:  true,
		StatsHTTPPort: "8080",
		StatsHTTPAddr: "",

		SFlowEnabled: true,
		SFlowPort:    6343,
		SFlowUDPSize: 1500,
		SFlowWorkers: 10,

		IPFIXEnabled:       true,
		IPFIXRPCEnabled:    true,
		IPFIXPort:          4739,
		IPFIXUDPSize:       1500,
		IPFIXWorkers:       10,
		IPFIXMirrorAddr:    "",
		IPFIXMirrorPort:    4172,
		IPFIXMirrorWorkers: 5,
		IPFIXTplCacheFile:  "/tmp/vflow.templates",

		MQName:       "kafka",
		MQConfigFile: "/usr/local/vflow/etc/kafka.conf",
	}
}

// GetOptions gets options through cmd and file
func GetOptions() *Options {
	opts := NewOptions()
	vFlowFlagSet(opts)

	if opts.Logfile != "" {
		f, err := os.OpenFile(opts.Logfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			opts.Logger.Println(err)
		} else {
			opts.Logger.SetOutput(f)
		}
	}

	return opts
}

func vFlowFlagSet(opts *Options) {

	var config string

	flag.StringVar(&config, "config", "/usr/local/vflow/etc/vflow.conf", "path to config file")

	vFlowLoadCfg(config, opts)

	// global options
	flag.BoolVar(&opts.Verbose, "verbose", opts.Verbose, "enable verbose logging")
	flag.StringVar(&opts.Logfile, "log-file", opts.Logfile, "log file name")

	// stats options
	flag.BoolVar(&opts.StatsEnabled, "stats-enabled", opts.StatsEnabled, "enable stats listener")
	flag.StringVar(&opts.StatsHTTPPort, "stats-http-port", opts.StatsHTTPPort, "stats port listener")
	flag.StringVar(&opts.StatsHTTPAddr, "stats-http-addr", opts.StatsHTTPAddr, "stats bind address listener")

	// sflow options
	flag.BoolVar(&opts.SFlowEnabled, "sflow-enabled", opts.SFlowEnabled, "enable sflow listener")
	flag.IntVar(&opts.SFlowPort, "sflow-port", opts.SFlowPort, "sflow port number")
	flag.IntVar(&opts.SFlowUDPSize, "sflow-max-udp-size", opts.SFlowUDPSize, "sflow maximum UDP size")
	flag.IntVar(&opts.SFlowWorkers, "sflow-workers", opts.SFlowWorkers, "sflow workers number")

	// ipfix options
	flag.BoolVar(&opts.IPFIXEnabled, "ipfix-enabled", opts.IPFIXEnabled, "enable IPFIX listener")
	flag.BoolVar(&opts.IPFIXRPCEnabled, "ipfix-rpc-enabled", opts.IPFIXRPCEnabled, "enable RPC IPFIX")
	flag.IntVar(&opts.IPFIXPort, "ipfix-port", opts.IPFIXPort, "IPFIX port number")
	flag.IntVar(&opts.IPFIXUDPSize, "ipfix-max-udp-size", opts.IPFIXUDPSize, "IPFIX maximum UDP size")
	flag.IntVar(&opts.IPFIXWorkers, "ipfix-workers", opts.IPFIXWorkers, "IPFIX workers number")
	flag.StringVar(&opts.IPFIXTplCacheFile, "ipfix-tpl-cache-file", opts.IPFIXTplCacheFile, "IPFIX template cache file")
	flag.StringVar(&opts.IPFIXMirrorAddr, "ipfix-mirror-addr", opts.IPFIXMirrorAddr, "IPFIX mirror destination address")
	flag.IntVar(&opts.IPFIXMirrorPort, "ipfix-mirror-port", opts.IPFIXMirrorPort, "IPFIX mirror destination port number")
	flag.IntVar(&opts.IPFIXMirrorWorkers, "ipfix-mirror-workers", opts.IPFIXMirrorWorkers, "IPFIX mirror workers number")

	// producer options
	flag.StringVar(&opts.MQName, "mqueue", opts.MQName, "producer message queue name")
	flag.StringVar(&opts.MQConfigFile, "mqueue-conf", opts.MQConfigFile, "producer message queue configuration file")

	flag.Parse()
}

func vFlowLoadCfg(f string, opts *Options) {
	b, err := ioutil.ReadFile(f)
	if err != nil {
		opts.Logger.Println(err)
		return
	}
	err = yaml.Unmarshal(b, opts)
	if err != nil {
		opts.Logger.Println(err)
	}
}
<|endoftext|>


<commit_before>package main

import(
	"fmt"
	aspell "github.com/hugbotme/go-aspell"
	s "strings"
	"bytes"
	"regexp"
	"io/ioutil"
)

type spellCheckFileProcessor struct {
	spellChecker aspell.Speller
	stopWords []string
	probableWords []string
}

func newSpellCheckFileProcessor(stopWordsFile string, probableWordsFile string) (spellCheckFileProcessor, error) {
	// Initialize the speller
	speller, err := aspell.NewSpeller(map[string]string{
		"lang": "en_US",
		//"personal": stopWordsFile,
	})
	// jvt: be sure to clean up, C lib being used here....
	defer speller.Delete()

	// jvt: read stop words file to array
	// jvt: @todo error handling?
	stopWordsContent, _ := ioutil.ReadFile(stopWordsFile)

	// jvt: read probable words words file to array
	// jvt: @todo error handling?
	probableWordsContent, _ := ioutil.ReadFile(probableWordsFile)

	return spellCheckFileProcessor{
		spellChecker: speller,
		stopWords: s.Split(string(stopWordsContent), "\n"),
		probableWords: s.Split(string(probableWordsContent), "\n"),
	}, err
}

/**
 * run a spell check on passed content
 * passes back original content if an error occurs
 */
func (spfp spellCheckFileProcessor) processContent (content []byte) string {
	var buffer bytes.Buffer
	var wordBuffer bytes.Buffer
	syntaxNestingLevel := 0
	contentLength := len(content)

	// jvt: start looping content bytes
	for index, b := range content {
		//fmt.Println(string(b))
		if spfp.isMarkdownSyntaxOpeningChar(b) {
			//fmt.Println("entering nesting level")
			syntaxNestingLevel ++
		} else if spfp.isMarkdownSyntaxClosingChar(b) {
			//fmt.Println("leaving nesting level")
			syntaxNestingLevel --

			// jvt: write byte to buffer
			buffer.WriteByte(b)

			// jvt: and continue to next byte
			continue
		}

		// jvt: @todo values under 0 most likely mean invalid markdown, ignoring for now
		if (syntaxNestingLevel > 0) {
			//fmt.Println("in nesting level")
			// jvt: we're ignoring content, just copy
			buffer.WriteByte(b)
		} else {
			var isWordEndingChar bool
			if index > 0 && index < contentLength {
				isWordEndingChar = spfp.isWordEndingChar(b, content[index - 1], content[index + 1])
			} else {
				isWordEndingChar = spfp.isWordEndingChar(b)
			}

			// jvt: check for end of word
			if wordBuffer.Len() > 0 && isWordEndingChar {
				//fmt.Println("found word " + wordBuffer.String())
				// jvt: process word & write back to buffer
				buffer.WriteString(spfp.processWord(wordBuffer.String()))

				// jvt: reset word buffer
				wordBuffer.Reset()
			} else if !isWordEndingChar {
				//fmt.Println("in word")
				// jvt: we're in a word, copy current byte to word buffer
				wordBuffer.WriteByte(b)
			}

			if (isWordEndingChar) {
				//fmt.Println("word-ending char")
				// jvt: write word-ending byte to buffer
				buffer.WriteByte(b)
			}
		}
	}

	// jvt: and pass back finished string
	return buffer.String()
}

func (spfp spellCheckFileProcessor) isMarkdownSyntaxOpeningChar (b byte) bool {
	char := string(b)
	return char == "[" || char == "(" || char == "`"
}

func (spfp spellCheckFileProcessor) isMarkdownSyntaxClosingChar (b byte) bool {
	char := string(b)
	return char == "]" || char == ")" || char == "´"
}

func (spfp spellCheckFileProcessor) isWordEndingChar (chars ...byte) bool {
	// jvt: @todo huh? byte -> string -> byte array type case is fine, but byte to byte array type cast not? missing something stupid here....
	// jvt: we always get the first param
	char := string(chars[0])

	var matched bool
	if len(chars) > 1 && spfp.isLookForwardAndBackChar(char) {
		//fmt.Println("checking for contraction " + char + string(chars[1]) + string(chars[2]))
		// jvt: try to detect contraction
		matched = spfp.matchLetter(string(chars[1])) && spfp.matchLetter(string(chars[2]))
	} else {
		matched = spfp.matchLetter(char)
	}

	return !matched
}

func (spfp spellCheckFileProcessor) matchLetter (char string) bool {
	matched, _ := regexp.Match("[A-Za-z]", []byte(char))
	return matched
}

func (spfp spellCheckFileProcessor) isLookForwardAndBackChar (char string) bool {
	return char == "'" || char == "-"
}

func (spfp spellCheckFileProcessor) processWord (word string) string {
	// jvt: check for stop word
	if spfp.checkForStopword(word) {
		return word
	}

	spellingCorrect, suggestions := spfp.checkSpelling(word)
	if (spellingCorrect) {
		return word
	} else {
		//fmt.Printf("Incorrect word, suggestions: %s\n", s.Join(suggestions, ", "))

		// jvt: @todo jup....
		if len(suggestions) > 0 {
			//fmt.Printf("suggestions: %s\n", s.Join(suggestions, ", "))
			preferredWord := spfp.checkForPreferred(word, suggestions)
			fmt.Println("Replacing \"" + word + "\" with \"" + preferredWord + "\"")
			return preferredWord
		}

		return word
	}
}

func (spfp spellCheckFileProcessor) checkForStopword (word string) bool {
	for _, stopword := range spfp.stopWords {
		if (word == stopword) {
			return true
		}
	}

	return false
}

func (spfp spellCheckFileProcessor) checkForPreferred (word string, suggestions []string) string {
	for _, suggestion := range suggestions {
		for _, preferred := range spfp.probableWords {
			if suggestion == preferred {
				fmt.Println("found preferred word")
				return preferred
			}
		}
	}

	// jvt: if we didn't find anything preferred, just return first suggestion
	return suggestions[0]
}

func (spfp spellCheckFileProcessor) checkSpelling (word string) (bool, []string) {
	if spfp.spellChecker.Check(word) {
		//fmt.Print("OK\n")
		return true, nil
	}

	suggestions := spfp.spellChecker.Suggest(word)
	//fmt.Printf("Spelling mistake:\"" + word + "\" suggestions: %s\n", s.Join(suggestions, ", "))
	return false, suggestions
}
<commit_msg>remove unused word param<commit_after>package main

import(
	"fmt"
	aspell "github.com/hugbotme/go-aspell"
	s "strings"
	"bytes"
	"regexp"
	"io/ioutil"
)

type spellCheckFileProcessor struct {
	spellChecker aspell.Speller
	stopWords []string
	probableWords []string
}

func newSpellCheckFileProcessor(stopWordsFile string, probableWordsFile string) (spellCheckFileProcessor, error) {
	// Initialize the speller
	speller, err := aspell.NewSpeller(map[string]string{
		"lang": "en_US",
		//"personal": stopWordsFile,
	})
	// jvt: be sure to clean up, C lib being used here....
	defer speller.Delete()

	// jvt: read stop words file to array
	// jvt: @todo error handling?
	stopWordsContent, _ := ioutil.ReadFile(stopWordsFile)

	// jvt: read probable words words file to array
	// jvt: @todo error handling?
	probableWordsContent, _ := ioutil.ReadFile(probableWordsFile)

	return spellCheckFileProcessor{
		spellChecker: speller,
		stopWords: s.Split(string(stopWordsContent), "\n"),
		probableWords: s.Split(string(probableWordsContent), "\n"),
	}, err
}

/**
 * run a spell check on passed content
 * passes back original content if an error occurs
 */
func (spfp spellCheckFileProcessor) processContent (content []byte) string {
	var buffer bytes.Buffer
	var wordBuffer bytes.Buffer
	syntaxNestingLevel := 0
	contentLength := len(content)

	// jvt: start looping content bytes
	for index, b := range content {
		//fmt.Println(string(b))
		if spfp.isMarkdownSyntaxOpeningChar(b) {
			//fmt.Println("entering nesting level")
			syntaxNestingLevel ++
		} else if spfp.isMarkdownSyntaxClosingChar(b) {
			//fmt.Println("leaving nesting level")
			syntaxNestingLevel --

			// jvt: write byte to buffer
			buffer.WriteByte(b)

			// jvt: and continue to next byte
			continue
		}

		// jvt: @todo values under 0 most likely mean invalid markdown, ignoring for now
		if (syntaxNestingLevel > 0) {
			//fmt.Println("in nesting level")
			// jvt: we're ignoring content, just copy
			buffer.WriteByte(b)
		} else {
			var isWordEndingChar bool
			if index > 0 && index < contentLength {
				isWordEndingChar = spfp.isWordEndingChar(b, content[index - 1], content[index + 1])
			} else {
				isWordEndingChar = spfp.isWordEndingChar(b)
			}

			// jvt: check for end of word
			if wordBuffer.Len() > 0 && isWordEndingChar {
				//fmt.Println("found word " + wordBuffer.String())
				// jvt: process word & write back to buffer
				buffer.WriteString(spfp.processWord(wordBuffer.String()))

				// jvt: reset word buffer
				wordBuffer.Reset()
			} else if !isWordEndingChar {
				//fmt.Println("in word")
				// jvt: we're in a word, copy current byte to word buffer
				wordBuffer.WriteByte(b)
			}

			if (isWordEndingChar) {
				//fmt.Println("word-ending char")
				// jvt: write word-ending byte to buffer
				buffer.WriteByte(b)
			}
		}
	}

	// jvt: and pass back finished string
	return buffer.String()
}

func (spfp spellCheckFileProcessor) isMarkdownSyntaxOpeningChar (b byte) bool {
	char := string(b)
	return char == "[" || char == "(" || char == "`"
}

func (spfp spellCheckFileProcessor) isMarkdownSyntaxClosingChar (b byte) bool {
	char := string(b)
	return char == "]" || char == ")" || char == "´"
}

func (spfp spellCheckFileProcessor) isWordEndingChar (chars ...byte) bool {
	// jvt: @todo huh? byte -> string -> byte array type case is fine, but byte to byte array type cast not? missing something stupid here....
	// jvt: we always get the first param
	char := string(chars[0])

	var matched bool
	if len(chars) > 1 && spfp.isLookForwardAndBackChar(char) {
		//fmt.Println("checking for contraction " + char + string(chars[1]) + string(chars[2]))
		// jvt: try to detect contraction
		matched = spfp.matchLetter(string(chars[1])) && spfp.matchLetter(string(chars[2]))
	} else {
		matched = spfp.matchLetter(char)
	}

	return !matched
}

func (spfp spellCheckFileProcessor) matchLetter (char string) bool {
	matched, _ := regexp.Match("[A-Za-z]", []byte(char))
	return matched
}

func (spfp spellCheckFileProcessor) isLookForwardAndBackChar (char string) bool {
	return char == "'" || char == "-"
}

func (spfp spellCheckFileProcessor) processWord (word string) string {
	// jvt: check for stop word
	if spfp.checkForStopword(word) {
		return word
	}

	spellingCorrect, suggestions := spfp.checkSpelling(word)
	if (spellingCorrect) {
		return word
	} else {
		//fmt.Printf("Incorrect word, suggestions: %s\n", s.Join(suggestions, ", "))

		// jvt: @todo jup....
		if len(suggestions) > 0 {
			//fmt.Printf("suggestions: %s\n", s.Join(suggestions, ", "))
			preferredWord := spfp.checkForPreferred(suggestions)
			fmt.Println("Replacing \"" + word + "\" with \"" + preferredWord + "\"")
			return preferredWord
		}

		return word
	}
}

func (spfp spellCheckFileProcessor) checkForStopword (word string) bool {
	for _, stopword := range spfp.stopWords {
		if (word == stopword) {
			return true
		}
	}

	return false
}

func (spfp spellCheckFileProcessor) checkForPreferred (suggestions []string) string {
	for _, suggestion := range suggestions {
		for _, preferred := range spfp.probableWords {
			if suggestion == preferred {
				fmt.Println("found preferred word: " + preferred)
				return preferred
			}
		}
	}

	// jvt: if we didn't find anything preferred, just return first suggestion
	return suggestions[0]
}

func (spfp spellCheckFileProcessor) checkSpelling (word string) (bool, []string) {
	if spfp.spellChecker.Check(word) {
		//fmt.Print("OK\n")
		return true, nil
	}

	suggestions := spfp.spellChecker.Suggest(word)
	//fmt.Printf("Spelling mistake:\"" + word + "\" suggestions: %s\n", s.Join(suggestions, ", "))
	return false, suggestions
}
<|endoftext|>


<commit_before>package validate

import (
	"fmt"
	"reflect"
	"strings"

	"github.com/dictyBase/apihelpers/aphcollection"
	jsapi "github.com/dictyBase/apihelpers/aphjsonapi"
	"github.com/manyminds/api2go/jsonapi"
)

//HasRelationships matches if the relationships rels are implemented in the
//given JSONAPI implementing data
func HasRelationships(data interface{}, rels []string) error {
	matchedRel := true
	matchedSelf := true
	self, ok := data.(jsapi.MarshalSelfRelations)
	if ok {
		for _, rel := range self.GetSelfLinksInfo() {
			if aphcollection.Contains(rels, rel.Name) {
				matchedSelf = true
				break
			}
		}
	}
	related, ok := data.(jsapi.MarshalRelatedRelations)
	if ok {
		for _, rel := range related.GetRelatedLinksInfo() {
			if !aphcollection.Contains(rels, rel.Name) {
				matchedRel = true
			}
		}
	}
	if !matchedRel && !matchedSelf {
		return fmt.Errorf("given names %s does not matches to any relationship", strings.Join(rels, ","))
	}
	return nil
}

func getTypeName(data interface{}) string {
	entity, ok := data.(jsonapi.EntityNamer)
	if ok {
		return entity.GetName()
	}
	rType := reflect.TypeOf(data)
	if rType.Kind() == reflect.Ptr {
		return jsonapi.Pluralize(jsonapi.Jsonify(rType.Elem().Name()))
	}
	return jsonapi.Pluralize(jsonapi.Jsonify(rType.Name()))
}
<commit_msg>added methods for validating type value of JSONAPI resources<commit_after>package validate

import (
	"fmt"
	"reflect"
	"strings"

	"github.com/dictyBase/apihelpers/aphcollection"
	jsapi "github.com/dictyBase/apihelpers/aphjsonapi"
	"github.com/manyminds/api2go/jsonapi"
)

//HasRelationships matches if the relationships rels are implemented in the
//given JSONAPI implementing data
func HasRelationships(data interface{}, rels []string) error {
	matchedRel := true
	matchedSelf := true
	self, ok := data.(jsapi.MarshalSelfRelations)
	if ok {
		for _, rel := range self.GetSelfLinksInfo() {
			if aphcollection.Contains(rels, rel.Name) {
				matchedSelf = true
				break
			}
		}
	}
	related, ok := data.(jsapi.MarshalRelatedRelations)
	if ok {
		for _, rel := range related.GetRelatedLinksInfo() {
			if !aphcollection.Contains(rels, rel.Name) {
				matchedRel = true
			}
		}
	}
	if !matchedRel && !matchedSelf {
		return fmt.Errorf("given names %s does not matches to any relationship", strings.Join(rels, ","))
	}
	return nil
}

func ResourceType(name string, data interface{}) bool {
	if name == getTypeName(data) {
		return true
	}
	return false
}

func RelatedResourceType(name string, data interface{}) bool {
	if aphcollection.Contains(GetRelatedTypeNames(data), name) {
		return true
	}
	return false
}

//GetRelatedTypeNames returns the JSONAPI types of the related resources
func GetRelatedTypeNames(data interface{}) []string {
	var names []string
	mtype := reflect.TypeOf((*jsonapi.MarshalIdentifier)(nil)).Elem()
	t := reflect.Indirect(reflect.ValueOf(data)).Type()
	for i := 0; i < t.NumField(); i++ {
		ftype := t.Field(i).Type
		if ftype.Kind() == reflect.Slice {
			if ftype.Elem().Implements(mtype) {
				names = append(
					names,
					jsonapi.Pluralize(
						jsonapi.Jsonify(
							ftype.Elem().Name(),
						),
					),
				)
				continue
			}
		}
		if ftype.Implements(mtype) {
			names = append(
				names,
				jsonapi.Pluralize(
					jsonapi.Jsonify(
						ftype.Name(),
					),
				),
			)
		}
	}
	return names
}

func getTypeName(data interface{}) string {
	entity, ok := data.(jsonapi.EntityNamer)
	if ok {
		return entity.GetName()
	}
	rType := reflect.TypeOf(data)
	if rType.Kind() == reflect.Ptr {
		return jsonapi.Pluralize(jsonapi.Jsonify(rType.Elem().Name()))
	}
	return jsonapi.Pluralize(jsonapi.Jsonify(rType.Name()))
}
<|endoftext|>