<commit_before>/*
   Nging is a toolbox for webmasters
   Copyright (C) 2018-present  Wenhui Shen <swh@admpub.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

package upload

import (
	"strings"

	"github.com/webx-top/echo"

	"github.com/admpub/nging/application/registry/upload/table"
)

// SubdirInfo 子目录信息
type SubdirInfo struct {
	Allowed     bool
	Key         string
	Name        string
	NameEN      string
	Description string

	tableName string
	fieldName string
	checker   Checker
}

func (i *SubdirInfo) String() string {
	if len(i.Name) > 0 {
		return i.Name
	}
	return i.Key
}

func (i *SubdirInfo) TableName() string {
	if len(i.tableName) == 0 {
		r := strings.SplitN(i.Key, `-`, 2)
		switch len(r) {
		case 2:
			i.fieldName = r[1]
			fallthrough
		case 1:
			i.tableName = r[0]
		}
	}
	return i.tableName
}

func (i *SubdirInfo) FieldName() string {
	return i.fieldName
}

func (i *SubdirInfo) SetTableName(tableName string) *SubdirInfo {
	i.tableName = tableName
	return i
}

func (i *SubdirInfo) SetFieldName(fieldName string) *SubdirInfo {
	i.fieldName = fieldName
	return i
}

func (i *SubdirInfo) GetNameEN() string {
	if len(i.NameEN) > 0 {
		return i.NameEN
	}
	return i.Name
}

func (i *SubdirInfo) SetChecker(checker Checker) *SubdirInfo {
	i.checker = checker
	return i
}

func (i *SubdirInfo) Checker() Checker {
	return i.checker
}

func (i *SubdirInfo) MustChecker() Checker {
	if i.checker != nil {
		return i.checker
	}
	return func(ctx echo.Context, tab table.TableInfoStorer) (subdir string, name string, err error) {
		subdir, name, err = DefaultChecker(ctx, tab)
		tab.SetTableName(i.TableName())
		tab.SetFieldName(i.FieldName())
		return
	}
}

func (i *SubdirInfo) SetAllowed(allowed bool) *SubdirInfo {
	i.Allowed = allowed
	return i
}

func (i *SubdirInfo) SetName(name string) *SubdirInfo {
	i.Name = name
	return i
}

func (i *SubdirInfo) SetNameEN(nameEN string) *SubdirInfo {
	i.NameEN = nameEN
	return i
}

func (i *SubdirInfo) SetDescription(description string) *SubdirInfo {
	i.Description = description
	return i
}
<commit_msg>update<commit_after>/*
   Nging is a toolbox for webmasters
   Copyright (C) 2018-present  Wenhui Shen <swh@admpub.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

package upload

import (
	"strings"

	"github.com/webx-top/echo"

	"github.com/admpub/nging/application/registry/upload/table"
)

// SubdirInfo 子目录信息
type SubdirInfo struct {
	Allowed     bool
	Key         string
	Name        string
	NameEN      string
	Description string

	tableName string
	fieldName string
	checker   Checker
}

func (i *SubdirInfo) String() string {
	if len(i.Name) > 0 {
		return i.Name
	}
	return i.Key
}

func (i *SubdirInfo) TableName() string {
	if len(i.tableName) == 0 {
		r := strings.SplitN(i.Key, `-`, 2)
		switch len(r) {
		case 2:
			i.fieldName = r[1]
			fallthrough
		case 1:
			i.tableName = r[0]
		}
	}
	return i.tableName
}

func (i *SubdirInfo) FieldName() string {
	return i.fieldName
}

func (i *SubdirInfo) SetTableName(tableName string) *SubdirInfo {
	i.tableName = tableName
	return i
}

func (i *SubdirInfo) SetTable(tableName string, fieldName string) *SubdirInfo {
	i.tableName = tableName
	i.fieldName = fieldName
	return i
}

func (i *SubdirInfo) SetFieldName(fieldName string) *SubdirInfo {
	i.fieldName = fieldName
	return i
}

func (i *SubdirInfo) GetNameEN() string {
	if len(i.NameEN) > 0 {
		return i.NameEN
	}
	return i.Name
}

func (i *SubdirInfo) SetChecker(checker Checker) *SubdirInfo {
	i.checker = checker
	return i
}

func (i *SubdirInfo) Checker() Checker {
	return i.checker
}

func (i *SubdirInfo) MustChecker() Checker {
	if i.checker != nil {
		return i.checker
	}
	return func(ctx echo.Context, tab table.TableInfoStorer) (subdir string, name string, err error) {
		subdir, name, err = DefaultChecker(ctx, tab)
		tab.SetTableName(i.TableName())
		tab.SetFieldName(i.FieldName())
		return
	}
}

func (i *SubdirInfo) SetAllowed(allowed bool) *SubdirInfo {
	i.Allowed = allowed
	return i
}

func (i *SubdirInfo) SetName(name string) *SubdirInfo {
	i.Name = name
	return i
}

func (i *SubdirInfo) SetNameEN(nameEN string) *SubdirInfo {
	i.NameEN = nameEN
	return i
}

func (i *SubdirInfo) SetDescription(description string) *SubdirInfo {
	i.Description = description
	return i
}
<|endoftext|>


<commit_before>// Copyright 2010  The "goheader" Authors
//
// Use of this source code is governed by the BSD-2 Clause license
// that can be found in the LICENSE file.
//
// This software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
// OR CONDITIONS OF ANY KIND, either express or implied. See the License
// for more details.

package main

import (
	"bufio"
	"container/vector"
	"fmt"
	"regexp"
	"os"
	"strconv"
	"strings"
)

const COMMENT_LINE = "//!!! "
const NoLastEnumValue = -1000

var goBase = `// {cmd}
// MACHINE GENERATED.

package {pkg}

`

// Regular expressions for C header.
var (
	reSkip = regexp.MustCompile(`^(\n|//)`) // Empty lines and comments.

	reTypedef     = regexp.MustCompile(`^(typedef)[ \t]+(.+)[ \t]+(.+)[;](.+)?`)
	reTypedefOnly = regexp.MustCompile(`^(typedef)[ \t]+`)

	reStruct          = regexp.MustCompile(`^(struct)[ \t]+(.+)[ \t]*{`)
	reStructField     = regexp.MustCompile(`^(.+)[ \t]+(.+)[;](.+)?`)
	reStructFieldName = regexp.MustCompile(`^([^_]*_)?(.+)`)

	reEnum      = regexp.MustCompile(`^(enum)[ \t]+(.+)[ \t]*{`)
	reEnumValue = regexp.MustCompile(`^(.+)[ \t]*=[ \t]*([^,]+)`)
	reEnumIota  = regexp.MustCompile(`^([^,]+)[,]?\n`)
	reEnumEnd   = regexp.MustCompile(`^};`)

	reDefine      = regexp.MustCompile(`^#[ \t]*(define|DEFINE)[ \t]+([^ \t]+)[ \t]+(.+)`)
	reDefineOnly  = regexp.MustCompile(`^#[ \t]*(define|DEFINE)[ \t]+`)
	reDefineMacro = regexp.MustCompile(`^.*(\(.*\))`)

	reSingleComment         = regexp.MustCompile(`^(.+)?/\*[ \t]*(.+)[ \t]*\*/`)
	reStartMultipleComment  = regexp.MustCompile(`^/\*(.+)?`)
	reMiddleMultipleComment = regexp.MustCompile(`^[ \t*]*(.+)`)
	reEndMultipleComment    = regexp.MustCompile(`^(.+)?\*/`)
)

// Translates C type declaration into Go type declaration.
//
// NOTE: the regular expression for single comments (reSingleComment) returns
// spaces before of "*/".
// The issue is that Go's regexp lib. doesn't support non greedy matches.
func (self *translate) C(file *os.File) os.Error {
	var isMultipleComment, isTypeBlock, isConstBlock, isStruct, isEnum bool
	lastEnumValue := -1
	extraTypedef := new(vector.StringVector) // Types defined in the header file.

	self.raw.WriteString(goBase)

	// === File to read
	fileBuf := bufio.NewReader(file)

	for {
		line, err := fileBuf.ReadString('\n')
		if err == os.EOF {
			break
		}
		line = strings.TrimSpace(line) + "\n"
		isSingleComment := false

		// === Translate comment of single line.
		if !isMultipleComment {
			if sub := reSingleComment.FindStringSubmatch(line); sub != nil {
				isSingleComment = true
				line = "// " + strings.TrimRight(sub[2], " ") + "\n"

				if sub[1] != "" {
					line = sub[1] + line
				}
			}
		}
		if !isSingleComment && !isMultipleComment && strings.HasPrefix(line, "/*") {
			isMultipleComment = true
		}

		// === Translate comments of multiple line.
		if isMultipleComment {
			if sub := reStartMultipleComment.FindStringSubmatch(line); sub != nil {
				if sub[1] != "\n" {
					self.raw.WriteString("// " + sub[1])
				}
				continue
			}
			if sub := reEndMultipleComment.FindStringSubmatch(line); sub != nil {
				if sub[1] != "" {
					self.raw.WriteString("// " + sub[1] + "\n")
				}
				isMultipleComment = false
				continue
			}
			if sub := reMiddleMultipleComment.FindStringSubmatch(line); sub != nil {
				if sub[1] != "\n" {
					self.raw.WriteString("// " + sub[1])
				} else {
					self.raw.WriteString("//" + sub[1])
				}
				continue
			}
		}

		// === Translate type definitions.
		if sub := reTypedef.FindStringSubmatch(line); sub != nil {
			// Add the new type.
			extraTypedef.Push(sub[3])

			gotype, ok := ctypeTogo(sub[2], extraTypedef)
			line = fmt.Sprintf("%s %s", sub[3], gotype)

			if sub[4] != "\n" {
				line += sub[4]
			} else {
				line += "\n"
			}

			if !isTypeBlock {
				// Get characters of next line.
				startNextLine, err := fileBuf.Peek(10)
				if err != nil {
					return err
				}

				// In single line.
				if !reTypedefOnly.Match(startNextLine) {
					line = "type " + line
				} else {
					isTypeBlock = true
					line = "type (\n" + line
				}
			}

			if !ok {
				line = COMMENT_LINE + line
			}

			self.raw.WriteString(line)
			continue
		}

		if isTypeBlock && line == "\n" {
			self.raw.WriteString(")\n\n")
			isTypeBlock = false
			continue
		}

		// === Translate 'define' to 'const'.
		if sub := reDefine.FindStringSubmatch(line); sub != nil {
			line = fmt.Sprintf("%s = %s", sub[2], sub[3])

			if !isConstBlock {
				// Get characters of next line.
				startNextLine, err := fileBuf.Peek(10)
				if err != nil {
					return err
				}

				// Constant in single line.
				if !reDefineOnly.Match(startNextLine) {
					line = "const " + line
				} else {
					isConstBlock = true
					line = "const (\n" + line
				}
			}

			// Removes comment (if any) to ckeck if it is a macro.
			lastField := strings.Split(sub[3], "//")[0]
			if reDefineMacro.MatchString(lastField) {
				line = COMMENT_LINE + line
			}

			self.raw.WriteString(line)
			continue
		}

		if isConstBlock && line == "\n" {
			self.raw.WriteString(")\n\n")
			isConstBlock = false
			continue
		}

		// === Translate enums
		if !isEnum {
			if sub := reEnum.FindStringSubmatch(line); sub != nil {
				isEnum = true
				lastEnumValue = -1
				if !isConstBlock {
					self.raw.WriteString("const (\n")
					isConstBlock = true
				}
				self.raw.WriteString(fmt.Sprintf("// enum %s\n",
					strings.Title(sub[2])))
				continue
			}
		} else {
			if sub := reEnumEnd.FindStringSubmatch(line); sub != nil {
				self.raw.WriteString("\n")
				isEnum = false
				continue
			}
			if sub := reEnumValue.FindStringSubmatch(line); sub != nil {
				self.raw.WriteString(fmt.Sprintf("%s = %s\n",
					strings.Title(sub[1]), sub[2]))
				if v, err := strconv.Atoi(sub[2]); err == nil {
					lastEnumValue = v
				} else {
					lastEnumValue = NoLastEnumValue
				}
				continue
			}
			if sub := reEnumIota.FindStringSubmatch(line); sub != nil {
				if lastEnumValue != NoLastEnumValue {
					lastEnumValue++
					self.raw.WriteString(fmt.Sprintf("%s = %d\n",
						strings.Title(sub[1]), lastEnumValue))
					continue
				}
			}
			self.raw.WriteString(fmt.Sprintf("%s%s", COMMENT_LINE, line))
			continue
		}

		// === Translate structs.
		if !isStruct {
			if sub := reStruct.FindStringSubmatch(line); sub != nil {
				isStruct = true

				if isConstBlock {
					self.raw.WriteString(")\n")
					isConstBlock = false
				}

				self.raw.WriteString(fmt.Sprintf(
					"type %s struct {\n", strings.Title(sub[2])))
				continue
			}
		} else {
			if sub := reStructField.FindStringSubmatch(line); sub != nil {
				// Translate the field type.
				gotype, ok := ctypeTogo(sub[1], extraTypedef)

				// === Translate the field name.
				fieldName := reStructFieldName.FindStringSubmatch(sub[2])
				_fieldName := ""

				if fieldName[1] != "" {
					_fieldName = fieldName[2]
				} else {
					_fieldName = fieldName[0]
				}
				// ===

				line = fmt.Sprintf("%s %s %s",
					strings.Title(_fieldName), gotype, sub[3])

				// C type not found.
				if !ok {
					line = COMMENT_LINE + line
				}

				self.raw.WriteString(line)
				continue
			}
			if strings.HasPrefix(line, "}") {
				self.raw.WriteString(strings.Replace(line, ";", "", 1))
				isStruct = false
				continue
			}
		}

		// Comment another C lines.
		//if line != "\n" && !strings.HasPrefix(line, "//") {
		if !reSkip.MatchString(line) {
			line = COMMENT_LINE + line
		}

		self.raw.WriteString(line)
	}

	return nil
}

// Translates a C type definition into Go definition. The C header could have
// defined new types so they're checked in the firs place.
func ctypeTogo(ctype string, extraCtype *vector.StringVector) (gotype string, ok bool) {
	for _, v := range *extraCtype {
		if v == ctype {
			return ctype, true
		}
	}

	switch ctype {
	case "char", "signed char":
		return "int8", true
	case "unsigned char":
		return "uint8", true
	case "short", "signed short", "short int", "signed short int":
		return "int16", true
	case "unsigned short", "unsigned short int":
		return "uint16", true
	case "int", "signed int", "signed":
		return "int16", true
	case "unsigned int", "unsigned":
		return "uint16", true
	case "long", "signed long", "long int", "signed long int":
		return "int32", true
	case "unsigned long", "unsigned long int":
		return "uint32", true
	case "size_t":
		return "int", true
	case "float":
		return "float32", true
	case "double", "long double":
		return "float64", true
	}
	return ctype, false
}
<commit_msg>Changed header at creating file<commit_after>// Copyright 2010  The "goheader" Authors
//
// Use of this source code is governed by the BSD-2 Clause license
// that can be found in the LICENSE file.
//
// This software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
// OR CONDITIONS OF ANY KIND, either express or implied. See the License
// for more details.

package main

import (
	"bufio"
	"container/vector"
	"fmt"
	"regexp"
	"os"
	"strconv"
	"strings"
)

const COMMENT_LINE = "//!!! "
const NoLastEnumValue = -1000

var goBase = `// {cmd}
// MACHINE GENERATED; DO NOT EDIT
// ===

