<commit_before>package kiwi

//TODO: switch from
//github.com/Andoryuuta/w32 to github.com/VividCortex/w32 if pull request is accepted.
import (
	"errors"
	"fmt"
	"github.com/Andoryuuta/w32"
	"path/filepath"
	"reflect"
	"unsafe"
)

type Process struct {
	Handle w32.HANDLE
	PID    uint32
}

const (
	PROCESS_ALL_ACCESS = w32.PROCESS_VM_READ | w32.PROCESS_VM_WRITE | w32.PROCESS_VM_OPERATION | w32.PROCESS_QUERY_INFORMATION
)

//getFileNameByPID returns a file name given a PID.
func getFileNameByPID(pid uint32) string {
	var fileName string = `<Unknown File>`

	//Open process
	hnd, ok := w32.OpenProcess(w32.PROCESS_QUERY_INFORMATION, false, pid)
	if !ok {
		return fileName
	}
	defer w32.CloseHandle(hnd)

	//Get file path
	path, ok := w32.GetProcessImageFileName(hnd)
	if !ok {
		return fileName
	}

	//Split file path to get file name
	_, fileName = filepath.Split(path)
	return fileName
}

func GetProcessByFileName(fileName string) (Process, error) {
	//Read in process ids
	PIDs := make([]uint32, 1024)
	var bytesRead uint32 = 0
	ok := w32.EnumProcesses(PIDs, uint32(len(PIDs)), &bytesRead)
	if !ok {
		panic("Error Enumerating processes.")
	}

	//Loop over pids,
	//Divide bytesRead by sizeof(uint32) to get how many processes there are.
	for i := uint32(0); i < (bytesRead / 4); i++ {
		//Make sure to skip over the system process with PID 0
		if PIDs[i] == 0 {
			continue
		}

		//Check if its the process
		if getFileNameByPID(PIDs[i]) == fileName {
			hnd, ok := w32.OpenProcess(PROCESS_ALL_ACCESS, false, PIDs[i])
			if !ok {
				return Process{}, errors.New(fmt.Sprintf("Error while opening process %d", PIDs[i]))
			}
			return Process{hnd, PIDs[i]}, nil
		}
	}

	//Couldn't find process, return an error
	return Process{}, errors.New("Couldn't find process with name " + fileName)
}

func (p *Process) ReadInt8(addr uintptr) (v int8, e error)       { e = p.read(addr, &v); return v, e }
func (p *Process) ReadInt16(addr uintptr) (v int16, e error)     { e = p.read(addr, &v); return v, e }
func (p *Process) ReadInt32(addr uintptr) (v int32, e error)     { e = p.read(addr, &v); return v, e }
func (p *Process) ReadInt64(addr uintptr) (v int64, e error)     { e = p.read(addr, &v); return v, e }
func (p *Process) ReadUint8(addr uintptr) (v uint8, e error)     { e = p.read(addr, &v); return v, e }
func (p *Process) ReadUint16(addr uintptr) (v uint16, e error)   { e = p.read(addr, &v); return v, e }
func (p *Process) ReadUint32(addr uintptr) (v uint32, e error)   { e = p.read(addr, &v); return v, e }
func (p *Process) ReadUint64(addr uintptr) (v uint64, e error)   { e = p.read(addr, &v); return v, e }
func (p *Process) ReadFloat32(addr uintptr) (v float32, e error) { e = p.read(addr, &v); return v, e }
func (p *Process) ReadFloat64(addr uintptr) (v float64, e error) { e = p.read(addr, &v); return v, e }
func (p *Process) ReadUintptr(addr uintptr) (v uintptr, e error) { e = p.read(addr, &v); return v, e }

func (p *Process) read(addr uintptr, ptr interface{}) error {
	v := reflect.ValueOf(ptr)
	i := reflect.Indirect(v)
	size := i.Type().Size()
	bytesRead, ok := w32.ReadProcessMemory(
		p.Handle,
		unsafe.Pointer(addr),
		unsafe.Pointer(i.UnsafeAddr()),
		size,
	)
	if !ok || bytesRead != size {
		return errors.New("Error on reading process memory.")
	}
	return nil
}

func (p *Process) WriteInt8(addr uintptr, v int8) (e error)       { return p.write(addr, &v) }
func (p *Process) WriteInt16(addr uintptr, v int16) (e error)     { return p.write(addr, &v) }
func (p *Process) WriteInt32(addr uintptr, v int32) (e error)     { return p.write(addr, &v) }
func (p *Process) WriteInt64(addr uintptr, v int64) (e error)     { return p.write(addr, &v) }
func (p *Process) WriteUint8(addr uintptr, v uint8) (e error)     { return p.write(addr, &v) }
func (p *Process) WriteUint16(addr uintptr, v uint16) (e error)   { return p.write(addr, &v) }
func (p *Process) WriteUint32(addr uintptr, v uint32) (e error)   { return p.write(addr, &v) }
func (p *Process) WriteUint64(addr uintptr, v uint64) (e error)   { return p.write(addr, &v) }
func (p *Process) WriteFloat32(addr uintptr, v float32) (e error) { return p.write(addr, &v) }
func (p *Process) WriteFloat64(addr uintptr, v float64) (e error) { return p.write(addr, &v) }
func (p *Process) WriteUintptr(addr uintptr, v uintptr) (e error) { return p.write(addr, &v) }

func (p *Process) write(addr uintptr, ptr interface{}) error {
	v := reflect.ValueOf(ptr)
	i := reflect.Indirect(v)
	size := i.Type().Size()
	bytesWritten, ok := w32.WriteProcessMemory(
		p.Handle,
		unsafe.Pointer(addr),
		unsafe.Pointer(i.UnsafeAddr()),
		size,
	)
	if !ok || bytesWritten != size {
		return errors.New("Error on writing process memory.")
	}
	return nil
}
<commit_msg>Added variadic func ReadUint32Ptr<commit_after>package kiwi

//TODO: switch from
//github.com/Andoryuuta/w32 to github.com/VividCortex/w32 if pull request is accepted.
import (
	"errors"
	"fmt"
	"github.com/Andoryuuta/w32"
	"path/filepath"
	"reflect"
	"unsafe"
)

type Process struct {
	Handle w32.HANDLE
	PID    uint32
}

const (
	PROCESS_ALL_ACCESS = w32.PROCESS_VM_READ | w32.PROCESS_VM_WRITE | w32.PROCESS_VM_OPERATION | w32.PROCESS_QUERY_INFORMATION | w32.PROCESS_CREATE_THREAD
)

//getFileNameByPID returns a file name given a PID.
func getFileNameByPID(pid uint32) string {
	var fileName string = `<Unknown File>`

	//Open process
	hnd, ok := w32.OpenProcess(w32.PROCESS_QUERY_INFORMATION, false, pid)
	if !ok {
		return fileName
	}
	defer w32.CloseHandle(hnd)

	//Get file path
	path, ok := w32.GetProcessImageFileName(hnd)
	if !ok {
		return fileName
	}

	//Split file path to get file name
	_, fileName = filepath.Split(path)
	return fileName
}

func GetProcessByFileName(fileName string) (Process, error) {
	//Read in process ids
	PIDs := make([]uint32, 1024)
	var bytesRead uint32 = 0
	ok := w32.EnumProcesses(PIDs, uint32(len(PIDs)), &bytesRead)
	if !ok {
		panic("Error Enumerating processes.")
	}

	//Loop over pids,
	//Divide bytesRead by sizeof(uint32) to get how many processes there are.
	for i := uint32(0); i < (bytesRead / 4); i++ {
		//Make sure to skip over the system process with PID 0
		if PIDs[i] == 0 {
			continue
		}

		//Check if its the process
		if getFileNameByPID(PIDs[i]) == fileName {
			hnd, ok := w32.OpenProcess(PROCESS_ALL_ACCESS, false, PIDs[i])
			if !ok {
				return Process{}, errors.New(fmt.Sprintf("Error while opening process %d", PIDs[i]))
			}
			return Process{hnd, PIDs[i]}, nil
		}
	}

	//Couldn't find process, return an error
	return Process{}, errors.New("Couldn't find process with name " + fileName)
}

func (p *Process) ReadInt8(addr uintptr) (v int8, e error)       { e = p.read(addr, &v); return v, e }
func (p *Process) ReadInt16(addr uintptr) (v int16, e error)     { e = p.read(addr, &v); return v, e }
func (p *Process) ReadInt32(addr uintptr) (v int32, e error)     { e = p.read(addr, &v); return v, e }
func (p *Process) ReadInt64(addr uintptr) (v int64, e error)     { e = p.read(addr, &v); return v, e }
func (p *Process) ReadUint8(addr uintptr) (v uint8, e error)     { e = p.read(addr, &v); return v, e }
func (p *Process) ReadUint16(addr uintptr) (v uint16, e error)   { e = p.read(addr, &v); return v, e }
func (p *Process) ReadUint32(addr uintptr) (v uint32, e error)   { e = p.read(addr, &v); return v, e }
func (p *Process) ReadUint64(addr uintptr) (v uint64, e error)   { e = p.read(addr, &v); return v, e }
func (p *Process) ReadFloat32(addr uintptr) (v float32, e error) { e = p.read(addr, &v); return v, e }
func (p *Process) ReadFloat64(addr uintptr) (v float64, e error) { e = p.read(addr, &v); return v, e }
func (p *Process) ReadUintptr(addr uintptr) (v uintptr, e error) { e = p.read(addr, &v); return v, e }

func (p *Process) read(addr uintptr, ptr interface{}) error {
	v := reflect.ValueOf(ptr)
	i := reflect.Indirect(v)
	size := i.Type().Size()
	bytesRead, ok := w32.ReadProcessMemory(
		p.Handle,
		unsafe.Pointer(addr),
		unsafe.Pointer(i.UnsafeAddr()),
		size,
	)
	if !ok || bytesRead != size {
		return errors.New("Error on reading process memory.")
	}
	return nil
}

func (p *Process) ReadUint32Ptr(addr uintptr, offsets ...uintptr) (uint32, error) {
	curPtr, err := p.ReadUint32(addr)
	if err != nil{
        return 0, errors.New("Error while trying to read from ptr base.")
    }

	for _, offset := range offsets{
		fmt.Printf("Adding offset % X\n", offset)
		curPtr, err = p.ReadUint32(uintptr(curPtr)+offset)
		if err != nil{
			return 0, errors.New("Error while trying to read from offset.")
		}
	}

	return curPtr, nil
}

func (p *Process) WriteInt8(addr uintptr, v int8) (e error)       { return p.write(addr, &v) }
func (p *Process) WriteInt16(addr uintptr, v int16) (e error)     { return p.write(addr, &v) }
func (p *Process) WriteInt32(addr uintptr, v int32) (e error)     { return p.write(addr, &v) }
func (p *Process) WriteInt64(addr uintptr, v int64) (e error)     { return p.write(addr, &v) }
func (p *Process) WriteUint8(addr uintptr, v uint8) (e error)     { return p.write(addr, &v) }
func (p *Process) WriteUint16(addr uintptr, v uint16) (e error)   { return p.write(addr, &v) }
func (p *Process) WriteUint32(addr uintptr, v uint32) (e error)   { return p.write(addr, &v) }
func (p *Process) WriteUint64(addr uintptr, v uint64) (e error)   { return p.write(addr, &v) }
func (p *Process) WriteFloat32(addr uintptr, v float32) (e error) { return p.write(addr, &v) }
func (p *Process) WriteFloat64(addr uintptr, v float64) (e error) { return p.write(addr, &v) }
func (p *Process) WriteUintptr(addr uintptr, v uintptr) (e error) { return p.write(addr, &v) }

func (p *Process) write(addr uintptr, ptr interface{}) error {
	v := reflect.ValueOf(ptr)
	i := reflect.Indirect(v)
	size := i.Type().Size()
	bytesWritten, ok := w32.WriteProcessMemory(
		p.Handle,
		unsafe.Pointer(addr),
		unsafe.Pointer(i.UnsafeAddr()),
		size,
	)
	if !ok || bytesWritten != size {
		return errors.New("Error on writing process memory.")
	}
	return nil
}
<|endoftext|>


<commit_before>package aceproject

import (
	"net/http"
	"strconv"

	sling "gopkg.in/dghubble/sling.v1"
)

// GetProjectsParam represents getprojects request parameter
type GetProjectsParam struct {
	FilterCompletedProject bool   `url:"Filtercompletedproject,omitempty"`
	ProjectID              string `url:"Projectid,omitempty"`
}

// ProjectResponse represents porject listing response
type ProjectResponse struct {
	Status  string    `json:"status"`
	Results []Project `json:"results"`
}

// Project is representing project in ACEProject
type Project struct {
	ID                int64   `json:"PROJECT_ID"`
	Name              string  `json:"PROJECT_NAME"`
	ProjectNumber     string  `json:"PROJECT_NUMBER"`
	TypeID            int64   `json:"PROJECT_TYPE"`
	Type              string  `json:"PROJECT_TYPE_NAME"`
	ProjectStatusName string  `json:"PROJECT_STATUS_NAME"`
	ErrorDesc         *string `json:"ERRORDESCRIPTION,omitempty"`
}

// ProjectService provides methods to interact with project specific action
type ProjectService struct {
	sling *sling.Sling
}

// NewProjectService return a new ProjectService
func NewProjectService(httpClient *http.Client, guidInfo *GUIDInfo) *ProjectService {
	return &ProjectService{
		sling: sling.New().Client(httpClient).Base(baseURL).QueryStruct(guidInfo),
	}
}

// List returns the project list
func (s *ProjectService) List() ([]Project, *http.Response, error) {
	projRes := new(ProjectResponse)
	resp, err := s.sling.New().
		QueryStruct(CreateFunctionParam("getprojects")).
		ReceiveSuccess(projRes)
	if projRes != nil && len(projRes.Results) > 0 {
		if projRes.Results[0].ErrorDesc != nil {
			return nil, resp, Error{*projRes.Results[0].ErrorDesc}
		}
		return *(&projRes.Results), resp, err
	}
	return make([]Project, 0), resp, err
}

