<commit_before>// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
// Package excelize providing a set of functions that allow you to write to
// and read from XLSX files. Support reads and writes XLSX file generated by
// Microsoft Excel™ 2007 and later. Support save file without losing original
// charts of XLSX. This library needs Go version 1.8 or later.

package excelize

import "math"

// Define the default cell size and EMU unit of measurement.
const (
	defaultColWidthPixels  float64 = 64
	defaultRowHeightPixels float64 = 20
	EMU                    int     = 9525
)

// GetColVisible provides a function to get visible of a single column by given
// worksheet name and column name. For example, get visible state of column D
// in Sheet1:
//
//    visiable, err := xlsx.GetColVisible("Sheet1", "D")
//
func (f *File) GetColVisible(sheet, col string) (bool, error) {
	visible := true
	colNum, err := ColumnNameToNumber(col)
	if err != nil {
		return visible, err
	}

	xlsx := f.workSheetReader(sheet)
	if xlsx.Cols == nil {
		return visible, err
	}

	for c := range xlsx.Cols.Col {
		colData := &xlsx.Cols.Col[c]
		if colData.Min <= colNum && colNum <= colData.Max {
			visible = !colData.Hidden
		}
	}
	return visible, err
}

// SetColVisible provides a function to set visible of a single column by given
// worksheet name and column name. For example, hide column D in Sheet1:
//
//    err := xlsx.SetColVisible("Sheet1", "D", false)
//
func (f *File) SetColVisible(sheet, col string, visible bool) error {
	colNum, err := ColumnNameToNumber(col)
	if err != nil {
		return err
	}
	colData := xlsxCol{
		Min:         colNum,
		Max:         colNum,
		Hidden:      !visible,
		CustomWidth: true,
	}
	xlsx := f.workSheetReader(sheet)
	if xlsx.Cols == nil {
		cols := xlsxCols{}
		cols.Col = append(cols.Col, colData)
		xlsx.Cols = &cols
		return err
	}
	for v := range xlsx.Cols.Col {
		if xlsx.Cols.Col[v].Min <= colNum && colNum <= xlsx.Cols.Col[v].Max {
			colData = xlsx.Cols.Col[v]
		}
	}
	colData.Min = colNum
	colData.Max = colNum
	colData.Hidden = !visible
	colData.CustomWidth = true
	xlsx.Cols.Col = append(xlsx.Cols.Col, colData)
	return err
}

// GetColOutlineLevel provides a function to get outline level of a single
// column by given worksheet name and column name. For example, get outline
// level of column D in Sheet1:
//
//    level, err := xlsx.GetColOutlineLevel("Sheet1", "D")
//
func (f *File) GetColOutlineLevel(sheet, col string) (uint8, error) {
	level := uint8(0)
	colNum, err := ColumnNameToNumber(col)
	if err != nil {
		return level, err
	}
	xlsx := f.workSheetReader(sheet)
	if xlsx.Cols == nil {
		return level, err
	}
	for c := range xlsx.Cols.Col {
		colData := &xlsx.Cols.Col[c]
		if colData.Min <= colNum && colNum <= colData.Max {
			level = colData.OutlineLevel
		}
	}
	return level, err
}

// SetColOutlineLevel provides a function to set outline level of a single
// column by given worksheet name and column name. For example, set outline
// level of column D in Sheet1 to 2:
//
//    err := xlsx.SetColOutlineLevel("Sheet1", "D", 2)
//
func (f *File) SetColOutlineLevel(sheet, col string, level uint8) error {
	colNum, err := ColumnNameToNumber(col)
	if err != nil {
		return err
	}
	colData := xlsxCol{
		Min:          colNum,
		Max:          colNum,
		OutlineLevel: level,
		CustomWidth:  true,
	}
	xlsx := f.workSheetReader(sheet)
	if xlsx.Cols == nil {
		cols := xlsxCols{}
		cols.Col = append(cols.Col, colData)
		xlsx.Cols = &cols
		return err
	}
	for v := range xlsx.Cols.Col {
		if xlsx.Cols.Col[v].Min <= colNum && colNum <= xlsx.Cols.Col[v].Max {
			colData = xlsx.Cols.Col[v]
		}
	}
	colData.Min = colNum
	colData.Max = colNum
	colData.OutlineLevel = level
	colData.CustomWidth = true
	xlsx.Cols.Col = append(xlsx.Cols.Col, colData)
	return err
}

// SetColWidth provides a function to set the width of a single column or
// multiple columns. For example:
//
//    xlsx := excelize.NewFile()
//    err := xlsx.SetColWidth("Sheet1", "A", "H", 20)
//
func (f *File) SetColWidth(sheet, startcol, endcol string, width float64) error {
	min, err := ColumnNameToNumber(startcol)
	if err != nil {
		return err
	}
	max, err := ColumnNameToNumber(endcol)
	if err != nil {
		return err
	}
	if min > max {
		min, max = max, min
	}

	xlsx := f.workSheetReader(sheet)
	col := xlsxCol{
		Min:         min,
		Max:         max,
		Width:       width,
		CustomWidth: true,
	}
	if xlsx.Cols != nil {
		xlsx.Cols.Col = append(xlsx.Cols.Col, col)
	} else {
		cols := xlsxCols{}
		cols.Col = append(cols.Col, col)
		xlsx.Cols = &cols
	}
	return err
}

// positionObjectPixels calculate the vertices that define the position of a
// graphical object within the worksheet in pixels.
//
//          +------------+------------+
//          |     A      |      B     |
//    +-----+------------+------------+
//    |     |(x1,y1)     |            |
//    |  1  |(A1)._______|______      |
//    |     |    |              |     |
//    |     |    |              |     |
//    +-----+----|    OBJECT    |-----+
//    |     |    |              |     |
//    |  2  |    |______________.     |
//    |     |            |        (B2)|
//    |     |            |     (x2,y2)|
//    +-----+------------+------------+
//
// Example of an object that covers some of the area from cell A1 to B2.
//
// Based on the width and height of the object we need to calculate 8 vars:
//
//    colStart, rowStart, colEnd, rowEnd, x1, y1, x2, y2.
//
// We also calculate the absolute x and y position of the top left vertex of
// the object. This is required for images.
//
// The width and height of the cells that the object occupies can be
// variable and have to be taken into account.
//
// The values of col_start and row_start are passed in from the calling
// function. The values of col_end and row_end are calculated by
// subtracting the width and height of the object from the width and
// height of the underlying cells.
//
//    colStart        # Col containing upper left corner of object.
//    x1              # Distance to left side of object.
//
//    rowStart        # Row containing top left corner of object.
//    y1              # Distance to top of object.
//
//    colEnd          # Col containing lower right corner of object.
//    x2              # Distance to right side of object.
//
//    rowEnd          # Row containing bottom right corner of object.
//    y2              # Distance to bottom of object.
//
//    width           # Width of object frame.
//    height          # Height of object frame.
//
//    xAbs            # Absolute distance to left side of object.
//    yAbs            # Absolute distance to top side of object.
//
func (f *File) positionObjectPixels(sheet string, col, row, x1, y1, width, height int) (int, int, int, int, int, int, int, int) {
	xAbs := 0
	yAbs := 0

	// Calculate the absolute x offset of the top-left vertex.
	for colID := 1; colID <= col; colID++ {
		xAbs += f.getColWidth(sheet, colID)
	}
	xAbs += x1

	// Calculate the absolute y offset of the top-left vertex.
	// Store the column change to allow optimisations.
	for rowID := 1; rowID <= row; rowID++ {
		yAbs += f.getRowHeight(sheet, rowID)
	}
	yAbs += y1

	// Adjust start column for offsets that are greater than the col width.
	for x1 >= f.getColWidth(sheet, col) {
		x1 -= f.getColWidth(sheet, col)
		col++
	}

	// Adjust start row for offsets that are greater than the row height.
	for y1 >= f.getRowHeight(sheet, row) {
		y1 -= f.getRowHeight(sheet, row)
		row++
	}

	// Initialise end cell to the same as the start cell.
	colEnd := col
	rowEnd := row

	width += x1
	height += y1

	// Subtract the underlying cell widths to find end cell of the object.
	for width >= f.getColWidth(sheet, colEnd + 1) {
		colEnd++
		width -= f.getColWidth(sheet, colEnd)
	}

	// Subtract the underlying cell heights to find end cell of the object.
	for height >= f.getRowHeight(sheet, rowEnd) {
		rowEnd++
		height -= f.getRowHeight(sheet, rowEnd)
	}

	// The end vertices are whatever is left from the width and height.
	x2 := width
	y2 := height
	return col, row, xAbs, yAbs, colEnd, rowEnd, x2, y2
}

// getColWidth provides a function to get column width in pixels by given
// sheet name and column index.
func (f *File) getColWidth(sheet string, col int) int {
	xlsx := f.workSheetReader(sheet)
	if xlsx.Cols != nil {
		var width float64
		for _, v := range xlsx.Cols.Col {
			if v.Min <= col && col <= v.Max {
				width = v.Width
			}
		}
		if width != 0 {
			return int(convertColWidthToPixels(width))
		}
	}
	// Optimisation for when the column widths haven't changed.
	return int(defaultColWidthPixels)
}

// GetColWidth provides a function to get column width by given worksheet name
// and column index.
func (f *File) GetColWidth(sheet, col string) (float64, error) {
	colNum, err := ColumnNameToNumber(col)
	if err != nil {
		return defaultColWidthPixels, err
	}
	xlsx := f.workSheetReader(sheet)
	if xlsx.Cols != nil {
		var width float64
		for _, v := range xlsx.Cols.Col {
			if v.Min <= colNum && colNum <= v.Max {
				width = v.Width
			}
		}
		if width != 0 {
			return width, err
		}
	}
	// Optimisation for when the column widths haven't changed.
	return defaultColWidthPixels, err
}

// InsertCol provides a function to insert a new column before given column
// index. For example, create a new column before column C in Sheet1:
//
//    err := xlsx.InsertCol("Sheet1", "C")
//
func (f *File) InsertCol(sheet, col string) error {
	num, err := ColumnNameToNumber(col)
	if err != nil {
		return err
	}
	return f.adjustHelper(sheet, columns, num, 1)
}

// RemoveCol provides a function to remove single column by given worksheet
// name and column index. For example, remove column C in Sheet1:
//
//    err := xlsx.RemoveCol("Sheet1", "C")
//
// Use this method with caution, which will affect changes in references such
// as formulas, charts, and so on. If there is any referenced value of the
// worksheet, it will cause a file error when you open it. The excelize only
// partially updates these references currently.
func (f *File) RemoveCol(sheet, col string) error {
	num, err := ColumnNameToNumber(col)
	if err != nil {
		return err
	}

	xlsx := f.workSheetReader(sheet)
	for rowIdx := range xlsx.SheetData.Row {
		rowData := &xlsx.SheetData.Row[rowIdx]
		for colIdx := range rowData.C {
			colName, _, _ := SplitCellName(rowData.C[colIdx].R)
			if colName == col {
				rowData.C = append(rowData.C[:colIdx], rowData.C[colIdx+1:]...)[:len(rowData.C)-1]
				break
			}
		}
	}
	return f.adjustHelper(sheet, columns, num, -1)
}