package {pkg}

`

// Regular expressions for C header.
var (
	reSkip = regexp.MustCompile(`^(\n|//)`) // Empty lines and comments.

	reTypedef     = regexp.MustCompile(`^(typedef)[ \t]+(.+)[ \t]+(.+)[;](.+)?`)
	reTypedefOnly = regexp.MustCompile(`^(typedef)[ \t]+`)

	reStruct          = regexp.MustCompile(`^(struct)[ \t]+(.+)[ \t]*{`)
	reStructField     = regexp.MustCompile(`^(.+)[ \t]+(.+)[;](.+)?`)
	reStructFieldName = regexp.MustCompile(`^([^_]*_)?(.+)`)

	reEnum      = regexp.MustCompile(`^(enum)[ \t]+(.+)[ \t]*{`)
	reEnumValue = regexp.MustCompile(`^(.+)[ \t]*=[ \t]*([^,]+)`)
	reEnumIota  = regexp.MustCompile(`^([^,]+)[,]?\n`)
	reEnumEnd   = regexp.MustCompile(`^};`)

	reDefine      = regexp.MustCompile(`^#[ \t]*(define|DEFINE)[ \t]+([^ \t]+)[ \t]+(.+)`)
	reDefineOnly  = regexp.MustCompile(`^#[ \t]*(define|DEFINE)[ \t]+`)
	reDefineMacro = regexp.MustCompile(`^.*(\(.*\))`)

	reSingleComment         = regexp.MustCompile(`^(.+)?/\*[ \t]*(.+)[ \t]*\*/`)
	reStartMultipleComment  = regexp.MustCompile(`^/\*(.+)?`)
	reMiddleMultipleComment = regexp.MustCompile(`^[ \t*]*(.+)`)
	reEndMultipleComment    = regexp.MustCompile(`^(.+)?\*/`)
)

// Translates C type declaration into Go type declaration.
//
// NOTE: the regular expression for single comments (reSingleComment) returns
// spaces before of "*/".
// The issue is that Go's regexp lib. doesn't support non greedy matches.
func (self *translate) C(file *os.File) os.Error {
	var isMultipleComment, isTypeBlock, isConstBlock, isStruct, isEnum bool
	lastEnumValue := -1
	extraTypedef := new(vector.StringVector) // Types defined in the header file.

	self.raw.WriteString(goBase)

	// === File to read
	fileBuf := bufio.NewReader(file)

	for {
		line, err := fileBuf.ReadString('\n')
		if err == os.EOF {
			break
		}
		line = strings.TrimSpace(line) + "\n"
		isSingleComment := false

		// === Translate comment of single line.
		if !isMultipleComment {
			if sub := reSingleComment.FindStringSubmatch(line); sub != nil {
				isSingleComment = true
				line = "// " + strings.TrimRight(sub[2], " ") + "\n"

				if sub[1] != "" {
					line = sub[1] + line
				}
			}
		}
		if !isSingleComment && !isMultipleComment && strings.HasPrefix(line, "/*") {
			isMultipleComment = true
		}

		// === Translate comments of multiple line.
		if isMultipleComment {
			if sub := reStartMultipleComment.FindStringSubmatch(line); sub != nil {
				if sub[1] != "\n" {
					self.raw.WriteString("// " + sub[1])
				}
				continue
			}
			if sub := reEndMultipleComment.FindStringSubmatch(line); sub != nil {
				if sub[1] != "" {
					self.raw.WriteString("// " + sub[1] + "\n")
				}
				isMultipleComment = false
				continue
			}
			if sub := reMiddleMultipleComment.FindStringSubmatch(line); sub != nil {
				if sub[1] != "\n" {
					self.raw.WriteString("// " + sub[1])
				} else {
					self.raw.WriteString("//" + sub[1])
				}
				continue
			}
		}

		// === Translate type definitions.
		if sub := reTypedef.FindStringSubmatch(line); sub != nil {
			// Add the new type.
			extraTypedef.Push(sub[3])

			gotype, ok := ctypeTogo(sub[2], extraTypedef)
			line = fmt.Sprintf("%s %s", sub[3], gotype)

			if sub[4] != "\n" {
				line += sub[4]
			} else {
				line += "\n"
			}

			if !isTypeBlock {
				// Get characters of next line.
				startNextLine, err := fileBuf.Peek(10)
				if err != nil {
					return err
				}

				// In single line.
				if !reTypedefOnly.Match(startNextLine) {
					line = "type " + line
				} else {
					isTypeBlock = true
					line = "type (\n" + line
				}
			}

			if !ok {
				line = COMMENT_LINE + line
			}

			self.raw.WriteString(line)
			continue
		}

		if isTypeBlock && line == "\n" {
			self.raw.WriteString(")\n\n")
			isTypeBlock = false
			continue
		}

		// === Translate 'define' to 'const'.
		if sub := reDefine.FindStringSubmatch(line); sub != nil {
			line = fmt.Sprintf("%s = %s", sub[2], sub[3])

			if !isConstBlock {
				// Get characters of next line.
				startNextLine, err := fileBuf.Peek(10)
				if err != nil {
					return err
				}

				// Constant in single line.
				if !reDefineOnly.Match(startNextLine) {
					line = "const " + line
				} else {
					isConstBlock = true
					line = "const (\n" + line
				}
			}

			// Removes comment (if any) to ckeck if it is a macro.
			lastField := strings.Split(sub[3], "//")[0]
			if reDefineMacro.MatchString(lastField) {
				line = COMMENT_LINE + line
			}

			self.raw.WriteString(line)
			continue
		}

		if isConstBlock && line == "\n" {
			self.raw.WriteString(")\n\n")
			isConstBlock = false
			continue
		}

		// === Translate enums
		if !isEnum {
			if sub := reEnum.FindStringSubmatch(line); sub != nil {
				isEnum = true
				lastEnumValue = -1
				if !isConstBlock {
					self.raw.WriteString("const (\n")
					isConstBlock = true
				}
				self.raw.WriteString(fmt.Sprintf("// enum %s\n",
					strings.Title(sub[2])))
				continue
			}
		} else {
			if sub := reEnumEnd.FindStringSubmatch(line); sub != nil {
				self.raw.WriteString("\n")
				isEnum = false
				continue
			}
			if sub := reEnumValue.FindStringSubmatch(line); sub != nil {
				self.raw.WriteString(fmt.Sprintf("%s = %s\n",
					strings.Title(sub[1]), sub[2]))
				if v, err := strconv.Atoi(sub[2]); err == nil {
					lastEnumValue = v
				} else {
					lastEnumValue = NoLastEnumValue
				}
				continue
			}
			if sub := reEnumIota.FindStringSubmatch(line); sub != nil {
				if lastEnumValue != NoLastEnumValue {
					lastEnumValue++
					self.raw.WriteString(fmt.Sprintf("%s = %d\n",
						strings.Title(sub[1]), lastEnumValue))
					continue
				}
			}
			self.raw.WriteString(fmt.Sprintf("%s%s", COMMENT_LINE, line))
			continue
		}

		// === Translate structs.
		if !isStruct {
			if sub := reStruct.FindStringSubmatch(line); sub != nil {
				isStruct = true

				if isConstBlock {
					self.raw.WriteString(")\n")
					isConstBlock = false
				}

				self.raw.WriteString(fmt.Sprintf(
					"type %s struct {\n", strings.Title(sub[2])))
				continue
			}
		} else {
			if sub := reStructField.FindStringSubmatch(line); sub != nil {
				// Translate the field type.
				gotype, ok := ctypeTogo(sub[1], extraTypedef)

				// === Translate the field name.
				fieldName := reStructFieldName.FindStringSubmatch(sub[2])
				_fieldName := ""

				if fieldName[1] != "" {
					_fieldName = fieldName[2]
				} else {
					_fieldName = fieldName[0]
				}
				// ===

				line = fmt.Sprintf("%s %s %s",
					strings.Title(_fieldName), gotype, sub[3])

				// C type not found.
				if !ok {
					line = COMMENT_LINE + line
				}

				self.raw.WriteString(line)
				continue
			}
			if strings.HasPrefix(line, "}") {
				self.raw.WriteString(strings.Replace(line, ";", "", 1))
				isStruct = false
				continue
			}
		}

		// Comment another C lines.
		//if line != "\n" && !strings.HasPrefix(line, "//") {
		if !reSkip.MatchString(line) {
			line = COMMENT_LINE + line
		}

		self.raw.WriteString(line)
	}

	return nil
}