// ListWithCompleteness returns the list of complete / incomplete projects
func (s *ProjectService) ListWithCompleteness(complete bool) ([]Project, *http.Response, error) {
	projRes := new(ProjectResponse)
	resp, err := s.sling.New().
		QueryStruct(CreateFunctionParam("getprojects")).
		QueryStruct(&GetProjectsParam{FilterCompletedProject: complete}).
		ReceiveSuccess(projRes)
	if projRes != nil && len(projRes.Results) > 0 {
		if projRes.Results[0].ErrorDesc != nil {
			return nil, resp, Error{*projRes.Results[0].ErrorDesc}
		}
		return *(&projRes.Results), resp, err
	}
	return make([]Project, 0), resp, err
}

// Get returns the project of given ID
func (s *ProjectService) Get(projectID int64) (*Project, *http.Response, error) {
	//
	projRes := new(ProjectResponse)
	resp, err := s.sling.New().
		QueryStruct(CreateFunctionParam("getprojects")).
		QueryStruct(&GetProjectsParam{ProjectID: strconv.FormatInt(projectID, 10)}).
		ReceiveSuccess(projRes)
	if projRes != nil && len(projRes.Results) > 0 {
		if projRes.Results[0].ErrorDesc != nil {
			return nil, resp, Error{*projRes.Results[0].ErrorDesc}
		}
		return &projRes.Results[0], resp, err
	}
	return nil, resp, err
}
<commit_msg>add more fields to project<commit_after>package aceproject

import (
	"net/http"
	"strconv"

	sling "gopkg.in/dghubble/sling.v1"
)

// GetProjectsParam represents getprojects request parameter
type GetProjectsParam struct {
	FilterCompletedProject bool   `url:"Filtercompletedproject,omitempty"`
	ProjectID              string `url:"Projectid,omitempty"`
}

// ProjectResponse represents porject listing response
type ProjectResponse struct {
	Status  string    `json:"status"`
	Results []Project `json:"results"`
}

// Project is representing project in ACEProject
type Project struct {
	ID                int64   `json:"PROJECT_ID"`
	Name              string  `json:"PROJECT_NAME"`
	ProjectNumber     string  `json:"PROJECT_NUMBER"`
	TypeID            int64   `json:"PROJECT_TYPE"`
	Type              string  `json:"PROJECT_TYPE_NAME"`
	ProjectStatusName string  `json:"PROJECT_STATUS_NAME"`
	ClientName        string  `json:"CLIENT_NAME"`
	ContactName       string  `json:"CONTACT_NAME"`
	ContactPhone      string  `json:"CONTACT_PHONE"`
	ErrorDesc         *string `json:"ERRORDESCRIPTION,omitempty"`
}

// ProjectService provides methods to interact with project specific action
type ProjectService struct {
	sling *sling.Sling
}

// NewProjectService return a new ProjectService
func NewProjectService(httpClient *http.Client, guidInfo *GUIDInfo) *ProjectService {
	return &ProjectService{
		sling: sling.New().Client(httpClient).Base(baseURL).QueryStruct(guidInfo),
	}
}

// List returns the project list
func (s *ProjectService) List() ([]Project, *http.Response, error) {
	projRes := new(ProjectResponse)
	resp, err := s.sling.New().
		QueryStruct(CreateFunctionParam("getprojects")).
		ReceiveSuccess(projRes)
	if projRes != nil && len(projRes.Results) > 0 {
		if projRes.Results[0].ErrorDesc != nil {
			return nil, resp, Error{*projRes.Results[0].ErrorDesc}
		}
		return *(&projRes.Results), resp, err
	}
	return make([]Project, 0), resp, err
}

// ListWithCompleteness returns the list of complete / incomplete projects
func (s *ProjectService) ListWithCompleteness(complete bool) ([]Project, *http.Response, error) {
	projRes := new(ProjectResponse)
	resp, err := s.sling.New().
		QueryStruct(CreateFunctionParam("getprojects")).
		QueryStruct(&GetProjectsParam{FilterCompletedProject: complete}).
		ReceiveSuccess(projRes)
	if projRes != nil && len(projRes.Results) > 0 {
		if projRes.Results[0].ErrorDesc != nil {
			return nil, resp, Error{*projRes.Results[0].ErrorDesc}
		}
		return *(&projRes.Results), resp, err
	}
	return make([]Project, 0), resp, err
}

// Get returns the project of given ID
func (s *ProjectService) Get(projectID int64) (*Project, *http.Response, error) {
	//
	projRes := new(ProjectResponse)
	resp, err := s.sling.New().
		QueryStruct(CreateFunctionParam("getprojects")).
		QueryStruct(&GetProjectsParam{ProjectID: strconv.FormatInt(projectID, 10)}).
		ReceiveSuccess(projRes)
	if projRes != nil && len(projRes.Results) > 0 {
		if projRes.Results[0].ErrorDesc != nil {
			return nil, resp, Error{*projRes.Results[0].ErrorDesc}
		}
		return &projRes.Results[0], resp, err
	}
	return nil, resp, err
}
<|endoftext|>


<commit_before>package pt

import (
	"math"

	embree "github.com/fogleman/go-embree"
)

type Mesh struct {
	Box       Box
	Triangles []*Triangle
	mesh      *embree.Mesh
}

func NewMesh(triangles []*Triangle) *Mesh {
	box := BoxForTriangles(triangles)
	return &Mesh{box, triangles, nil}
}

func (m *Mesh) Compile() {
	if m.mesh == nil {
		triangles := make([]embree.Triangle, len(m.Triangles))
		for i, t := range m.Triangles {
			triangles[i] = embree.Triangle{
				embree.Vector{t.V1.X, t.V1.Y, t.V1.Z},
				embree.Vector{t.V2.X, t.V2.Y, t.V2.Z},
				embree.Vector{t.V3.X, t.V3.Y, t.V3.Z},
			}
		}
		m.mesh = embree.NewMesh(triangles)
	}
}

func (m *Mesh) BoundingBox() Box {
	return m.Box
}

func (m *Mesh) Intersect(r Ray) Hit {
	ray := embree.Ray{
		embree.Vector{r.Origin.X, r.Origin.Y, r.Origin.Z},
		embree.Vector{r.Direction.X, r.Direction.Y, r.Direction.Z},
	}
	hit := m.mesh.Intersect(ray)
	if hit.Index >= 0 {
		triangle := m.Triangles[hit.Index]
		t := triangle.Intersect(r).T
		return Hit{triangle, t, nil}
	} else {
		return NoHit
	}
}

func (m *Mesh) UV(p Vector) Vector {
	return Vector{} // not implemented
}

func (m *Mesh) MaterialAt(p Vector) Material {
	return Material{} // not implemented
}

func (m *Mesh) NormalAt(p Vector) Vector {
	return Vector{} // not implemented
}

func (m *Mesh) UpdateBoundingBox() {
	m.Box = BoxForTriangles(m.Triangles)
}

func smoothNormalsThreshold(normal Vector, normals []Vector, threshold float64) Vector {
	result := Vector{}
	for _, x := range normals {
		if x.Dot(normal) >= threshold {
			result = result.Add(x)
		}
	}
	return result.Normalize()
}

func (m *Mesh) SmoothNormalsThreshold(radians float64) {
	threshold := math.Cos(radians)
	lookup := make(map[Vector][]Vector)
	for _, t := range m.Triangles {
		lookup[t.V1] = append(lookup[t.V1], t.N1)
		lookup[t.V2] = append(lookup[t.V2], t.N2)
		lookup[t.V3] = append(lookup[t.V3], t.N3)
	}
	for _, t := range m.Triangles {
		t.N1 = smoothNormalsThreshold(t.N1, lookup[t.V1], threshold)
		t.N2 = smoothNormalsThreshold(t.N2, lookup[t.V2], threshold)
		t.N3 = smoothNormalsThreshold(t.N3, lookup[t.V3], threshold)
	}
}

func (m *Mesh) SmoothNormals() {
	lookup := make(map[Vector]Vector)
	for _, t := range m.Triangles {
		lookup[t.V1] = lookup[t.V1].Add(t.N1)
		lookup[t.V2] = lookup[t.V2].Add(t.N2)
		lookup[t.V3] = lookup[t.V3].Add(t.N3)
	}
	for k, v := range lookup {
		lookup[k] = v.Normalize()
	}
	for _, t := range m.Triangles {
		t.N1 = lookup[t.V1]
		t.N2 = lookup[t.V2]
		t.N3 = lookup[t.V3]
	}
}

func (m *Mesh) UnitCube() {
	m.FitInside(Box{Vector{}, Vector{1, 1, 1}}, Vector{})
	m.MoveTo(Vector{}, Vector{0.5, 0.5, 0.5})
}

func (m *Mesh) MoveTo(position, anchor Vector) {
	matrix := Translate(position.Sub(m.Box.Anchor(anchor)))
	m.Transform(matrix)
}

func (m *Mesh) FitInside(box Box, anchor Vector) {
	scale := box.Size().Div(m.BoundingBox().Size()).MinComponent()
	extra := box.Size().Sub(m.BoundingBox().Size().MulScalar(scale))
	matrix := Identity()
	matrix = matrix.Translate(m.BoundingBox().Min.MulScalar(-1))
	matrix = matrix.Scale(Vector{scale, scale, scale})
	matrix = matrix.Translate(box.Min.Add(extra.Mul(anchor)))
	m.Transform(matrix)
}

func (m *Mesh) Transform(matrix Matrix) {
	for _, t := range m.Triangles {
		t.V1 = matrix.MulPosition(t.V1)
		t.V2 = matrix.MulPosition(t.V2)
		t.V3 = matrix.MulPosition(t.V3)
		t.N1 = matrix.MulDirection(t.N1)
		t.N2 = matrix.MulDirection(t.N2)
		t.N3 = matrix.MulDirection(t.N3)
		t.UpdateBoundingBox()
	}
	m.UpdateBoundingBox()
	m.mesh = nil // dirty
}

func (m *Mesh) SaveSTL(path string) error {
	return SaveSTL(path, m)
}
<commit_msg>simplified<commit_after>package pt

import (
	"math"

	embree "github.com/fogleman/go-embree"
)

type Mesh struct {
	Box       Box
	Triangles []*Triangle
	mesh      *embree.Mesh
}

func NewMesh(triangles []*Triangle) *Mesh {
	box := BoxForTriangles(triangles)
	return &Mesh{box, triangles, nil}
}

func (m *Mesh) Compile() {
	if m.mesh == nil {
		triangles := make([]embree.Triangle, len(m.Triangles))
		for i, t := range m.Triangles {
			triangles[i] = embree.Triangle{
				embree.Vector{t.V1.X, t.V1.Y, t.V1.Z},
				embree.Vector{t.V2.X, t.V2.Y, t.V2.Z},
				embree.Vector{t.V3.X, t.V3.Y, t.V3.Z},
			}
		}
		m.mesh = embree.NewMesh(triangles)
	}
}

func (m *Mesh) BoundingBox() Box {
	return m.Box
}

func (m *Mesh) Intersect(r Ray) Hit {
	ray := embree.Ray{
		embree.Vector{r.Origin.X, r.Origin.Y, r.Origin.Z},
		embree.Vector{r.Direction.X, r.Direction.Y, r.Direction.Z},
	}
	hit := m.mesh.Intersect(ray)
	if hit.Index >= 0 {
		return m.Triangles[hit.Index].Intersect(r)
	} else {
		return NoHit
	}
}

func (m *Mesh) UV(p Vector) Vector {
	return Vector{} // not implemented
}

func (m *Mesh) MaterialAt(p Vector) Material {
	return Material{} // not implemented
}

func (m *Mesh) NormalAt(p Vector) Vector {
	return Vector{} // not implemented
}

func (m *Mesh) UpdateBoundingBox() {
	m.Box = BoxForTriangles(m.Triangles)
}

func smoothNormalsThreshold(normal Vector, normals []Vector, threshold float64) Vector {
	result := Vector{}
	for _, x := range normals {
		if x.Dot(normal) >= threshold {
			result = result.Add(x)
		}
	}
	return result.Normalize()
}

func (m *Mesh) SmoothNormalsThreshold(radians float64) {
	threshold := math.Cos(radians)
	lookup := make(map[Vector][]Vector)
	for _, t := range m.Triangles {
		lookup[t.V1] = append(lookup[t.V1], t.N1)
		lookup[t.V2] = append(lookup[t.V2], t.N2)
		lookup[t.V3] = append(lookup[t.V3], t.N3)
	}
	for _, t := range m.Triangles {
		t.N1 = smoothNormalsThreshold(t.N1, lookup[t.V1], threshold)
		t.N2 = smoothNormalsThreshold(t.N2, lookup[t.V2], threshold)
		t.N3 = smoothNormalsThreshold(t.N3, lookup[t.V3], threshold)
	}
}

func (m *Mesh) SmoothNormals() {
	lookup := make(map[Vector]Vector)
	for _, t := range m.Triangles {
		lookup[t.V1] = lookup[t.V1].Add(t.N1)
		lookup[t.V2] = lookup[t.V2].Add(t.N2)
		lookup[t.V3] = lookup[t.V3].Add(t.N3)
	}
	for k, v := range lookup {
		lookup[k] = v.Normalize()
	}
	for _, t := range m.Triangles {
		t.N1 = lookup[t.V1]
		t.N2 = lookup[t.V2]
		t.N3 = lookup[t.V3]
	}
}

func (m *Mesh) UnitCube() {
	m.FitInside(Box{Vector{}, Vector{1, 1, 1}}, Vector{})
	m.MoveTo(Vector{}, Vector{0.5, 0.5, 0.5})
}

func (m *Mesh) MoveTo(position, anchor Vector) {
	matrix := Translate(position.Sub(m.Box.Anchor(anchor)))
	m.Transform(matrix)
}

func (m *Mesh) FitInside(box Box, anchor Vector) {
	scale := box.Size().Div(m.BoundingBox().Size()).MinComponent()
	extra := box.Size().Sub(m.BoundingBox().Size().MulScalar(scale))
	matrix := Identity()
	matrix = matrix.Translate(m.BoundingBox().Min.MulScalar(-1))
	matrix = matrix.Scale(Vector{scale, scale, scale})
	matrix = matrix.Translate(box.Min.Add(extra.Mul(anchor)))
	m.Transform(matrix)
}

func (m *Mesh) Transform(matrix Matrix) {
	for _, t := range m.Triangles {
		t.V1 = matrix.MulPosition(t.V1)
		t.V2 = matrix.MulPosition(t.V2)
		t.V3 = matrix.MulPosition(t.V3)
		t.N1 = matrix.MulDirection(t.N1)
		t.N2 = matrix.MulDirection(t.N2)
		t.N3 = matrix.MulDirection(t.N3)
		t.UpdateBoundingBox()
	}
	m.UpdateBoundingBox()
	m.mesh = nil // dirty
}