// convertColWidthToPixels provieds function to convert the width of a cell
// from user's units to pixels. Excel rounds the column width to the nearest
// pixel. If the width hasn't been set by the user we use the default value.
// If the column is hidden it has a value of zero.
func convertColWidthToPixels(width float64) float64 {
	var padding float64 = 5
	var pixels float64
	var maxDigitWidth float64 = 7
	if width == 0 {
		return pixels
	}
	if width < 1 {
		pixels = (width * 12) + 0.5
		return math.Ceil(pixels)
	}
	pixels = (width*maxDigitWidth + 0.5) + padding
	return math.Ceil(pixels)
}
<commit_msg>Fixed bug in the calculation target cell(row). The target cell for calclator the height was shifted by 1.<commit_after>// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
// Package excelize providing a set of functions that allow you to write to
// and read from XLSX files. Support reads and writes XLSX file generated by
// Microsoft Excel™ 2007 and later. Support save file without losing original
// charts of XLSX. This library needs Go version 1.8 or later.

package excelize

import "math"

// Define the default cell size and EMU unit of measurement.
const (
	defaultColWidthPixels  float64 = 64
	defaultRowHeightPixels float64 = 20
	EMU                    int     = 9525
)

// GetColVisible provides a function to get visible of a single column by given
// worksheet name and column name. For example, get visible state of column D
// in Sheet1:
//
//    visiable, err := xlsx.GetColVisible("Sheet1", "D")
//
func (f *File) GetColVisible(sheet, col string) (bool, error) {
	visible := true
	colNum, err := ColumnNameToNumber(col)
	if err != nil {
		return visible, err
	}

	xlsx := f.workSheetReader(sheet)
	if xlsx.Cols == nil {
		return visible, err
	}

	for c := range xlsx.Cols.Col {
		colData := &xlsx.Cols.Col[c]
		if colData.Min <= colNum && colNum <= colData.Max {
			visible = !colData.Hidden
		}
	}
	return visible, err
}

// SetColVisible provides a function to set visible of a single column by given
// worksheet name and column name. For example, hide column D in Sheet1:
//
//    err := xlsx.SetColVisible("Sheet1", "D", false)
//
func (f *File) SetColVisible(sheet, col string, visible bool) error {
	colNum, err := ColumnNameToNumber(col)
	if err != nil {
		return err
	}
	colData := xlsxCol{
		Min:         colNum,
		Max:         colNum,
		Hidden:      !visible,
		CustomWidth: true,
	}
	xlsx := f.workSheetReader(sheet)
	if xlsx.Cols == nil {
		cols := xlsxCols{}
		cols.Col = append(cols.Col, colData)
		xlsx.Cols = &cols
		return err
	}
	for v := range xlsx.Cols.Col {
		if xlsx.Cols.Col[v].Min <= colNum && colNum <= xlsx.Cols.Col[v].Max {
			colData = xlsx.Cols.Col[v]
		}
	}
	colData.Min = colNum
	colData.Max = colNum
	colData.Hidden = !visible
	colData.CustomWidth = true
	xlsx.Cols.Col = append(xlsx.Cols.Col, colData)
	return err
}

// GetColOutlineLevel provides a function to get outline level of a single
// column by given worksheet name and column name. For example, get outline
// level of column D in Sheet1:
//
//    level, err := xlsx.GetColOutlineLevel("Sheet1", "D")
//
func (f *File) GetColOutlineLevel(sheet, col string) (uint8, error) {
	level := uint8(0)
	colNum, err := ColumnNameToNumber(col)
	if err != nil {
		return level, err
	}
	xlsx := f.workSheetReader(sheet)
	if xlsx.Cols == nil {
		return level, err
	}
	for c := range xlsx.Cols.Col {
		colData := &xlsx.Cols.Col[c]
		if colData.Min <= colNum && colNum <= colData.Max {
			level = colData.OutlineLevel
		}
	}
	return level, err
}

// SetColOutlineLevel provides a function to set outline level of a single
// column by given worksheet name and column name. For example, set outline
// level of column D in Sheet1 to 2:
//
//    err := xlsx.SetColOutlineLevel("Sheet1", "D", 2)
//
func (f *File) SetColOutlineLevel(sheet, col string, level uint8) error {
	colNum, err := ColumnNameToNumber(col)
	if err != nil {
		return err
	}
	colData := xlsxCol{
		Min:          colNum,
		Max:          colNum,
		OutlineLevel: level,
		CustomWidth:  true,
	}
	xlsx := f.workSheetReader(sheet)
	if xlsx.Cols == nil {
		cols := xlsxCols{}
		cols.Col = append(cols.Col, colData)
		xlsx.Cols = &cols
		return err
	}
	for v := range xlsx.Cols.Col {
		if xlsx.Cols.Col[v].Min <= colNum && colNum <= xlsx.Cols.Col[v].Max {
			colData = xlsx.Cols.Col[v]
		}
	}
	colData.Min = colNum
	colData.Max = colNum
	colData.OutlineLevel = level
	colData.CustomWidth = true
	xlsx.Cols.Col = append(xlsx.Cols.Col, colData)
	return err
}

// SetColWidth provides a function to set the width of a single column or
// multiple columns. For example:
//
//    xlsx := excelize.NewFile()
//    err := xlsx.SetColWidth("Sheet1", "A", "H", 20)
//
func (f *File) SetColWidth(sheet, startcol, endcol string, width float64) error {
	min, err := ColumnNameToNumber(startcol)
	if err != nil {
		return err
	}
	max, err := ColumnNameToNumber(endcol)
	if err != nil {
		return err
	}
	if min > max {
		min, max = max, min
	}

	xlsx := f.workSheetReader(sheet)
	col := xlsxCol{
		Min:         min,
		Max:         max,
		Width:       width,
		CustomWidth: true,
	}
	if xlsx.Cols != nil {
		xlsx.Cols.Col = append(xlsx.Cols.Col, col)
	} else {
		cols := xlsxCols{}
		cols.Col = append(cols.Col, col)
		xlsx.Cols = &cols
	}
	return err
}

// positionObjectPixels calculate the vertices that define the position of a
// graphical object within the worksheet in pixels.
//
//          +------------+------------+
//          |     A      |      B     |
//    +-----+------------+------------+
//    |     |(x1,y1)     |            |
//    |  1  |(A1)._______|______      |
//    |     |    |              |     |
//    |     |    |              |     |
//    +-----+----|    OBJECT    |-----+
//    |     |    |              |     |
//    |  2  |    |______________.     |
//    |     |            |        (B2)|
//    |     |            |     (x2,y2)|
//    +-----+------------+------------+
//
// Example of an object that covers some of the area from cell A1 to B2.
//
// Based on the width and height of the object we need to calculate 8 vars:
//
//    colStart, rowStart, colEnd, rowEnd, x1, y1, x2, y2.
//
// We also calculate the absolute x and y position of the top left vertex of
// the object. This is required for images.
//
// The width and height of the cells that the object occupies can be
// variable and have to be taken into account.
//
// The values of col_start and row_start are passed in from the calling
// function. The values of col_end and row_end are calculated by
// subtracting the width and height of the object from the width and
// height of the underlying cells.
//
//    colStart        # Col containing upper left corner of object.
//    x1              # Distance to left side of object.
//
//    rowStart        # Row containing top left corner of object.
//    y1              # Distance to top of object.
//
//    colEnd          # Col containing lower right corner of object.
//    x2              # Distance to right side of object.
//
//    rowEnd          # Row containing bottom right corner of object.
//    y2              # Distance to bottom of object.
//
//    width           # Width of object frame.
//    height          # Height of object frame.
//
//    xAbs            # Absolute distance to left side of object.
//    yAbs            # Absolute distance to top side of object.
//
func (f *File) positionObjectPixels(sheet string, col, row, x1, y1, width, height int) (int, int, int, int, int, int, int, int) {
	xAbs := 0
	yAbs := 0

	// Calculate the absolute x offset of the top-left vertex.
	for colID := 1; colID <= col; colID++ {
		xAbs += f.getColWidth(sheet, colID)
	}
	xAbs += x1

	// Calculate the absolute y offset of the top-left vertex.
	// Store the column change to allow optimisations.
	for rowID := 1; rowID <= row; rowID++ {
		yAbs += f.getRowHeight(sheet, rowID)
	}
	yAbs += y1

	// Adjust start column for offsets that are greater than the col width.
	for x1 >= f.getColWidth(sheet, col) {
		x1 -= f.getColWidth(sheet, col)
		col++
	}

	// Adjust start row for offsets that are greater than the row height.
	for y1 >= f.getRowHeight(sheet, row) {
		y1 -= f.getRowHeight(sheet, row)
		row++
	}

	// Initialise end cell to the same as the start cell.
	colEnd := col
	rowEnd := row

	width += x1
	height += y1

	// Subtract the underlying cell widths to find end cell of the object.
	for width >= f.getColWidth(sheet, colEnd + 1) {
		colEnd++
		width -= f.getColWidth(sheet, colEnd)
	}

	// Subtract the underlying cell heights to find end cell of the object.
	for height >= f.getRowHeight(sheet, rowEnd) {
		height -= f.getRowHeight(sheet, rowEnd)
		rowEnd++
	}

	// The end vertices are whatever is left from the width and height.
	x2 := width
	y2 := height
	return col, row, xAbs, yAbs, colEnd, rowEnd, x2, y2
}

// getColWidth provides a function to get column width in pixels by given
// sheet name and column index.
func (f *File) getColWidth(sheet string, col int) int {
	xlsx := f.workSheetReader(sheet)
	if xlsx.Cols != nil {
		var width float64
		for _, v := range xlsx.Cols.Col {
			if v.Min <= col && col <= v.Max {
				width = v.Width
			}
		}
		if width != 0 {
			return int(convertColWidthToPixels(width))
		}
	}
	// Optimisation for when the column widths haven't changed.
	return int(defaultColWidthPixels)
}

// GetColWidth provides a function to get column width by given worksheet name
// and column index.
func (f *File) GetColWidth(sheet, col string) (float64, error) {
	colNum, err := ColumnNameToNumber(col)
	if err != nil {
		return defaultColWidthPixels, err
	}
	xlsx := f.workSheetReader(sheet)
	if xlsx.Cols != nil {
		var width float64
		for _, v := range xlsx.Cols.Col {
			if v.Min <= colNum && colNum <= v.Max {
				width = v.Width
			}
		}
		if width != 0 {
			return width, err
		}
	}
	// Optimisation for when the column widths haven't changed.
	return defaultColWidthPixels, err
}

// InsertCol provides a function to insert a new column before given column
// index. For example, create a new column before column C in Sheet1:
//
//    err := xlsx.InsertCol("Sheet1", "C")
//
func (f *File) InsertCol(sheet, col string) error {
	num, err := ColumnNameToNumber(col)
	if err != nil {
		return err
	}
	return f.adjustHelper(sheet, columns, num, 1)
}

// RemoveCol provides a function to remove single column by given worksheet
// name and column index. For example, remove column C in Sheet1:
//
//    err := xlsx.RemoveCol("Sheet1", "C")
//
// Use this method with caution, which will affect changes in references such
// as formulas, charts, and so on. If there is any referenced value of the
// worksheet, it will cause a file error when you open it. The excelize only
// partially updates these references currently.
func (f *File) RemoveCol(sheet, col string) error {
	num, err := ColumnNameToNumber(col)
	if err != nil {
		return err
	}

	xlsx := f.workSheetReader(sheet)
	for rowIdx := range xlsx.SheetData.Row {
		rowData := &xlsx.SheetData.Row[rowIdx]
		for colIdx := range rowData.C {
			colName, _, _ := SplitCellName(rowData.C[colIdx].R)
			if colName == col {
				rowData.C = append(rowData.C[:colIdx], rowData.C[colIdx+1:]...)[:len(rowData.C)-1]
				break
			}
		}
	}
	return f.adjustHelper(sheet, columns, num, -1)
}