// Translates a C type definition into Go definition. The C header could have
// defined new types so they're checked in the firs place.
func ctypeTogo(ctype string, extraCtype *vector.StringVector) (gotype string, ok bool) {
	for _, v := range *extraCtype {
		if v == ctype {
			return ctype, true
		}
	}

	switch ctype {
	case "char", "signed char":
		return "int8", true
	case "unsigned char":
		return "uint8", true
	case "short", "signed short", "short int", "signed short int":
		return "int16", true
	case "unsigned short", "unsigned short int":
		return "uint16", true
	case "int", "signed int", "signed":
		return "int16", true
	case "unsigned int", "unsigned":
		return "uint16", true
	case "long", "signed long", "long int", "signed long int":
		return "int32", true
	case "unsigned long", "unsigned long int":
		return "uint32", true
	case "size_t":
		return "int", true
	case "float":
		return "float32", true
	case "double", "long double":
		return "float64", true
	}
	return ctype, false
}
<|endoftext|>


<commit_before>package qb

import (
	"github.com/stretchr/testify/assert"
	"testing"
)

type UserMetadata struct {
	ID int
}

func TestMetadata(t *testing.T) {

	engine, _ := NewEngine("postgres", "user=root dbname=pqtest")
	metadata := NewMetaData(engine)

	metadata.Add(UserMetadata{})
}

type UserMetadataError struct {
	ID int `qb:"constraints:i:nvalid"`
}

func TestMetadataAddError(t *testing.T) {

	engine, _ := NewEngine("postgres", "user=root dbname=pqtest")
	metadata := NewMetaData(engine)

	assert.Panics(t, func() { metadata.Add(UserMetadataError{}) })
	assert.Equal(t, len(metadata.Tables()), 0)
}

func TestMetadataAddTable(t *testing.T) {

	engine, _ := NewEngine("postgres", "user=root dbname=pqtest")
	metadata := NewMetaData(engine)

	table := NewTable(
		engine.Driver(),
		"user",
		[]Column{
			NewColumn("id", BigInt(), []Constraint{}),
		},
		[]Constraint{},
	)

	metadata.AddTable(table)

	assert.Equal(t, metadata.Tables(), []*Table{table})
}

func TestMetadataTable(t *testing.T) {
	engine, _ := NewEngine("postgres", "user=root dbname=pqtest")
	metadata := NewMetaData(engine)

	assert.Nil(t, metadata.Table("invalid-table"))
}

func TestMetadataFailCreateDropAll(t *testing.T) {
	engine, _ := NewEngine("postgres", "user=root dbname=pqtest")
	metadata := NewMetaData(engine)
	metadata.Engine().DB().Close()

	assert.NotNil(t, metadata.CreateAll())
	assert.NotNil(t, metadata.DropAll())
}
<commit_msg>fix connections params of create drop all fails tests<commit_after>package qb

import (
	"github.com/stretchr/testify/assert"
	"testing"
)

type UserMetadata struct {
	ID int
}

func TestMetadata(t *testing.T) {

	engine, _ := NewEngine("postgres", "user=root dbname=pqtest")
	metadata := NewMetaData(engine)

	metadata.Add(UserMetadata{})
}

type UserMetadataError struct {
	ID int `qb:"constraints:i:nvalid"`
}

func TestMetadataAddError(t *testing.T) {

	engine, _ := NewEngine("postgres", "user=root dbname=pqtest")
	metadata := NewMetaData(engine)

	assert.Panics(t, func() { metadata.Add(UserMetadataError{}) })
	assert.Equal(t, len(metadata.Tables()), 0)
}

func TestMetadataAddTable(t *testing.T) {

	engine, _ := NewEngine("postgres", "user=root dbname=pqtest")
	metadata := NewMetaData(engine)

	table := NewTable(
		engine.Driver(),
		"user",
		[]Column{
			NewColumn("id", BigInt(), []Constraint{}),
		},
		[]Constraint{},
	)

	metadata.AddTable(table)

	assert.Equal(t, metadata.Tables(), []*Table{table})
}

func TestMetadataTable(t *testing.T) {
	engine, _ := NewEngine("postgres", "user=root dbname=pqtest")
	metadata := NewMetaData(engine)

	assert.Nil(t, metadata.Table("invalid-table"))
}

func TestMetadataFailCreateDropAll(t *testing.T) {
	engine, _ := NewEngine("postgres", "user=postgres dbname=qb_test")
	metadata := NewMetaData(engine)
	metadata.Engine().DB().Close()
	assert.NotNil(t, metadata.CreateAll())
	assert.NotNil(t, metadata.DropAll())
}
<|endoftext|>


<commit_before>package main

import (
	"os/exec"
	"io"
	"os"
	"io/ioutil"
	"strings"
	"syscall"
	"fmt"

	"github.com/flynn/go-discover/discover"
)

func main() {
	root := "/var/lib/demo/apps"
	hostname := shell("curl -s icanhazip.com")

	client, err := discover.NewClient()
	if err != nil {
		panic(err)
	}
	set, _ := client.Services("shelf")
	addrs := set.OnlineAddrs()
	if len(addrs) < 1 {
		panic("Shelf is not discoverable")
	}
	shelfHost := addrs[0]

	app := os.Args[2]
	os.MkdirAll(root + "/" + app, 0755)

	fmt.Printf("-----> Building %s on %s ...\n", app, hostname)

	cmd := exec.Command("docker", "run", "-i", "-a=stdin", "-a=stdout", "flynn/slugbuilder", "http://"+shelfHost+"/"+app+".tgz")
	errCh, startCh := attachCmd(cmd, os.Stdout, os.Stderr, os.Stdin)
	err = cmd.Start()
	if err != nil {
		panic(err)
	}
	close(startCh)
	exitCh := exitStatusCh(cmd)
	if err = <-errCh; err != nil {
		panic(err)
	}
	<-exitCh

	fmt.Printf("-----> Deploying %s ...\n", app)
	if _, err := os.Stat(root + "/" + app + "/CONTAINER"); err == nil {
    	oldid := readFile(root + "/" + app + "/CONTAINER")
    	shell("docker kill " + oldid)
	}

	id := shell("docker run -d -p 5000 -e PORT=5000 -e SLUG_URL=http://"+shelfHost+"/"+app+".tgz flynn/slugrunner start web")
	writeFile(root + "/" + app + "/CONTAINER", id)
	port := shell("docker port "+id+" 5000 | sed 's/0.0.0.0://'")
	writeFile(root + "/" + app + "/PORT", port)
	writeFile(root + "/" + app + "/URL", "http://"+hostname+":"+port)

	fmt.Printf("=====> Application deployed:\n")
	fmt.Printf("       %s\n", readFile(root + "/" + app + "/URL"))
	fmt.Println("")

}

func readFile(filename string) string {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		panic(err)
	}
	return string(data)
}

func writeFile(filename, data string) {
	err := ioutil.WriteFile(filename, []byte(data), 0644)
	if err != nil {
		panic(err)
	}
}

func shell(cmdline string) string {
	out, err := exec.Command("bash", "-c", cmdline).Output()
	if err != nil {
		panic(err)
	}
	return strings.Trim(string(out), " \n")
}

func attachCmd(cmd *exec.Cmd, stdout, stderr io.Writer, stdin io.Reader) (chan error, chan interface{}) {
	errCh := make(chan error)
	startCh := make(chan interface{})

	stdinIn, err := cmd.StdinPipe()
	if err != nil {
		panic(err)
	}
	stdoutOut, err := cmd.StdoutPipe()
	if err != nil {
		panic(err)
	}
	stderrOut, err := cmd.StderrPipe()
	if err != nil {
		panic(err)
	}

	go func() {
		<-startCh
		go func() {
			_, e := io.Copy(stdinIn, stdin)
			errCh <- e
		}()
		go func() {
			_, e := io.Copy(stdout, stdoutOut)
			errCh <- e
		}()
		go func() {
			_, e := io.Copy(stderr, stderrOut)
			errCh <- e
		}()
	}()

	return errCh, startCh
}

func exitStatusCh(cmd *exec.Cmd) chan uint {
	exitCh := make(chan uint)
	go func() {
		err := cmd.Wait()
		if err != nil {
			if exiterr, ok := err.(*exec.ExitError); ok {
				// There is no plattform independent way to retrieve
				// the exit code, but the following will work on Unix
				if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
					exitCh <- uint(status.ExitStatus())
				}
			} else {
				panic(err)
			}
			return
		}
		exitCh <- uint(0)
	}()
	return exitCh
}<commit_msg>receiver: never mind<commit_after>package main

import (
	"os/exec"
	"io"
	"os"
	"io/ioutil"
	"strings"
	"syscall"
	"fmt"

	"github.com/flynn/go-discover/discover"
)

func main() {
	root := "/var/lib/demo/apps"
	hostname := shell("curl -s icanhazip.com")

	client, err := discover.NewClient()
	if err != nil {
		panic(err)
	}
	set, _ := client.Services("shelf")
	addrs := set.OnlineAddrs()
	if len(addrs) < 1 {
		panic("Shelf is not discoverable")
	}
	shelfHost := addrs[0]

	app := os.Args[2]
	os.MkdirAll(root + "/" + app, 0755)

	fmt.Printf("-----> Building %s on %s ...\n", app, hostname)

	cmd := exec.Command("docker", "run", "-i", "-a=stdin", "-a=stdout", "flynn/slugbuilder", "http://"+shelfHost+"/"+app+".tgz")
	errCh := attachCmd(cmd, os.Stdout, os.Stderr, os.Stdin)
	err = cmd.Start()
	if err != nil {
		panic(err)
	}
	exitCh := exitStatusCh(cmd)
	if err = <-errCh; err != nil {
		panic(err)
	}
	<-exitCh

	fmt.Printf("-----> Deploying %s ...\n", app)
	if _, err := os.Stat(root + "/" + app + "/CONTAINER"); err == nil {
    	oldid := readFile(root + "/" + app + "/CONTAINER")
    	shell("docker kill " + oldid)
	}

	id := shell("docker run -d -p 5000 -e PORT=5000 -e SLUG_URL=http://"+shelfHost+"/"+app+".tgz flynn/slugrunner start web")
	writeFile(root + "/" + app + "/CONTAINER", id)
	port := shell("docker port "+id+" 5000 | sed 's/0.0.0.0://'")
	writeFile(root + "/" + app + "/PORT", port)
	writeFile(root + "/" + app + "/URL", "http://"+hostname+":"+port)

	fmt.Printf("=====> Application deployed:\n")
	fmt.Printf("       %s\n", readFile(root + "/" + app + "/URL"))
	fmt.Println("")

}

func readFile(filename string) string {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		panic(err)
	}
	return string(data)
}

func writeFile(filename, data string) {
	err := ioutil.WriteFile(filename, []byte(data), 0644)
	if err != nil {
		panic(err)
	}
}

func shell(cmdline string) string {
	out, err := exec.Command("bash", "-c", cmdline).Output()
	if err != nil {
		panic(err)
	}
	return strings.Trim(string(out), " \n")
}

func attachCmd(cmd *exec.Cmd, stdout, stderr io.Writer, stdin io.Reader) chan error {
	errCh := make(chan error)

	stdinIn, err := cmd.StdinPipe()
	if err != nil {
		panic(err)
	}
	stdoutOut, err := cmd.StdoutPipe()
	if err != nil {
		panic(err)
	}
	stderrOut, err := cmd.StderrPipe()
	if err != nil {
		panic(err)
	}

	go func() {
		_, e := io.Copy(stdinIn, stdin)
		errCh <- e
	}()
	go func() {
		_, e := io.Copy(stdout, stdoutOut)
		errCh <- e
	}()
	go func() {
		_, e := io.Copy(stderr, stderrOut)
		errCh <- e
	}()

	return errCh
}

func exitStatusCh(cmd *exec.Cmd) chan uint {
	exitCh := make(chan uint)
	go func() {
		err := cmd.Wait()
		if err != nil {
			if exiterr, ok := err.(*exec.ExitError); ok {
				// There is no plattform independent way to retrieve
				// the exit code, but the following will work on Unix
				if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
					exitCh <- uint(status.ExitStatus())
				}
			} else {
				panic(err)
			}
			return
		}
		exitCh <- uint(0)
	}()
	return exitCh
}<|endoftext|>