func (m *Mesh) SaveSTL(path string) error {
	return SaveSTL(path, m)
}
<|endoftext|>


<commit_before>package raidman

import (
	"bytes"
	pb "code.google.com/p/goprotobuf/proto"
	"encoding/binary"
	"errors"
	"fmt"
	"github.com/amir/raidman/proto"
	"net"
	"os"
	"reflect"
	"sync"
)

type network interface {
	Send(message *proto.Msg, conn net.Conn) (*proto.Msg, error)
}

type tcp struct{}

type udp struct{}

// Client represents a connection to a Riemann server
type Client struct {
	sync.Mutex
	net        network
	connection net.Conn
}

// An Event represents a single Riemann event
type Event struct {
	Ttl         float32
	Time        int64
	Tags        []string
	Host        string // Defaults to os.Hostname()
	State       string
	Service     string
	Metric      interface{} // Could be Int, Float32, Float64
	Description string
}

// Dial establishes a connection to a Riemann server at addr, on the network
// netwrk.
//
// Known networks are "tcp", "tcp4", "tcp6", "udp", "udp4", and "udp6".
func Dial(netwrk, addr string) (c *Client, err error) {
	c = new(Client)

	var cnet network
	switch netwrk {
	case "tcp", "tcp4", "tcp6":
		cnet = new(tcp)
	case "udp", "udp4", "udp6":
		cnet = new(udp)
	default:
		return nil, fmt.Errorf("dial %q: unsupported network %q", netwrk, netwrk)
	}

	c.net = cnet
	c.connection, err = net.Dial(netwrk, addr)
	if err != nil {
		return nil, err
	}

	return c, nil
}

func (network *tcp) Send(message *proto.Msg, conn net.Conn) (*proto.Msg, error) {
	msg := &proto.Msg{}
	data, err := pb.Marshal(message)
	if err != nil {
		return msg, err
	}
	b := new(bytes.Buffer)
	if err = binary.Write(b, binary.BigEndian, uint32(len(data))); err != nil {
		return msg, err
	}
	if _, err = conn.Write(b.Bytes()); err != nil {
		return msg, err
	}
	if _, err = conn.Write(data); err != nil {
		return msg, err
	}
	var header uint32
	if err = binary.Read(conn, binary.BigEndian, &header); err != nil {
		return msg, err
	}
	response := make([]byte, header)
	if _, err = conn.Read(response); err != nil {
		return msg, err
	}
	if err = pb.Unmarshal(response, msg); err != nil {
		return msg, err
	}
	if msg.GetOk() != true {
		return msg, errors.New(msg.GetError())
	}
	return msg, nil
}

func (network *udp) Send(message *proto.Msg, conn net.Conn) (*proto.Msg, error) {
	data, err := pb.Marshal(message)
	if err != nil {
		return nil, err
	}
	if _, err = conn.Write(data); err != nil {
		return nil, err
	}

	return nil, nil
}

func eventToPbEvent(event *Event) (*proto.Event, error) {
	var e proto.Event

	if event.Host == "" {
		event.Host, _ = os.Hostname()
	}
	t := reflect.ValueOf(&e).Elem()
	s := reflect.ValueOf(event).Elem()
	typeOfEvent := s.Type()
	for i := 0; i < s.NumField(); i++ {
		f := s.Field(i)
		value := reflect.ValueOf(f.Interface())
		if reflect.Zero(f.Type()) != value && f.Interface() != nil {
			name := typeOfEvent.Field(i).Name
			switch name {
			case "State", "Service", "Host", "Description":
				tmp := reflect.ValueOf(pb.String(value.String()))
				t.FieldByName(name).Set(tmp)
			case "Ttl":
				tmp := reflect.ValueOf(pb.Float32(float32(value.Float())))
				t.FieldByName(name).Set(tmp)
			case "Time":
				tmp := reflect.ValueOf(pb.Int64(value.Int()))
				t.FieldByName(name).Set(tmp)
			case "Tags":
				tmp := reflect.ValueOf(value.Interface().([]string))
				t.FieldByName(name).Set(tmp)
			case "Metric":
				switch reflect.TypeOf(f.Interface()).Kind() {
				case reflect.Int:
					tmp := reflect.ValueOf(pb.Int64(int64(value.Int())))
					t.FieldByName("MetricSint64").Set(tmp)
				case reflect.Float32:
					tmp := reflect.ValueOf(pb.Float32(float32(value.Float())))
					t.FieldByName("MetricF").Set(tmp)
				case reflect.Float64:
					tmp := reflect.ValueOf(pb.Float64(value.Float()))
					t.FieldByName("MetricD").Set(tmp)
				default:
					return nil, fmt.Errorf("Metric of invalid type (type %v)",
						reflect.TypeOf(f.Interface()).Kind())
				}
			}
		}
	}

	return &e, nil
}

func pbEventsToEvents(pbEvents []*proto.Event) []Event {
	var events []Event

	for _, event := range pbEvents {
		e := Event{
			State:       event.GetState(),
			Service:     event.GetService(),
			Host:        event.GetHost(),
			Description: event.GetDescription(),
			Ttl:         event.GetTtl(),
			Time:        event.GetTime(),
			Tags:        event.GetTags(),
		}
		if event.MetricF != nil {
			e.Metric = event.GetMetricF()
		} else if event.MetricD != nil {
			e.Metric = event.GetMetricD()
		} else {
			e.Metric = event.GetMetricSint64()
		}

		events = append(events, e)
	}

	return events
}

// Send sends an event to Riemann
func (c *Client) Send(event *Event) error {
	e, err := eventToPbEvent(event)
	if err != nil {
		return err
	}
	message := &proto.Msg{}
	message.Events = append(message.Events, e)
	c.Lock()
	defer c.Unlock()
	_, err = c.net.Send(message, c.connection)
	if err != nil {
		return err
	}

	return nil
}

// Query returns a list of events matched by query
func (c *Client) Query(q string) ([]Event, error) {
	switch c.net.(type) {
	case *udp:
		return nil, errors.New("Querying over UDP is not supported")
	}
	query := &proto.Query{}
	query.String_ = pb.String(q)
	message := &proto.Msg{}
	message.Query = query
	c.Lock()
	defer c.Unlock()
	response, err := c.net.Send(message, c.connection)
	if err != nil {
		return nil, err
	}
	return pbEventsToEvents(response.GetEvents()), nil
}

// Close closes the connection to Riemann
func (c *Client) Close() {
	c.Lock()
	c.connection.Close()
	c.Unlock()
}
<commit_msg>Organize imports<commit_after>package raidman

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"net"
	"os"
	"reflect"
	"sync"

	pb "code.google.com/p/goprotobuf/proto"
	"github.com/amir/raidman/proto"
)

type network interface {
	Send(message *proto.Msg, conn net.Conn) (*proto.Msg, error)
}

type tcp struct{}

type udp struct{}

// Client represents a connection to a Riemann server
type Client struct {
	sync.Mutex
	net        network
	connection net.Conn
}

// An Event represents a single Riemann event
type Event struct {
	Ttl         float32
	Time        int64
	Tags        []string
	Host        string // Defaults to os.Hostname()
	State       string
	Service     string
	Metric      interface{} // Could be Int, Float32, Float64
	Description string
}

// Dial establishes a connection to a Riemann server at addr, on the network
// netwrk.
//
// Known networks are "tcp", "tcp4", "tcp6", "udp", "udp4", and "udp6".
func Dial(netwrk, addr string) (c *Client, err error) {
	c = new(Client)

	var cnet network
	switch netwrk {
	case "tcp", "tcp4", "tcp6":
		cnet = new(tcp)
	case "udp", "udp4", "udp6":
		cnet = new(udp)
	default:
		return nil, fmt.Errorf("dial %q: unsupported network %q", netwrk, netwrk)
	}

	c.net = cnet
	c.connection, err = net.Dial(netwrk, addr)
	if err != nil {
		return nil, err
	}

	return c, nil
}

func (network *tcp) Send(message *proto.Msg, conn net.Conn) (*proto.Msg, error) {
	msg := &proto.Msg{}
	data, err := pb.Marshal(message)
	if err != nil {
		return msg, err
	}
	b := new(bytes.Buffer)
	if err = binary.Write(b, binary.BigEndian, uint32(len(data))); err != nil {
		return msg, err
	}
	if _, err = conn.Write(b.Bytes()); err != nil {
		return msg, err
	}
	if _, err = conn.Write(data); err != nil {
		return msg, err
	}
	var header uint32
	if err = binary.Read(conn, binary.BigEndian, &header); err != nil {
		return msg, err
	}
	response := make([]byte, header)
	if _, err = conn.Read(response); err != nil {
		return msg, err
	}
	if err = pb.Unmarshal(response, msg); err != nil {
		return msg, err
	}
	if msg.GetOk() != true {
		return msg, errors.New(msg.GetError())
	}
	return msg, nil
}

func (network *udp) Send(message *proto.Msg, conn net.Conn) (*proto.Msg, error) {
	data, err := pb.Marshal(message)
	if err != nil {
		return nil, err
	}
	if _, err = conn.Write(data); err != nil {
		return nil, err
	}

	return nil, nil
}

func eventToPbEvent(event *Event) (*proto.Event, error) {
	var e proto.Event

	if event.Host == "" {
		event.Host, _ = os.Hostname()
	}
	t := reflect.ValueOf(&e).Elem()
	s := reflect.ValueOf(event).Elem()
	typeOfEvent := s.Type()
	for i := 0; i < s.NumField(); i++ {
		f := s.Field(i)
		value := reflect.ValueOf(f.Interface())
		if reflect.Zero(f.Type()) != value && f.Interface() != nil {
			name := typeOfEvent.Field(i).Name
			switch name {
			case "State", "Service", "Host", "Description":
				tmp := reflect.ValueOf(pb.String(value.String()))
				t.FieldByName(name).Set(tmp)
			case "Ttl":
				tmp := reflect.ValueOf(pb.Float32(float32(value.Float())))
				t.FieldByName(name).Set(tmp)
			case "Time":
				tmp := reflect.ValueOf(pb.Int64(value.Int()))
				t.FieldByName(name).Set(tmp)
			case "Tags":
				tmp := reflect.ValueOf(value.Interface().([]string))
				t.FieldByName(name).Set(tmp)
			case "Metric":
				switch reflect.TypeOf(f.Interface()).Kind() {
				case reflect.Int:
					tmp := reflect.ValueOf(pb.Int64(int64(value.Int())))
					t.FieldByName("MetricSint64").Set(tmp)
				case reflect.Float32:
					tmp := reflect.ValueOf(pb.Float32(float32(value.Float())))
					t.FieldByName("MetricF").Set(tmp)
				case reflect.Float64:
					tmp := reflect.ValueOf(pb.Float64(value.Float()))
					t.FieldByName("MetricD").Set(tmp)
				default:
					return nil, fmt.Errorf("Metric of invalid type (type %v)",
						reflect.TypeOf(f.Interface()).Kind())
				}
			}
		}
	}

	return &e, nil
}

func pbEventsToEvents(pbEvents []*proto.Event) []Event {
	var events []Event

	for _, event := range pbEvents {
		e := Event{
			State:       event.GetState(),
			Service:     event.GetService(),
			Host:        event.GetHost(),
			Description: event.GetDescription(),
			Ttl:         event.GetTtl(),
			Time:        event.GetTime(),
			Tags:        event.GetTags(),
		}
		if event.MetricF != nil {
			e.Metric = event.GetMetricF()
		} else if event.MetricD != nil {
			e.Metric = event.GetMetricD()
		} else {
			e.Metric = event.GetMetricSint64()
		}

		events = append(events, e)
	}

	return events
}

// Send sends an event to Riemann
func (c *Client) Send(event *Event) error {
	e, err := eventToPbEvent(event)
	if err != nil {
		return err
	}
	message := &proto.Msg{}
	message.Events = append(message.Events, e)
	c.Lock()
	defer c.Unlock()
	_, err = c.net.Send(message, c.connection)
	if err != nil {
		return err
	}

	return nil
}

// Query returns a list of events matched by query
func (c *Client) Query(q string) ([]Event, error) {
	switch c.net.(type) {
	case *udp:
		return nil, errors.New("Querying over UDP is not supported")
	}
	query := &proto.Query{}
	query.String_ = pb.String(q)
	message := &proto.Msg{}
	message.Query = query
	c.Lock()
	defer c.Unlock()
	response, err := c.net.Send(message, c.connection)
	if err != nil {
		return nil, err
	}
	return pbEventsToEvents(response.GetEvents()), nil
}

// Close closes the connection to Riemann
func (c *Client) Close() {
	c.Lock()
	c.connection.Close()
	c.Unlock()
}
<|endoftext|>


<commit_before>package quorum

import (
	"common"
	"common/crypto"
	"testing"
	"time"
)

// test create heartbeat

// test heartbeat.marshal and heartbeat.unmarshal