// convertColWidthToPixels provieds function to convert the width of a cell
// from user's units to pixels. Excel rounds the column width to the nearest
// pixel. If the width hasn't been set by the user we use the default value.
// If the column is hidden it has a value of zero.
func convertColWidthToPixels(width float64) float64 {
	var padding float64 = 5
	var pixels float64
	var maxDigitWidth float64 = 7
	if width == 0 {
		return pixels
	}
	if width < 1 {
		pixels = (width * 12) + 0.5
		return math.Ceil(pixels)
	}
	pixels = (width*maxDigitWidth + 0.5) + padding
	return math.Ceil(pixels)
}
<|endoftext|>


<commit_before>package dht

import (
	_ "crypto/sha1"
	"encoding/hex"
	"errors"
	"math/big"
	"math/rand"
	"net"
	"strconv"
	"time"

	"github.com/anacrolix/torrent/iplist"
	"github.com/anacrolix/torrent/metainfo"

	"github.com/anacrolix/dht/krpc"
)

const (
	maxNodes = 320
)

var (
	queryResendEvery = 5 * time.Second
)

var maxDistance big.Int

func init() {
	var zero big.Int
	maxDistance.SetBit(&zero, 160, 1)
}

// Uniquely identifies a transaction to us.
type transactionKey struct {
	RemoteAddr string // host:port
	T          string // The KRPC transaction ID.
}

// ServerConfig allows to set up a  configuration of the `Server` instance
// to be created with NewServer
type ServerConfig struct {
	// Listen address. Used if Conn is nil.
	Addr string

	// Set NodeId Manually. Caller must ensure that, if NodeId does not
	// conform to DHT Security Extensions, that NoSecurity is also set. This
	// should be given as a HEX string.
	NodeIdHex string

	Conn net.PacketConn
	// Don't respond to queries from other nodes.
	Passive bool
	// DHT Bootstrap nodes
	BootstrapNodes []string
	// Disable bootstrapping from global servers even if given no BootstrapNodes.
	// This creates a solitary node that awaits other nodes; it's only useful if
	// you're creating your own DHT and want to avoid accidental crossover, without
	// spoofing a bootstrap node and filling your logs with connection errors.
	NoDefaultBootstrap bool

	// Disable the DHT security extension:
	// http://www.libtorrent.org/dht_sec.html.
	NoSecurity bool
	// Initial IP blocklist to use. Applied before serving and bootstrapping
	// begins.
	IPBlocklist iplist.Ranger
	// Used to secure the server's ID. Defaults to the Conn's LocalAddr().
	PublicIP net.IP

	// Hook received queries. Return true if you don't want to propagate to
	// the default handlers.
	OnQuery func(query *krpc.Msg, source net.Addr) (propagate bool)
	// Called when a peer successfully announces to us.
	OnAnnouncePeer func(infoHash metainfo.Hash, peer Peer)
}

// ServerStats instance is returned by Server.Stats() and stores Server metrics
type ServerStats struct {
	// Count of nodes in the node table that responded to our last query or
	// haven't yet been queried.
	GoodNodes int
	// Count of nodes in the node table.
	Nodes int
	// Transactions awaiting a response.
	OutstandingTransactions int
	// Individual announce_peer requests that got a success response.
	ConfirmedAnnounces int
	// Nodes that have been blocked.
	BadNodes uint
}

func makeSocket(addr string) (socket *net.UDPConn, err error) {
	addr_, err := net.ResolveUDPAddr("", addr)
	if err != nil {
		return
	}
	socket, err = net.ListenUDP("udp", addr_)
	return
}

type nodeID struct {
	i   big.Int
	set bool
}

func (me nodeID) String() string {
	b := me.i.Bytes()
	if len(b) < 20 {
		b = append(make([]byte, 20-len(b)), b...)
	}
	return hex.EncodeToString(b)
}

func (nid *nodeID) IsUnset() bool {
	return !nid.set
}

func nodeIDFromString(s string) (ret nodeID) {
	if s == "" {
		return
	}
	ret.i.SetBytes([]byte(s))
	ret.set = true
	return
}

func (nid0 *nodeID) Distance(nid1 *nodeID) (ret big.Int) {
	if nid0.IsUnset() != nid1.IsUnset() {
		ret = maxDistance
		return
	}
	ret.Xor(&nid0.i, &nid1.i)
	return
}

func (nid nodeID) ByteString() string {
	var buf [20]byte
	b := nid.i.Bytes()
	copy(buf[20-len(b):], b)
	return string(buf[:])
}

type node struct {
	addr          Addr
	id            nodeID
	announceToken string

	lastGotQuery    time.Time
	lastGotResponse time.Time
	lastSentQuery   time.Time
}

func (n *node) IsSecure() bool {
	if n.id.IsUnset() {
		return false
	}
	return NodeIdSecure(n.id.ByteString(), n.addr.UDPAddr().IP)
}

func (n *node) idString() string {
	return n.id.ByteString()
}

func (n *node) SetIDFromBytes(b []byte) {
	if len(b) != 20 {
		panic(b)
	}
	n.id.i.SetBytes(b)
	n.id.set = true
}

func (n *node) SetIDFromString(s string) {
	n.SetIDFromBytes([]byte(s))
}

func (n *node) IDNotSet() bool {
	return n.id.i.Int64() == 0
}

func (n *node) NodeInfo() (ret krpc.NodeInfo) {
	ret.Addr = n.addr.UDPAddr()
	if n := copy(ret.ID[:], n.idString()); n != 20 {
		panic(n)
	}
	return
}

func (n *node) DefinitelyGood() bool {
	if len(n.idString()) != 20 {
		return false
	}
	// No reason to think ill of them if they've never been queried.
	if n.lastSentQuery.IsZero() {
		return true
	}
	// They answered our last query.
	if n.lastSentQuery.Before(n.lastGotResponse) {
		return true
	}
	return true
}

func jitterDuration(average time.Duration, plusMinus time.Duration) time.Duration {
	return average - plusMinus/2 + time.Duration(rand.Int63n(int64(plusMinus)))
}

type Peer struct {
	IP   net.IP
	Port int
}

func (p *Peer) String() string {
	return net.JoinHostPort(p.IP.String(), strconv.FormatInt(int64(p.Port), 10))
}

func bootstrapAddrs(nodeAddrs []string) (addrs []*net.UDPAddr, err error) {
	bootstrapNodes := nodeAddrs
	if len(bootstrapNodes) == 0 {
		bootstrapNodes = []string{
			"router.utorrent.com:6881",
			"router.bittorrent.com:6881",
		}
	}
	for _, addrStr := range bootstrapNodes {
		udpAddr, err := net.ResolveUDPAddr("udp4", addrStr)
		if err != nil {
			continue
		}
		addrs = append(addrs, udpAddr)
	}
	if len(addrs) == 0 {
		err = errors.New("nothing resolved")
	}
	return
}
<commit_msg>Improve ServerConfig.PublicIP doc<commit_after>package dht

import (
	_ "crypto/sha1"
	"encoding/hex"
	"errors"
	"math/big"
	"math/rand"
	"net"
	"strconv"
	"time"

	"github.com/anacrolix/torrent/iplist"
	"github.com/anacrolix/torrent/metainfo"

	"github.com/anacrolix/dht/krpc"
)

const (
	maxNodes = 320
)

var (
	queryResendEvery = 5 * time.Second
)

var maxDistance big.Int

func init() {
	var zero big.Int
	maxDistance.SetBit(&zero, 160, 1)
}

// Uniquely identifies a transaction to us.
type transactionKey struct {
	RemoteAddr string // host:port
	T          string // The KRPC transaction ID.
}

// ServerConfig allows to set up a  configuration of the `Server` instance
// to be created with NewServer
type ServerConfig struct {
	// Listen address. Used if Conn is nil.
	Addr string

	// Set NodeId Manually. Caller must ensure that, if NodeId does not
	// conform to DHT Security Extensions, that NoSecurity is also set. This
	// should be given as a HEX string.
	NodeIdHex string

	Conn net.PacketConn
	// Don't respond to queries from other nodes.
	Passive bool
	// DHT Bootstrap nodes
	BootstrapNodes []string
	// Disable bootstrapping from global servers even if given no BootstrapNodes.
	// This creates a solitary node that awaits other nodes; it's only useful if
	// you're creating your own DHT and want to avoid accidental crossover, without
	// spoofing a bootstrap node and filling your logs with connection errors.
	NoDefaultBootstrap bool

	// Disable the DHT security extension:
	// http://www.libtorrent.org/dht_sec.html.
	NoSecurity bool
	// Initial IP blocklist to use. Applied before serving and bootstrapping
	// begins.
	IPBlocklist iplist.Ranger
	// Used to secure the server's ID. Defaults to the Conn's LocalAddr(). Set
	// to the IP that remote nodes will see, as that IP is what they'll use to
	// validate our ID.
	PublicIP net.IP

	// Hook received queries. Return true if you don't want to propagate to
	// the default handlers.
	OnQuery func(query *krpc.Msg, source net.Addr) (propagate bool)
	// Called when a peer successfully announces to us.
	OnAnnouncePeer func(infoHash metainfo.Hash, peer Peer)
}

// ServerStats instance is returned by Server.Stats() and stores Server metrics
type ServerStats struct {
	// Count of nodes in the node table that responded to our last query or
	// haven't yet been queried.
	GoodNodes int
	// Count of nodes in the node table.
	Nodes int
	// Transactions awaiting a response.
	OutstandingTransactions int
	// Individual announce_peer requests that got a success response.
	ConfirmedAnnounces int
	// Nodes that have been blocked.
	BadNodes uint
}

func makeSocket(addr string) (socket *net.UDPConn, err error) {
	addr_, err := net.ResolveUDPAddr("", addr)
	if err != nil {
		return
	}
	socket, err = net.ListenUDP("udp", addr_)
	return
}

type nodeID struct {
	i   big.Int
	set bool
}

func (me nodeID) String() string {
	b := me.i.Bytes()
	if len(b) < 20 {
		b = append(make([]byte, 20-len(b)), b...)
	}
	return hex.EncodeToString(b)
}

func (nid *nodeID) IsUnset() bool {
	return !nid.set
}

func nodeIDFromString(s string) (ret nodeID) {
	if s == "" {
		return
	}
	ret.i.SetBytes([]byte(s))
	ret.set = true
	return
}

func (nid0 *nodeID) Distance(nid1 *nodeID) (ret big.Int) {
	if nid0.IsUnset() != nid1.IsUnset() {
		ret = maxDistance
		return
	}
	ret.Xor(&nid0.i, &nid1.i)
	return
}

func (nid nodeID) ByteString() string {
	var buf [20]byte
	b := nid.i.Bytes()
	copy(buf[20-len(b):], b)
	return string(buf[:])
}

type node struct {
	addr          Addr
	id            nodeID
	announceToken string

	lastGotQuery    time.Time
	lastGotResponse time.Time
	lastSentQuery   time.Time
}

func (n *node) IsSecure() bool {
	if n.id.IsUnset() {
		return false
	}
	return NodeIdSecure(n.id.ByteString(), n.addr.UDPAddr().IP)
}

func (n *node) idString() string {
	return n.id.ByteString()
}

func (n *node) SetIDFromBytes(b []byte) {
	if len(b) != 20 {
		panic(b)
	}
	n.id.i.SetBytes(b)
	n.id.set = true
}

func (n *node) SetIDFromString(s string) {
	n.SetIDFromBytes([]byte(s))
}

func (n *node) IDNotSet() bool {
	return n.id.i.Int64() == 0
}