<commit_before>package gophercloud

import (
	"github.com/racker/perigee"
)

// WithReauth wraps a Perigee request fragment with logic to perform re-authentication
// if it's deemed necessary.
//
// Do not confuse this function with WithReauth()!  Although they work together to support reauthentication,
// WithReauth() actually contains the decision-making logic to determine when to perform a reauth,
// while WithReauthHandler() is used to configure what a reauth actually entails.
func (c *Context) WithReauth(ap AccessProvider, f func() error) error {
	err := f()
	cause, ok := err.(*perigee.UnexpectedResponseCodeError)
	if ok && cause.Actual == 401 {
		err = c.reauthHandler(ap)
		if err == nil {
			err = f()
		}
	}
	return err
}
<commit_msg>Add ResponseWithReauth to do WithReauth that returns a perigee.Response<commit_after>package gophercloud

import (
	"github.com/racker/perigee"
)

// WithReauth wraps a Perigee request fragment with logic to perform re-authentication
// if it's deemed necessary.
//
// Do not confuse this function with WithReauth()!  Although they work together to support reauthentication,
// WithReauth() actually contains the decision-making logic to determine when to perform a reauth,
// while WithReauthHandler() is used to configure what a reauth actually entails.
func (c *Context) WithReauth(ap AccessProvider, f func() error) error {
	err := f()
	cause, ok := err.(*perigee.UnexpectedResponseCodeError)
	if ok && cause.Actual == 401 {
		err = c.reauthHandler(ap)
		if err == nil {
			err = f()
		}
	}
	return err
}

// This is like WithReauth above but returns a perigee Response object
func (c *Context) ResponseWithReauth(ap AccessProvider, f func() (*perigee.Response, error)) (*perigee.Response, error) {
	response, err := f()
	cause, ok := err.(*perigee.UnexpectedResponseCodeError)
	if ok && cause.Actual == 401 {
		err = c.reauthHandler(ap)
		if err == nil {
			response, err = f()
		}
	}
	return response, err
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"encoding/binary"
	"os"
	"time"

	"github.com/phil-mansfield/gotetra"
)

func main() {
	t0 := time.Now().UnixNano()

	_, ps :=  gotetra.ReadGadget(os.Args[1], binary.LittleEndian)

	t1 := time.Now().UnixNano()

	m := make(map[int64]int)
	for i, p := range ps {
		m[p.Id] = i
	}

	t2 := time.Now().UnixNano()

	fmt.Printf("Reading: %.0f ms, Mapping: %.0f ms\n",
		float64(t1 - t0) / 1e6, float64(t2 - t1) / 1e6)
}
<commit_msg>Removed test.go<commit_after><|endoftext|>


<commit_before>// Copyright The OpenTelemetry 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 exporterhelper // import "go.opentelemetry.io/collector/exporter/exporterhelper"

import (
	"context"
	"errors"
	"fmt"
	"time"

	"github.com/cenkalti/backoff/v4"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/trace"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"

	"go.opentelemetry.io/collector/consumer/consumererror"
)

var (
	errSendingQueueIsFull = errors.New("sending_queue is full")
)

// RetrySettings defines configuration for retrying batches in case of export failure.
// The current supported strategy is exponential backoff.
type RetrySettings struct {
	// Enabled indicates whether to not retry sending batches in case of export failure.
	Enabled bool `mapstructure:"enabled"`
	// InitialInterval the time to wait after the first failure before retrying.
	InitialInterval time.Duration `mapstructure:"initial_interval"`
	// MaxInterval is the upper bound on backoff interval. Once this value is reached the delay between
	// consecutive retries will always be `MaxInterval`.
	MaxInterval time.Duration `mapstructure:"max_interval"`
	// MaxElapsedTime is the maximum amount of time (including retries) spent trying to send a request/batch.
	// Once this value is reached, the data is discarded.
	MaxElapsedTime time.Duration `mapstructure:"max_elapsed_time"`
}

// NewDefaultRetrySettings returns the default settings for RetrySettings.
func NewDefaultRetrySettings() RetrySettings {
	return RetrySettings{
		Enabled:         true,
		InitialInterval: 5 * time.Second,
		MaxInterval:     30 * time.Second,
		MaxElapsedTime:  5 * time.Minute,
	}
}

func createSampledLogger(logger *zap.Logger) *zap.Logger {
	if logger.Core().Enabled(zapcore.DebugLevel) {
		// Debugging is enabled. Don't do any sampling.
		return logger
	}

	// Create a logger that samples all messages to 1 per 10 seconds initially,
	// and 1/100 of messages after that.
	opts := zap.WrapCore(func(core zapcore.Core) zapcore.Core {
		return zapcore.NewSamplerWithOptions(
			core,
			10*time.Second,
			1,
			100,
		)
	})
	return logger.WithOptions(opts)
}

// send implements the requestSender interface
func (qrs *queuedRetrySender) send(req request) error {
	if !qrs.cfg.Enabled {
		err := qrs.consumerSender.send(req)
		if err != nil {
			qrs.logger.Error(
				"Exporting failed. Dropping data. Try enabling sending_queue to survive temporary failures.",
				zap.Int("dropped_items", req.count()),
			)
		}
		return err
	}

	// Prevent cancellation and deadline to propagate to the context stored in the queue.
	// The grpc/http based receivers will cancel the request context after this function returns.
	req.setContext(noCancellationContext{Context: req.context()})

	span := trace.SpanFromContext(req.context())
	if !qrs.queue.Produce(req) {
		qrs.logger.Error(
			"Dropping data because sending_queue is full. Try increasing queue_size.",
			zap.Int("dropped_items", req.count()),
		)
		span.AddEvent("Dropped item, sending_queue is full.", trace.WithAttributes(qrs.traceAttributes...))
		return errSendingQueueIsFull
	}

	span.AddEvent("Enqueued item.", trace.WithAttributes(qrs.traceAttributes...))
	return nil
}

// TODO: Clean this by forcing all exporters to return an internal error type that always include the information about retries.
type throttleRetry struct {
	err   error
	delay time.Duration
}

func (t throttleRetry) Error() string {
	return "Throttle (" + t.delay.String() + "), error: " + t.err.Error()
}

func (t throttleRetry) Unwrap() error {
	return t.err
}

// NewThrottleRetry creates a new throttle retry error.
func NewThrottleRetry(err error, delay time.Duration) error {
	return throttleRetry{
		err:   err,
		delay: delay,
	}
}

type onRequestHandlingFinishedFunc func(*zap.Logger, request, error) error

type retrySender struct {
	traceAttribute     attribute.KeyValue
	cfg                RetrySettings
	nextSender         requestSender
	stopCh             chan struct{}
	logger             *zap.Logger
	onTemporaryFailure onRequestHandlingFinishedFunc
}

// send implements the requestSender interface
func (rs *retrySender) send(req request) error {
	if !rs.cfg.Enabled {
		err := rs.nextSender.send(req)
		if err != nil {
			rs.logger.Error(
				"Exporting failed. Try enabling retry_on_failure config option.",
				zap.Error(err),
			)
		}
		return err
	}

	// Do not use NewExponentialBackOff since it calls Reset and the code here must
	// call Reset after changing the InitialInterval (this saves an unnecessary call to Now).
	expBackoff := backoff.ExponentialBackOff{
		InitialInterval:     rs.cfg.InitialInterval,
		RandomizationFactor: backoff.DefaultRandomizationFactor,
		Multiplier:          backoff.DefaultMultiplier,
		MaxInterval:         rs.cfg.MaxInterval,
		MaxElapsedTime:      rs.cfg.MaxElapsedTime,
		Stop:                backoff.Stop,
		Clock:               backoff.SystemClock,
	}
	expBackoff.Reset()
	span := trace.SpanFromContext(req.context())
	retryNum := int64(0)
	for {
		span.AddEvent(
			"Sending request.",
			trace.WithAttributes(rs.traceAttribute, attribute.Int64("retry_num", retryNum)))

		err := rs.nextSender.send(req)
		if err == nil {
			return nil
		}

		// Immediately drop data on permanent errors.
		if consumererror.IsPermanent(err) {
			rs.logger.Error(
				"Exporting failed. The error is not retryable. Dropping data.",
				zap.Error(err),
				zap.Int("dropped_items", req.count()),
			)
			return err
		}

		// Give the request a chance to extract signal data to retry if only some data
		// failed to process.
		req = req.onError(err)

		backoffDelay := expBackoff.NextBackOff()
		if backoffDelay == backoff.Stop {
			// throw away the batch
			err = fmt.Errorf("max elapsed time expired %w", err)
			return rs.onTemporaryFailure(rs.logger, req, err)
		}

		throttleErr := throttleRetry{}
		isThrottle := errors.As(err, &throttleErr)
		if isThrottle {
			backoffDelay = max(backoffDelay, throttleErr.delay)
		}

		backoffDelayStr := backoffDelay.String()
		span.AddEvent(
			"Exporting failed. Will retry the request after interval.",
			trace.WithAttributes(
				rs.traceAttribute,
				attribute.String("interval", backoffDelayStr),
				attribute.String("error", err.Error())))
		rs.logger.Info(
			"Exporting failed. Will retry the request after interval.",
			zap.Error(err),
			zap.String("interval", backoffDelayStr),
		)
		retryNum++

		// back-off, but get interrupted when shutting down or request is cancelled or timed out.
		select {
		case <-req.context().Done():
			return fmt.Errorf("request is cancelled or timed out %w", err)
		case <-rs.stopCh:
			return fmt.Errorf("interrupted due to shutdown %w", err)
		case <-time.After(backoffDelay):
		}
	}
}

// max returns the larger of x or y.
func max(x, y time.Duration) time.Duration {
	if x < y {
		return y
	}
	return x
}

type noCancellationContext struct {
	context.Context
}

func (noCancellationContext) Deadline() (deadline time.Time, ok bool) {
	return
}

func (noCancellationContext) Done() <-chan struct{} {
	return nil
}