// An incomplete set of tests: the more complete suite will
// attack the system as a whole.
func TestHandleSignedHeartbeat(t *testing.T) {
	// create a state and populate it with the signatories as participants
	s, err := CreateState(0)
	if err != nil {
		t.Fatal("error creating state!")
	}

	// create some public keys
	pubKey1, secKey1, err := crypto.CreateKeyPair()
	if err != nil {
		t.Fatal("calling CreateKeyPair() failed!")
	}

	pubKey2, secKey2, err := crypto.CreateKeyPair()
	if err != nil {
		t.Fatal("second call to CreateKeyPair() failed!")
	}

	// Add keys as participants
	s.AddParticipant(pubKey1, 1)
	s.AddParticipant(pubKey2, 2)

	// create SignedHeartbeat
	var sh SignedHeartbeat
	sh.Heartbeat, err = s.NewHeartbeat()
	if err != nil {
		t.Fatal(err)
	}
	sh.HeartbeatHash, err = crypto.CalculateTruncatedHash([]byte(sh.Heartbeat.Marshal()))
	if err != nil {
		t.Fatal(err)
	}
	sh.Signatures = make([]crypto.Signature, 2)
	sh.Signatories = make([]ParticipantIndex, 2)

	// Create a set of signatures for the SignedHeartbeat
	signature1, err := crypto.Sign(secKey1, string(sh.HeartbeatHash[:]))
	if err != nil {
		t.Fatal("error signing HeartbeatHash")
	}

	signature2, err := crypto.Sign(secKey2, signature1.CombinedMessage())
	if err != nil {
		t.Fatal("error with second signing")
	}

	// build a valid SignedHeartbeat
	sh.Signatures[0] = signature1.Signature
	sh.Signatures[1] = signature2.Signature
	sh.Signatories[0] = 1
	sh.Signatories[1] = 2

	// handle the signed heartbeat, expecting code 0
	returnCode := s.HandleSignedHeartbeat(&sh)
	if returnCode != 0 {
		t.Fatal("expected heartbeat to succeed:", returnCode)
	}

	// verify that a repeat heartbeat gets ignored
	returnCode = s.HandleSignedHeartbeat(&sh)
	if returnCode != 8 {
		t.Fatal("expected heartbeat to get ignored as a duplicate:", returnCode)
	}

	// create a different heartbeat, this will be used to test the fail conditions
	sh.Heartbeat, err = s.NewHeartbeat()
	if err != nil {
		t.Fatal(err)
	}
	sh.HeartbeatHash, err = crypto.CalculateTruncatedHash([]byte(sh.Heartbeat.Marshal()))
	if err != nil {
		t.Fatal(err)
	}

	// verify a heartbeat with bad signatures is rejected
	returnCode = s.HandleSignedHeartbeat(&sh)
	if returnCode != 6 {
		t.Fatal("expected heartbeat to get ignored as having invalid signatures: ", returnCode)
	}

	// give heartbeat repeat signatures
	signature1, err = crypto.Sign(secKey1, string(sh.HeartbeatHash[:]))
	if err != nil {
		t.Fatal("error with third signing")
	}

	signature2, err = crypto.Sign(secKey1, signature1.CombinedMessage())
	if err != nil {
		t.Fatal("error with fourth signing")
	}

	// adjust signatories slice
	sh.Signatures[0] = signature1.Signature
	sh.Signatures[1] = signature2.Signature
	sh.Signatories[0] = 1
	sh.Signatories[1] = 1

	// verify repeated signatures are rejected
	returnCode = s.HandleSignedHeartbeat(&sh)
	if returnCode != 5 {
		t.Fatal("expected heartbeat to be rejected for duplicate signatures: ", returnCode)
	}

	// remove second signature
	sh.Signatures = sh.Signatures[:1]
	sh.Signatories = sh.Signatories[:1]

	// handle heartbeat when tick is larger than num signatures
	s.CurrentStep = 2
	returnCode = s.HandleSignedHeartbeat(&sh)
	if returnCode != 2 {
		t.Fatal("expected heartbeat to be rejected as out-of-sync: ", returnCode)
	}

	// send a heartbeat right at the edge of a new block
	// test takes time; skip in short tests
	if testing.Short() {
		t.Skip()
	}

	// put block at edge
	s.CurrentStep = common.QuorumSize

	// submit heartbeat in separate thread
	go func() {
		returnCode = s.HandleSignedHeartbeat(&sh)
		if returnCode != 0 {
			t.Fatal("expected heartbeat to succeed!: ", returnCode)
		}
	}()

	time.Sleep(time.Second)
	s.CurrentStep = 1

	// verify that new heartbeats get properly sent out with valid signatures
}

// add fuzzing tests for HandleSignedHeartbeat
// test race conditions on HandleSignedHeartbeat

func TestProcessHeartbeat(t *testing.T) {
	// heh
}

func TestCompile(t *testing.T) {
	// confirm the ordering is consistent with the algorithm
	// this should probably just use a hard-coded example? not sure...
	//
	// check all participant stuffs in the for loop
	// have some empty participants, make sure 'continue' is reached
	// have participants without heartbeats
	// have participants with extra heartbeats
	// have participants  with 1 heartbeat, make sure process() gets called
	//
	// check that a new heartbeat is created
	// check that the SignedHeartbeat is correctly created
	//
	// check that heartbeat is properly sent to everybody who remains

	s, err := CreateState(0)
	if err != nil {
		t.Fatal(err)
	}
	s.Compile()
}

// Ensures that Tick() updates CurrentStep
func TestRegularTick(t *testing.T) {
	// test takes common.StepDuration seconds; skip for short testing
	if testing.Short() {
		t.Skip()
	}

	s, err := CreateState(0)
	if err != nil {
		t.Fatal(err)
	}

	// verify that tick is updating CurrentStep
	s.CurrentStep = 1
	go s.Tick()
	time.Sleep(common.StepDuration)
	time.Sleep(time.Second)
	if s.CurrentStep != 2 {
		t.Fatal("s.CurrentStep failed to update correctly: ", s.CurrentStep)
	}
}

func TestCompilationTick(t *testing.T) {
	// test takes common.StepDuration seconds; skip for short testing
	if testing.Short() {
		t.Skip()
	}

	s, err := CreateState(0)
	if err != nil {
		t.Fatal(err)
	}

	// verify that tick is wrapping around properly
	s.CurrentStep = common.QuorumSize
	go s.Tick()
	time.Sleep(common.StepDuration)
	time.Sleep(time.Second)
	if s.CurrentStep != 1 {
		t.Fatal("s.CurrentStep failed to roll over: ", s.CurrentStep)
	}

	// check if s.Compile() got called
}
<commit_msg>Add TestNewHeartbeat()<commit_after>package quorum

import (
	"common"
	"common/crypto"
	"testing"
	"time"
)

// test create heartbeat
func TestNewHeartbeat(t *testing.T) {
	s, err := CreateState(0)
	if err != nil {
		t.Fatal(err)
	}

	hb, err := s.NewHeartbeat()
	if err != nil {
		t.Fatal(err)
	}

	// make sure that EntropyStage1 matches the hash of what gets stored
	storedEntropyHash, err := crypto.CalculateTruncatedHash(s.StoredEntropyStage2[:])
	if err != nil {
		t.Fatal(err)
	} else if hb.EntropyStage1 != storedEntropyHash {
		t.Fatal("NewHeartbeat() incorrectly producing EntropyStage1 from s.StoredEntropyStage2")
	}
}

// test heartbeat.marshal and heartbeat.unmarshal

// An incomplete set of tests: the more complete suite will
// attack the system as a whole.
func TestHandleSignedHeartbeat(t *testing.T) {
	// create a state and populate it with the signatories as participants
	s, err := CreateState(0)
	if err != nil {
		t.Fatal("error creating state!")
	}

	// create some public keys
	pubKey1, secKey1, err := crypto.CreateKeyPair()
	if err != nil {
		t.Fatal("calling CreateKeyPair() failed!")
	}

	pubKey2, secKey2, err := crypto.CreateKeyPair()
	if err != nil {
		t.Fatal("second call to CreateKeyPair() failed!")
	}

	// Add keys as participants
	s.AddParticipant(pubKey1, 1)
	s.AddParticipant(pubKey2, 2)

	// create SignedHeartbeat
	var sh SignedHeartbeat
	sh.Heartbeat, err = s.NewHeartbeat()
	if err != nil {
		t.Fatal(err)
	}
	sh.HeartbeatHash, err = crypto.CalculateTruncatedHash([]byte(sh.Heartbeat.Marshal()))
	if err != nil {
		t.Fatal(err)
	}
	sh.Signatures = make([]crypto.Signature, 2)
	sh.Signatories = make([]ParticipantIndex, 2)

	// Create a set of signatures for the SignedHeartbeat
	signature1, err := crypto.Sign(secKey1, string(sh.HeartbeatHash[:]))
	if err != nil {
		t.Fatal("error signing HeartbeatHash")
	}

	signature2, err := crypto.Sign(secKey2, signature1.CombinedMessage())
	if err != nil {
		t.Fatal("error with second signing")
	}

	// build a valid SignedHeartbeat
	sh.Signatures[0] = signature1.Signature
	sh.Signatures[1] = signature2.Signature
	sh.Signatories[0] = 1
	sh.Signatories[1] = 2

	// handle the signed heartbeat, expecting code 0
	returnCode := s.HandleSignedHeartbeat(&sh)
	if returnCode != 0 {
		t.Fatal("expected heartbeat to succeed:", returnCode)
	}

	// verify that a repeat heartbeat gets ignored
	returnCode = s.HandleSignedHeartbeat(&sh)
	if returnCode != 8 {
		t.Fatal("expected heartbeat to get ignored as a duplicate:", returnCode)
	}

	// create a different heartbeat, this will be used to test the fail conditions
	sh.Heartbeat, err = s.NewHeartbeat()
	if err != nil {
		t.Fatal(err)
	}
	sh.HeartbeatHash, err = crypto.CalculateTruncatedHash([]byte(sh.Heartbeat.Marshal()))
	if err != nil {
		t.Fatal(err)
	}

	// verify a heartbeat with bad signatures is rejected
	returnCode = s.HandleSignedHeartbeat(&sh)
	if returnCode != 6 {
		t.Fatal("expected heartbeat to get ignored as having invalid signatures: ", returnCode)
	}

	// give heartbeat repeat signatures
	signature1, err = crypto.Sign(secKey1, string(sh.HeartbeatHash[:]))
	if err != nil {
		t.Fatal("error with third signing")
	}

	signature2, err = crypto.Sign(secKey1, signature1.CombinedMessage())
	if err != nil {
		t.Fatal("error with fourth signing")
	}

	// adjust signatories slice
	sh.Signatures[0] = signature1.Signature
	sh.Signatures[1] = signature2.Signature
	sh.Signatories[0] = 1
	sh.Signatories[1] = 1

	// verify repeated signatures are rejected
	returnCode = s.HandleSignedHeartbeat(&sh)
	if returnCode != 5 {
		t.Fatal("expected heartbeat to be rejected for duplicate signatures: ", returnCode)
	}

	// remove second signature
	sh.Signatures = sh.Signatures[:1]
	sh.Signatories = sh.Signatories[:1]

	// handle heartbeat when tick is larger than num signatures
	s.CurrentStep = 2
	returnCode = s.HandleSignedHeartbeat(&sh)
	if returnCode != 2 {
		t.Fatal("expected heartbeat to be rejected as out-of-sync: ", returnCode)
	}

	// send a heartbeat right at the edge of a new block
	// test takes time; skip in short tests
	if testing.Short() {
		t.Skip()
	}

	// put block at edge
	s.CurrentStep = common.QuorumSize

	// submit heartbeat in separate thread
	go func() {
		returnCode = s.HandleSignedHeartbeat(&sh)
		if returnCode != 0 {
			t.Fatal("expected heartbeat to succeed!: ", returnCode)
		}
	}()

	time.Sleep(time.Second)
	s.CurrentStep = 1

	// verify that new heartbeats get properly sent out with valid signatures
}

// add fuzzing tests for HandleSignedHeartbeat
// test race conditions on HandleSignedHeartbeat

func TestProcessHeartbeat(t *testing.T) {
	// heh
}

func TestCompile(t *testing.T) {
	// confirm the ordering is consistent with the algorithm
	// this should probably just use a hard-coded example? not sure...
	//
	// check all participant stuffs in the for loop
	// have some empty participants, make sure 'continue' is reached
	// have participants without heartbeats
	// have participants with extra heartbeats
	// have participants  with 1 heartbeat, make sure process() gets called
	//
	// check that a new heartbeat is created
	// check that the SignedHeartbeat is correctly created
	//
	// check that heartbeat is properly sent to everybody who remains

	s, err := CreateState(0)
	if err != nil {
		t.Fatal(err)
	}
	s.Compile()
}

// Ensures that Tick() updates CurrentStep
func TestRegularTick(t *testing.T) {
	// test takes common.StepDuration seconds; skip for short testing
	if testing.Short() {
		t.Skip()
	}

	s, err := CreateState(0)
	if err != nil {
		t.Fatal(err)
	}

	// verify that tick is updating CurrentStep
	s.CurrentStep = 1
	go s.Tick()
	time.Sleep(common.StepDuration)
	time.Sleep(time.Second)
	if s.CurrentStep != 2 {
		t.Fatal("s.CurrentStep failed to update correctly: ", s.CurrentStep)
	}
}

func TestCompilationTick(t *testing.T) {
	// test takes common.StepDuration seconds; skip for short testing
	if testing.Short() {
		t.Skip()
	}

	s, err := CreateState(0)
	if err != nil {
		t.Fatal(err)
	}

	// verify that tick is wrapping around properly
	s.CurrentStep = common.QuorumSize
	go s.Tick()
	time.Sleep(common.StepDuration)
	time.Sleep(time.Second)
	if s.CurrentStep != 1 {
		t.Fatal("s.CurrentStep failed to roll over: ", s.CurrentStep)
	}

	// check if s.Compile() got called
}
<|endoftext|>


<commit_before>// Copyright 2016 The Prometheus Authors
// 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 collector

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/log"
)

// Numerical metric provided by /proc/drbd.
type drbdNumericalMetric struct {
	desc       *prometheus.Desc
	valueType  prometheus.ValueType
	multiplier float64
}

func newDRBDNumericalMetric(name string, desc string, valueType prometheus.ValueType, multiplier float64) drbdNumericalMetric {
	return drbdNumericalMetric{
		desc: prometheus.NewDesc(
			prometheus.BuildFQName(Namespace, "drbd", name),
			desc,
			[]string{"device"}, nil),
		valueType:  valueType,
		multiplier: multiplier,
	}
}

// String pair metric provided by /proc/drbd.
type drbdStringPairMetric struct {
	desc      *prometheus.Desc
	valueOkay string
}

func (metric *drbdStringPairMetric) isOkay(value string) float64 {
	if value == metric.valueOkay {
		return 1
	}
	return 0
}

func newDRBDStringPairMetric(name string, desc string, valueOkay string) drbdStringPairMetric {
	return drbdStringPairMetric{
		desc: prometheus.NewDesc(
			prometheus.BuildFQName(Namespace, "drbd", name),
			desc,
			[]string{"device", "node"}, nil),
		valueOkay: valueOkay,
	}
}