func (n *node) NodeInfo() (ret krpc.NodeInfo) {
	ret.Addr = n.addr.UDPAddr()
	if n := copy(ret.ID[:], n.idString()); n != 20 {
		panic(n)
	}
	return
}

func (n *node) DefinitelyGood() bool {
	if len(n.idString()) != 20 {
		return false
	}
	// No reason to think ill of them if they've never been queried.
	if n.lastSentQuery.IsZero() {
		return true
	}
	// They answered our last query.
	if n.lastSentQuery.Before(n.lastGotResponse) {
		return true
	}
	return true
}

func jitterDuration(average time.Duration, plusMinus time.Duration) time.Duration {
	return average - plusMinus/2 + time.Duration(rand.Int63n(int64(plusMinus)))
}

type Peer struct {
	IP   net.IP
	Port int
}

func (p *Peer) String() string {
	return net.JoinHostPort(p.IP.String(), strconv.FormatInt(int64(p.Port), 10))
}

func bootstrapAddrs(nodeAddrs []string) (addrs []*net.UDPAddr, err error) {
	bootstrapNodes := nodeAddrs
	if len(bootstrapNodes) == 0 {
		bootstrapNodes = []string{
			"router.utorrent.com:6881",
			"router.bittorrent.com:6881",
		}
	}
	for _, addrStr := range bootstrapNodes {
		udpAddr, err := net.ResolveUDPAddr("udp4", addrStr)
		if err != nil {
			continue
		}
		addrs = append(addrs, udpAddr)
	}
	if len(addrs) == 0 {
		err = errors.New("nothing resolved")
	}
	return
}
<|endoftext|>


<commit_before>// Hanayo is the Ripple front-end web server.
package main

// version is the current version of hanayo
const version = "v1.8.0"
<commit_msg>⬆ v1.8.1 ⬆<commit_after>// Hanayo is the Ripple front-end web server.
package main

// version is the current version of hanayo
const version = "v1.8.1"
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"gnd.la/mux"
	"gnd.la/util"
	"gnd.la/util/pkgutil"
	"go/ast"
	"go/build"
	"go/doc"
	"go/parser"
	"go/token"
	"html/template"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strings"
)

var (
	srcDir    = util.RelativePath("src")
	cwd       = util.RelativePath("..")
	srcPrefix = srcDir[len(cwd)+1:]
)

func noBuildable(err error) bool {
	return strings.Contains(err.Error(), "no buildable")
}

func buildContext() *build.Context {
	ctx := build.Default
	ctx.GOPATH = util.RelativePath(".")
	return &ctx
}

type Package struct {
	ctx      *mux.Context
	fset     *token.FileSet
	name     string
	bpkg     *build.Package
	apkg     *ast.Package
	dpkg     *doc.Package
	Packages []*Package
}

func (p *Package) symbolHref(symbol string) string {
	key := symbol
	if key[len(key)-1] == ')' && key[len(key)-2] == '(' {
		key = key[:len(key)-2]
	}
	if obj := p.apkg.Scope.Objects[key]; obj != nil {
		switch obj.Kind {
		case ast.Typ:
			return "#type-" + key
		case ast.Fun:
			return "#func-" + key
		case ast.Con:
			if obj.Type == nil {
				return "#pkg-constants"
			}
		case ast.Var:
			return "#pkg-variables"
		}
	}
	if dot := strings.IndexByte(key, '.'); dot > 0 {
		tn := key[:dot]
		fn := key[dot+1:]
		if obj := p.apkg.Scope.Objects[tn]; obj != nil && obj.Kind == ast.Typ {
			for _, v := range p.dpkg.Types {
				if v.Name == tn {
					for _, m := range v.Methods {
						if m.Name == fn {
							return "#type-" + tn + "-method-" + fn
						}
					}
					return ""
				}
			}
		}
	}
	return ""
}

func (p *Package) href(word string, scope string) string {
	slash := strings.IndexByte(word, '/')
	dot := strings.IndexByte(word, '.')
	if slash > 0 || dot > 0 {
		// Check if there's a type or function mentioned
		// after the package.
		if pn, tn := pkgutil.SplitQualifiedName(word); pn != "" && tn != "" {
			if pn[0] == '*' {
				pn = pn[1:]
			}
			if pkg, err := ImportPackage(p.ctx, pn); err == nil {
				if sr := pkg.symbolHref(tn); sr != "" {
					return p.ctx.MustReverse("doc", pn) + sr
				}
			}
		} else if _, err := buildContext().Import(word, "", build.FindOnly); err == nil {
			return p.ctx.MustReverse("doc", word)
		}
	}
	if dot > 0 {
		// Check the package imports, to see if any of them matches
		// TODO: Check for packages imported with a different local
		// name.
		base := word[:dot]
		for _, v := range p.bpkg.Imports {
			if path.Base(v) == base && v != base {
				return p.href(v+"."+word[dot+1:], scope)
			}
		}
	}
	if word[0]&0x20 == 0 {
		// Uppercase
		if scope != "" {
			if href := p.symbolHref(scope + "." + word); href != "" {
				return href
			}
		}
		return p.symbolHref(word)
	}
	return ""
}

func (p *Package) writeWord(bw *bufio.Writer, buf *bytes.Buffer, scope string, ignored map[string]struct{}) {
	if word := buf.String(); word != "" {
		if _, ign := ignored[word]; ign || word == scope {
			bw.WriteString(word)
		} else {
			if href := p.href(word, scope); href != "" {
				bw.WriteString("")
				bw.WriteString(word)
				bw.WriteString("")
			} else {
				bw.WriteString(word)
			}
		}
	}
}

func (p *Package) linkify(w io.Writer, input string, scope string, ignored map[string]struct{}) error {
	bw := bufio.NewWriterSize(w, 512)
	var buf bytes.Buffer
	for ii := 0; ii < len(input); ii++ {
		c := input[ii]
		switch c {
		// Include * and & in the list of stop characters,
		// so pointers get the link for the pointed type.
		// Include ;, so escaped amperstands do not end up
		// in the type names.
		case ',', ' ', '\n', '\t', '(', ')', '*', '&', '{', '}', ';':
			p.writeWord(bw, &buf, scope, ignored)
			bw.WriteByte(c)
			buf.Reset()
		case '.':
			if next := ii + 1; next < len(input) {
				if nc := input[next]; nc == ' ' || nc == '\t' || nc == '\n' {
					p.writeWord(bw, &buf, scope, ignored)
					bw.WriteByte(c)
					buf.Reset()
					continue
				}
			}
			fallthrough
		default:
			buf.WriteByte(c)
		}
	}
	bw.WriteString(buf.String())
	return bw.Flush()
}

func (p *Package) Name() string {
	if p.bpkg != nil {
		return p.bpkg.Name
	}
	return p.name
}

func (p *Package) ImportPath() string {
	if p.bpkg != nil {
		path := p.bpkg.ImportPath
		if strings.HasPrefix(path, srcPrefix) {
			path = path[len(srcPrefix)+1:]
		}
		return path
	}
	return ""
}

func (p *Package) Synopsis() string {
	if p.dpkg != nil {
		return doc.Synopsis(p.dpkg.Doc)
	}
	return ""
}

func (p *Package) Filenames() []string {
	if b := p.bpkg; b != nil {
		var files []string
		for _, v := range [][]string{b.GoFiles, b.CgoFiles, b.IgnoredGoFiles, b.CFiles, b.CXXFiles, b.HFiles, b.SFiles, b.SysoFiles, b.SwigFiles, b.SwigCXXFiles} {
			files = append(files, v...)
		}
		sort.Strings(files)
		return files
	}
	return nil
}

func (p *Package) Position(n ast.Node) string {
	pos := p.fset.Position(n.Pos())
	filename := pos.Filename
	if strings.HasPrefix(filename, srcDir) {
		filename = filename[len(srcDir)+1:]
	}
	if gr := buildContext().GOROOT; strings.HasPrefix(filename, gr) {
		// Skip the src/ after GOROOT
		filename = "go" + filename[len(gr)+4:]
	}
	return fmt.Sprintf("%s#line-%d", filename, pos.Line)
}

func (p *Package) HasDoc() bool {
	return p.dpkg != nil && strings.TrimSpace(doc.Synopsis(p.dpkg.Doc)) != strings.TrimSpace(p.dpkg.Doc)
}

func (p *Package) Doc() *doc.Package {
	return p.dpkg
}

func (p *Package) html(text string, scope string) template.HTML {
	var buf bytes.Buffer
	doc.ToHTML(&buf, text, nil)
	var out bytes.Buffer
	p.linkify(&out, buf.String(), scope, nil)
	return template.HTML(out.String())
}

func (p *Package) HTML(text string) template.HTML {
	return p.html(text, "")
}

func (p *Package) ScopedHTML(text string, scope string) template.HTML {
	return p.html(text, scope)
}

func (p *Package) HTMLDoc() template.HTML {
	return p.HTML(p.dpkg.Doc)
}

func (p *Package) HTMLDecl(node interface{}) (template.HTML, error) {
	s, err := FormatNode(p.fset, node)
	if err == nil {
		var scope string
		var ignored map[string]struct{}
		ignore := func(x string) {
			if ignored == nil {
				ignored = make(map[string]struct{})
			}
			ignored[x] = struct{}{}
		}
		switch n := node.(type) {
		case *ast.FuncDecl:
			scope = n.Name.Name
		case *ast.GenDecl:
			for _, spec := range n.Specs {
				switch s := spec.(type) {
				case *ast.TypeSpec:
					scope = s.Name.Name
				case *ast.ValueSpec:
					for _, name := range s.Names {
						ignore(name.Name)
					}
				}
			}
		}
		var buf bytes.Buffer
		p.linkify(&buf, s, scope, ignored)
		s = buf.String()
	}
	return template.HTML(s), err
}

func pkgImporter(imports map[string]*ast.Object, path string) (*ast.Object, error) {
	pkg := imports[path]
	if pkg == nil {
		// note that strings.LastIndex returns -1 if there is no "/"
		pkg = ast.NewObj(ast.Pkg, path[strings.LastIndex(path, "/")+1:])
		pkg.Data = ast.NewScope(nil) // required by ast.NewPackage for dot-import
		imports[path] = pkg
	}
	return pkg, nil
}

func parseFiles(fset *token.FileSet, abspath string, names []string) (map[string]*ast.File, error) {
	files := make(map[string]*ast.File)
	for _, f := range names {
		absname := filepath.Join(abspath, f)
		file, err := parser.ParseFile(fset, absname, nil, parser.ParseComments)
		if err != nil {
			return nil, err
		}
		files[absname] = file
	}
	return files, nil
}

func ImportPackage(ctx *mux.Context, p string) (*Package, error) {
	bctx := buildContext()
	b, err := bctx.Import(p, "", 0)
	if err != nil {
		if noBuildable(err) {
			return nil, err
		}
		b, err = bctx.ImportDir(p, 0)
		if err != nil {
			return nil, err
		}
	}
	fset := token.NewFileSet()
	names := b.GoFiles
	names = append(names, b.CgoFiles...)
	files, err := parseFiles(fset, b.Dir, names)
	if err != nil {
		return nil, err
	}
	// NewPackage will always return errors because it won't
	// resolve builtin types.
	a, _ := ast.NewPackage(fset, files, pkgImporter, nil)
	flags := doc.AllMethods
	if p == "builtin" {
		flags |= doc.AllDecls
	}
	pkg := &Package{
		ctx:  ctx,
		fset: fset,
		bpkg: b,
		apkg: a,
		dpkg: doc.New(a, b.ImportPath, flags),
	}
	sub, err := ImportPackages(ctx, b.Dir)
	if err != nil {
		return nil, err
	}
	pkg.Packages = sub
	return pkg, nil
}