func (noCancellationContext) Err() error {
	return nil
}
<commit_msg>Try to clarify the suggestion in the export failures when retry_on_failure is disabled (#5276)<commit_after>// Copyright The OpenTelemetry 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 exporterhelper // import "go.opentelemetry.io/collector/exporter/exporterhelper"

import (
	"context"
	"errors"
	"fmt"
	"time"

	"github.com/cenkalti/backoff/v4"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/trace"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"

	"go.opentelemetry.io/collector/consumer/consumererror"
)

var (
	errSendingQueueIsFull = errors.New("sending_queue is full")
)

// RetrySettings defines configuration for retrying batches in case of export failure.
// The current supported strategy is exponential backoff.
type RetrySettings struct {
	// Enabled indicates whether to not retry sending batches in case of export failure.
	Enabled bool `mapstructure:"enabled"`
	// InitialInterval the time to wait after the first failure before retrying.
	InitialInterval time.Duration `mapstructure:"initial_interval"`
	// MaxInterval is the upper bound on backoff interval. Once this value is reached the delay between
	// consecutive retries will always be `MaxInterval`.
	MaxInterval time.Duration `mapstructure:"max_interval"`
	// MaxElapsedTime is the maximum amount of time (including retries) spent trying to send a request/batch.
	// Once this value is reached, the data is discarded.
	MaxElapsedTime time.Duration `mapstructure:"max_elapsed_time"`
}

// NewDefaultRetrySettings returns the default settings for RetrySettings.
func NewDefaultRetrySettings() RetrySettings {
	return RetrySettings{
		Enabled:         true,
		InitialInterval: 5 * time.Second,
		MaxInterval:     30 * time.Second,
		MaxElapsedTime:  5 * time.Minute,
	}
}

func createSampledLogger(logger *zap.Logger) *zap.Logger {
	if logger.Core().Enabled(zapcore.DebugLevel) {
		// Debugging is enabled. Don't do any sampling.
		return logger
	}

	// Create a logger that samples all messages to 1 per 10 seconds initially,
	// and 1/100 of messages after that.
	opts := zap.WrapCore(func(core zapcore.Core) zapcore.Core {
		return zapcore.NewSamplerWithOptions(
			core,
			10*time.Second,
			1,
			100,
		)
	})
	return logger.WithOptions(opts)
}

// send implements the requestSender interface
func (qrs *queuedRetrySender) send(req request) error {
	if !qrs.cfg.Enabled {
		err := qrs.consumerSender.send(req)
		if err != nil {
			qrs.logger.Error(
				"Exporting failed. Dropping data. Try enabling sending_queue to survive temporary failures.",
				zap.Int("dropped_items", req.count()),
			)
		}
		return err
	}

	// Prevent cancellation and deadline to propagate to the context stored in the queue.
	// The grpc/http based receivers will cancel the request context after this function returns.
	req.setContext(noCancellationContext{Context: req.context()})

	span := trace.SpanFromContext(req.context())
	if !qrs.queue.Produce(req) {
		qrs.logger.Error(
			"Dropping data because sending_queue is full. Try increasing queue_size.",
			zap.Int("dropped_items", req.count()),
		)
		span.AddEvent("Dropped item, sending_queue is full.", trace.WithAttributes(qrs.traceAttributes...))
		return errSendingQueueIsFull
	}

	span.AddEvent("Enqueued item.", trace.WithAttributes(qrs.traceAttributes...))
	return nil
}

// TODO: Clean this by forcing all exporters to return an internal error type that always include the information about retries.
type throttleRetry struct {
	err   error
	delay time.Duration
}

func (t throttleRetry) Error() string {
	return "Throttle (" + t.delay.String() + "), error: " + t.err.Error()
}

func (t throttleRetry) Unwrap() error {
	return t.err
}

// NewThrottleRetry creates a new throttle retry error.
func NewThrottleRetry(err error, delay time.Duration) error {
	return throttleRetry{
		err:   err,
		delay: delay,
	}
}

type onRequestHandlingFinishedFunc func(*zap.Logger, request, error) error

type retrySender struct {
	traceAttribute     attribute.KeyValue
	cfg                RetrySettings
	nextSender         requestSender
	stopCh             chan struct{}
	logger             *zap.Logger
	onTemporaryFailure onRequestHandlingFinishedFunc
}

// send implements the requestSender interface
func (rs *retrySender) send(req request) error {
	if !rs.cfg.Enabled {
		err := rs.nextSender.send(req)
		if err != nil {
			rs.logger.Error(
				"Exporting failed. Try enabling retry_on_failure config option to retry on retryable errors",
				zap.Error(err),
			)
		}
		return err
	}

	// Do not use NewExponentialBackOff since it calls Reset and the code here must
	// call Reset after changing the InitialInterval (this saves an unnecessary call to Now).
	expBackoff := backoff.ExponentialBackOff{
		InitialInterval:     rs.cfg.InitialInterval,
		RandomizationFactor: backoff.DefaultRandomizationFactor,
		Multiplier:          backoff.DefaultMultiplier,
		MaxInterval:         rs.cfg.MaxInterval,
		MaxElapsedTime:      rs.cfg.MaxElapsedTime,
		Stop:                backoff.Stop,
		Clock:               backoff.SystemClock,
	}
	expBackoff.Reset()
	span := trace.SpanFromContext(req.context())
	retryNum := int64(0)
	for {
		span.AddEvent(
			"Sending request.",
			trace.WithAttributes(rs.traceAttribute, attribute.Int64("retry_num", retryNum)))

		err := rs.nextSender.send(req)
		if err == nil {
			return nil
		}

		// Immediately drop data on permanent errors.
		if consumererror.IsPermanent(err) {
			rs.logger.Error(
				"Exporting failed. The error is not retryable. Dropping data.",
				zap.Error(err),
				zap.Int("dropped_items", req.count()),
			)
			return err
		}

		// Give the request a chance to extract signal data to retry if only some data
		// failed to process.
		req = req.onError(err)

		backoffDelay := expBackoff.NextBackOff()
		if backoffDelay == backoff.Stop {
			// throw away the batch
			err = fmt.Errorf("max elapsed time expired %w", err)
			return rs.onTemporaryFailure(rs.logger, req, err)
		}

		throttleErr := throttleRetry{}
		isThrottle := errors.As(err, &throttleErr)
		if isThrottle {
			backoffDelay = max(backoffDelay, throttleErr.delay)
		}

		backoffDelayStr := backoffDelay.String()
		span.AddEvent(
			"Exporting failed. Will retry the request after interval.",
			trace.WithAttributes(
				rs.traceAttribute,
				attribute.String("interval", backoffDelayStr),
				attribute.String("error", err.Error())))
		rs.logger.Info(
			"Exporting failed. Will retry the request after interval.",
			zap.Error(err),
			zap.String("interval", backoffDelayStr),
		)
		retryNum++

		// back-off, but get interrupted when shutting down or request is cancelled or timed out.
		select {
		case <-req.context().Done():
			return fmt.Errorf("request is cancelled or timed out %w", err)
		case <-rs.stopCh:
			return fmt.Errorf("interrupted due to shutdown %w", err)
		case <-time.After(backoffDelay):
		}
	}
}

// max returns the larger of x or y.
func max(x, y time.Duration) time.Duration {
	if x < y {
		return y
	}
	return x
}

type noCancellationContext struct {
	context.Context
}

func (noCancellationContext) Deadline() (deadline time.Time, ok bool) {
	return
}

func (noCancellationContext) Done() <-chan struct{} {
	return nil
}

func (noCancellationContext) Err() error {
	return nil
}
<|endoftext|>


<commit_before>package libvirt

import "encoding/xml"

type Domain struct {
	XMLName xml.Name `xml:"domain"`
	ID      int      `xml:"id,attr,omitempty"`
	Type    string   `xml:"type,attr"`
	Name    string   `xml:"name,omitempty"`
	UUID    string   `xml:"uuid,omitempty"`
	// TODO: metadata

	OS    OS     `xml:"os"`
	IDMap *IDMap `xml:"idmap,omitempty"`

	Memory UnitInt `xml:"memory"`
	VCPU   int     `xml:"vcpu"`

	OnPoweroff string `xml:"on_poweroff,omitempty"`
	OnReboot   string `xml:"on_reboot,omitempty"`
	OnCrash    string `xml:"on_crash,omitempty"`

	Devices Devices `xml:"devices"`
}

func (d *Domain) XML() []byte {
	data, _ := xml.Marshal(d)
	return data
}

type OS struct {
	Type     OSType   `xml:"type"`
	Init     string   `xml:"init"`
	InitArgs []string `xml:"initarg,omitempty"`
}

type OSType struct {
	Value   string `xml:",chardata"`
	Arch    string `xml:"arch,attr,omitempty"`
	Machine string `xml:"machine,attr,omitempty"`
}

type IDMap struct {
	Uid IDMapping `xml:"uid"`
	Gid IDMapping `xml:"gid"`
}

type IDMapping struct {
	Start  int `xml:"start,attr"`
	Target int `xml:"target,attr"`
	Count  int `xml:"count,attr"`
}

type UnitInt struct {
	Value int    `xml:",chardata"`
	Unit  string `xml:"unit,attr,omitempty"`
}

type Devices struct {
	Emulator    string       `xml:"emulator,omitempty"`
	Filesystems []Filesystem `xml:"filesystem"`
	HostDevs    []HostDev    `xml:"hostdev"`
	Interfaces  []Interface  `xml:"interface"`
	Consoles    []Console    `xml:"console"`
}

type Filesystem struct {
	Type   string    `xml:"type,attr,omitempty"`
	Driver *FSDriver `xml:"driver,omitempty"`
	Source FSRef     `xml:"source"`
	Target FSRef     `xml:"target"`
}

type FSDriver struct {
	Name   string `xml:"name,attr,omitempty"`
	Type   string `xml:"type,attr,omitempty"`
	Format string `xml:"format,attr,omitempty"`
}

type FSRef struct {
	Dir  string `xml:"dir,attr,omitempty"`
	File string `xml:"file,attr,omitempty"`
}

type HostDev struct {
	Mode         string `xml:"mode,attr"`
	Type         string `xml:"type,attr"`
	SrcBlock     string `xml:"source>block,omitempty"`
	SrcChar      string `xml:"source>char,omitempty"`
	SrcInterface string `xml:"source>interface,omitempty"`
}

type Interface struct {
	Type   string        `xml:"type,attr"`
	Source InterfaceSrc  `xml:"source"`
	Target *InterfaceSrc `xml:"target,omitempty"`
}

type InterfaceSrc struct {
	Network string `xml:"network,attr,omitempty"`
	Dev     string `xml:"dev,attr,omitempty"`
	Mode    string `xml:"mode,attr,omitempty"`
}

type Console struct {
	Type string `xml:"type,attr"`
}

type Network struct {
	XMLName xml.Name `xml:"network"`
	Name    string   `xml:"name"`
	Bridge  Bridge   `xml:"bridge"`
	Forward Forward  `xml:"forward"`
	IP      IP       `xml:"ip"`
	MAC     MAC      `xml:"mac"`
}

func (n *Network) XML() []byte {
	data, _ := xml.Marshal(n)
	return data
}

type Bridge struct {
	Name string `xml:"name,attr"`
	STP  string `xml:"stp,attr"`
}

type Forward struct {
	Mode string `xml:"mode,attr"`
}

type IP struct {
	Address string `xml:"address,attr"`
	Netmask string `xml:"netmask,attr"`
}

type MAC struct {
	Address string `xml:"address,attr"`
}
<commit_msg>host: Fix libvirt network XML<commit_after>package libvirt

import "encoding/xml"

type Domain struct {
	XMLName xml.Name `xml:"domain"`
	ID      int      `xml:"id,attr,omitempty"`
	Type    string   `xml:"type,attr"`
	Name    string   `xml:"name,omitempty"`
	UUID    string   `xml:"uuid,omitempty"`
	// TODO: metadata

	OS    OS     `xml:"os"`
	IDMap *IDMap `xml:"idmap,omitempty"`

	Memory UnitInt `xml:"memory"`
	VCPU   int     `xml:"vcpu"`

	OnPoweroff string `xml:"on_poweroff,omitempty"`
	OnReboot   string `xml:"on_reboot,omitempty"`
	OnCrash    string `xml:"on_crash,omitempty"`

	Devices Devices `xml:"devices"`
}

func (d *Domain) XML() []byte {
	data, _ := xml.Marshal(d)
	return data
}

type OS struct {
	Type     OSType   `xml:"type"`
	Init     string   `xml:"init"`
	InitArgs []string `xml:"initarg,omitempty"`
}

type OSType struct {
	Value   string `xml:",chardata"`
	Arch    string `xml:"arch,attr,omitempty"`
	Machine string `xml:"machine,attr,omitempty"`
}

type IDMap struct {
	Uid IDMapping `xml:"uid"`
	Gid IDMapping `xml:"gid"`
}

type IDMapping struct {
	Start  int `xml:"start,attr"`
	Target int `xml:"target,attr"`
	Count  int `xml:"count,attr"`
}

type UnitInt struct {
	Value int    `xml:",chardata"`
	Unit  string `xml:"unit,attr,omitempty"`
}

type Devices struct {
	Emulator    string       `xml:"emulator,omitempty"`
	Filesystems []Filesystem `xml:"filesystem"`
	HostDevs    []HostDev    `xml:"hostdev"`
	Interfaces  []Interface  `xml:"interface"`
	Consoles    []Console    `xml:"console"`
}

type Filesystem struct {
	Type   string    `xml:"type,attr,omitempty"`
	Driver *FSDriver `xml:"driver,omitempty"`
	Source FSRef     `xml:"source"`
	Target FSRef     `xml:"target"`
}

type FSDriver struct {
	Name   string `xml:"name,attr,omitempty"`
	Type   string `xml:"type,attr,omitempty"`
	Format string `xml:"format,attr,omitempty"`
}

type FSRef struct {
	Dir  string `xml:"dir,attr,omitempty"`
	File string `xml:"file,attr,omitempty"`
}

type HostDev struct {
	Mode         string `xml:"mode,attr"`
	Type         string `xml:"type,attr"`
	SrcBlock     string `xml:"source>block,omitempty"`
	SrcChar      string `xml:"source>char,omitempty"`
	SrcInterface string `xml:"source>interface,omitempty"`
}

type Interface struct {
	Type   string        `xml:"type,attr"`
	Source InterfaceSrc  `xml:"source"`
	Target *InterfaceSrc `xml:"target,omitempty"`
}

type InterfaceSrc struct {
	Network string `xml:"network,attr,omitempty"`
	Dev     string `xml:"dev,attr,omitempty"`
	Mode    string `xml:"mode,attr,omitempty"`
}

type Console struct {
	Type string `xml:"type,attr"`
}

type Network struct {
	XMLName xml.Name `xml:"network"`
	Name    string   `xml:"name"`
	Bridge  Bridge   `xml:"bridge"`
	Forward Forward  `xml:"forward"`
	IP      *IP      `xml:"ip,omitempty"`
	MAC     *MAC     `xml:"mac,omitempty"`
}

func (n *Network) XML() []byte {
	data, _ := xml.Marshal(n)
	return data
}

type Bridge struct {
	Name string `xml:"name,attr"`
	STP  string `xml:"stp,attr"`
}

type Forward struct {
	Mode string `xml:"mode,attr"`
}

type IP struct {
	Address string `xml:"address,attr"`
	Netmask string `xml:"netmask,attr"`
}

type MAC struct {
	Address string `xml:"address,attr"`
}
<|endoftext|>


<commit_before>package pgtype

import (
	"encoding/binary"
	"reflect"

	errors "golang.org/x/xerrors"
)

// Record is the generic PostgreSQL record type such as is created with the
// "row" function. Record only implements BinaryEncoder and Value. The text
// format output format from PostgreSQL does not include type information and is
// therefore impossible to decode. No encoders are implemented because
// PostgreSQL does not support input of generic records.
type Record struct {
	Fields []Value
	Status Status
}

func (dst *Record) Set(src interface{}) error {
	if src == nil {
		*dst = Record{Status: Null}
		return nil
	}

	if value, ok := src.(interface{ Get() interface{} }); ok {
		value2 := value.Get()
		if value2 != value {
			return dst.Set(value2)
		}
	}

	switch value := src.(type) {
	case []Value:
		*dst = Record{Fields: value, Status: Present}
	default:
		return errors.Errorf("cannot convert %v to Record", src)
	}

	return nil
}

func (dst Record) Get() interface{} {
	switch dst.Status {
	case Present:
		return dst.Fields
	case Null:
		return nil
	default:
		return dst.Status
	}
}

func (src *Record) AssignTo(dst interface{}) error {
	switch src.Status {
	case Present:
		switch v := dst.(type) {
		case *[]Value:
			*v = make([]Value, len(src.Fields))
			copy(*v, src.Fields)
			return nil
		case *[]interface{}:
			*v = make([]interface{}, len(src.Fields))
			for i := range *v {
				(*v)[i] = src.Fields[i].Get()
			}
			return nil
		default:
			if nextDst, retry := GetAssignToDstType(dst); retry {
				return src.AssignTo(nextDst)
			}
			return errors.Errorf("unable to assign to %T", dst)
		}
	case Null:
		return NullAssignTo(dst)
	}

	return errors.Errorf("cannot decode %#v into %T", src, dst)
}

func (dst *Record) DecodeBinary(ci *ConnInfo, src []byte) error {
	if src == nil {
		*dst = Record{Status: Null}
		return nil
	}

	rp := 0

	if len(src[rp:]) < 4 {
		return errors.Errorf("Record incomplete %v", src)
	}
	fieldCount := int(int32(binary.BigEndian.Uint32(src[rp:])))
	rp += 4

	fields := make([]Value, fieldCount)

	for i := 0; i < fieldCount; i++ {
		if len(src[rp:]) < 8 {
			return errors.Errorf("Record incomplete %v", src)
		}
		fieldOID := binary.BigEndian.Uint32(src[rp:])
		rp += 4

		fieldLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
		rp += 4

		var binaryDecoder BinaryDecoder
		if dt, ok := ci.DataTypeForOID(fieldOID); ok {
			binaryDecoder, _ = dt.Value.(BinaryDecoder)
		}
		if binaryDecoder == nil {
			return errors.Errorf("unknown oid while decoding record: %v", fieldOID)
		}

		var fieldBytes []byte
		if fieldLen >= 0 {
			if len(src[rp:]) < fieldLen {
				return errors.Errorf("Record incomplete %v", src)
			}
			fieldBytes = src[rp : rp+fieldLen]
			rp += fieldLen
		}

		// Duplicate struct to scan into
		binaryDecoder = reflect.New(reflect.ValueOf(binaryDecoder).Elem().Type()).Interface().(BinaryDecoder)

		if err := binaryDecoder.DecodeBinary(ci, fieldBytes); err != nil {
			return err
		}

		fields[i] = binaryDecoder.(Value)
	}

	*dst = Record{Fields: fields, Status: Present}

	return nil
}
<commit_msg>Refactor lowlevel record field iteration<commit_after>package pgtype

import (
	"encoding/binary"
	"reflect"

	errors "golang.org/x/xerrors"
)

// Record is the generic PostgreSQL record type such as is created with the
// "row" function. Record only implements BinaryEncoder and Value. The text
// format output format from PostgreSQL does not include type information and is
// therefore impossible to decode. No encoders are implemented because
// PostgreSQL does not support input of generic records.
type Record struct {
	Fields []Value
	Status Status
}

func (dst *Record) Set(src interface{}) error {
	if src == nil {
		*dst = Record{Status: Null}
		return nil
	}

	if value, ok := src.(interface{ Get() interface{} }); ok {
		value2 := value.Get()
		if value2 != value {
			return dst.Set(value2)
		}
	}

	switch value := src.(type) {
	case []Value:
		*dst = Record{Fields: value, Status: Present}
	default:
		return errors.Errorf("cannot convert %v to Record", src)
	}

	return nil
}

func (dst Record) Get() interface{} {
	switch dst.Status {
	case Present:
		return dst.Fields
	case Null:
		return nil
	default:
		return dst.Status
	}
}

func (src *Record) AssignTo(dst interface{}) error {
	switch src.Status {
	case Present:
		switch v := dst.(type) {
		case *[]Value:
			*v = make([]Value, len(src.Fields))
			copy(*v, src.Fields)
			return nil
		case *[]interface{}:
			*v = make([]interface{}, len(src.Fields))
			for i := range *v {
				(*v)[i] = src.Fields[i].Get()
			}
			return nil
		default:
			if nextDst, retry := GetAssignToDstType(dst); retry {
				return src.AssignTo(nextDst)
			}
			return errors.Errorf("unable to assign to %T", dst)
		}
	case Null:
		return NullAssignTo(dst)
	}

	return errors.Errorf("cannot decode %#v into %T", src, dst)
}

type fieldIter struct {
	rp         int
	fieldCount int
	src        []byte
}

func newFieldIterator(src []byte) (fieldIter, error) {
	rp := 0
	if len(src[rp:]) < 4 {
		return fieldIter{}, errors.Errorf("Record incomplete %v", src)
	}

	fieldCount := int(int32(binary.BigEndian.Uint32(src[rp:])))
	rp += 4

	return fieldIter{
		rp:         rp,
		fieldCount: fieldCount,
		src:        src,
	}, nil
}

func (fi *fieldIter) next() (fieldOID uint32, buf []byte, eof bool, err error) {
	if fi.rp == len(fi.src) {
		eof = true
		return
	}

	if len(fi.src[fi.rp:]) < 8 {
		err = errors.Errorf("Record incomplete %v", fi.src)
		return
	}
	fieldOID = binary.BigEndian.Uint32(fi.src[fi.rp:])
	fi.rp += 4

	fieldLen := int(int32(binary.BigEndian.Uint32(fi.src[fi.rp:])))
	fi.rp += 4

	if fieldLen >= 0 {
		if len(fi.src[fi.rp:]) < fieldLen {
			err = errors.Errorf("Record incomplete rp=%d src=%v", fi.rp, fi.src)
			return
		}
		buf = fi.src[fi.rp : fi.rp+fieldLen]
		fi.rp += fieldLen
	}

	return
}

func (dst *Record) DecodeBinary(ci *ConnInfo, src []byte) error {
	if src == nil {
		*dst = Record{Status: Null}
		return nil
	}

	fieldIter, err := newFieldIterator(src)
	if err != nil {
		return err
	}

	fields := make([]Value, fieldIter.fieldCount)
	fieldOID, fieldBytes, eof, err := fieldIter.next()

	for i := 0; !eof; i++ {
		if err != nil {
			return err
		}
		var binaryDecoder BinaryDecoder

		if dt, ok := ci.DataTypeForOID(fieldOID); ok {
			binaryDecoder, _ = dt.Value.(BinaryDecoder)
		} else {
			return errors.Errorf("unknown oid while decoding record: %v", fieldOID)
		}

		if binaryDecoder == nil {
			return errors.Errorf("no binary decoder registered for: %v", fieldOID)
		}

		// Duplicate struct to scan into
		binaryDecoder = reflect.New(reflect.ValueOf(binaryDecoder).Elem().Type()).Interface().(BinaryDecoder)
		if err := binaryDecoder.DecodeBinary(ci, fieldBytes); err != nil {
			return err
		}

		fields[i] = binaryDecoder.(Value)
		fieldOID, fieldBytes, eof, err = fieldIter.next()
	}

	*dst = Record{Fields: fields, Status: Present}

	return nil
}
<|endoftext|>


<commit_before>package dexcom

import (
	"bytes"
	"fmt"
	"time"
)

// nolint
type (
	Record struct {
		Timestamp Timestamp
		Info      interface{}
	}

	Records []Record

	SensorInfo struct {
		Unfiltered uint32
		Filtered   uint32
		RSSI       int8
		Unknown    byte
	}

	EGVInfo struct {
		Glucose     uint16
		DisplayOnly bool
		Noise       uint8
		Trend       Trend
	}

	InsertionInfo struct {
		SystemTime time.Time
		Event      SensorChange
	}

	MeterInfo struct {
		Glucose   uint16
		MeterTime time.Time
	}

	CalibrationInfo struct {
		Slope     float64
		Intercept float64
		Scale     float64
		Decay     float64
		Data      []CalibrationRecord
	}

	CalibrationRecord struct {
		TimeEntered time.Time
		Glucose     int32
		Raw         int32
		TimeApplied time.Time
	}

	// BGInfo is a synthetic BG record combining sensor and EGV info.
	BGInfo struct {
		Sensor SensorInfo
		EGV    EGVInfo
	}
)

// Time returns the record's display time.
func (r Record) Time() time.Time {
	return r.Timestamp.DisplayTime
}

// Glucose returns the glucose field from an EGV or BG record.
func (r Record) Glucose() uint16 {
	switch info := r.Info.(type) {
	case EGVInfo:
		return info.Glucose
	case BGInfo:
		return info.EGV.Glucose
	}
	panic(fmt.Sprintf("Glucose %+v", r))
}

// Len returns the number of records.
func (v Records) Len() int {
	return len(v)
}

// Time returns the time of the record at index i.
func (v Records) Time(i int) time.Time {
	return v[i].Time()
}

var recordUnmarshal = map[PageType]func(*Record, []byte){
	ManufacturingData: umarshalXMLInfo,
	FirmwareData:      umarshalXMLInfo,
	SoftwareData:      umarshalXMLInfo,
	SensorData:        unmarshalSensorInfo,
	EGVData:           umarshalEGVInfo,
	CalibrationData:   unmarshalCalibrationInfo,
	InsertionTimeData: unmarshalInsertionInfo,
	MeterData:         unmarshalMeterInfo,
}

func (r *Record) unmarshal(pageType PageType, v []byte) error {
	f, found := recordUnmarshal[pageType]
	if !found {
		return fmt.Errorf("unmarshaling of %v records is unimplemented: % X", pageType, v)
	}
	r.Timestamp.unmarshal(v[0:8])
	f(r, v)
	return nil
}

func unmarshalSensorInfo(r *Record, v []byte) {
	r.Info = SensorInfo{
		Unfiltered: unmarshalUint32(v[8:12]),
		Filtered:   unmarshalUint32(v[12:16]),
		RSSI:       int8(v[16]),
		Unknown:    v[17],
	}
}

// SpecialGlucose represents a glucose value that indicates an exceptional condition.
type SpecialGlucose uint16

//go:generate stringer -type SpecialGlucose

// Exceptional conditions.
const (
	SensorNotActive     SpecialGlucose = 1
	MinimalDeviation    SpecialGlucose = 2
	NoAntenna           SpecialGlucose = 3
	SensorNotCalibrated SpecialGlucose = 5
	CountDeviation      SpecialGlucose = 6
	AbsoluteDeviation   SpecialGlucose = 9
	PowerDeviation      SpecialGlucose = 10
	BadRF               SpecialGlucose = 12

	specialLimit = BadRF
)

// IsSpecial checks whether a glucose value falls in the SpecialGlucose range.
func IsSpecial(glucose uint16) bool {
	return glucose <= uint16(specialLimit)
}

// Trend represents a directional arrow displayed by the Dexcom CGM receiver.
type Trend byte

//go:generate stringer -type Trend

// Trend arrows.
const (
	UpUp          Trend = 1
	Up            Trend = 2
	Up45          Trend = 3
	Flat          Trend = 4
	Down45        Trend = 5
	Down          Trend = 6
	DownDown      Trend = 7
	NotComputable Trend = 8
	OutOfRange    Trend = 9
)

var trendSymbol = map[Trend]string{
	UpUp:          "⇈",
	Up:            "↑",
	Up45:          "↗",
	Flat:          "→",
	Down45:        "↘",
	Down:          "↓",
	DownDown:      "⇊",
	NotComputable: "⁇",
	OutOfRange:    "⋯",
}

// Symbol converts a Trend to a graphical representation.
func (t Trend) Symbol() string {
	return trendSymbol[t]
}

// Constants used to extract EGV, noise, and trend.
const (
	EGVDisplayOnly = 1 << 15
	EGVValueMask   = 0x3FF
	EGVNoiseMask   = 0x70
	EGVTrendMask   = 0xF
)

func umarshalEGVInfo(r *Record, v []byte) {
	g := unmarshalUint16(v[8:10])
	r.Info = EGVInfo{
		Glucose:     g & EGVValueMask,
		DisplayOnly: g&EGVDisplayOnly != 0,
		Noise:       v[10] & EGVNoiseMask >> 4,
		Trend:       Trend(v[10] & EGVTrendMask),
	}
}

func unmarshalCalibrationInfo(r *Record, v []byte) {
	cal := CalibrationInfo{
		Slope:     unmarshalFloat64(v[8:16]),
		Intercept: unmarshalFloat64(v[16:24]),
		Scale:     unmarshalFloat64(v[24:32]),
		Decay:     unmarshalFloat64(v[35:43]),
	}
	n := int(v[43])
	cal.Data = make([]CalibrationRecord, n)
	v = v[44:]
	offset := r.Timestamp.DisplayTime.Sub(r.Timestamp.SystemTime)
	for i := 0; i < n; i++ {
		cal.Data[i].unmarshal(v)
		cal.Data[i].TimeEntered = cal.Data[i].TimeEntered.Add(offset)
		cal.Data[i].TimeApplied = cal.Data[i].TimeApplied.Add(offset)
		v = v[17:]
	}
	r.Info = cal
}

func (r *CalibrationRecord) unmarshal(v []byte) {
	r.TimeEntered = unmarshalTime(v[0:4])
	r.Glucose = unmarshalInt32(v[4:8])
	r.Raw = unmarshalInt32(v[8:12])
	r.TimeApplied = unmarshalTime(v[12:16])
}

// SensorChange represents a sensor change.
type SensorChange byte

//go:generate stringer -type SensorChange

// Sensor change values.
const (
	Stopped SensorChange = 1
	Started SensorChange = 7
)

var (
	invalidTime = []byte{0xFF, 0xFF, 0xFF, 0xFF}
)

func unmarshalInsertionInfo(r *Record, v []byte) {
	t := time.Time{}
	u := v[8:12]
	if !bytes.Equal(u, invalidTime) {
		t = unmarshalTime(u)
	}
	r.Info = InsertionInfo{
		SystemTime: t,
		Event:      SensorChange(v[12]),
	}
}

func unmarshalMeterInfo(r *Record, v []byte) {
	r.Info = MeterInfo{
		Glucose:   unmarshalUint16(v[8:10]),
		MeterTime: unmarshalTime(v[10:14]),
	}
}
<commit_msg>Remove synthetic BGInfo struct<commit_after>package dexcom

import (
	"bytes"
	"fmt"
	"time"
)

// nolint
type (
	Record struct {
		Timestamp Timestamp
		Info      interface{}
	}

	Records []Record

	SensorInfo struct {
		Unfiltered uint32
		Filtered   uint32
		RSSI       int8
		Unknown    byte
	}

	EGVInfo struct {
		Glucose     uint16
		DisplayOnly bool
		Noise       uint8
		Trend       Trend
	}

	InsertionInfo struct {
		SystemTime time.Time
		Event      SensorChange
	}

	MeterInfo struct {
		Glucose   uint16
		MeterTime time.Time
	}

	CalibrationInfo struct {
		Slope     float64
		Intercept float64
		Scale     float64
		Decay     float64
		Data      []CalibrationRecord
	}

	CalibrationRecord struct {
		TimeEntered time.Time
		Glucose     int32
		Raw         int32
		TimeApplied time.Time
	}
)

// Time returns the record's display time.
func (r Record) Time() time.Time {
	return r.Timestamp.DisplayTime
}

// Glucose returns the glucose field from an EGV record.
func (r Record) Glucose() uint16 {
	return r.Info.(EGVInfo).Glucose
}

// Len returns the number of records.
func (v Records) Len() int {
	return len(v)
}

// Time returns the time of the record at index i.
func (v Records) Time(i int) time.Time {
	return v[i].Time()
}

var recordUnmarshal = map[PageType]func(*Record, []byte){
	ManufacturingData: umarshalXMLInfo,
	FirmwareData:      umarshalXMLInfo,
	SoftwareData:      umarshalXMLInfo,
	SensorData:        unmarshalSensorInfo,
	EGVData:           umarshalEGVInfo,
	CalibrationData:   unmarshalCalibrationInfo,
	InsertionTimeData: unmarshalInsertionInfo,
	MeterData:         unmarshalMeterInfo,
}

func (r *Record) unmarshal(pageType PageType, v []byte) error {
	f, found := recordUnmarshal[pageType]
	if !found {
		return fmt.Errorf("unmarshaling of %v records is unimplemented: % X", pageType, v)
	}
	r.Timestamp.unmarshal(v[0:8])
	f(r, v)
	return nil
}

func unmarshalSensorInfo(r *Record, v []byte) {
	r.Info = SensorInfo{
		Unfiltered: unmarshalUint32(v[8:12]),
		Filtered:   unmarshalUint32(v[12:16]),
		RSSI:       int8(v[16]),
		Unknown:    v[17],
	}
}

// SpecialGlucose represents a glucose value that indicates an exceptional condition.
type SpecialGlucose uint16

//go:generate stringer -type SpecialGlucose

// Exceptional conditions.
const (
	SensorNotActive     SpecialGlucose = 1
	MinimalDeviation    SpecialGlucose = 2
	NoAntenna           SpecialGlucose = 3
	SensorNotCalibrated SpecialGlucose = 5
	CountDeviation      SpecialGlucose = 6
	AbsoluteDeviation   SpecialGlucose = 9
	PowerDeviation      SpecialGlucose = 10
	BadRF               SpecialGlucose = 12

	specialLimit = BadRF
)

// IsSpecial checks whether a glucose value falls in the SpecialGlucose range.
func IsSpecial(glucose uint16) bool {
	return glucose <= uint16(specialLimit)
}

// Trend represents a directional arrow displayed by the Dexcom CGM receiver.
type Trend byte

//go:generate stringer -type Trend

// Trend arrows.
const (
	UpUp          Trend = 1
	Up            Trend = 2
	Up45          Trend = 3
	Flat          Trend = 4
	Down45        Trend = 5
	Down          Trend = 6
	DownDown      Trend = 7
	NotComputable Trend = 8
	OutOfRange    Trend = 9
)

var trendSymbol = map[Trend]string{
	UpUp:          "⇈",
	Up:            "↑",
	Up45:          "↗",
	Flat:          "→",
	Down45:        "↘",
	Down:          "↓",
	DownDown:      "⇊",
	NotComputable: "⁇",
	OutOfRange:    "⋯",
}

// Symbol converts a Trend to a graphical representation.
func (t Trend) Symbol() string {
	return trendSymbol[t]
}

// Constants used to extract EGV, noise, and trend.
const (
	EGVDisplayOnly = 1 << 15
	EGVValueMask   = 0x3FF
	EGVNoiseMask   = 0x70
	EGVTrendMask   = 0xF
)

func umarshalEGVInfo(r *Record, v []byte) {
	g := unmarshalUint16(v[8:10])
	r.Info = EGVInfo{
		Glucose:     g & EGVValueMask,
		DisplayOnly: g&EGVDisplayOnly != 0,
		Noise:       v[10] & EGVNoiseMask >> 4,
		Trend:       Trend(v[10] & EGVTrendMask),
	}
}

func unmarshalCalibrationInfo(r *Record, v []byte) {
	cal := CalibrationInfo{
		Slope:     unmarshalFloat64(v[8:16]),
		Intercept: unmarshalFloat64(v[16:24]),
		Scale:     unmarshalFloat64(v[24:32]),
		Decay:     unmarshalFloat64(v[35:43]),
	}
	n := int(v[43])
	cal.Data = make([]CalibrationRecord, n)
	v = v[44:]
	offset := r.Timestamp.DisplayTime.Sub(r.Timestamp.SystemTime)
	for i := 0; i < n; i++ {
		cal.Data[i].unmarshal(v)
		cal.Data[i].TimeEntered = cal.Data[i].TimeEntered.Add(offset)
		cal.Data[i].TimeApplied = cal.Data[i].TimeApplied.Add(offset)
		v = v[17:]
	}
	r.Info = cal
}

func (r *CalibrationRecord) unmarshal(v []byte) {
	r.TimeEntered = unmarshalTime(v[0:4])
	r.Glucose = unmarshalInt32(v[4:8])
	r.Raw = unmarshalInt32(v[8:12])
	r.TimeApplied = unmarshalTime(v[12:16])
}

// SensorChange represents a sensor change.
type SensorChange byte

//go:generate stringer -type SensorChange

// Sensor change values.
const (
	Stopped SensorChange = 1
	Started SensorChange = 7
)

var (
	invalidTime = []byte{0xFF, 0xFF, 0xFF, 0xFF}
)

func unmarshalInsertionInfo(r *Record, v []byte) {
	t := time.Time{}
	u := v[8:12]
	if !bytes.Equal(u, invalidTime) {
		t = unmarshalTime(u)
	}
	r.Info = InsertionInfo{
		SystemTime: t,
		Event:      SensorChange(v[12]),
	}
}

func unmarshalMeterInfo(r *Record, v []byte) {
	r.Info = MeterInfo{
		Glucose:   unmarshalUint16(v[8:10]),
		MeterTime: unmarshalTime(v[10:14]),
	}
}
<|endoftext|>


<commit_before>package sudoku

type forcingChainsTechnique struct {
	*basicSolveTechnique
}

func (self *forcingChainsTechnique) HumanLikelihood() float64 {
	//TODO: figure out what the baseDifficulty should be
	return self.difficultyHelper(200.0)
}

func (self *forcingChainsTechnique) Description(step *SolveStep) string {
	//TODO: implement this
	return "ERROR: NOT IMPLEMENTED"
}

func (self *forcingChainsTechnique) Find(grid *Grid, results chan *SolveStep, done chan bool) {
	//TODO: test that this will find multiple if they exist.
	//TODO: Implement this.

	getter := grid.queue().DefaultGetter()

	_MAX_IMPLICATION_STEPS := 6

	for {

		//Check if it's time to stop.
		select {
		case <-done:
			return
		default:
		}

		candidate := getter.GetSmallerThan(3)

		if candidate == nil {
			break
		}

		candidateCell := candidate.(*Cell)

		if len(candidateCell.Possibilities()) != 2 {
			//We found one with 1 possibility, which isn't interesting for us--nakedSingle should do that one.
			continue
		}

		firstPossibilityNum := candidateCell.Possibilities()[0]
		secondPossibilityNum := candidateCell.Possibilities()[1]

		firstGrid := grid.Copy()
		secondGrid := grid.Copy()

		//Check that the neighbor isn't just already having a single possibility, because then this technique is overkill.

		firstAffectedCellSets, firstAffectedCellNums := chainSearcher(_MAX_IMPLICATION_STEPS,
			candidateCell.InGrid(firstGrid),
			firstPossibilityNum,
			[]cellSet{cellSet{}},
			[]map[*Cell]int{make(map[*Cell]int)})

		secondAffectedCellSets, secondAffectedCellNums := chainSearcher(_MAX_IMPLICATION_STEPS,
			candidateCell.InGrid(secondGrid),
			secondPossibilityNum,
			[]cellSet{cellSet{}},
			[]map[*Cell]int{make(map[*Cell]int)})

		//Check if the sets overlap.

		//Check pairwise through each of the result sets for each side and see if any overlap in an interestin way

		for i, theSet := range firstAffectedCellSets {
			theCellMapping := firstAffectedCellNums[i]
			for j, theSecondSet := range secondAffectedCellSets {
				theSecondCellMapping := secondAffectedCellNums[j]

				intersection := theSet.intersection(theSecondSet)
				if len(intersection) > 0 {
					//Okay, a cell overlapped... did they both set the same number?
					//TODO: should we look at all items that overlap if it's greater than 1?

					cell := intersection.toSlice()[0]

					if theCellMapping[cell] == theSecondCellMapping[cell] {
						//Booyah, found a step.

						step := &SolveStep{self,
							CellSlice{cell},
							IntSlice{theCellMapping[cell]},
							CellSlice{candidateCell},
							candidateCell.Possibilities(),
						}

						if step.IsUseful(grid) {
							select {
							case results <- step:
							case <-done:
								return
							}
						}
					}
				}

			}
		}

	}
}

func chainSearcher(i int, cell *Cell, numToApply int, affectedCellSetsSoFar []cellSet, affectedCellNumsSoFar []map[*Cell]int) (affectedCellSets []cellSet, affectedCellNums []map[*Cell]int) {
	if i <= 0 || cell == nil {
		//Base case
		return affectedCellSetsSoFar, affectedCellNumsSoFar
	}

	if len(affectedCellSetsSoFar) != len(affectedCellNumsSoFar) {
		panic("Mismatched sizes of arrays to chainSearcher")
	}

	var resultAffectedCellSets []cellSet
	var resultAffectedCellNums []map[*Cell]int

	for k, affectedCellSet := range affectedCellSetsSoFar {

		//Before we make the change, make sure the change will force
		//another cell. (We don't just set it and see if there are any
		//singleLegals in neigbhors because this technique is only
		//concerned with CHAINS of cells that we bring into existence.

		affectedCellNums := affectedCellNumsSoFar[k]

		//Find the nextCells that will have their numbers forced by the cell we're thinking of fillint.
		for j, nextCell := range cell.Neighbors().FilterByPossible(numToApply).FilterByNumPossibilities(2) {
			forcedNum := nextCell.Possibilities().Difference(IntSlice{numToApply})[0]

			var newAffectedNums map[*Cell]int

			//If it's not the first one, we're effectively branching.
			if j == 0 {
				newAffectedNums = affectedCellNums

			} else {
				newGrid := nextCell.grid.Copy()
				nextCell = nextCell.InGrid(newGrid)

				newAffectedNums = make(map[*Cell]int)

				for key, val := range affectedCellNums {
					newAffectedNums[key] = val
				}

			}

			newAffectedNums[nextCell] = forcedNum

			nextCell.SetNumber(forcedNum)

			theAffectedCellSets, theAffectedCellNums := chainSearcher(i-1,
				nextCell,
				forcedNum,
				[]cellSet{affectedCellSet.union(cellSet{nextCell: true})},
				[]map[*Cell]int{newAffectedNums})

			resultAffectedCellSets = append(resultAffectedCellSets, theAffectedCellSets...)
			resultAffectedCellNums = append(resultAffectedCellNums, theAffectedCellNums...)
		}
	}
	return resultAffectedCellSets, resultAffectedCellNums

}
<commit_msg>TESTS FAIL. Reimplemented the first part of chainSearcher. I'm more confident that the basic logic is right becuase the recursion is much more straight forward.<commit_after>package sudoku

import (
	"log"
)

type forcingChainsTechnique struct {
	*basicSolveTechnique
}

func (self *forcingChainsTechnique) HumanLikelihood() float64 {
	//TODO: figure out what the baseDifficulty should be
	return self.difficultyHelper(200.0)
}

func (self *forcingChainsTechnique) Description(step *SolveStep) string {
	//TODO: implement this
	return "ERROR: NOT IMPLEMENTED"
}

func (self *forcingChainsTechnique) Find(grid *Grid, results chan *SolveStep, done chan bool) {
	//TODO: test that this will find multiple if they exist.
	//TODO: Implement this.

	getter := grid.queue().DefaultGetter()

	_MAX_IMPLICATION_STEPS := 6

	for {

		//Check if it's time to stop.
		select {
		case <-done:
			return
		default:
		}

		candidate := getter.GetSmallerThan(3)

		if candidate == nil {
			break
		}

		candidateCell := candidate.(*Cell)

		if len(candidateCell.Possibilities()) != 2 {
			//We found one with 1 possibility, which isn't interesting for us--nakedSingle should do that one.
			continue
		}

		firstPossibilityNum := candidateCell.Possibilities()[0]
		secondPossibilityNum := candidateCell.Possibilities()[1]

		firstGrid := grid.Copy()
		secondGrid := grid.Copy()

		//Check that the neighbor isn't just already having a single possibility, because then this technique is overkill.

		firstAccumulator := makeChainSeacherAccumulator(_MAX_IMPLICATION_STEPS)
		secondAccumulator := makeChainSeacherAccumulator(_MAX_IMPLICATION_STEPS)

		chainSearcher(_MAX_IMPLICATION_STEPS,
			candidateCell.InGrid(firstGrid),
			firstPossibilityNum,
			firstAccumulator)

		chainSearcher(_MAX_IMPLICATION_STEPS,
			candidateCell.InGrid(secondGrid),
			secondPossibilityNum,
			secondAccumulator)

		//TODO:Check if the sets overlap.

		log.Println(firstAccumulator)
		log.Println(secondAccumulator)

		/*
			//Check pairwise through each of the result sets for each side and see if any overlap in an interestin way

			for i, theSet := range firstAffectedCellSets {
				theCellMapping := firstAffectedCellNums[i]
				for j, theSecondSet := range secondAffectedCellSets {
					theSecondCellMapping := secondAffectedCellNums[j]

					intersection := theSet.intersection(theSecondSet)
					if len(intersection) > 0 {
						//Okay, a cell overlapped... did they both set the same number?
						//TODO: should we look at all items that overlap if it's greater than 1?

						cell := intersection.toSlice()[0]

						if theCellMapping[cell] == theSecondCellMapping[cell] {
							//Booyah, found a step.

							step := &SolveStep{self,
								CellSlice{cell},
								IntSlice{theCellMapping[cell]},
								CellSlice{candidateCell},
								candidateCell.Possibilities(),
							}

							if step.IsUseful(grid) {
								select {
								case results <- step:
								case <-done:
									return
								}
							}
						}
					}

				}
			}
		*/

	}
}

type chainSearcherGenerationDetails struct {
	affectedCells cellSet
	filledNumbers map[*Cell]int
}

type chainSearcherAccumulator []*chainSearcherGenerationDetails

func makeChainSeacherAccumulator(size int) chainSearcherAccumulator {
	result := make(chainSearcherAccumulator, size)
	for i := 0; i < size; i++ {
		result[i] = &chainSearcherGenerationDetails{
			affectedCells: make(cellSet),
			filledNumbers: make(map[*Cell]int),
		}
	}
	return result
}

func chainSearcher(i int, cell *Cell, numToApply int, accumulator chainSearcherAccumulator) {
	if i <= 0 || cell == nil {
		//Base case
		return
	}

	if i-1 >= len(accumulator) {
		panic("The accumulator provided was not big enough for the i provided.")
	}

	generationDetails := accumulator[i-1]

	//Find the nextCells that WILL have their numbers forced by the cell we're thinking of fillint.
	cellsToVisit := cell.Neighbors().FilterByPossible(numToApply).FilterByNumPossibilities(2)

	//Now that we know which cells will be affected and what their next number will be,
	//set the number in the given cell and then recurse downward down each branch.
	cell.SetNumber(numToApply)

	generationDetails.affectedCells[cell] = true
	generationDetails.filledNumbers[cell] = numToApply

	for _, cellToVisit := range cellsToVisit {

		possibilities := cellToVisit.Possibilities()

		if len(possibilities) != 1 {
			panic("Expected the cell to have one possibility")
		}

		forcedNum := possibilities[0]

		//Each branch modifies the grid, so create a new copy
		newGrid := cellToVisit.grid.Copy()
		cellToVisit = cellToVisit.InGrid(newGrid)

		//Recurse downward
		chainSearcher(i-1, cellToVisit, forcedNum, accumulator)

	}

}
<|endoftext|>


<commit_before>// +build dragonfly freebsd linux nacl netbsd openbsd solaris

// Copyright 2016 Florian Pigorsch. All rights reserved.
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package findfont

import (
	"os"
	"path/filepath"
)

func getFontDirectories() (paths []string) {
	directories := getUserFontDirs()
	directories = append(directories, getSystemFontDirs()...)
	return directories
}

func getUserFontDirs() (paths []string) {
	if dataPath := os.Getenv("XDG_DATA_HOME"); dataPath != "" {
		return []string{expandUser("~/.fonts/"), filepath.Join(expandUser(dataPath), "fonts")}
	}
	return []string{expandUser("~/.fonts/"), expandUser("~/.local/share/fonts/")}
}

func getSystemFontDirs() (paths []string) {
	if dataPaths := os.Getenv("XDG_DATA_DIRS"); dataPaths == "" {
		for _, dataPath := range filepath.SplitList(dataPaths) {
			paths = append(paths, filepath.Join(expandUser(dataPath), "fonts"))
		}
		return paths
	}
	return []string{"/usr/local/share/fonts/", "/usr/share/fonts/"}
}
<commit_msg>Fix system font dirs for *nix<commit_after>// +build dragonfly freebsd linux nacl netbsd openbsd solaris

// Copyright 2016 Florian Pigorsch. All rights reserved.
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package findfont

import (
	"os"
	"path/filepath"
)

func getFontDirectories() (paths []string) {
	directories := getUserFontDirs()
	directories = append(directories, getSystemFontDirs()...)
	return directories
}

func getUserFontDirs() (paths []string) {
	if dataPath := os.Getenv("XDG_DATA_HOME"); dataPath != "" {
		return []string{expandUser("~/.fonts/"), filepath.Join(expandUser(dataPath), "fonts")}
	}
	return []string{expandUser("~/.fonts/"), expandUser("~/.local/share/fonts/")}
}

func getSystemFontDirs() (paths []string) {
	if dataPaths := os.Getenv("XDG_DATA_DIRS"); dataPaths != "" {
		for _, dataPath := range filepath.SplitList(dataPaths) {
			paths = append(paths, filepath.Join(expandUser(dataPath), "fonts"))
		}
		return paths
	}
	return []string{"/usr/local/share/fonts/", "/usr/share/fonts/"}
}
<|endoftext|>