var (
	drbdNumericalMetrics = map[string]drbdNumericalMetric{
		"ns": newDRBDNumericalMetric(
			"network_sent_bytes_total",
			"Total number of bytes sent via the network.",
			prometheus.CounterValue,
			1024),
		"nr": newDRBDNumericalMetric(
			"network_received_bytes_total",
			"Total number of bytes received via the network.",
			prometheus.CounterValue,
			1),
		"dw": newDRBDNumericalMetric(
			"disk_written_bytes_total",
			"Net data written on local hard disk; in bytes.",
			prometheus.CounterValue,
			1024),
		"dr": newDRBDNumericalMetric(
			"disk_read_bytes_total",
			"Net data read from local hard disk; in bytes.",
			prometheus.CounterValue,
			1024),
		"al": newDRBDNumericalMetric(
			"activitylog_writes_total",
			"Number of updates of the activity log area of the meta data.",
			prometheus.CounterValue,
			1),
		"bm": newDRBDNumericalMetric(
			"bitmap_writes_total",
			"Number of updates of the bitmap area of the meta data.",
			prometheus.CounterValue,
			1),
		"lo": newDRBDNumericalMetric(
			"local_pending",
			"Number of open requests to the local I/O sub-system.",
			prometheus.GaugeValue,
			1),
		"pe": newDRBDNumericalMetric(
			"remote_pending",
			"Number of requests sent to the peer, but that have not yet been answered by the latter.",
			prometheus.GaugeValue,
			1),
		"ua": newDRBDNumericalMetric(
			"remote_unacknowledged",
			"Number of requests received by the peer via the network connection, but that have not yet been answered.",
			prometheus.GaugeValue,
			1),
		"ap": newDRBDNumericalMetric(
			"application_pending",
			"Number of block I/O requests forwarded to DRBD, but not yet answered by DRBD.",
			prometheus.GaugeValue,
			1),
		"ep": newDRBDNumericalMetric(
			"epochs",
			"Number of Epochs currently on the fly.",
			prometheus.GaugeValue,
			1),
		"oos": newDRBDNumericalMetric(
			"out_of_sync_bytes",
			"Amount of data known to be out of sync; in bytes.",
			prometheus.GaugeValue,
			1024),
	}
	drbdStringPairMetrics = map[string]drbdStringPairMetric{
		"ro": newDRBDStringPairMetric(
			"node_role_is_primary",
			"Whether the role of the node is in the primary state.",
			"Primary"),
		"ds": newDRBDStringPairMetric(
			"disk_state_is_up_to_date",
			"Whether the disk of the node is up to date.",
			"UpToDate"),
	}

	drbdConnected = prometheus.NewDesc(
		prometheus.BuildFQName(Namespace, "drbd", "connected"),
		"Whether DRBD is connected to the peer.",
		[]string{"device"}, nil)
)

type drbdCollector struct{}

func init() {
	Factories["drbd"] = newDRBDCollector
}

func newDRBDCollector() (Collector, error) {
	return &drbdCollector{}, nil
}

func (c *drbdCollector) Update(ch chan<- prometheus.Metric) (err error) {
	statsFile := procFilePath("drbd")
	file, err := os.Open(statsFile)
	if err != nil {
		if os.IsNotExist(err) {
			log.Debugf("Not collecting DRBD statistics, as %s does not exist: %s", statsFile, err)
			return nil
		}
		return err
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	scanner.Split(bufio.ScanWords)
	device := "unknown"
	for scanner.Scan() {
		field := scanner.Text()
		if kv := strings.Split(field, ":"); len(kv) == 2 {
			if id, err := strconv.ParseUint(kv[0], 10, 64); err == nil && kv[1] == "" {
				device = fmt.Sprintf("drbd%d", id)
			} else if metric, ok := drbdNumericalMetrics[kv[0]]; ok {
				// Numerical value.
				value, err := strconv.ParseFloat(kv[1], 64)
				if err != nil {
					return err
				}
				ch <- prometheus.MustNewConstMetric(
					metric.desc, metric.valueType,
					value*metric.multiplier, device)
			} else if metric, ok := drbdStringPairMetrics[kv[0]]; ok {
				// String pair value.
				values := strings.Split(kv[1], "/")
				ch <- prometheus.MustNewConstMetric(
					metric.desc, prometheus.GaugeValue,
					metric.isOkay(values[0]), device, "local")
				ch <- prometheus.MustNewConstMetric(
					metric.desc, prometheus.GaugeValue,
					metric.isOkay(values[1]), device, "remote")
			} else if kv[0] == "cs" {
				// Connection state.
				var connected float64
				if kv[1] == "Connected" {
					connected = 1
				}
				ch <- prometheus.MustNewConstMetric(
					drbdConnected, prometheus.GaugeValue,
					connected, device)
			} else {
				log.Infof("Don't know how to process key-value pair [%s: %q]", kv[0], kv[1])
			}
		} else {
			log.Infof("Don't know how to process string %q", field)
		}
	}
	return scanner.Err()
}
<commit_msg>Reduce the severity of these messages.<commit_after>// Copyright 2016 The Prometheus Authors
// 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 collector

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/log"
)

// Numerical metric provided by /proc/drbd.
type drbdNumericalMetric struct {
	desc       *prometheus.Desc
	valueType  prometheus.ValueType
	multiplier float64
}

func newDRBDNumericalMetric(name string, desc string, valueType prometheus.ValueType, multiplier float64) drbdNumericalMetric {
	return drbdNumericalMetric{
		desc: prometheus.NewDesc(
			prometheus.BuildFQName(Namespace, "drbd", name),
			desc,
			[]string{"device"}, nil),
		valueType:  valueType,
		multiplier: multiplier,
	}
}

// String pair metric provided by /proc/drbd.
type drbdStringPairMetric struct {
	desc      *prometheus.Desc
	valueOkay string
}

func (metric *drbdStringPairMetric) isOkay(value string) float64 {
	if value == metric.valueOkay {
		return 1
	}
	return 0
}

func newDRBDStringPairMetric(name string, desc string, valueOkay string) drbdStringPairMetric {
	return drbdStringPairMetric{
		desc: prometheus.NewDesc(
			prometheus.BuildFQName(Namespace, "drbd", name),
			desc,
			[]string{"device", "node"}, nil),
		valueOkay: valueOkay,
	}
}

var (
	drbdNumericalMetrics = map[string]drbdNumericalMetric{
		"ns": newDRBDNumericalMetric(
			"network_sent_bytes_total",
			"Total number of bytes sent via the network.",
			prometheus.CounterValue,
			1024),
		"nr": newDRBDNumericalMetric(
			"network_received_bytes_total",
			"Total number of bytes received via the network.",
			prometheus.CounterValue,
			1),
		"dw": newDRBDNumericalMetric(
			"disk_written_bytes_total",
			"Net data written on local hard disk; in bytes.",
			prometheus.CounterValue,
			1024),
		"dr": newDRBDNumericalMetric(
			"disk_read_bytes_total",
			"Net data read from local hard disk; in bytes.",
			prometheus.CounterValue,
			1024),
		"al": newDRBDNumericalMetric(
			"activitylog_writes_total",
			"Number of updates of the activity log area of the meta data.",
			prometheus.CounterValue,
			1),
		"bm": newDRBDNumericalMetric(
			"bitmap_writes_total",
			"Number of updates of the bitmap area of the meta data.",
			prometheus.CounterValue,
			1),
		"lo": newDRBDNumericalMetric(
			"local_pending",
			"Number of open requests to the local I/O sub-system.",
			prometheus.GaugeValue,
			1),
		"pe": newDRBDNumericalMetric(
			"remote_pending",
			"Number of requests sent to the peer, but that have not yet been answered by the latter.",
			prometheus.GaugeValue,
			1),
		"ua": newDRBDNumericalMetric(
			"remote_unacknowledged",
			"Number of requests received by the peer via the network connection, but that have not yet been answered.",
			prometheus.GaugeValue,
			1),
		"ap": newDRBDNumericalMetric(
			"application_pending",
			"Number of block I/O requests forwarded to DRBD, but not yet answered by DRBD.",
			prometheus.GaugeValue,
			1),
		"ep": newDRBDNumericalMetric(
			"epochs",
			"Number of Epochs currently on the fly.",
			prometheus.GaugeValue,
			1),
		"oos": newDRBDNumericalMetric(
			"out_of_sync_bytes",
			"Amount of data known to be out of sync; in bytes.",
			prometheus.GaugeValue,
			1024),
	}
	drbdStringPairMetrics = map[string]drbdStringPairMetric{
		"ro": newDRBDStringPairMetric(
			"node_role_is_primary",
			"Whether the role of the node is in the primary state.",
			"Primary"),
		"ds": newDRBDStringPairMetric(
			"disk_state_is_up_to_date",
			"Whether the disk of the node is up to date.",
			"UpToDate"),
	}

	drbdConnected = prometheus.NewDesc(
		prometheus.BuildFQName(Namespace, "drbd", "connected"),
		"Whether DRBD is connected to the peer.",
		[]string{"device"}, nil)
)

type drbdCollector struct{}

func init() {
	Factories["drbd"] = newDRBDCollector
}

func newDRBDCollector() (Collector, error) {
	return &drbdCollector{}, nil
}