func ImportPackages(ctx *mux.Context, dir string) ([]*Package, error) {
	var pkgs []*Package
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		return nil, err
	}
	for _, v := range files {
		n := v.Name()
		if n == "test_data" || n[0] == '.' || n[0] == '_' {
			continue
		}
		abs := filepath.Join(dir, n)
		// Follow symlinks
		if st, err := os.Stat(abs); err == nil && st.IsDir() {
			pkg, err := ImportPackage(ctx, abs)
			if err != nil {
				if noBuildable(err) {
					sub, err := ImportPackages(ctx, abs)
					if err != nil {
						return nil, err
					}
					pkgs = append(pkgs, sub...)
					continue
				}
				return nil, err
			}
			pkgs = append(pkgs, pkg)
		}
	}
	return pkgs, nil
}

type packageGroup struct {
	Title    string
	Packages []*Package
}

func DocListHandler(ctx *mux.Context) {
	pkgs, err := ImportPackages(ctx, filepath.Join(srcDir, "gnd.la"))
	if err != nil {
		panic(err)
	}
	groups := []packageGroup{
		{Title: "Gondola Packages", Packages: pkgs},
	}
	infos, _ := ioutil.ReadDir(srcDir)
	var opkgs []*Package
	for _, v := range infos {
		if v.IsDir() && v.Name() != "gnd.la" {
			p, _ := ImportPackages(ctx, filepath.Join(srcDir, v.Name()))
			opkgs = append(opkgs, p...)
		}
	}
	if len(opkgs) > 0 {
		groups = append(groups, packageGroup{
			Title:    "Other useful Rainy Cape's packages",
			Packages: opkgs,
		})
	}
	title := "Package Index"
	data := map[string]interface{}{
		"HeaderTitle": title,
		"Subtitle":    title,
		"Section":     "docs",
		"Groups":      groups,
	}
	ctx.MustExecute("pkgs.html", data)
}

func DocHandler(ctx *mux.Context) {
	path := ctx.IndexValue(0)
	pkg, err := ImportPackage(ctx, path)
	if err != nil {
		if noBuildable(err) {
			sub, err := ImportPackages(ctx, filepath.Join(srcDir, path))
			if err != nil {
				panic(err)
			}
			pkg = &Package{name: path, Packages: sub}
		} else {
			panic(err)
		}
	}
	title := "Package " + pkg.Name()
	breadcrumbs := []*Breadcrumb{
		{Title: "Index", Href: ctx.MustReverse("doc-list")},
	}
	for ii := 0; ii < len(path); {
		var end int
		slash := strings.IndexByte(path[ii:], '/')
		if slash < 0 {
			end = len(path)
		} else {
			end = ii + slash
		}
		breadcrumbs = append(breadcrumbs, &Breadcrumb{
			Title: path[ii:end],
			Href:  ctx.MustReverse("doc", path[:end]),
		})
		ii = end + 1
	}
	data := map[string]interface{}{
		"HeaderTitle": title,
		"Subtitle":    title,
		"Section":     "docs",
		"Breadcrumbs": breadcrumbs,
		"Package":     pkg,
	}
	ctx.MustExecute("package.html", data)
}
<commit_msg>Correctly resolve qualified names which refer to the same pkg<commit_after>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"gnd.la/mux"
	"gnd.la/util"
	"gnd.la/util/pkgutil"
	"go/ast"
	"go/build"
	"go/doc"
	"go/parser"
	"go/token"
	"html/template"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strings"
)

var (
	srcDir    = util.RelativePath("src")
	cwd       = util.RelativePath("..")
	srcPrefix = srcDir[len(cwd)+1:]
)

func noBuildable(err error) bool {
	return strings.Contains(err.Error(), "no buildable")
}

func buildContext() *build.Context {
	ctx := build.Default
	ctx.GOPATH = util.RelativePath(".")
	return &ctx
}

type Package struct {
	ctx      *mux.Context
	fset     *token.FileSet
	name     string
	bpkg     *build.Package
	apkg     *ast.Package
	dpkg     *doc.Package
	Packages []*Package
}

func (p *Package) symbolHref(symbol string) string {
	key := symbol
	if key[len(key)-1] == ')' && key[len(key)-2] == '(' {
		key = key[:len(key)-2]
	}
	if obj := p.apkg.Scope.Objects[key]; obj != nil {
		switch obj.Kind {
		case ast.Typ:
			return "#type-" + key
		case ast.Fun:
			return "#func-" + key
		case ast.Con:
			if obj.Type == nil {
				return "#pkg-constants"
			}
		case ast.Var:
			return "#pkg-variables"
		}
	}
	if dot := strings.IndexByte(key, '.'); dot > 0 {
		tn := key[:dot]
		fn := key[dot+1:]
		if obj := p.apkg.Scope.Objects[tn]; obj != nil && obj.Kind == ast.Typ {
			for _, v := range p.dpkg.Types {
				if v.Name == tn {
					for _, m := range v.Methods {
						if m.Name == fn {
							return "#type-" + tn + "-method-" + fn
						}
					}
					return ""
				}
			}
		}
	}
	return ""
}

func (p *Package) href(word string, scope string) string {
	slash := strings.IndexByte(word, '/')
	dot := strings.IndexByte(word, '.')
	if slash > 0 || dot > 0 {
		// Check if there's a type or function mentioned
		// after the package.
		if pn, tn := pkgutil.SplitQualifiedName(word); pn != "" && tn != "" {
			if pn[0] == '*' {
				pn = pn[1:]
			}
			if pkg, err := ImportPackage(p.ctx, pn); err == nil {
				if sr := pkg.symbolHref(tn); sr != "" {
					return p.ctx.MustReverse("doc", pn) + sr
				}
			}
			if pn == p.dpkg.Name {
				return p.symbolHref(tn)
			}
		} else if _, err := buildContext().Import(word, "", build.FindOnly); err == nil {
			return p.ctx.MustReverse("doc", word)
		}
	}
	if dot > 0 {
		// Check the package imports, to see if any of them matches
		// TODO: Check for packages imported with a different local
		// name.
		base := word[:dot]
		for _, v := range p.bpkg.Imports {
			if path.Base(v) == base && v != base {
				return p.href(v+"."+word[dot+1:], scope)
			}
		}
	}
	if word[0]&0x20 == 0 {
		// Uppercase
		if scope != "" {
			if href := p.symbolHref(scope + "." + word); href != "" {
				return href
			}
		}
		return p.symbolHref(word)
	}
	return ""
}

func (p *Package) writeWord(bw *bufio.Writer, buf *bytes.Buffer, scope string, ignored map[string]struct{}) {
	if word := buf.String(); word != "" {
		if _, ign := ignored[word]; ign || word == scope {
			bw.WriteString(word)
		} else {
			if href := p.href(word, scope); href != "" {
				bw.WriteString("")
				bw.WriteString(word)
				bw.WriteString("")
			} else {
				bw.WriteString(word)
			}
		}
	}
}

func (p *Package) linkify(w io.Writer, input string, scope string, ignored map[string]struct{}) error {
	bw := bufio.NewWriterSize(w, 512)
	var buf bytes.Buffer
	for ii := 0; ii < len(input); ii++ {
		c := input[ii]
		switch c {
		// Include * and & in the list of stop characters,
		// so pointers get the link for the pointed type.
		// Include ;, so escaped amperstands do not end up
		// in the type names.
		case ',', ' ', '\n', '\t', '(', ')', '*', '&', '{', '}', ';':
			p.writeWord(bw, &buf, scope, ignored)
			bw.WriteByte(c)
			buf.Reset()
		case '.':
			if next := ii + 1; next < len(input) {
				if nc := input[next]; nc == ' ' || nc == '\t' || nc == '\n' {
					p.writeWord(bw, &buf, scope, ignored)
					bw.WriteByte(c)
					buf.Reset()
					continue
				}
			}
			fallthrough
		default:
			buf.WriteByte(c)
		}
	}
	bw.WriteString(buf.String())
	return bw.Flush()
}

func (p *Package) Name() string {
	if p.bpkg != nil {
		return p.bpkg.Name
	}
	return p.name
}

func (p *Package) ImportPath() string {
	if p.bpkg != nil {
		path := p.bpkg.ImportPath
		if strings.HasPrefix(path, srcPrefix) {
			path = path[len(srcPrefix)+1:]
		}
		return path
	}
	return ""
}

func (p *Package) Synopsis() string {
	if p.dpkg != nil {
		return doc.Synopsis(p.dpkg.Doc)
	}
	return ""
}

func (p *Package) Filenames() []string {
	if b := p.bpkg; b != nil {
		var files []string
		for _, v := range [][]string{b.GoFiles, b.CgoFiles, b.IgnoredGoFiles, b.CFiles, b.CXXFiles, b.HFiles, b.SFiles, b.SysoFiles, b.SwigFiles, b.SwigCXXFiles} {
			files = append(files, v...)
		}
		sort.Strings(files)
		return files
	}
	return nil
}

func (p *Package) Position(n ast.Node) string {
	pos := p.fset.Position(n.Pos())
	filename := pos.Filename
	if strings.HasPrefix(filename, srcDir) {
		filename = filename[len(srcDir)+1:]
	}
	if gr := buildContext().GOROOT; strings.HasPrefix(filename, gr) {
		// Skip the src/ after GOROOT
		filename = "go" + filename[len(gr)+4:]
	}
	return fmt.Sprintf("%s#line-%d", filename, pos.Line)
}

func (p *Package) HasDoc() bool {
	return p.dpkg != nil && strings.TrimSpace(doc.Synopsis(p.dpkg.Doc)) != strings.TrimSpace(p.dpkg.Doc)
}

func (p *Package) Doc() *doc.Package {
	return p.dpkg
}

func (p *Package) html(text string, scope string) template.HTML {
	var buf bytes.Buffer
	doc.ToHTML(&buf, text, nil)
	var out bytes.Buffer
	p.linkify(&out, buf.String(), scope, nil)
	return template.HTML(out.String())
}

func (p *Package) HTML(text string) template.HTML {
	return p.html(text, "")
}

func (p *Package) ScopedHTML(text string, scope string) template.HTML {
	return p.html(text, scope)
}

func (p *Package) HTMLDoc() template.HTML {
	return p.HTML(p.dpkg.Doc)
}

func (p *Package) HTMLDecl(node interface{}) (template.HTML, error) {
	s, err := FormatNode(p.fset, node)
	if err == nil {
		var scope string
		var ignored map[string]struct{}
		ignore := func(x string) {
			if ignored == nil {
				ignored = make(map[string]struct{})
			}
			ignored[x] = struct{}{}
		}
		switch n := node.(type) {
		case *ast.FuncDecl:
			scope = n.Name.Name
		case *ast.GenDecl:
			for _, spec := range n.Specs {
				switch s := spec.(type) {
				case *ast.TypeSpec:
					scope = s.Name.Name
				case *ast.ValueSpec:
					for _, name := range s.Names {
						ignore(name.Name)
					}
				}
			}
		}
		var buf bytes.Buffer
		p.linkify(&buf, s, scope, ignored)
		s = buf.String()
	}
	return template.HTML(s), err
}

func pkgImporter(imports map[string]*ast.Object, path string) (*ast.Object, error) {
	pkg := imports[path]
	if pkg == nil {
		// note that strings.LastIndex returns -1 if there is no "/"
		pkg = ast.NewObj(ast.Pkg, path[strings.LastIndex(path, "/")+1:])
		pkg.Data = ast.NewScope(nil) // required by ast.NewPackage for dot-import
		imports[path] = pkg
	}
	return pkg, nil
}