func (c *drbdCollector) Update(ch chan<- prometheus.Metric) (err error) {
	statsFile := procFilePath("drbd")
	file, err := os.Open(statsFile)
	if err != nil {
		if os.IsNotExist(err) {
			log.Debugf("Not collecting DRBD statistics, as %s does not exist: %s", statsFile, err)
			return nil
		}
		return err
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	scanner.Split(bufio.ScanWords)
	device := "unknown"
	for scanner.Scan() {
		field := scanner.Text()
		if kv := strings.Split(field, ":"); len(kv) == 2 {
			if id, err := strconv.ParseUint(kv[0], 10, 64); err == nil && kv[1] == "" {
				device = fmt.Sprintf("drbd%d", id)
			} else if metric, ok := drbdNumericalMetrics[kv[0]]; ok {
				// Numerical value.
				value, err := strconv.ParseFloat(kv[1], 64)
				if err != nil {
					return err
				}
				ch <- prometheus.MustNewConstMetric(
					metric.desc, metric.valueType,
					value*metric.multiplier, device)
			} else if metric, ok := drbdStringPairMetrics[kv[0]]; ok {
				// String pair value.
				values := strings.Split(kv[1], "/")
				ch <- prometheus.MustNewConstMetric(
					metric.desc, prometheus.GaugeValue,
					metric.isOkay(values[0]), device, "local")
				ch <- prometheus.MustNewConstMetric(
					metric.desc, prometheus.GaugeValue,
					metric.isOkay(values[1]), device, "remote")
			} else if kv[0] == "cs" {
				// Connection state.
				var connected float64
				if kv[1] == "Connected" {
					connected = 1
				}
				ch <- prometheus.MustNewConstMetric(
					drbdConnected, prometheus.GaugeValue,
					connected, device)
			} else {
				log.Debugf("Don't know how to process key-value pair [%s: %q]", kv[0], kv[1])
			}
		} else {
			log.Debugf("Don't know how to process string %q", field)
		}
	}
	return scanner.Err()
}
<|endoftext|>


<commit_before>package evar

import (
	// "fmt"
	"strings"

	"github.com/spf13/cobra"

	"github.com/nanobox-io/nanobox/commands/steps"
	"github.com/nanobox-io/nanobox/helpers"
	"github.com/nanobox-io/nanobox/models"
	app_evar "github.com/nanobox-io/nanobox/processors/app/evar"
	production_evar "github.com/nanobox-io/nanobox/processors/evar"
	"github.com/nanobox-io/nanobox/util/config"
	"github.com/nanobox-io/nanobox/util/display"
)

// RemoveCmd ...
var RemoveCmd = &cobra.Command{
	Use:   "rm",
	Short: "Remove environment variable(s)",
	Long:  ``,
	// PreRun: steps.Run("login"),
	Run: removeFn,
}

// removeFn ...
func removeFn(ccmd *cobra.Command, args []string) {
	// parse the evars excluding the context
	env, _ := models.FindEnvByID(config.EnvID())
	args, location, name := helpers.Endpoint(env, args, 0)
	evars := parseKeys(args)

	switch location {
	case "local":
		app, _ := models.FindAppBySlug(config.EnvID(), name)
		display.CommandErr(app_evar.Remove(app, evars))
	case "production":
		steps.Run("login")(ccmd, args)

		env, _ := models.FindEnvByID(config.EnvID())

		production_evar.Remove(env, name, evars)
	}
}

func parseKeys(args []string) []string {
	keys := []string{}

	for _, arg := range args {
		for _, key := range strings.Split(arg, ",") {
			if key != "" {
				keys = append(keys, key)
			}
		}
	}

	return keys
}
<commit_msg>Unify removing an evar (case insensitivity)<commit_after>package evar

import (
	"fmt"
	"strings"

	"github.com/spf13/cobra"

	"github.com/nanobox-io/nanobox/commands/steps"
	"github.com/nanobox-io/nanobox/helpers"
	"github.com/nanobox-io/nanobox/models"
	app_evar "github.com/nanobox-io/nanobox/processors/app/evar"
	production_evar "github.com/nanobox-io/nanobox/processors/evar"
	"github.com/nanobox-io/nanobox/util/config"
	"github.com/nanobox-io/nanobox/util/display"
)

// RemoveCmd removes an evar.
var RemoveCmd = &cobra.Command{
	Use:   "rm [local|dry-run] key",
	Short: "Remove environment variable(s)",
	Long:  ``,
	// PreRun: steps.Run("login"),
	Run: removeFn,
}

// removeFn ...
func removeFn(ccmd *cobra.Command, args []string) {
	// parse the evars excluding the context
	env, _ := models.FindEnvByID(config.EnvID())
	args, location, name := helpers.Endpoint(env, args, 0)

	if len(args) < 1 {
		fmt.Printf(`
--------------------------------------------
Please provide the key you'd like to remove!
--------------------------------------------

`)
		ccmd.HelpFunc()(ccmd, args)
		return
	}

	evars := parseKeys(args)

	switch location {
	case "local":
		app, _ := models.FindAppBySlug(config.EnvID(), name)
		display.CommandErr(app_evar.Remove(app, evars))
	case "production":
		steps.Run("login")(ccmd, args)

		env, _ := models.FindEnvByID(config.EnvID())

		production_evar.Remove(env, name, evars)
	}
}

func parseKeys(args []string) []string {
	keys := []string{}

	for _, arg := range args {
		for _, key := range strings.Split(arg, ",") {
			if key != "" {
				keys = append(keys, strings.ToUpper(key))
			}
		}
	}

	return keys
}
<|endoftext|>


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

// +build freebsd

package cgo

import _ "unsafe" // for go:linkname

// Supply environ and __progname, because we don't
// link against the standard FreeBSD crt0.o and the
// libc dynamic library needs them.

//go:linkname _environ environ
//go:linkname _progname __progname

//go:cgo_export_static environ
//go:cgo_export_static __progname

var _environ uintptr
var _progname uintptr
<commit_msg>[dev.cc] [dev.cc] runtime: fix freebsd cgo __progname export<commit_after>// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build freebsd

package cgo

import _ "unsafe" // for go:linkname

// Supply environ and __progname, because we don't
// link against the standard FreeBSD crt0.o and the
// libc dynamic library needs them.

//go:linkname _environ environ
//go:linkname _progname __progname

//go:cgo_export_dynamic environ
//go:cgo_export_dynamic __progname

var _environ uintptr
var _progname uintptr
<|endoftext|>


<commit_before>package common

import (
	"encoding/json"
	"fmt"
	"strings"

	"gitlab.com/gitlab-org/gitlab-ci-multi-runner/helpers"
)

type BuildOptions map[string]interface{}

func (m *BuildOptions) Get(keys ...string) (interface{}, bool) {
	return helpers.GetMapKey(*m, keys...)
}

func (m *BuildOptions) GetSubOptions(keys ...string) (result BuildOptions, ok bool) {
	value, ok := helpers.GetMapKey(*m, keys...)
	if ok {
		result, ok = value.(map[string]interface{})
	}
	return
}

func (m *BuildOptions) GetString(keys ...string) (result string, ok bool) {
	value, ok := helpers.GetMapKey(*m, keys...)
	if ok {
		result, ok = value.(string)
	}
	return
}

func (m *BuildOptions) Decode(result interface{}, keys ...string) error {
	value, ok := m.Get(keys...)
	if !ok {
		return fmt.Errorf("key not found %v", strings.Join(keys, "."))
	}

	data, err := json.Marshal(value)
	if err != nil {
		return err
	}

	return json.Unmarshal(data, result)
}

func convertMapToStringMap(in interface{}) (out interface{}, err error) {
	mapString, ok := in.(map[string]interface{})
	if ok {
		for k, v := range mapString {
			mapString[k], err = convertMapToStringMap(v)
			if err != nil {
				return
			}
		}
		return mapString, nil
	}

	mapInterface, ok := in.(map[interface{}]interface{})
	if ok {
		mapString := make(map[string]interface{})
		for k, v := range mapInterface {
			kString, ok := k.(string)
			if !ok {
				return nil, fmt.Errorf("failed to convert %v to string", k)
			}

			mapString[kString], err = convertMapToStringMap(v)
			if err != nil {
				return
			}
		}
		return mapString, nil
	}

	return in, nil
}

func (m *BuildOptions) Sanitize() (err error) {
	n := make(BuildOptions)
	for k, v := range *m {
		n[k], err = convertMapToStringMap(v)
		if err != nil {
			return
		}
	}
	*m = n
	return
}
<commit_msg>Make lint happy<commit_after>package common

import (
	"encoding/json"
	"fmt"
	"strings"

	"gitlab.com/gitlab-org/gitlab-ci-multi-runner/helpers"
)

type BuildOptions map[string]interface{}

func (m *BuildOptions) Get(keys ...string) (interface{}, bool) {
	return helpers.GetMapKey(*m, keys...)
}

func (m *BuildOptions) GetSubOptions(keys ...string) (result BuildOptions, ok bool) {
	value, ok := helpers.GetMapKey(*m, keys...)
	if ok {
		result, ok = value.(map[string]interface{})
	}
	return
}

func (m *BuildOptions) GetString(keys ...string) (result string, ok bool) {
	value, ok := helpers.GetMapKey(*m, keys...)
	if ok {
		result, ok = value.(string)
	}
	return
}

func (m *BuildOptions) Decode(result interface{}, keys ...string) error {
	value, ok := m.Get(keys...)
	if !ok {
		return fmt.Errorf("key not found %v", strings.Join(keys, "."))
	}

	data, err := json.Marshal(value)
	if err != nil {
		return err
	}

	return json.Unmarshal(data, result)
}

func convertMapToStringMap(in interface{}) (out interface{}, err error) {
	mapString, ok := in.(map[string]interface{})
	if ok {
		for k, v := range mapString {
			mapString[k], err = convertMapToStringMap(v)
			if err != nil {
				return
			}
		}
		return mapString, nil
	}

	mapInterface, ok := in.(map[interface{}]interface{})
	if ok {
		mapString := make(map[string]interface{})
		for k, v := range mapInterface {
			key, ok := k.(string)
			if !ok {
				return nil, fmt.Errorf("failed to convert %v to string", k)
			}

			mapString[key], err = convertMapToStringMap(v)
			if err != nil {
				return
			}
		}
		return mapString, nil
	}

	return in, nil
}

func (m *BuildOptions) Sanitize() (err error) {
	n := make(BuildOptions)
	for k, v := range *m {
		n[k], err = convertMapToStringMap(v)
		if err != nil {
			return
		}
	}
	*m = n
	return
}
<|endoftext|>


<commit_before>// Copyright 2014 The Serviced Authors.
// 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 docker

import (
	"fmt"

	"github.com/control-center/serviced/commons"
	"github.com/zenoss/glog"
)

// ServiceUse will tag a new image (imageName) in a given registry for a given tenant
// to latest, making sure to push changes to the registry
func ServiceUse(serviceID string, imageName string, registry string, noOp bool) (string, error) {
	pullImage := PullImage
	findImage := FindImage
	tagImage := TagImage
	if noOp {
		pullImage = noOpPullImage
		findImage = noOpFindImage
		tagImage = noOpTagImage
	}

	glog.V(0).Infof("preparing to use image: %s", imageName)
	imageID, err := commons.ParseImageID(imageName)
	if err != nil {
		return "", err
	}
	if imageID.Tag == "" {
		imageID.Tag = "latest"
	}
	glog.Infof("pulling image %s, this may take a while...", imageID)
	if err := pullImage(imageID.String()); err != nil {
		glog.Warningf("unable to pull image %s", imageID)
	}

	//verify image has been pulled
	img, err := findImage(imageID.String(), false)
	if err != nil {
		err = fmt.Errorf("could not look up image %s: %s. Check your docker login and retry service deployment.", imageID, err)
		return "", err
	}

	//Tag images to latest all images
	var newTag *commons.ImageID

	newTag, err = commons.RenameImageID(registry, serviceID, imageID.String(), "latest")
	if err != nil {
		return "", err
	}
	glog.Infof("tagging image %s to %s ", imageName, newTag)
	if _, err = tagImage(img, newTag.String()); err != nil {
		glog.Errorf("could not tag image: %s (%v)", imageName, err)
		return "", err
	}
	return newTag.String(), nil
}

func noOpTagImage(img *Image, tag string) (*Image, error) {
	return nil, nil
}

func noOpFindImage(repotag string, pull bool) (*Image, error) {
	return nil, nil
}

func noOpPullImage(repotag string) error {
	return nil
}
<commit_msg>Review feedback, add comment to clarify noOp code<commit_after>// Copyright 2014 The Serviced Authors.
// 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 docker

import (
	"fmt"

	"github.com/control-center/serviced/commons"
	"github.com/zenoss/glog"
)

// ServiceUse will tag a new image (imageName) in a given registry for a given tenant
// to latest, making sure to push changes to the registry
func ServiceUse(serviceID string, imageName string, registry string, noOp bool) (string, error) {
	// If noOp is True, then replace the 'real' functions that talk to Docker with
	// no-op functions (for dry run purposes)
	pullImage := PullImage
	findImage := FindImage
	tagImage := TagImage
	if noOp {
		pullImage = noOpPullImage
		findImage = noOpFindImage
		tagImage = noOpTagImage
	}

	glog.V(0).Infof("preparing to use image: %s", imageName)
	imageID, err := commons.ParseImageID(imageName)
	if err != nil {
		return "", err
	}
	if imageID.Tag == "" {
		imageID.Tag = "latest"
	}
	glog.Infof("pulling image %s, this may take a while...", imageID)
	if err := pullImage(imageID.String()); err != nil {
		glog.Warningf("unable to pull image %s", imageID)
	}

	//verify image has been pulled
	img, err := findImage(imageID.String(), false)
	if err != nil {
		err = fmt.Errorf("could not look up image %s: %s. Check your docker login and retry service deployment.", imageID, err)
		return "", err
	}

	//Tag images to latest all images
	var newTag *commons.ImageID

	newTag, err = commons.RenameImageID(registry, serviceID, imageID.String(), "latest")
	if err != nil {
		return "", err
	}
	glog.Infof("tagging image %s to %s ", imageName, newTag)
	if _, err = tagImage(img, newTag.String()); err != nil {
		glog.Errorf("could not tag image: %s (%v)", imageName, err)
		return "", err
	}
	return newTag.String(), nil
}

func noOpTagImage(img *Image, tag string) (*Image, error) {
	return nil, nil
}

func noOpFindImage(repotag string, pull bool) (*Image, error) {
	return nil, nil
}

func noOpPullImage(repotag string) error {
	return nil
}
<|endoftext|>


<commit_before>package lxc

import (
	"fmt"
	"github.com/mitchellh/packer/packer"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"syscall"
	"strings"
)

type LxcAttachCommunicator struct {
	RootFs        string
	ContainerName string
	CmdWrapper    CommandWrapper
}

func (c *LxcAttachCommunicator) Start(cmd *packer.RemoteCmd) error {
	localCmd, err := c.Execute(cmd.Command)

	if err != nil {
		return err
	}

	localCmd.Stdin = cmd.Stdin
	localCmd.Stdout = cmd.Stdout
	localCmd.Stderr = cmd.Stderr
	if err := localCmd.Start(); err != nil {
		return err
	}

	go func() {
		exitStatus := 0
		if err := localCmd.Wait(); err != nil {
			if exitErr, ok := err.(*exec.ExitError); ok {
				exitStatus = 1

				// There is no process-independent way to get the REAL
				// exit status so we just try to go deeper.
				if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
					exitStatus = status.ExitStatus()
				}
			}
		}

		log.Printf(
			"lxc-attach execution exited with '%d': '%s'",
			exitStatus, cmd.Command)
		cmd.SetExited(exitStatus)
	}()

	return nil
}

func (c *LxcAttachCommunicator) Upload(dst string, r io.Reader, fi *os.FileInfo) error {
	dst = filepath.Join(c.RootFs, dst)
	log.Printf("Uploading to rootfs: %s", dst)
	tf, err := ioutil.TempFile("", "packer-lxc-attach")
	if err != nil {
		return fmt.Errorf("Error uploading file to rootfs: %s", err)
	}
	defer os.Remove(tf.Name())
	io.Copy(tf, r)

	cpCmd, err := c.CmdWrapper(fmt.Sprintf("sudo cp %s %s", tf.Name(), dst))
	if err != nil {
		return err
	}

	log.Printf("Running copy command: %s", dst)

	return ShellCommand(cpCmd).Run()
}

func (c *LxcAttachCommunicator) UploadDir(dst string, src string, exclude []string) error {
	// TODO: remove any file copied if it appears in `exclude`
	dest := filepath.Join(c.RootFs, dst)
	log.Printf("Uploading directory '%s' to rootfs '%s'", src, dest)
	cpCmd, err := c.CmdWrapper(fmt.Sprintf("sudo cp -R %s %s", src, dest))
	if err != nil {
		return err
	}

	return ShellCommand(cpCmd).Run()
}

func (c *LxcAttachCommunicator) Download(src string, w io.Writer) error {
	src = filepath.Join(c.RootFs, src)
	log.Printf("Downloading from rootfs dir: %s", src)
	f, err := os.Open(src)
	if err != nil {
		return err
	}
	defer f.Close()

	if _, err := io.Copy(w, f); err != nil {
		return err
	}

	return nil
}

func (c *LxcAttachCommunicator) Execute(commandString string) (*exec.Cmd, error) {
	log.Printf("Executing with lxc-attach in container: %s %s %s", c.ContainerName, c.RootFs, commandString)
	command, err := c.CmdWrapper(
		fmt.Sprintf("sudo lxc-attach --name %s -- /bin/sh -c \"%s\"", c.ContainerName, commandString))
	if err != nil {
		return nil, err
	}

	localCmd := ShellCommand(command)
	log.Printf("Executing lxc-attach: %s %#v", localCmd.Path, localCmd.Args)

	return localCmd, nil
}

func (c *LxcAttachCommunicator) CheckInit() (string, error) {
	log.Printf("Debug runlevel exec")
	localCmd, err := c.Execute("/sbin/runlevel")

	if err != nil {
		return "", err
	}

	pr, _ := localCmd.StdoutPipe()
	if err = localCmd.Start(); err != nil {
		return "", err
	}

	output, err := ioutil.ReadAll(pr)

	if err != nil {
		return "", err
	}

	err = localCmd.Wait()

	if err != nil {
		return "", err
	}

	return strings.TrimSpace(string(output)), nil
}<commit_msg>Use /. to avoid cp to automatically creating a subdirectory.<commit_after>package lxc

import (
	"fmt"
	"github.com/mitchellh/packer/packer"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"syscall"
	"strings"
)

type LxcAttachCommunicator struct {
	RootFs        string
	ContainerName string
	CmdWrapper    CommandWrapper
}

func (c *LxcAttachCommunicator) Start(cmd *packer.RemoteCmd) error {
	localCmd, err := c.Execute(cmd.Command)

	if err != nil {
		return err
	}

	localCmd.Stdin = cmd.Stdin
	localCmd.Stdout = cmd.Stdout
	localCmd.Stderr = cmd.Stderr
	if err := localCmd.Start(); err != nil {
		return err
	}

	go func() {
		exitStatus := 0
		if err := localCmd.Wait(); err != nil {
			if exitErr, ok := err.(*exec.ExitError); ok {
				exitStatus = 1

				// There is no process-independent way to get the REAL
				// exit status so we just try to go deeper.
				if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
					exitStatus = status.ExitStatus()
				}
			}
		}

		log.Printf(
			"lxc-attach execution exited with '%d': '%s'",
			exitStatus, cmd.Command)
		cmd.SetExited(exitStatus)
	}()

	return nil
}

func (c *LxcAttachCommunicator) Upload(dst string, r io.Reader, fi *os.FileInfo) error {
	dst = filepath.Join(c.RootFs, dst)
	log.Printf("Uploading to rootfs: %s", dst)
	tf, err := ioutil.TempFile("", "packer-lxc-attach")
	if err != nil {
		return fmt.Errorf("Error uploading file to rootfs: %s", err)
	}
	defer os.Remove(tf.Name())
	io.Copy(tf, r)

	cpCmd, err := c.CmdWrapper(fmt.Sprintf("sudo cp %s %s", tf.Name(), dst))
	if err != nil {
		return err
	}

	log.Printf("Running copy command: %s", dst)

	return ShellCommand(cpCmd).Run()
}

func (c *LxcAttachCommunicator) UploadDir(dst string, src string, exclude []string) error {
	// TODO: remove any file copied if it appears in `exclude`
	dest := filepath.Join(c.RootFs, dst)
	log.Printf("Uploading directory '%s' to rootfs '%s'", src, dest)
	cpCmd, err := c.CmdWrapper(fmt.Sprintf("sudo cp -R %s/. %s", src, dest))
	if err != nil {
		return err
	}

	return ShellCommand(cpCmd).Run()
}

func (c *LxcAttachCommunicator) Download(src string, w io.Writer) error {
	src = filepath.Join(c.RootFs, src)
	log.Printf("Downloading from rootfs dir: %s", src)
	f, err := os.Open(src)
	if err != nil {
		return err
	}
	defer f.Close()

	if _, err := io.Copy(w, f); err != nil {
		return err
	}

	return nil
}

func (c *LxcAttachCommunicator) Execute(commandString string) (*exec.Cmd, error) {
	log.Printf("Executing with lxc-attach in container: %s %s %s", c.ContainerName, c.RootFs, commandString)
	command, err := c.CmdWrapper(
		fmt.Sprintf("sudo lxc-attach --name %s -- /bin/sh -c \"%s\"", c.ContainerName, commandString))
	if err != nil {
		return nil, err
	}

	localCmd := ShellCommand(command)
	log.Printf("Executing lxc-attach: %s %#v", localCmd.Path, localCmd.Args)

	return localCmd, nil
}

func (c *LxcAttachCommunicator) CheckInit() (string, error) {
	log.Printf("Debug runlevel exec")
	localCmd, err := c.Execute("/sbin/runlevel")

	if err != nil {
		return "", err
	}

	pr, _ := localCmd.StdoutPipe()
	if err = localCmd.Start(); err != nil {
		return "", err
	}

	output, err := ioutil.ReadAll(pr)

	if err != nil {
		return "", err
	}

	err = localCmd.Wait()

	if err != nil {
		return "", err
	}

	return strings.TrimSpace(string(output)), nil
}<|endoftext|>


<commit_before>package translator

import (
	"fmt"
	"go/token"
	"strings"

	"github.com/cznic/cc"
	"github.com/cznic/xc"
)

func (t *Translator) walkTranslationUnit(unit *cc.TranslationUnit) {
	t.fileScope = unit.Declarations
	for unit != nil {
		t.walkExternalDeclaration(unit.ExternalDeclaration)
		unit = unit.TranslationUnit
	}
}

func (t *Translator) walkExternalDeclaration(d *cc.ExternalDeclaration) {
	switch d.Case {
	case 0: // FunctionDefinition
		var decl *CDecl
		if declr := d.FunctionDefinition.Declarator; declr != nil {
			decl = t.declarator(declr)
			t.registerTagsOf(decl)
		} else {
			return
		}
		if decl.IsTypedef {
			t.typedefs = append(t.typedefs, decl)
			t.typedefsSet[decl.Name] = struct{}{}
			return
		}
		t.declares = append(t.declares, decl)
	case 1: // Declaration
		declares := t.walkDeclaration(d.Declaration)
		for _, decl := range declares {
			if decl.IsTypedef {
				t.typedefs = append(t.typedefs, decl)
				t.typedefsSet[decl.Name] = struct{}{}
				continue
			}
			t.declares = append(t.declares, decl)
		}
	}
}

func (t *Translator) walkDeclaration(d *cc.Declaration) (declared []*CDecl) {
	if d.InitDeclaratorListOpt != nil {
		list := d.InitDeclaratorListOpt.InitDeclaratorList
		for list != nil {
			decl := t.declarator(list.InitDeclarator.Declarator)
			init := list.InitDeclarator.Initializer
			if init != nil && init.Expression != nil {
				decl.Value = init.Expression.Value
				decl.Expression = blessName(init.Expression.Token.S())
			}
			t.registerTagsOf(decl)
			declared = append(declared, decl)
			if init != nil {
				t.valueMap[decl.Name] = decl.Value
				t.exprMap[decl.Name] = decl.Expression
			}
			list = list.InitDeclaratorList
		}
	} else if declr := d.Declarator(); declr != nil {
		decl := t.declarator(declr)
		t.registerTagsOf(decl)
		declared = append(declared, decl)
	}
	return
}

func (t *Translator) declarator(d *cc.Declarator) *CDecl {
	specifier := d.RawSpecifier()
	decl := &CDecl{
		Spec:      t.typeSpec(d.Type, 0, false),
		Name:      identifierOf(d.DirectDeclarator),
		IsTypedef: specifier.IsTypedef(),
		IsStatic:  specifier.IsStatic(),
		Pos:       d.Pos(),
	}
	return decl
}

func (t *Translator) getStructTag(typ cc.Type) (tag string) {
	b := t.fileScope.Lookup(cc.NSTags, typ.Tag())
	switch v := b.Node.(type) {
	case *cc.StructOrUnionSpecifier:
		if v.IdentifierOpt != nil {
			return blessName(v.IdentifierOpt.Token.S())
		}
	case xc.Token:
		return blessName(v.S())
	}
	return
}

func (t *Translator) enumSpec(base *CTypeSpec, typ cc.Type) *CEnumSpec {
	tag := blessName(xc.Dict.S(typ.Tag()))
	spec := &CEnumSpec{
		Tag:      tag,
		Pointers: base.Pointers,
		OuterArr: base.OuterArr,
		InnerArr: base.InnerArr,
	}
	list := typ.EnumeratorList()
	for _, en := range list {
		name := blessName(en.DefTok.S())
		m := &CDecl{
			Name: name,
			Pos:  en.DefTok.Pos(),
		}
		switch {
		case en.Value == nil:
			panic("value cannot be nil in enum")
		case t.constRules[ConstEnum] == ConstCGOAlias:
			m.Expression = fmt.Sprintf("C.%s", name)
		case t.constRules[ConstEnum] == ConstExpand:
			srcParts := make([]string, 0, len(en.Tokens))
			exprParts := make([]string, 0, len(en.Tokens))
			valid := true

			// TODO: some state machine
			needsTypecast := false
			typecastValue := false
			typecastValueParens := 0

			for _, token := range en.Tokens {
				src := cc.TokSrc(token)
				srcParts = append(srcParts, src)
				switch token.Rune {
				case cc.IDENTIFIER:
					exprParts = append(exprParts, string(t.TransformName(TargetConst, src, true)))
				default:
					// TODO: state machine
					const (
						lparen = rune(40)
						rparen = rune(41)
					)
					switch {
					case needsTypecast && token.Rune == rparen:
						typecastValue = true
						needsTypecast = false
						exprParts = append(exprParts, src+"(")
					case typecastValue && token.Rune == lparen:
						typecastValueParens++
					case typecastValue && token.Rune == rparen:
						if typecastValueParens == 0 {
							typecastValue = false
							exprParts = append(exprParts, ")"+src)
						} else {
							typecastValueParens--
						}
					default:
						// somewhere in the world a helpless kitten died because of this
						if token.Rune == '~' {
							src = "^"
						}
						if runes := []rune(src); len(runes) > 0 && isNumeric(runes) {
							// TODO(xlab): better const handling
							src = readNumeric(runes)
						}
						exprParts = append(exprParts, src)
					}
				}
				if !valid {
					break
				}
			}
			if typecastValue {
				// still in typecast value, need to close paren
				exprParts = append(exprParts, ")")
				typecastValue = false
			}

			if len(exprParts) > 0 {
				m.Expression = strings.Join(exprParts, " ")
			} else {
				m.Value = en.Value
			}
			m.Src = strings.Join(srcParts, " ")
		default:
			m.Value = en.Value
		}
		m.Spec = spec.PromoteType(en.Value)
		spec.Members = append(spec.Members, m)
		t.valueMap[m.Name] = en.Value
		t.exprMap[m.Name] = m.Expression
	}

	return spec
}

func (t *Translator) walkEnumerator(e *cc.Enumerator) *CDecl {
	decl := &CDecl{
		Name: blessName(e.EnumerationConstant.Token.S()),
	}
	switch e.Case {
	case 0: // EnumerationConstant
	case 1: // EnumerationConstant '=' ConstantExpression
		decl.Value = e.ConstantExpression.Value
		decl.Expression = string(e.ConstantExpression.Expression.Token.S())
	}
	return decl
}

const maxDeepLevel = 3

func (t *Translator) structSpec(base *CTypeSpec, typ cc.Type, deep int) *CStructSpec {
	tag := t.getStructTag(typ)
	spec := &CStructSpec{
		Tag:      tag,
		IsUnion:  typ.Kind() == cc.Union,
		Pointers: base.Pointers,
		OuterArr: base.OuterArr,
		InnerArr: base.InnerArr,
	}
	if deep > maxDeepLevel {
		return spec
	}
	members, _ := typ.Members()
	for i, m := range members {
		var pos token.Pos
		if m.Declarator != nil {
			pos = m.Declarator.Pos()
		}
		spec.Members = append(spec.Members, &CDecl{
			Name: memberName(i, m),
			Spec: t.typeSpec(m.Type, deep+1, false),
			Pos:  pos,
		})
	}
	return spec
}

func (t *Translator) functionSpec(base *CTypeSpec, typ cc.Type, deep int) *CFunctionSpec {
	spec := &CFunctionSpec{
		Pointers: base.Pointers,
	}
	if deep > 2 { // a function inside params of another function
		spec.Raw = typedefNameOf(typ)
	} else {
		spec.Raw = identifierOf(typ.Declarator().DirectDeclarator)
	}
	if deep > maxDeepLevel {
		return spec
	}
	if ret := typ.Result(); ret != nil && ret.Kind() != cc.Void {
		spec.Return = t.typeSpec(ret, deep+1, true)
	}
	params, _ := typ.Parameters()
	for i, p := range params {
		spec.Params = append(spec.Params, &CDecl{
			Name: paramName(i, p),
			Spec: t.typeSpec(p.Type, deep+1, false),
			Pos:  p.Declarator.Pos(),
		})
	}
	return spec
}

func (t *Translator) typeSpec(typ cc.Type, deep int, isRet bool) CType {
	spec := &CTypeSpec{
		Const: typ.Specifier().IsConst(),
	}
	if !isRet {
		spec.Raw = typedefNameOf(typ)
	}

	for typ.Kind() == cc.Array {
		size := typ.Elements()
		typ = typ.Element()
		if size >= 0 {
			spec.AddOuterArr(uint64(size))
		}
	}
	for typ.Kind() == cc.Ptr {
		typ = typ.Element()
		spec.Pointers++
	}
	for typ.Kind() == cc.Array {
		size := typ.Elements()
		typ = typ.Element()
		if size >= 0 {
			spec.AddInnerArr(uint64(size))
		}
	}

	switch typ.Kind() {
	case cc.Void:
		spec.Base = "void"
	case cc.Char:
		spec.Base = "char"
	case cc.SChar:
		spec.Base = "char"
		spec.Signed = true
	case cc.UChar:
		spec.Base = "char"
		spec.Unsigned = true
	case cc.Short:
		spec.Base = "int"
		spec.Short = true
	case cc.UShort:
		spec.Base = "int"
		spec.Short = true
		spec.Unsigned = true
	case cc.Int:
		spec.Base = "int"
	case cc.UInt:
		spec.Base = "int"
		spec.Unsigned = true
	case cc.Long:
		spec.Base = "int"
		spec.Long = true
	case cc.ULong:
		spec.Base = "int"
		spec.Long = true
		spec.Unsigned = true
	case cc.LongLong:
		spec.Base = "long"
		spec.Long = true
	case cc.ULongLong:
		spec.Base = "long"
		spec.Long = true
		spec.Unsigned = true
	case cc.Float:
		spec.Base = "float"
	case cc.Double:
		spec.Base = "double"
	case cc.LongDouble:
		spec.Base = "double"
		spec.Long = true
	case cc.Bool:
		spec.Base = "_Bool"
	case cc.FloatComplex:
		spec.Base = "complexfloat"
		spec.Complex = true
	case cc.DoubleComplex:
		spec.Base = "complexdouble"
		spec.Complex = true
	case cc.LongDoubleComplex:
		spec.Base = "complexdouble"
		spec.Long = true
		spec.Complex = true
	case cc.Enum:
		s := t.enumSpec(spec, typ)
		if !isRet {
			s.Typedef = typedefNameOf(typ)
		}
		return s
	case cc.Union:
		return &CStructSpec{
			Tag:      t.getStructTag(typ),
			IsUnion:  true,
			Pointers: spec.Pointers,
			OuterArr: spec.OuterArr,
			InnerArr: spec.InnerArr,
			Typedef:  typedefNameOf(typ),
		}
	case cc.Struct:
		s := t.structSpec(spec, typ, deep+1)
		if !isRet {
			s.Typedef = typedefNameOf(typ)
		}
		return s
	case cc.Function:
		s := t.functionSpec(spec, typ, deep+1)
		if !isRet && !typ.Specifier().IsTypedef() {
			s.Typedef = typedefNameOf(typ)
			retTyp := typ.Result().RawDeclarator().Type
			retTypedef := typedefNameOf(retTyp)
			if s.Return != nil {
				s.Return.SetRaw(retTypedef)
			}
		}
		return s
	default:
		panic("unknown type " + typ.String())
	}

	return spec
}

func paramName(n int, p cc.Parameter) string {
	if p.Name == 0 {
		return fmt.Sprintf("arg%d", n)
	}
	return blessName(xc.Dict.S(p.Name))
}

func memberName(n int, m cc.Member) string {
	if m.Name == 0 {
		return fmt.Sprintf("field%d", n)
	}
	return blessName(xc.Dict.S(m.Name))
}