func parseFiles(fset *token.FileSet, abspath string, names []string) (map[string]*ast.File, error) {
	files := make(map[string]*ast.File)
	for _, f := range names {
		absname := filepath.Join(abspath, f)
		file, err := parser.ParseFile(fset, absname, nil, parser.ParseComments)
		if err != nil {
			return nil, err
		}
		files[absname] = file
	}
	return files, nil
}

func ImportPackage(ctx *mux.Context, p string) (*Package, error) {
	bctx := buildContext()
	b, err := bctx.Import(p, "", 0)
	if err != nil {
		if noBuildable(err) {
			return nil, err
		}
		b, err = bctx.ImportDir(p, 0)
		if err != nil {
			return nil, err
		}
	}
	fset := token.NewFileSet()
	names := b.GoFiles
	names = append(names, b.CgoFiles...)
	files, err := parseFiles(fset, b.Dir, names)
	if err != nil {
		return nil, err
	}
	// NewPackage will always return errors because it won't
	// resolve builtin types.
	a, _ := ast.NewPackage(fset, files, pkgImporter, nil)
	flags := doc.AllMethods
	if p == "builtin" {
		flags |= doc.AllDecls
	}
	pkg := &Package{
		ctx:  ctx,
		fset: fset,
		bpkg: b,
		apkg: a,
		dpkg: doc.New(a, b.ImportPath, flags),
	}
	sub, err := ImportPackages(ctx, b.Dir)
	if err != nil {
		return nil, err
	}
	pkg.Packages = sub
	return pkg, nil
}

func ImportPackages(ctx *mux.Context, dir string) ([]*Package, error) {
	var pkgs []*Package
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		return nil, err
	}
	for _, v := range files {
		n := v.Name()
		if n == "test_data" || n[0] == '.' || n[0] == '_' {
			continue
		}
		abs := filepath.Join(dir, n)
		// Follow symlinks
		if st, err := os.Stat(abs); err == nil && st.IsDir() {
			pkg, err := ImportPackage(ctx, abs)
			if err != nil {
				if noBuildable(err) {
					sub, err := ImportPackages(ctx, abs)
					if err != nil {
						return nil, err
					}
					pkgs = append(pkgs, sub...)
					continue
				}
				return nil, err
			}
			pkgs = append(pkgs, pkg)
		}
	}
	return pkgs, nil
}

type packageGroup struct {
	Title    string
	Packages []*Package
}

func DocListHandler(ctx *mux.Context) {
	pkgs, err := ImportPackages(ctx, filepath.Join(srcDir, "gnd.la"))
	if err != nil {
		panic(err)
	}
	groups := []packageGroup{
		{Title: "Gondola Packages", Packages: pkgs},
	}
	infos, _ := ioutil.ReadDir(srcDir)
	var opkgs []*Package
	for _, v := range infos {
		if v.IsDir() && v.Name() != "gnd.la" {
			p, _ := ImportPackages(ctx, filepath.Join(srcDir, v.Name()))
			opkgs = append(opkgs, p...)
		}
	}
	if len(opkgs) > 0 {
		groups = append(groups, packageGroup{
			Title:    "Other useful Rainy Cape's packages",
			Packages: opkgs,
		})
	}
	title := "Package Index"
	data := map[string]interface{}{
		"HeaderTitle": title,
		"Subtitle":    title,
		"Section":     "docs",
		"Groups":      groups,
	}
	ctx.MustExecute("pkgs.html", data)
}

func DocHandler(ctx *mux.Context) {
	path := ctx.IndexValue(0)
	pkg, err := ImportPackage(ctx, path)
	if err != nil {
		if noBuildable(err) {
			sub, err := ImportPackages(ctx, filepath.Join(srcDir, path))
			if err != nil {
				panic(err)
			}
			pkg = &Package{name: path, Packages: sub}
		} else {
			panic(err)
		}
	}
	title := "Package " + pkg.Name()
	breadcrumbs := []*Breadcrumb{
		{Title: "Index", Href: ctx.MustReverse("doc-list")},
	}
	for ii := 0; ii < len(path); {
		var end int
		slash := strings.IndexByte(path[ii:], '/')
		if slash < 0 {
			end = len(path)
		} else {
			end = ii + slash
		}
		breadcrumbs = append(breadcrumbs, &Breadcrumb{
			Title: path[ii:end],
			Href:  ctx.MustReverse("doc", path[:end]),
		})
		ii = end + 1
	}
	data := map[string]interface{}{
		"HeaderTitle": title,
		"Subtitle":    title,
		"Section":     "docs",
		"Breadcrumbs": breadcrumbs,
		"Package":     pkg,
	}
	ctx.MustExecute("package.html", data)
}
<|endoftext|>


<commit_before>// Copyright 2013 by Dobrosław Żybort. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

/*
Package slug generate slug from unicode string, URL-friendly slugify with
multiple languages support.

Example:

	package main

	import(
		"github.com/gosimple/slug"
		"fmt"
	)

	func main () {
		text := slug.Make("Hellö Wörld хелло ворлд")
		fmt.Println(text) // Will print hello-world-khello-vorld

		someText := slug.Make("影師")
		fmt.Println(someText) // Will print: ying-shi

		enText := slug.MakeLang("This & that", "en")
		fmt.Println(enText) // Will print 'this-and-that'

		deText := slug.MakeLang("Diese & Dass", "de")
		fmt.Println(deText) // Will print 'diese-und-dass'

		slug.CustomSub = map[string]string{
			"water": "sand",
		}
		textSub := slug.Make("water is hot")
		fmt.Println(textSub) // Will print 'sand-is-hot'
	}

Requests or bugs?

https://github.com/gosimple/slug/issues
*/
package slug
<commit_msg>Update doc.go with new Lowercase variable<commit_after>// Copyright 2013 by Dobrosław Żybort. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

/*
Package slug generate slug from unicode string, URL-friendly slugify with
multiple languages support.

Example:

	package main

	import(
		"github.com/gosimple/slug"
		"fmt"
	)

	func main () {
		text := slug.Make("Hellö Wörld хелло ворлд")
		fmt.Println(text) // Will print: "hello-world-khello-vorld"

		someText := slug.Make("影師")
		fmt.Println(someText) // Will print: "ying-shi"

		enText := slug.MakeLang("This & that", "en")
		fmt.Println(enText) // Will print: "this-and-that"

		deText := slug.MakeLang("Diese & Dass", "de")
		fmt.Println(deText) // Will print: "diese-und-dass"

		slug.Lowercase = false // Keep uppercase characters
		deUppercaseText := slug.MakeLang("Diese & Dass", "de")
		fmt.Println(deUppercaseText) // Will print: "Diese-und-Dass"

		slug.CustomSub = map[string]string{
			"water": "sand",
		}
		textSub := slug.Make("water is hot")
		fmt.Println(textSub) // Will print: "sand-is-hot"
	}

Requests or bugs?

https://github.com/gosimple/slug/issues
*/
package slug
<|endoftext|>


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

// Package bdmsg implements bidirectional directly message protocol.
// Message is defined as variable-length byte array, they are
// distinguished by message-type, they can be freely transferred between
// the server and the client.
//
// You can provide your own "Converter" to customize the message IO.
// The default converter "DefaultIOC" use "MsgRWIO", message layout is:
//  A(length) + B(type) + C(data)
//  A is 4-bytes int, big-endian
//  B is 4-bytes int, big-endian
//  C is byte array, its length is (A) - 4
//
// Here is a quick example, includes protocol, server, client.
//
// Protocol
//  const (
//      MsgTypeConnect      = 1
//      MsgTypeConnectReply = 2
//  )
//
//  type ConnectRequst struct {
//      Name string
//      Pass string
//  }
//
//  func (p *ConnectRequst) Marshal() ([]byte, error) {
//      return json.Marshal(p)
//  }
//
//  func (p *ConnectRequst) Unmarshal(b []byte) error {
//      return json.Unmarshal(b, p)
//  }
//
//  type ConnectReply struct {
//      Code  int
//      Token string
//  }
//
//  func (p *ConnectReply) Marshal() ([]byte, error) {
//      return json.Marshal(p)
//  }
//
//  func (p *ConnectReply) Unmarshal(b []byte) error {
//      return json.Unmarshal(b, p)
//  }
//
// Server
//  type server struct {
//      *bdmsg.Server
//  }
//
//  func newService(l net.Listener, handshakeTO time.Duration,
//      pumperInN, pumperOutN int) *server {
//
//      s := &server{}
//
//      mux := bdmsg.NewPumpMux(nil)
//      mux.HandleFunc(MsgTypeConnect, s.handleConnect)
//
//      s.Server = bdmsg.NewServerF(l, bdmsg.DefaultIOC, handshakeTO,
//          mux, pumperInN, pumperOutN)
//      s.Server.Start()
//      return s
//  }
//
//  func (s *server) handleConnect(ctx context.Context,
//      p *bdmsg.Pumper, t bdmsg.MsgType, m bdmsg.Msg) {
//
//      msc := p.UserData().(*bdmsg.SClient)
//      if msc.Handshaked() {
//          panic(errors.New("Unexpected"))
//      }
//
//      var request ConnectRequst
//      request.Unmarshal(m) // unmarshal request
//
//      // process connect request
//
//      // tell bdmsg that client is authorized
//      msc.Handshake()
//
//      var reply ConnectReply
//      // init reply
//      mr, _ := reply.Marshal() // marshal reply
//
//      msc.Output(MsgTypeConnectReply, mr)
//  }
// Client
//  type client struct {
//      *bdmsg.Client
//      connected chan bool
//  }
//
//  func newClient(conn net.Conn, pumperInN, pumperOutN int) *client {
//
//      c := &client{connected: make(chan bool)}
//
//      mux := bdmsg.NewPumpMux(nil)
//      mux.HandleFunc(MsgTypeConnectReply, c.handleConnectReply)
//
//      c.Client = bdmsg.NewClient(nil, conn, bdmsg.DefaultIOC,
//          mux, pumperInN, pumperOutN)
//      c.doConnect()
//      return c
//  }
//
//  func (c *client) doConnect() {
//      var request ConnectRequst
//      // init request
//      mr, _ := request.Marshal() // marshal request
//
//      c.Client.Output(MsgTypeConnect, mr)
//  }
//
//  func (c *client) handleConnectReply(ctx context.Context,
//      p *bdmsg.Pumper, t bdmsg.MsgType, m bdmsg.Msg) {
//
//      var reply ConnectReply
//      reply.Unmarshal(m) // unmarshal reply
//
//      // process connect reply
//
//      close(c.connected)
//  }
package bdmsg
<commit_msg>update doc for msgpump<commit_after>// Copyright 2015 someonegg. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package bdmsg implements bidirectional directly message protocol.
//
//  This package now has a better alternative which is more concise and customizable:
//
//  https://github.com/someonegg/msgpump.
//
// Message is defined as variable-length byte array, they are
// distinguished by message-type, they can be freely transferred between
// the server and the client.
//
// You can provide your own "Converter" to customize the message IO.
// The default converter "DefaultIOC" use "MsgRWIO", message layout is:
//  A(length) + B(type) + C(data)
//  A is 4-bytes int, big-endian
//  B is 4-bytes int, big-endian
//  C is byte array, its length is (A) - 4
//
// Here is a quick example, includes protocol, server, client.
//
// Protocol
//  const (
//      MsgTypeConnect      = 1
//      MsgTypeConnectReply = 2
//  )
//
//  type ConnectRequst struct {
//      Name string
//      Pass string
//  }
//
//  func (p *ConnectRequst) Marshal() ([]byte, error) {
//      return json.Marshal(p)
//  }
//
//  func (p *ConnectRequst) Unmarshal(b []byte) error {
//      return json.Unmarshal(b, p)
//  }
//
//  type ConnectReply struct {
//      Code  int
//      Token string
//  }
//
//  func (p *ConnectReply) Marshal() ([]byte, error) {
//      return json.Marshal(p)
//  }
//
//  func (p *ConnectReply) Unmarshal(b []byte) error {
//      return json.Unmarshal(b, p)
//  }
//
// Server
//  type server struct {
//      *bdmsg.Server
//  }
//
//  func newService(l net.Listener, handshakeTO time.Duration,
//      pumperInN, pumperOutN int) *server {
//
//      s := &server{}
//
//      mux := bdmsg.NewPumpMux(nil)
//      mux.HandleFunc(MsgTypeConnect, s.handleConnect)
//
//      s.Server = bdmsg.NewServerF(l, bdmsg.DefaultIOC, handshakeTO,
//          mux, pumperInN, pumperOutN)
//      s.Server.Start()
//      return s
//  }
//
//  func (s *server) handleConnect(ctx context.Context,
//      p *bdmsg.Pumper, t bdmsg.MsgType, m bdmsg.Msg) {
//
//      msc := p.UserData().(*bdmsg.SClient)
//      if msc.Handshaked() {
//          panic(errors.New("Unexpected"))
//      }
//
//      var request ConnectRequst
//      request.Unmarshal(m) // unmarshal request
//
//      // process connect request
//
//      // tell bdmsg that client is authorized
//      msc.Handshake()
//
//      var reply ConnectReply
//      // init reply
//      mr, _ := reply.Marshal() // marshal reply
//
//      msc.Output(MsgTypeConnectReply, mr)
//  }
// Client
//  type client struct {
//      *bdmsg.Client
//      connected chan bool
//  }
//
//  func newClient(conn net.Conn, pumperInN, pumperOutN int) *client {
//
//      c := &client{connected: make(chan bool)}
//
//      mux := bdmsg.NewPumpMux(nil)
//      mux.HandleFunc(MsgTypeConnectReply, c.handleConnectReply)
//
//      c.Client = bdmsg.NewClient(nil, conn, bdmsg.DefaultIOC,
//          mux, pumperInN, pumperOutN)
//      c.doConnect()
//      return c
//  }
//
//  func (c *client) doConnect() {
//      var request ConnectRequst
//      // init request
//      mr, _ := request.Marshal() // marshal request
//
//      c.Client.Output(MsgTypeConnect, mr)
//  }
//
//  func (c *client) handleConnectReply(ctx context.Context,
//      p *bdmsg.Pumper, t bdmsg.MsgType, m bdmsg.Msg) {
//
//      var reply ConnectReply
//      reply.Unmarshal(m) // unmarshal reply
//
//      // process connect reply
//
//      close(c.connected)
//  }
package bdmsg
<|endoftext|>


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

/*

Package xorm is a simple and powerful ORM for Go.

Installation

Make sure you have installed Go 1.1+ and then:

    go get github.com/go-xorm/xorm

Create Engine

Firstly, we should new an engine for a database

    engine, err := xorm.NewEngine(driverName, dataSourceName)

Method NewEngine's parameters is the same as sql.Open. It depends
drivers' implementation.
Generally, one engine for an application is enough. You can set it as package variable.

Raw Methods

Xorm also support raw sql execution:

1. query a SQL string, the returned results is []map[string][]byte

    results, err := engine.Query("select * from user")

2. execute a SQL string, the returned results

    affected, err := engine.Exec("update user set .... where ...")

ORM Methods

There are 7 major ORM methods and many helpful methods to use to operate database.

1. Insert one or multiple records to database

    affected, err := engine.Insert(&struct)
    // INSERT INTO struct () values ()
    affected, err := engine.Insert(&struct1, &struct2)
    // INSERT INTO struct1 () values ()
    // INSERT INTO struct2 () values ()
    affected, err := engine.Insert(&sliceOfStruct)
    // INSERT INTO struct () values (),(),()
    affected, err := engine.Insert(&struct1, &sliceOfStruct2)
    // INSERT INTO struct1 () values ()
    // INSERT INTO struct2 () values (),(),()

2. Query one record from database

    has, err := engine.Get(&user)
    // SELECT * FROM user LIMIT 1

3. Query multiple records from database

    sliceOfStructs := new(Struct)
    err := engine.Find(sliceOfStructs)
    // SELECT * FROM user

4. Query multiple records and record by record handle, there two methods, one is Iterate,
another is Rows

    err := engine.Iterate(...)
    // SELECT * FROM user

    rows, err := engine.Rows(...)
    // SELECT * FROM user
    defer rows.Close()
    bean := new(Struct)
    for rows.Next() {
        err = rows.Scan(bean)
    }

5. Update one or more records

    affected, err := engine.Id(...).Update(&user)
    // UPDATE user SET ...

6. Delete one or more records, Delete MUST has condition

    affected, err := engine.Where(...).Delete(&user)
    // DELETE FROM user Where ...

7. Count records

    counts, err := engine.Count(&user)
    // SELECT count(*) AS total FROM user

Conditions

The above 7 methods could use with condition methods chainable.
Attention: the above 7 methods should be the last chainable method.

1. Id, In

    engine.Id(1).Get(&user) // for single primary key
    // SELECT * FROM user WHERE id = 1
    engine.Id(core.PK{1, 2}).Get(&user) // for composite primary keys
    // SELECT * FROM user WHERE id1 = 1 AND id2 = 2
    engine.In("id", 1, 2, 3).Find(&users)
    // SELECT * FROM user WHERE id IN (1, 2, 3)
    engine.In("id", []int{1, 2, 3})
    // SELECT * FROM user WHERE id IN (1, 2, 3)

2. Where, And, Or

    engine.Where().And().Or().Find()
    // SELECT * FROM user WHERE (.. AND ..) OR ...

3. OrderBy, Asc, Desc

    engine.Asc().Desc().Find()
    // SELECT * FROM user ORDER BY .. ASC, .. DESC
    engine.OrderBy().Find()
    // SELECT * FROM user ORDER BY ..

4. Limit, Top

    engine.Limit().Find()
    // SELECT * FROM user LIMIT .. OFFSET ..
    engine.Top(5).Find()
    // SELECT TOP 5 * FROM user // for mssql
    // SELECT * FROM user LIMIT .. OFFSET 0 //for other databases

5. Sql, let you custom SQL

    var users []User
    engine.Sql("select * from user").Find(&users)

6. Cols, Omit, Distinct

    var users []*User
    engine.Cols("col1, col2").Find(&users)
    // SELECT col1, col2 FROM user
    engine.Cols("col1", "col2").Where().Update(user)
    // UPDATE user set col1 = ?, col2 = ? Where ...
    engine.Omit("col1").Find(&users)
    // SELECT col2, col3 FROM user
    engine.Omit("col1").Insert(&user)
    // INSERT INTO table (non-col1) VALUES ()
    engine.Distinct("col1").Find(&users)
    // SELECT DISTINCT col1 FROM user

7. Join, GroupBy, Having

    engine.GroupBy("name").Having("name='xlw'").Find(&users)
    //SELECT * FROM user GROUP BY name HAVING name='xlw'
    engine.Join("LEFT", "userdetail", "user.id=userdetail.id").Find(&users)
    //SELECT * FROM user LEFT JOIN userdetail ON user.id=userdetail.id

More usage, please visit http://xorm.io/docs
*/
package xorm
<commit_msg>fix wrong type in doc<commit_after>// Copyright 2013 - 2016 The XORM Authors. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

/*

Package xorm is a simple and powerful ORM for Go.

Installation

Make sure you have installed Go 1.1+ and then:

    go get github.com/go-xorm/xorm

Create Engine

Firstly, we should new an engine for a database

    engine, err := xorm.NewEngine(driverName, dataSourceName)

Method NewEngine's parameters is the same as sql.Open. It depends
drivers' implementation.
Generally, one engine for an application is enough. You can set it as package variable.

Raw Methods

Xorm also support raw sql execution:

1. query a SQL string, the returned results is []map[string][]byte

    results, err := engine.Query("select * from user")

2. execute a SQL string, the returned results

    affected, err := engine.Exec("update user set .... where ...")

ORM Methods

There are 7 major ORM methods and many helpful methods to use to operate database.

1. Insert one or multiple records to database

    affected, err := engine.Insert(&struct)
    // INSERT INTO struct () values ()
    affected, err := engine.Insert(&struct1, &struct2)
    // INSERT INTO struct1 () values ()
    // INSERT INTO struct2 () values ()
    affected, err := engine.Insert(&sliceOfStruct)
    // INSERT INTO struct () values (),(),()
    affected, err := engine.Insert(&struct1, &sliceOfStruct2)
    // INSERT INTO struct1 () values ()
    // INSERT INTO struct2 () values (),(),()

2. Query one record from database

    has, err := engine.Get(&user)
    // SELECT * FROM user LIMIT 1

3. Query multiple records from database

    var sliceOfStructs []Struct
    err := engine.Find(sliceOfStructs)
    // SELECT * FROM user

4. Query multiple records and record by record handle, there two methods, one is Iterate,
another is Rows

    err := engine.Iterate(...)
    // SELECT * FROM user

    rows, err := engine.Rows(...)
    // SELECT * FROM user
    defer rows.Close()
    bean := new(Struct)
    for rows.Next() {
        err = rows.Scan(bean)
    }

5. Update one or more records

    affected, err := engine.Id(...).Update(&user)
    // UPDATE user SET ...

6. Delete one or more records, Delete MUST has condition

    affected, err := engine.Where(...).Delete(&user)
    // DELETE FROM user Where ...

7. Count records

    counts, err := engine.Count(&user)
    // SELECT count(*) AS total FROM user

Conditions

The above 7 methods could use with condition methods chainable.
Attention: the above 7 methods should be the last chainable method.

1. Id, In

    engine.Id(1).Get(&user) // for single primary key
    // SELECT * FROM user WHERE id = 1
    engine.Id(core.PK{1, 2}).Get(&user) // for composite primary keys
    // SELECT * FROM user WHERE id1 = 1 AND id2 = 2
    engine.In("id", 1, 2, 3).Find(&users)
    // SELECT * FROM user WHERE id IN (1, 2, 3)
    engine.In("id", []int{1, 2, 3})
    // SELECT * FROM user WHERE id IN (1, 2, 3)

2. Where, And, Or

    engine.Where().And().Or().Find()
    // SELECT * FROM user WHERE (.. AND ..) OR ...

3. OrderBy, Asc, Desc

    engine.Asc().Desc().Find()
    // SELECT * FROM user ORDER BY .. ASC, .. DESC
    engine.OrderBy().Find()
    // SELECT * FROM user ORDER BY ..

4. Limit, Top

    engine.Limit().Find()
    // SELECT * FROM user LIMIT .. OFFSET ..
    engine.Top(5).Find()
    // SELECT TOP 5 * FROM user // for mssql
    // SELECT * FROM user LIMIT .. OFFSET 0 //for other databases

5. Sql, let you custom SQL

    var users []User
    engine.Sql("select * from user").Find(&users)

6. Cols, Omit, Distinct

    var users []*User
    engine.Cols("col1, col2").Find(&users)
    // SELECT col1, col2 FROM user
    engine.Cols("col1", "col2").Where().Update(user)
    // UPDATE user set col1 = ?, col2 = ? Where ...
    engine.Omit("col1").Find(&users)
    // SELECT col2, col3 FROM user
    engine.Omit("col1").Insert(&user)
    // INSERT INTO table (non-col1) VALUES ()
    engine.Distinct("col1").Find(&users)
    // SELECT DISTINCT col1 FROM user

7. Join, GroupBy, Having

    engine.GroupBy("name").Having("name='xlw'").Find(&users)
    //SELECT * FROM user GROUP BY name HAVING name='xlw'
    engine.Join("LEFT", "userdetail", "user.id=userdetail.id").Find(&users)
    //SELECT * FROM user LEFT JOIN userdetail ON user.id=userdetail.id

More usage, please visit http://xorm.io/docs
*/
package xorm
<|endoftext|>