func typedefNameOf(typ cc.Type) string {
	// There is a bug in cc's parser that causes it to misidentify the type of
	// a function pointer as its return type.
	// (See https://github.com/cznic/cc/issues/100)
	// To work around this bug, we first check if the type is a function and if
	// so, verify it's declared via a typedef before proceeding to get the
	// typedef's name.
	if typ.Kind() == cc.Function && typ.Declarator().DirectDeclarator.Case != 0 {
		return ""
	}
	rawSpec := typ.Declarator().RawSpecifier()
	if name := rawSpec.TypedefName(); name > 0 {
		return blessName(xc.Dict.S(name))
	} else if rawSpec.IsTypedef() {
		return identifierOf(typ.Declarator().DirectDeclarator)
	}
	return ""
}

func identifierOf(dd *cc.DirectDeclarator) string {
	switch dd.Case {
	case 0: // IDENTIFIER
		if dd.Token.Val == 0 {
			return ""
		}
		return blessName(dd.Token.S())
	case 1: // '(' Declarator ')'
		return identifierOf(dd.Declarator.DirectDeclarator)
	default:
		//	DirectDeclarator '[' TypeQualifierListOpt ExpressionOpt ']'
		//	DirectDeclarator '[' "static" TypeQualifierListOpt Expression ']'
		//	DirectDeclarator '[' TypeQualifierList "static" Expression ']'
		//	DirectDeclarator '[' TypeQualifierListOpt '*' ']'
		//	DirectDeclarator '(' ParameterTypeList ')'
		//	DirectDeclarator '(' IdentifierListOpt ')'
		return identifierOf(dd.DirectDeclarator)
	}
}
<commit_msg>Revert "Workaround issue #100 in cc" See https://github.com/xlab/pocketsphinx-go/issues/9<commit_after>package translator

import (
	"fmt"
	"go/token"
	"strings"

	"github.com/cznic/cc"
	"github.com/cznic/xc"
)

func (t *Translator) walkTranslationUnit(unit *cc.TranslationUnit) {
	t.fileScope = unit.Declarations
	for unit != nil {
		t.walkExternalDeclaration(unit.ExternalDeclaration)
		unit = unit.TranslationUnit
	}
}

func (t *Translator) walkExternalDeclaration(d *cc.ExternalDeclaration) {
	switch d.Case {
	case 0: // FunctionDefinition
		var decl *CDecl
		if declr := d.FunctionDefinition.Declarator; declr != nil {
			decl = t.declarator(declr)
			t.registerTagsOf(decl)
		} else {
			return
		}
		if decl.IsTypedef {
			t.typedefs = append(t.typedefs, decl)
			t.typedefsSet[decl.Name] = struct{}{}
			return
		}
		t.declares = append(t.declares, decl)
	case 1: // Declaration
		declares := t.walkDeclaration(d.Declaration)
		for _, decl := range declares {
			if decl.IsTypedef {
				t.typedefs = append(t.typedefs, decl)
				t.typedefsSet[decl.Name] = struct{}{}
				continue
			}
			t.declares = append(t.declares, decl)
		}
	}
}

func (t *Translator) walkDeclaration(d *cc.Declaration) (declared []*CDecl) {
	if d.InitDeclaratorListOpt != nil {
		list := d.InitDeclaratorListOpt.InitDeclaratorList
		for list != nil {
			decl := t.declarator(list.InitDeclarator.Declarator)
			init := list.InitDeclarator.Initializer
			if init != nil && init.Expression != nil {
				decl.Value = init.Expression.Value
				decl.Expression = blessName(init.Expression.Token.S())
			}
			t.registerTagsOf(decl)
			declared = append(declared, decl)
			if init != nil {
				t.valueMap[decl.Name] = decl.Value
				t.exprMap[decl.Name] = decl.Expression
			}
			list = list.InitDeclaratorList
		}
	} else if declr := d.Declarator(); declr != nil {
		decl := t.declarator(declr)
		t.registerTagsOf(decl)
		declared = append(declared, decl)
	}
	return
}

func (t *Translator) declarator(d *cc.Declarator) *CDecl {
	specifier := d.RawSpecifier()
	decl := &CDecl{
		Spec:      t.typeSpec(d.Type, 0, false),
		Name:      identifierOf(d.DirectDeclarator),
		IsTypedef: specifier.IsTypedef(),
		IsStatic:  specifier.IsStatic(),
		Pos:       d.Pos(),
	}
	return decl
}

func (t *Translator) getStructTag(typ cc.Type) (tag string) {
	b := t.fileScope.Lookup(cc.NSTags, typ.Tag())
	switch v := b.Node.(type) {
	case *cc.StructOrUnionSpecifier:
		if v.IdentifierOpt != nil {
			return blessName(v.IdentifierOpt.Token.S())
		}
	case xc.Token:
		return blessName(v.S())
	}
	return
}

func (t *Translator) enumSpec(base *CTypeSpec, typ cc.Type) *CEnumSpec {
	tag := blessName(xc.Dict.S(typ.Tag()))
	spec := &CEnumSpec{
		Tag:      tag,
		Pointers: base.Pointers,
		OuterArr: base.OuterArr,
		InnerArr: base.InnerArr,
	}
	list := typ.EnumeratorList()
	for _, en := range list {
		name := blessName(en.DefTok.S())
		m := &CDecl{
			Name: name,
			Pos:  en.DefTok.Pos(),
		}
		switch {
		case en.Value == nil:
			panic("value cannot be nil in enum")
		case t.constRules[ConstEnum] == ConstCGOAlias:
			m.Expression = fmt.Sprintf("C.%s", name)
		case t.constRules[ConstEnum] == ConstExpand:
			srcParts := make([]string, 0, len(en.Tokens))
			exprParts := make([]string, 0, len(en.Tokens))
			valid := true

			// TODO: some state machine
			needsTypecast := false
			typecastValue := false
			typecastValueParens := 0

			for _, token := range en.Tokens {
				src := cc.TokSrc(token)
				srcParts = append(srcParts, src)
				switch token.Rune {
				case cc.IDENTIFIER:
					exprParts = append(exprParts, string(t.TransformName(TargetConst, src, true)))
				default:
					// TODO: state machine
					const (
						lparen = rune(40)
						rparen = rune(41)
					)
					switch {
					case needsTypecast && token.Rune == rparen:
						typecastValue = true
						needsTypecast = false
						exprParts = append(exprParts, src+"(")
					case typecastValue && token.Rune == lparen:
						typecastValueParens++
					case typecastValue && token.Rune == rparen:
						if typecastValueParens == 0 {
							typecastValue = false
							exprParts = append(exprParts, ")"+src)
						} else {
							typecastValueParens--
						}
					default:
						// somewhere in the world a helpless kitten died because of this
						if token.Rune == '~' {
							src = "^"
						}
						if runes := []rune(src); len(runes) > 0 && isNumeric(runes) {
							// TODO(xlab): better const handling
							src = readNumeric(runes)
						}
						exprParts = append(exprParts, src)
					}
				}
				if !valid {
					break
				}
			}
			if typecastValue {
				// still in typecast value, need to close paren
				exprParts = append(exprParts, ")")
				typecastValue = false
			}

			if len(exprParts) > 0 {
				m.Expression = strings.Join(exprParts, " ")
			} else {
				m.Value = en.Value
			}
			m.Src = strings.Join(srcParts, " ")
		default:
			m.Value = en.Value
		}
		m.Spec = spec.PromoteType(en.Value)
		spec.Members = append(spec.Members, m)
		t.valueMap[m.Name] = en.Value
		t.exprMap[m.Name] = m.Expression
	}

	return spec
}

func (t *Translator) walkEnumerator(e *cc.Enumerator) *CDecl {
	decl := &CDecl{
		Name: blessName(e.EnumerationConstant.Token.S()),
	}
	switch e.Case {
	case 0: // EnumerationConstant
	case 1: // EnumerationConstant '=' ConstantExpression
		decl.Value = e.ConstantExpression.Value
		decl.Expression = string(e.ConstantExpression.Expression.Token.S())
	}
	return decl
}

const maxDeepLevel = 3

func (t *Translator) structSpec(base *CTypeSpec, typ cc.Type, deep int) *CStructSpec {
	tag := t.getStructTag(typ)
	spec := &CStructSpec{
		Tag:      tag,
		IsUnion:  typ.Kind() == cc.Union,
		Pointers: base.Pointers,
		OuterArr: base.OuterArr,
		InnerArr: base.InnerArr,
	}
	if deep > maxDeepLevel {
		return spec
	}
	members, _ := typ.Members()
	for i, m := range members {
		var pos token.Pos
		if m.Declarator != nil {
			pos = m.Declarator.Pos()
		}
		spec.Members = append(spec.Members, &CDecl{
			Name: memberName(i, m),
			Spec: t.typeSpec(m.Type, deep+1, false),
			Pos:  pos,
		})
	}
	return spec
}

func (t *Translator) functionSpec(base *CTypeSpec, typ cc.Type, deep int) *CFunctionSpec {
	spec := &CFunctionSpec{
		Pointers: base.Pointers,
	}
	if deep > 2 { // a function inside params of another function
		spec.Raw = typedefNameOf(typ)
	} else {
		spec.Raw = identifierOf(typ.Declarator().DirectDeclarator)
	}
	if deep > maxDeepLevel {
		return spec
	}
	if ret := typ.Result(); ret != nil && ret.Kind() != cc.Void {
		spec.Return = t.typeSpec(ret, deep+1, true)
	}
	params, _ := typ.Parameters()
	for i, p := range params {
		spec.Params = append(spec.Params, &CDecl{
			Name: paramName(i, p),
			Spec: t.typeSpec(p.Type, deep+1, false),
			Pos:  p.Declarator.Pos(),
		})
	}
	return spec
}

func (t *Translator) typeSpec(typ cc.Type, deep int, isRet bool) CType {
	spec := &CTypeSpec{
		Const: typ.Specifier().IsConst(),
	}
	if !isRet {
		spec.Raw = typedefNameOf(typ)
	}

	for typ.Kind() == cc.Array {
		size := typ.Elements()
		typ = typ.Element()
		if size >= 0 {
			spec.AddOuterArr(uint64(size))
		}
	}
	for typ.Kind() == cc.Ptr {
		typ = typ.Element()
		spec.Pointers++
	}
	for typ.Kind() == cc.Array {
		size := typ.Elements()
		typ = typ.Element()
		if size >= 0 {
			spec.AddInnerArr(uint64(size))
		}
	}

	switch typ.Kind() {
	case cc.Void:
		spec.Base = "void"
	case cc.Char:
		spec.Base = "char"
	case cc.SChar:
		spec.Base = "char"
		spec.Signed = true
	case cc.UChar:
		spec.Base = "char"
		spec.Unsigned = true
	case cc.Short:
		spec.Base = "int"
		spec.Short = true
	case cc.UShort:
		spec.Base = "int"
		spec.Short = true
		spec.Unsigned = true
	case cc.Int:
		spec.Base = "int"
	case cc.UInt:
		spec.Base = "int"
		spec.Unsigned = true
	case cc.Long:
		spec.Base = "int"
		spec.Long = true
	case cc.ULong:
		spec.Base = "int"
		spec.Long = true
		spec.Unsigned = true
	case cc.LongLong:
		spec.Base = "long"
		spec.Long = true
	case cc.ULongLong:
		spec.Base = "long"
		spec.Long = true
		spec.Unsigned = true
	case cc.Float:
		spec.Base = "float"
	case cc.Double:
		spec.Base = "double"
	case cc.LongDouble:
		spec.Base = "double"
		spec.Long = true
	case cc.Bool:
		spec.Base = "_Bool"
	case cc.FloatComplex:
		spec.Base = "complexfloat"
		spec.Complex = true
	case cc.DoubleComplex:
		spec.Base = "complexdouble"
		spec.Complex = true
	case cc.LongDoubleComplex:
		spec.Base = "complexdouble"
		spec.Long = true
		spec.Complex = true
	case cc.Enum:
		s := t.enumSpec(spec, typ)
		if !isRet {
			s.Typedef = typedefNameOf(typ)
		}
		return s
	case cc.Union:
		return &CStructSpec{
			Tag:      t.getStructTag(typ),
			IsUnion:  true,
			Pointers: spec.Pointers,
			OuterArr: spec.OuterArr,
			InnerArr: spec.InnerArr,
			Typedef:  typedefNameOf(typ),
		}
	case cc.Struct:
		s := t.structSpec(spec, typ, deep+1)
		if !isRet {
			s.Typedef = typedefNameOf(typ)
		}
		return s
	case cc.Function:
		s := t.functionSpec(spec, typ, deep+1)
		if !isRet && !typ.Specifier().IsTypedef() {
			s.Typedef = typedefNameOf(typ)
			retTyp := typ.Result().RawDeclarator().Type
			retTypedef := typedefNameOf(retTyp)
			if s.Return != nil {
				s.Return.SetRaw(retTypedef)
			}
		}
		return s
	default:
		panic("unknown type " + typ.String())
	}

	return spec
}

func paramName(n int, p cc.Parameter) string {
	if p.Name == 0 {
		return fmt.Sprintf("arg%d", n)
	}
	return blessName(xc.Dict.S(p.Name))
}

func memberName(n int, m cc.Member) string {
	if m.Name == 0 {
		return fmt.Sprintf("field%d", n)
	}
	return blessName(xc.Dict.S(m.Name))
}

func typedefNameOf(typ cc.Type) string {
	rawSpec := typ.Declarator().RawSpecifier()
	if name := rawSpec.TypedefName(); name > 0 {
		return blessName(xc.Dict.S(name))
	} else if rawSpec.IsTypedef() {
		return identifierOf(typ.Declarator().DirectDeclarator)
	}
	return ""
}

func identifierOf(dd *cc.DirectDeclarator) string {
	switch dd.Case {
	case 0: // IDENTIFIER
		if dd.Token.Val == 0 {
			return ""
		}
		return blessName(dd.Token.S())
	case 1: // '(' Declarator ')'
		return identifierOf(dd.Declarator.DirectDeclarator)
	default:
		//	DirectDeclarator '[' TypeQualifierListOpt ExpressionOpt ']'
		//	DirectDeclarator '[' "static" TypeQualifierListOpt Expression ']'
		//	DirectDeclarator '[' TypeQualifierList "static" Expression ']'
		//	DirectDeclarator '[' TypeQualifierListOpt '*' ']'
		//	DirectDeclarator '(' ParameterTypeList ')'
		//	DirectDeclarator '(' IdentifierListOpt ')'
		return identifierOf(dd.DirectDeclarator)
	}
}
<|endoftext|>