<commit_before>/*
 go-offheap-hashtable

The purpose here is to have hash table that can work away
from Go's Garbage Collector, to avoid long GC pause times.

We accomplish this by writing our own Malloc() and Free() implementation
(see malloc.go) which requests memory directly from the OS.

The keys, values, and entire hash table is kept on off-heap
storage. This storage can also optionally be backed by memory mapped file
for speedy persistence and fast startup times.

Initial HashTable implementation inspired by the public domain C++ code of
    https://github.com/preshing/CompareIntegerMaps
See also
    http://preshing.com/20130107/this-hash-table-is-faster-than-a-judy-array/
for performance studies of the C++ code.

HashTable

Maps pointer-sized integers to Cell structures, which in turn hold Val_t
as well as key_t structures.

Uses open addressing with linear probing. This makes it very cache
friendly and thus very fast.

In the t.Cells array, UnHashedKey = 0 is reserved to indicate an unused cell.
Actual value for key 0 (if any) is stored in t.ZeroCell.
The hash table automatically doubles in size when it becomes 75% full.
The hash table never shrinks in size, even after Clear(), unless you explicitly
call Compact().

Basic operations: Lookup(), Insert(), DeleteKey(). These are the
equivalent of the builtin map[uint64]interface{}.

As an example of how to specialize for a map[string]*Cell equivalent,
see the following functions in the bytekey.go file:

    func (t *HashTable) InsertStringKey(strkey string, value interface{}) bool
    func (t *HashTable) LookupStringKey(strkey string) (Val_t, bool)
    func (t *HashTable) DeleteStringKey(strkey string) bool

Example use:

    h := offheap.NewHashTable(2)

    // basic three operations are:
    h.InsertStringKey("My number", 43)
    val, ok := h.LookupStringKey("My number")
    h.DeleteStringKey("My number")

*/
package offheap
<commit_msg>atg. doc++<commit_after>/*
 go-offheap-hashtable

The purpose here is to have hash table that can work away
from Go's Garbage Collector, to avoid long GC pause times.

We accomplish this by writing our own Malloc() and Free() implementation
(see malloc.go) which requests memory directly from the OS.

The keys, values, and entire hash table is kept on off-heap
storage. This storage can also optionally be backed by memory mapped file
for speedy persistence and fast startup times.

Initial HashTable implementation inspired by the public domain C++ code of
    https://github.com/preshing/CompareIntegerMaps
See also
    http://preshing.com/20130107/this-hash-table-is-faster-than-a-judy-array/
for performance studies of the C++ code.

HashTable

Maps pointer-sized integers to Cell structures, which in turn hold Val_t
as well as key_t structures.

Uses open addressing with linear probing. This makes it very cache
friendly and thus very fast.

In the t.Cells array, UnHashedKey = 0 is reserved to indicate an unused cell.
Actual value for key 0 (if any) is stored in t.ZeroCell.
The hash table automatically doubles in size when it becomes 75% full.
The hash table never shrinks in size, even after Clear(), unless you explicitly
call Compact().

Basic operations: Lookup(), Insert(), DeleteKey(). These are the
equivalent of the builtin map[uint64]interface{}.

As an example of how to specialize for a map[string]*Cell equivalent,
see the following functions in the bytekey.go file:

    func (t *HashTable) InsertStringKey(strkey string, value interface{}) bool
    func (t *HashTable) LookupStringKey(strkey string) (Val_t, bool)
    func (t *HashTable) DeleteStringKey(strkey string) bool

Example use:

    h := offheap.NewHashTable(2)

    // basic three operations are:
    h.InsertStringKey("My number", 43)
    val, ok := h.LookupStringKey("My number")
    h.DeleteStringKey("My number")

Note that this library is only a starting point of source code, and not intended to be used without customization. Users of the HashTable will have to customize it by changing the definitions of key_t and Val_t to suite their needs. I'm experimenting next with storing objects in Capnproto serialized format, but this branch (branch capnp) isn't quite ready for use.

*/
package offheap
<|endoftext|>


<commit_before>// Package gofast implements a high performance symmetric protocol for on the
// wire data transport.
//
// opaque-space, is range of uint64 values reserved for tagging packets. They
// shall be supplied via settings while instantiating the transport.
//
// messages, are golang objects implementing the Message{} interface. Message
// objects need to be subscribed with transport before they are exchanged over
// the transport. It is also expected that distributed systems must
// pre-define messages and their Ids.
//
// message ids, need to be unique for every type of message transfered over
// using gofast protocol, following id range is reserved for internal use:
//
//		0x00 - 0x0F -- reserved messages ids.
//
// transport instantiation steps:
//
//		setts := Settings{"log.level": "info", "log.file": logfile}
//		log := SetLogger(nil /* use-default-logging */, setts)
//		t := NewTransport(conn, &ver, nil, settings)
//		t.SubscribeMessage(&msg1, handler1) // subscribe message
//		t.SubscribeMessage(&msg2, handler2) // subscribe another message
//		t.Handshake()
//		t.FlushPeriod(tm)                   // optional
//		t.SendHeartbeat(tm)                 // optional

package gofast
<commit_msg>fixes to godoc.<commit_after>// Package gofast implements a high performance symmetric protocol for on the
// wire data transport.
//
// opaque-space, is range of uint64 values reserved for tagging packets. They
// shall be supplied via settings while instantiating the transport.
//
// messages, are golang objects implementing the Message{} interface. Message
// objects need to be subscribed with transport before they are exchanged over
// the transport. It is also expected that distributed systems must
// pre-define messages and their Ids.
//
// message ids, need to be unique for every type of message transfered over
// using gofast protocol, following id range is reserved for internal use:
//
//		0x00 - 0x0F -- reserved messages ids.
//
// transport instantiation steps:
//
//		setts := Settings{"log.level": "info", "log.file": logfile}
//		log := SetLogger(nil /* use-default-logging */, setts)
//		t := NewTransport(conn, &ver, nil, settings)
//		t.SubscribeMessage(&msg1, handler1) // subscribe message
//		t.SubscribeMessage(&msg2, handler2) // subscribe another message
//		t.Handshake()
//		t.FlushPeriod(tm)                   // optional
//		t.SendHeartbeat(tm)                 // optional
package gofast
<|endoftext|>


<commit_before>/*
Package workerpool queues work to a limited number of goroutines.

The purpose of the worker pool is to limit the concurrency of the task
performed by the workers.  This is useful when performing a task that requires
sufficient resources (CPU, memory, etc.), that running too many tasks at the
same time would exhaust resources.

Non-blocking task submission

A task is a function submitted to the worker pool for execution.  Submitting
tasks to this worker pool will not block, regardless of the number of tasks.
Tasks read from the input task queue are immediately dispatched to an available
worker.  If no worker is immediately available, then the task is passed to a go
routine which is started to wait for an available worker.  This clears the task
from the task queue immediately, whether or not a worker is currently
available, and will not block the submission of tasks.

The intent of the worker pool is to limit the concurrency of task execution,
not limit the number of tasks queued to be executed. Therefore, this unbounded
input of tasks is acceptable as the tasks cannot be discarded.  If the number
of inbound tasks is too many to even queue for pending processing, then the
solution is outside the scope of workerpool, and should be solved by
distributing load over multiple systems, and/or storing input for pending
processing in intermediate storage such as a database, file system, distributed
message queue, etc.

Dispatcher

This worker pool uses a single dispatcher goroutine to read tasks from the
input task queue and dispatch them to a worker goroutine.  This allows for a
small input channel, and lets the dispatcher queue as many tasks as are
submitted when there are no available workers (using goroutines).
Additionally, the dispatcher can adjust the number of workers as appropriate
for the work load, without having to utilize locked counters and checks
incurred on task submission.

When no tasks have been submitted for a period of time, a worker is removed by
the dispatcher.  This is done until there are no more workers to remove.  The
minimum number of workers is always zero, because the time to start new workers
is insignificant.

Usage note

It is advisable to use different worker pools for tasks that are bound by
different resources, or that have different resource use patterns.  For
example, tasks that use X Mb of memory may need different concurrency limits
than tasks that use Y Mb of memory.

Credits

This implementation builds on ideas from the following:

http://marcio.io/2015/07/handling-1-million-requests-per-minute-with-golang
http://nesv.github.io/golang/2014/02/25/worker-queues-in-go.html

*/
package workerpool
<commit_msg>Update doc to descript waiting queue.<commit_after>/*
Package workerpool queues work to a limited number of goroutines.

The purpose of the worker pool is to limit the concurrency of the task
performed by the workers.  This is useful when performing a task that requires
sufficient resources (CPU, memory, etc.), that running too many tasks at the
same time would exhaust resources.

Non-blocking task submission

A task is a function submitted to the worker pool for execution.  Submitting
tasks to this worker pool will not block, regardless of the number of tasks.
Tasks read from the input task queue are immediately dispatched to an available
worker.  If no worker is immediately available, or there are already tasks
waiting for an available worker, then the task is put on a waiting queue to
wait for an available worker.  This clears the incoming task from the task
queue immediately, whether or not a worker is currently available, and will not
block the submission of tasks.

The intent of the worker pool is to limit the concurrency of task execution,
not limit the number of tasks queued to be executed.  Therefore, this unbounded
input of tasks is acceptable as the tasks cannot be discarded.  If the number
of inbound tasks is too many to even queue for pending processing, then the
solution is outside the scope of workerpool, and should be solved by
distributing load over multiple systems, and/or storing input for pending
processing in intermediate storage such as a database, file system, distributed
message queue, etc.

Dispatcher

This worker pool uses a single dispatcher goroutine to read tasks from the
input task queue and dispatch them to a worker goroutine.  This allows for a
small input channel, and lets the dispatcher queue as many tasks as are
submitted when there are no available workers.  Additionally, the dispatcher
can adjust the number of workers as appropriate for the work load, without
having to utilize locked counters and checks incurred on task submission.

When no tasks have been submitted for a period of time, a worker is removed by
the dispatcher.  This is done until there are no more workers to remove.  The
minimum number of workers is always zero, because the time to start new workers
is insignificant.

Usage note

It is advisable to use different worker pools for tasks that are bound by
different resources, or that have different resource use patterns.  For
example, tasks that use X Mb of memory may need different concurrency limits
than tasks that use Y Mb of memory.

Waiting queue vs goroutines

When there are no available workers to handle incoming tasks, the tasks are put
on a waiting queue.  In previous versions of workerpool, these tasks were
passed to goroutines.  Using a queue is faster and has less memory overhead
than creating a separate goroutine for each waiting task, allowing a much
higher number of waiting tasks.

Credits

This implementation builds on ideas from the following:

http://marcio.io/2015/07/handling-1-million-requests-per-minute-with-golang
http://nesv.github.io/golang/2014/02/25/worker-queues-in-go.html

*/
package workerpool
<|endoftext|>