<commit_before>package message

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"math"
	"net/http"
	"strings"

	"github.com/flamingyawn/discryptord/lib/api"
	"github.com/flamingyawn/discryptord/lib/drawer"
	"github.com/flamingyawn/discryptord/lib/types"

	"github.com/bwmarrin/discordgo"
)

// Create :: called once for every message on any channel that the autenticated bot has access to.
func Create(s *discordgo.Session, m *discordgo.MessageCreate) {

	// // //
	// prevent overflow
	if len(m.Content) <= 2 {
		return
	}

	hasBeenInvoked := strings.HasPrefix(m.Content, "!") // check invocation
	authorIsHuman := (m.Author.ID != s.State.User.ID)   // check humanity of invoker
	if authorIsHuman && hasBeenInvoked {
		// // //
		// separate ticker from invocation
		// and set default RSI presence
		splitCommand := strings.Split(m.Content, " ")
		rsiEnabled, logEnabled := false, false
		candle := "24h"

		if len(splitCommand) > 1 {
			for strings.HasPrefix(splitCommand[len(splitCommand)-1], "-") || splitCommand[len(splitCommand)-1] == "" {
				flag := splitCommand[len(splitCommand)-1]
				splitCommand = splitCommand[:len(splitCommand)-1]

				switch flag {
				case "-3d", "-w", "-m", "-3m", "-6m", "-y":
					candle = flag[1:len(flag)]
				case "-rsi", "-RSI":
					rsiEnabled = true
				case "-log", "-LOG":
					logEnabled = true
				}

			}
		}

		// // //
		// prevent overflow
		if len(splitCommand) <= 2 {
			// // //
			// get tickers
			coin := strings.ToUpper(splitCommand[0][1:])

			base := "USD"
			if len(splitCommand) == 2 {
				base = strings.ToUpper(splitCommand[1])
			}

			// // //
			// fetch data
			var histoData types.HistoResponse
			var apiURL, timerange string
			switch candle {
			case "24h", "3d", "w", "m", "3m", "6m", "y":
				apiURL = api.BuildHistoryApiUrl(candle, coin, base)
				timerange = strings.ToUpper(candle)
			}

			resp, err := http.Get(apiURL)
			if err != nil {
				fmt.Println(err)
				return
			}
			defer resp.Body.Close()

			histoMinuteBody, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				fmt.Println(err)
				return
			}

			err = json.Unmarshal(histoMinuteBody, &histoData)
			if err != nil || histoData.Response == "Error" {
				fmt.Println(err)
				return
			}

			// // //
			// format axes
			axes := drawer.ParsePriceData(histoData.Data, logEnabled)

			// // //
			// draw chart
			buffer, err := drawer.DrawChart(axes, rsiEnabled, logEnabled)
			if err != nil {
				fmt.Println(err)
				return
			}

			// // //
			// format closing price
			var sym string
			color := 0x5dff9f
			lastPrice, firstPrice := 0.0, 0.0
			hi, lo := axes.Ymax, axes.Ymin
			logText := ""
			changeSign := "-"

			switch base {
			case "usd", "usdt", "USDT", "USD":
				sym = "$"
			case "btc", "BTC":
				sym = "Ƀ"
			case "eth", "ETH":
				sym = "Ξ"
			default:
				sym = ""
			}

			if len(axes.Y) > 0 {
				lastPrice = axes.Y[len(axes.Y)-1]
				firstPrice = axes.Y[0]
			}

			if logEnabled && len(axes.Y) > 0 {
				logText = "Logarithmic "

				if lastPrice > 0 {
					lastPrice = math.Pow(10, lastPrice)
				}
				if firstPrice > 0 {
					firstPrice = math.Pow(10, firstPrice)
				}
				if hi > 0 {
					hi = math.Pow(10, hi)
				}
				if lo > 0 {
					lo = math.Pow(10, lo)
				}

			}

			if lastPrice >= firstPrice {
				changeSign = "+"
			}

			//	//
			//	build message
			delta := lastPrice - firstPrice
			pairing := fmt.Sprintf("%s/%s %sPrice Chart (%s)", coin, base, logText, timerange)
			deltaPct := fmt.Sprintf("%.2f%%", delta/firstPrice*100)

			if delta < 0 {
				color = 0xE94335
			}

			embed := NewEmbed().
				SetAuthor(pairing, "https://cdn.discordapp.com/app-icons/359564584564293632/21fb4ad276ed1ddc3318ce0b1a663395.png").
				AddField("Last", fmt.Sprintf("%s%f", sym, lastPrice)).
				AddField("First", fmt.Sprintf("%s%f", sym, firstPrice)).
				AddField("∆", fmt.Sprintf("`%s%s%f (%s%s)`", changeSign, sym, math.Abs(delta), changeSign, deltaPct)).
				AddField("Hi", fmt.Sprintf("%s%f", sym, hi)).
				AddField("Lo", fmt.Sprintf("%s%f", sym, lo)).
				InlineAllFields().
				SetColor(color).
				MessageEmbed

			s.ChannelMessageSendEmbed(m.ChannelID, embed)
			s.ChannelFileSendWithMessage(m.ChannelID, "", coin+base+".png", bytes.NewReader(buffer.Bytes()))

		}
	}
}
<commit_msg>add 5y flag to parser and fix log in card<commit_after>package message

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"math"
	"net/http"
	"strings"

	"github.com/flamingyawn/discryptord/lib/api"
	"github.com/flamingyawn/discryptord/lib/drawer"
	"github.com/flamingyawn/discryptord/lib/types"

	"github.com/bwmarrin/discordgo"
)

// Create :: called once for every message on any channel that the autenticated bot has access to.
func Create(s *discordgo.Session, m *discordgo.MessageCreate) {

	// // //
	// prevent overflow
	if len(m.Content) <= 2 {
		return
	}

	hasBeenInvoked := strings.HasPrefix(m.Content, "!") // check invocation
	authorIsHuman := (m.Author.ID != s.State.User.ID)   // check humanity of invoker
	if authorIsHuman && hasBeenInvoked {
		// // //
		// separate ticker from invocation
		// and set default RSI presence
		splitCommand := strings.Split(m.Content, " ")
		rsiEnabled, logEnabled := false, false
		candle := "24h"

		if len(splitCommand) > 1 {
			for strings.HasPrefix(splitCommand[len(splitCommand)-1], "-") || splitCommand[len(splitCommand)-1] == "" {
				flag := splitCommand[len(splitCommand)-1]
				splitCommand = splitCommand[:len(splitCommand)-1]

				switch flag {
				case "-3d", "-w", "-m", "-3m", "-6m", "-y", "-5y":
					candle = flag[1:len(flag)]
				case "-rsi", "-RSI":
					rsiEnabled = true
				case "-log", "-LOG":
					logEnabled = true
				}

			}
		}

		// // //
		// prevent overflow
		if len(splitCommand) <= 2 {
			// // //
			// get tickers
			coin := strings.ToUpper(splitCommand[0][1:])

			base := "USD"
			if len(splitCommand) == 2 {
				base = strings.ToUpper(splitCommand[1])
			}

			// // //
			// fetch data
			var histoData types.HistoResponse
			var apiURL, timerange string
			switch candle {
			case "24h", "3d", "w", "m", "3m", "6m", "y", "5y":
				apiURL = api.BuildHistoryApiUrl(candle, coin, base)
				timerange = strings.ToUpper(candle)
			}

			resp, err := http.Get(apiURL)
			if err != nil {
				fmt.Println(err)
				return
			}
			defer resp.Body.Close()

			histoMinuteBody, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				fmt.Println(err)
				return
			}

			err = json.Unmarshal(histoMinuteBody, &histoData)
			if err != nil || histoData.Response == "Error" {
				fmt.Println(err)
				return
			}

			// // //
			// format axes
			axes := drawer.ParsePriceData(histoData.Data, logEnabled)

			// // //
			// draw chart
			buffer, err := drawer.DrawChart(axes, rsiEnabled, logEnabled)
			if err != nil {
				fmt.Println(err)
				return
			}

			// // //
			// format closing price
			var sym string
			color := 0x5dff9f
			lastPrice, firstPrice := 0.0, 0.0
			hi, lo := axes.Ymax, axes.Ymin
			logText := ""
			changeSign := "-"

			switch base {
			case "usd", "usdt", "USDT", "USD":
				sym = "$"
			case "btc", "BTC":
				sym = "Ƀ"
			case "eth", "ETH":
				sym = "Ξ"
			default:
				sym = ""
			}

			if logEnabled && len(axes.Y) > 0 {
				normalAxes := drawer.ParsePriceData(histoData.Data, false)

				logText = "Logarithmic "

				lastPrice = normalAxes.Y[len(normalAxes.Y)-1]
				firstPrice = normalAxes.Y[0]
				hi = normalAxes.Ymax
				lo = normalAxes.Ymin

				fmt.Printf("Last %s%f", sym, lastPrice)
				fmt.Printf("First %s%f", sym, firstPrice)
				fmt.Printf("Hi %s%f", sym, hi)
				fmt.Printf("Lo %s%f", sym, lo)

			} else if len(axes.Y) > 0 {
				lastPrice = axes.Y[len(axes.Y)-1]
				firstPrice = axes.Y[0]
			}

			if lastPrice >= firstPrice {
				changeSign = "+"
			}

			//	//
			//	build message
			delta := lastPrice - firstPrice
			pairing := fmt.Sprintf("%s/%s %sPrice Chart (%s)", coin, base, logText, timerange)
			deltaPct := fmt.Sprintf("%.2f%%", delta/firstPrice*100)

			if delta < 0 {
				color = 0xE94335
			}

			embed := NewEmbed().
				SetAuthor(pairing, "https://cdn.discordapp.com/app-icons/359564584564293632/21fb4ad276ed1ddc3318ce0b1a663395.png").
				AddField("Last", fmt.Sprintf("%s%f", sym, lastPrice)).
				AddField("First", fmt.Sprintf("%s%f", sym, firstPrice)).
				AddField("∆", fmt.Sprintf("`%s%s%f (%s%s)`", changeSign, sym, math.Abs(delta), changeSign, deltaPct)).
				AddField("Hi", fmt.Sprintf("%s%f", sym, hi)).
				AddField("Lo", fmt.Sprintf("%s%f", sym, lo)).
				InlineAllFields().
				SetColor(color).
				MessageEmbed

			s.ChannelMessageSendEmbed(m.ChannelID, embed)
			s.ChannelFileSendWithMessage(m.ChannelID, "", coin+base+".png", bytes.NewReader(buffer.Bytes()))

		}
	}
}
<|endoftext|>


<commit_before>package main

import (
  "fmt"
)

const (
  white = 18
  black = 19
)

func (p *Piet) Run() {
  var cont bool = true
  var dpstat = []string{"RIGHT", "DOWN", "LEFT", "UP"}
  var ccstat = []string{"LEFT", "RIGHT"}
  for i := 1; cont; i++ {
    if p.debug {
      fmt.Printf("step %04d : %s ; DP=%s, CC=%s\n", i, p.now.ToString(), dpstat[p.DP], ccstat[BoolToInt64(!p.CC)])
    }
    cont = p.Step()
    if p.debug {
      fmt.Println(p.stack)
    }
  }
  if p.debug {
    fmt.Println("Finished.")
  }
}

var dr = [...]Point{Point{1, 0}, Point{0, 1}, Point{-1, 0}, Point{0, -1}}

var commandsstr = [][3]string{
  {"None", "Push", "Pop"},
  {"Add", "Subtract", "Multiply"},
  {"Divide", "Mod", "Not"},
  {"Greater", "Pointer", "Switch"},
  {"Duplicate", "Roll", "InNumber"},
  {"InChar", "OutNumber", "OutChar"}}

func (p *Piet) Step() bool {
  var commands = [][3]func(){
    {p.None, p.Push, p.Pop},
    {p.Add, p.Subtract, p.Multiply},
    {p.Divide, p.Mod, p.Not},
    {p.Greater, p.Pointer, p.Switch},
    {p.Duplicate, p.Roll, p.InNumber},
    {p.InChar, p.OutNumber, p.OutChar}}

  var sc = []Point{}
  p.CalculateArea(&sc, p.GetCodel(p.now), p.now)
  var edge, dest Point
  if p.GetCodel(p.now) == white {
    edge = p.now
    for a := AddPoints(edge, dr[p.DP]); p.IsMovableCodel(a) && p.GetCodel(a) == white; a = AddPoints(a, dr[p.DP]) {
      edge = a
    }
    dest = AddPoints(edge, dr[p.DP])
    if p.IsMovableCodel(dest) {
      p.from = edge
      p.now = dest
      return true
    }
  }
  p.area = int64(len(sc))

  // determine where to go
  for i := 0; i < 8; i++ {
    edge = p.GetEdge(sc)
    dest = AddPoints(edge, dr[p.DP])
    if p.IsMovableCodel(dest){
      break
    }
    if i % 2 == 0 {
      p.CC = !p.CC
    } else {
      p.DP = (p.DP + 1) % 4
    }
    if i == 7 {
      // end of the program
      return false
    }
  }

  if p.GetCodel(p.now) != white && p.GetCodel(dest) != white {
    dh := (p.GetCodel(dest)/3 - p.GetCodel(p.now)/3 + 30) % 6
    dl := (p.GetCodel(dest) - p.GetCodel(p.now) + 30) % 3
    if p.debug {
      fmt.Println(commandsstr[dh][dl])
    }
    commands[dh][dl]()
  }
  p.from = edge
  p.now = dest
  return true
}

func (p *Piet) GetEdge(sc []Point) Point {
  var rev bool = p.DP < 2
  var target bool = p.DP % 2 == 0
  sc = SortPointSlice(sc, target, rev)
  if (p.DP % 2 == 0) == p.CC {
    rev = !rev
  }

  var r int = 1

  for ; r < len(sc); r++ {
    if target {
      if sc[r].x != sc[0].x {
        break
      }
    } else {
      if sc[r].y != sc[0].y {
        break
      }
    }
  }
  target = !target

  xs := sc[r:]
  sc = append(SortPointSlice(sc[:r], target, rev), xs...)
  return sc[0]
}

func (p *Piet) CalculateArea(sc *[]Point, color int, offset Point) {
  *sc = append(*sc, offset)
  for _, d := range dr {
    target := AddPoints(offset, d)
    if p.IsMovableCodel(target) {
      if !contains(*sc, target) && color == p.GetCodel(target) {
        p.CalculateArea(sc, color, target)
      }
    }
  }
}

func (p *Piet) IsMovableCodel(point Point) bool {
  return all(
    point.x >= 0,
    point.x < p.width,
    point.y >= 0,
    point.y < p.height,
    p.GetCodel(point) != black)
}<commit_msg>slightly speed up<commit_after>package main

import (
  "fmt"
)

const (
  white = 18
  black = 19
)

func (p *Piet) Run() {
  var cont bool = true
  var dpstat = []string{"RIGHT", "DOWN", "LEFT", "UP"}
  var ccstat = []string{"LEFT", "RIGHT"}
  for i := 1; cont; i++ {
    if p.debug {
      fmt.Printf("step %04d : %s ; DP=%s, CC=%s\n", i, p.now.ToString(), dpstat[p.DP], ccstat[BoolToInt64(!p.CC)])
    }
    cont = p.Step()
    if p.debug {
      fmt.Println(p.stack)
    }
  }
  if p.debug {
    fmt.Println("Finished.")
  }
}

var dr = [...]Point{Point{1, 0}, Point{0, 1}, Point{-1, 0}, Point{0, -1}}

var commandsstr = [][3]string{
  {"None", "Push", "Pop"},
  {"Add", "Subtract", "Multiply"},
  {"Divide", "Mod", "Not"},
  {"Greater", "Pointer", "Switch"},
  {"Duplicate", "Roll", "InNumber"},
  {"InChar", "OutNumber", "OutChar"}}

func (p *Piet) Step() bool {
  var commands = [][3]func(){
    {p.None, p.Push, p.Pop},
    {p.Add, p.Subtract, p.Multiply},
    {p.Divide, p.Mod, p.Not},
    {p.Greater, p.Pointer, p.Switch},
    {p.Duplicate, p.Roll, p.InNumber},
    {p.InChar, p.OutNumber, p.OutChar}}

  var edge, dest Point
  if p.GetCodel(p.now) == white {
    edge = p.now
    for a := AddPoints(edge, dr[p.DP]); p.IsMovableCodel(a) && p.GetCodel(a) == white; a = AddPoints(a, dr[p.DP]) {
      edge = a
    }
    dest = AddPoints(edge, dr[p.DP])
    if p.IsMovableCodel(dest) {
      p.from = edge
      p.now = dest
      return true
    }
  }
  var sc = []Point{}
  p.CalculateArea(&sc, p.GetCodel(p.now), p.now)
  p.area = int64(len(sc))

  // determine where to go
  for i := 0; i < 8; i++ {
    edge = p.GetEdge(sc)
    dest = AddPoints(edge, dr[p.DP])
    if p.IsMovableCodel(dest){
      break
    }
    if i % 2 == 0 {
      p.CC = !p.CC
    } else {
      p.DP = (p.DP + 1) % 4
    }
    if i == 7 {
      // end of the program
      return false
    }
  }

  if p.GetCodel(p.now) != white && p.GetCodel(dest) != white {
    dh := (p.GetCodel(dest)/3 - p.GetCodel(p.now)/3 + 30) % 6
    dl := (p.GetCodel(dest) - p.GetCodel(p.now) + 30) % 3
    if p.debug {
      fmt.Println(commandsstr[dh][dl])
    }
    commands[dh][dl]()
  }
  p.from = edge
  p.now = dest
  return true
}

func (p *Piet) GetEdge(sc []Point) Point {
  var rev bool = p.DP < 2
  var target bool = p.DP % 2 == 0
  sc = SortPointSlice(sc, target, rev)
  if (p.DP % 2 == 0) == p.CC {
    rev = !rev
  }

  var r int = 1

  for ; r < len(sc); r++ {
    if target {
      if sc[r].x != sc[0].x {
        break
      }
    } else {
      if sc[r].y != sc[0].y {
        break
      }
    }
  }
  target = !target

  xs := sc[r:]
  sc = append(SortPointSlice(sc[:r], target, rev), xs...)
  return sc[0]
}

func (p *Piet) CalculateArea(sc *[]Point, color int, offset Point) {
  *sc = append(*sc, offset)
  for _, d := range dr {
    target := AddPoints(offset, d)
    if p.IsMovableCodel(target) {
      if !contains(*sc, target) && color == p.GetCodel(target) {
        p.CalculateArea(sc, color, target)
      }
    }
  }
}

func (p *Piet) IsMovableCodel(point Point) bool {
  return all(
    point.x >= 0,
    point.x < p.width,
    point.y >= 0,
    point.y < p.height,
    p.GetCodel(point) != black)
}<|endoftext|>


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

package math

// Sqrt returns the square root of x.
//
// Special cases are:
//	Sqrt(+Inf) = +Inf
//	Sqrt(±0) = ±0
//	Sqrt(x < 0) = NaN
//	Sqrt(NaN) = NaN
func Sqrt(x float64) float64

// The original C code and the long comment below are
// from FreeBSD's /usr/src/lib/msun/src/e_sqrt.c and
// came with this notice.  The go code is a simplified
// version of the original C.
//
// ====================================================
// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
//
// Developed at SunPro, a Sun Microsystems, Inc. business.
// Permission to use, copy, modify, and distribute this
// software is freely granted, provided that this notice
// is preserved.
// ====================================================
//
// __ieee754_sqrt(x)
// Return correctly rounded sqrt.
//           -----------------------------------------
//           | Use the hardware sqrt if you have one |
//           -----------------------------------------
// Method:
//   Bit by bit method using integer arithmetic. (Slow, but portable)
//   1. Normalization
//      Scale x to y in [1,4) with even powers of 2:
//      find an integer k such that  1 <= (y=x*2**(2k)) < 4, then
//              sqrt(x) = 2**k * sqrt(y)
//   2. Bit by bit computation
//      Let q  = sqrt(y) truncated to i bit after binary point (q = 1),
//           i                                                   0
//                                     i+1         2
//          s  = 2*q , and      y  =  2   * ( y - q  ).          (1)
//           i      i            i                 i
//
//      To compute q    from q , one checks whether
//                  i+1       i
//
//                            -(i+1) 2
//                      (q + 2      )  <= y.                     (2)
//                        i
//                                                            -(i+1)
//      If (2) is false, then q   = q ; otherwise q   = q  + 2      .
//                             i+1   i             i+1   i
//
//      With some algebraic manipulation, it is not difficult to see
//      that (2) is equivalent to
//                             -(i+1)
//                      s  +  2       <= y                       (3)
//                       i                i
//
//      The advantage of (3) is that s  and y  can be computed by
//                                    i      i
//      the following recurrence formula:
//          if (3) is false
//
//          s     =  s  ,       y    = y   ;                     (4)
//           i+1      i          i+1    i
//
//      otherwise,
//                         -i                      -(i+1)
//          s     =  s  + 2  ,  y    = y  -  s  - 2              (5)
//           i+1      i          i+1    i     i
//
//      One may easily use induction to prove (4) and (5).
//      Note. Since the left hand side of (3) contain only i+2 bits,
//            it does not necessary to do a full (53-bit) comparison
//            in (3).
//   3. Final rounding
//      After generating the 53 bits result, we compute one more bit.
//      Together with the remainder, we can decide whether the
//      result is exact, bigger than 1/2ulp, or less than 1/2ulp
//      (it will never equal to 1/2ulp).
//      The rounding mode can be detected by checking whether
//      huge + tiny is equal to huge, and whether huge - tiny is
//      equal to huge for some floating point number "huge" and "tiny".
//
//
// Notes:  Rounding mode detection omitted.  The constants "mask", "shift",
// and "bias" are found in src/pkg/math/bits.go

// Sqrt returns the square root of x.
//
// Special cases are:
//	Sqrt(+Inf) = +Inf
//	Sqrt(±0) = ±0
//	Sqrt(x < 0) = NaN
//	Sqrt(NaN) = NaN
func sqrt(x float64) float64 {
	// special cases
	switch {
	case x == 0 || IsNaN(x) || IsInf(x, 1):
		return x
	case x < 0:
		return NaN()
	}
	ix := Float64bits(x)
	// normalize x
	exp := int((ix >> shift) & mask)
	if exp == 0 { // subnormal x
		for ix&1<<shift == 0 {
			ix <<= 1
			exp--
		}
		exp++
	}
	exp -= bias // unbias exponent
	ix &^= mask << shift
	ix |= 1 << shift
	if exp&1 == 1 { // odd exp, double x to make it even
		ix <<= 1
	}
	exp >>= 1 // exp = exp/2, exponent of square root
	// generate sqrt(x) bit by bit
	ix <<= 1
	var q, s uint64               // q = sqrt(x)
	r := uint64(1 << (shift + 1)) // r = moving bit from MSB to LSB
	for r != 0 {
		t := s + r
		if t <= ix {
			s = t + r
			ix -= t
			q += r
		}
		ix <<= 1
		r >>= 1
	}
	// final rounding
	if ix != 0 { // remainder, result not exact
		q += q & 1 // round according to extra bit
	}
	ix = q>>1 + uint64(exp-1+bias)<<shift // significand + biased exponent
	return Float64frombits(ix)
}

func sqrtC(f float64, r *float64) {
	*r = sqrt(f)
}
<commit_msg>math: remove repeated comment.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package math

// The original C code and the long comment below are
// from FreeBSD's /usr/src/lib/msun/src/e_sqrt.c and
// came with this notice.  The go code is a simplified
// version of the original C.
//
// ====================================================
// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
//
// Developed at SunPro, a Sun Microsystems, Inc. business.
// Permission to use, copy, modify, and distribute this
// software is freely granted, provided that this notice
// is preserved.
// ====================================================
//
// __ieee754_sqrt(x)
// Return correctly rounded sqrt.
//           -----------------------------------------
//           | Use the hardware sqrt if you have one |
//           -----------------------------------------
// Method:
//   Bit by bit method using integer arithmetic. (Slow, but portable)
//   1. Normalization
//      Scale x to y in [1,4) with even powers of 2:
//      find an integer k such that  1 <= (y=x*2**(2k)) < 4, then
//              sqrt(x) = 2**k * sqrt(y)
//   2. Bit by bit computation
//      Let q  = sqrt(y) truncated to i bit after binary point (q = 1),
//           i                                                   0
//                                     i+1         2
//          s  = 2*q , and      y  =  2   * ( y - q  ).          (1)
//           i      i            i                 i
//
//      To compute q    from q , one checks whether
//                  i+1       i
//
//                            -(i+1) 2
//                      (q + 2      )  <= y.                     (2)
//                        i
//                                                            -(i+1)
//      If (2) is false, then q   = q ; otherwise q   = q  + 2      .
//                             i+1   i             i+1   i
//
//      With some algebraic manipulation, it is not difficult to see
//      that (2) is equivalent to
//                             -(i+1)
//                      s  +  2       <= y                       (3)
//                       i                i
//
//      The advantage of (3) is that s  and y  can be computed by
//                                    i      i
//      the following recurrence formula:
//          if (3) is false
//
//          s     =  s  ,       y    = y   ;                     (4)
//           i+1      i          i+1    i
//
//      otherwise,
//                         -i                      -(i+1)
//          s     =  s  + 2  ,  y    = y  -  s  - 2              (5)
//           i+1      i          i+1    i     i
//
//      One may easily use induction to prove (4) and (5).
//      Note. Since the left hand side of (3) contain only i+2 bits,
//            it does not necessary to do a full (53-bit) comparison
//            in (3).
//   3. Final rounding
//      After generating the 53 bits result, we compute one more bit.
//      Together with the remainder, we can decide whether the
//      result is exact, bigger than 1/2ulp, or less than 1/2ulp
//      (it will never equal to 1/2ulp).
//      The rounding mode can be detected by checking whether
//      huge + tiny is equal to huge, and whether huge - tiny is
//      equal to huge for some floating point number "huge" and "tiny".
//
//
// Notes:  Rounding mode detection omitted.  The constants "mask", "shift",
// and "bias" are found in src/pkg/math/bits.go

// Sqrt returns the square root of x.
//
// Special cases are:
//	Sqrt(+Inf) = +Inf
//	Sqrt(±0) = ±0
//	Sqrt(x < 0) = NaN
//	Sqrt(NaN) = NaN
func Sqrt(x float64) float64

func sqrt(x float64) float64 {
	// special cases
	switch {
	case x == 0 || IsNaN(x) || IsInf(x, 1):
		return x
	case x < 0:
		return NaN()
	}
	ix := Float64bits(x)
	// normalize x
	exp := int((ix >> shift) & mask)
	if exp == 0 { // subnormal x
		for ix&1<<shift == 0 {
			ix <<= 1
			exp--
		}
		exp++
	}
	exp -= bias // unbias exponent
	ix &^= mask << shift
	ix |= 1 << shift
	if exp&1 == 1 { // odd exp, double x to make it even
		ix <<= 1
	}
	exp >>= 1 // exp = exp/2, exponent of square root
	// generate sqrt(x) bit by bit
	ix <<= 1
	var q, s uint64               // q = sqrt(x)
	r := uint64(1 << (shift + 1)) // r = moving bit from MSB to LSB
	for r != 0 {
		t := s + r
		if t <= ix {
			s = t + r
			ix -= t
			q += r
		}
		ix <<= 1
		r >>= 1
	}
	// final rounding
	if ix != 0 { // remainder, result not exact
		q += q & 1 // round according to extra bit
	}
	ix = q>>1 + uint64(exp-1+bias)<<shift // significand + biased exponent
	return Float64frombits(ix)
}

func sqrtC(f float64, r *float64) {
	*r = sqrt(f)
}
<|endoftext|>


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

// Package sort provides primitives for sorting slices and user-defined
// collections.
package sort

import "math"

// A type, typically a collection, that satisfies sort.Interface can be
// sorted by the routines in this package.  The methods require that the
// elements of the collection be enumerated by an integer index.
type Interface interface {
	// Len is the number of elements in the collection.
	Len() int
	// Less returns whether the element with index i should sort
	// before the element with index j.
	Less(i, j int) bool
	// Swap swaps the elements with indexes i and j.
	Swap(i, j int)
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

// Insertion sort
func insertionSort(data Interface, a, b int) {
	for i := a + 1; i < b; i++ {
		for j := i; j > a && data.Less(j, j-1); j-- {
			data.Swap(j, j-1)
		}
	}
}

// siftDown implements the heap property on data[lo, hi).
// first is an offset into the array where the root of the heap lies.
func siftDown(data Interface, lo, hi, first int) {
	root := lo
	for {
		child := 2*root + 1
		if child >= hi {
			break
		}
		if child+1 < hi && data.Less(first+child, first+child+1) {
			child++
		}
		if !data.Less(first+root, first+child) {
			return
		}
		data.Swap(first+root, first+child)
		root = child
	}
}

func heapSort(data Interface, a, b int) {
	first := a
	lo := 0
	hi := b - a

	// Build heap with greatest element at top.
	for i := (hi - 1) / 2; i >= 0; i-- {
		siftDown(data, i, hi, first)
	}

	// Pop elements, largest first, into end of data.
	for i := hi - 1; i >= 0; i-- {
		data.Swap(first, first+i)
		siftDown(data, lo, i, first)
	}
}

// Quicksort, following Bentley and McIlroy,
// ``Engineering a Sort Function,'' SP&E November 1993.

// medianOfThree moves the median of the three values data[a], data[b], data[c] into data[a].
func medianOfThree(data Interface, a, b, c int) {
	m0 := b
	m1 := a
	m2 := c
	// bubble sort on 3 elements
	if data.Less(m1, m0) {
		data.Swap(m1, m0)
	}
	if data.Less(m2, m1) {
		data.Swap(m2, m1)
	}
	if data.Less(m1, m0) {
		data.Swap(m1, m0)
	}
	// now data[m0] <= data[m1] <= data[m2]
}

func swapRange(data Interface, a, b, n int) {
	for i := 0; i < n; i++ {
		data.Swap(a+i, b+i)
	}
}

func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
	m := lo + (hi-lo)/2 // Written like this to avoid integer overflow.
	if hi-lo > 40 {
		// Tukey's ``Ninther,'' median of three medians of three.
		s := (hi - lo) / 8
		medianOfThree(data, lo, lo+s, lo+2*s)
		medianOfThree(data, m, m-s, m+s)
		medianOfThree(data, hi-1, hi-1-s, hi-1-2*s)
	}
	medianOfThree(data, lo, m, hi-1)

	// Invariants are:
	//	data[lo] = pivot (set up by ChoosePivot)
	//	data[lo <= i < a] = pivot
	//	data[a <= i < b] < pivot
	//	data[b <= i < c] is unexamined
	//	data[c <= i < d] > pivot
	//	data[d <= i < hi] = pivot
	//
	// Once b meets c, can swap the "= pivot" sections
	// into the middle of the slice.
	pivot := lo
	a, b, c, d := lo+1, lo+1, hi, hi
	for b < c {
		if data.Less(b, pivot) { // data[b] < pivot
			b++
			continue
		}
		if !data.Less(pivot, b) { // data[b] = pivot
			data.Swap(a, b)
			a++
			b++
			continue
		}
		if data.Less(pivot, c-1) { // data[c-1] > pivot
			c--
			continue
		}
		if !data.Less(c-1, pivot) { // data[c-1] = pivot
			data.Swap(c-1, d-1)
			c--
			d--
			continue
		}
		// data[b] > pivot; data[c-1] < pivot
		data.Swap(b, c-1)
		b++
		c--
	}

	n := min(b-a, a-lo)
	swapRange(data, lo, b-n, n)

	n = min(hi-d, d-c)
	swapRange(data, c, hi-n, n)

	return lo + b - a, hi - (d - c)
}

func quickSort(data Interface, a, b, maxDepth int) {
	for b-a > 7 {
		if maxDepth == 0 {
			heapSort(data, a, b)
			return
		}
		maxDepth--
		mlo, mhi := doPivot(data, a, b)
		// Avoiding recursion on the larger subproblem guarantees
		// a stack depth of at most lg(b-a).
		if mlo-a < b-mhi {
			quickSort(data, a, mlo, maxDepth)
			a = mhi // i.e., quickSort(data, mhi, b)
		} else {
			quickSort(data, mhi, b, maxDepth)
			b = mlo // i.e., quickSort(data, a, mlo)
		}
	}
	if b-a > 1 {
		insertionSort(data, a, b)
	}
}

// Sort sorts data.
// The algorithm used is not guaranteed to be a stable sort.
func Sort(data Interface) {
	// Switch to heapsort if depth of 2*ceil(lg(n)) is reached.
	n := data.Len()
	maxDepth := 0
	for 1<<uint(maxDepth) < n {
		maxDepth++
	}
	maxDepth *= 2
	quickSort(data, 0, n, maxDepth)
}

// IsSorted reports whether data is sorted.
func IsSorted(data Interface) bool {
	n := data.Len()
	for i := n - 1; i > 0; i-- {
		if data.Less(i, i-1) {
			return false
		}
	}
	return true
}

// Convenience types for common cases

// IntSlice attaches the methods of Interface to []int, sorting in increasing order.
type IntSlice []int

func (p IntSlice) Len() int           { return len(p) }
func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p IntSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// Sort is a convenience method.
func (p IntSlice) Sort() { Sort(p) }

// Float64Slice attaches the methods of Interface to []float64, sorting in increasing order.
type Float64Slice []float64

func (p Float64Slice) Len() int           { return len(p) }
func (p Float64Slice) Less(i, j int) bool { return p[i] < p[j] || math.IsNaN(p[i]) && !math.IsNaN(p[j]) }
func (p Float64Slice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// Sort is a convenience method.
func (p Float64Slice) Sort() { Sort(p) }

// StringSlice attaches the methods of Interface to []string, sorting in increasing order.
type StringSlice []string

func (p StringSlice) Len() int           { return len(p) }
func (p StringSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p StringSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// Sort is a convenience method.
func (p StringSlice) Sort() { Sort(p) }

// Convenience wrappers for common cases

// Ints sorts a slice of ints in increasing order.
func Ints(a []int) { Sort(IntSlice(a)) }

// Float64s sorts a slice of float64s in increasing order.
func Float64s(a []float64) { Sort(Float64Slice(a)) }

// Strings sorts a slice of strings in increasing order.
func Strings(a []string) { Sort(StringSlice(a)) }

// IntsAreSorted tests whether a slice of ints is sorted in increasing order.
func IntsAreSorted(a []int) bool { return IsSorted(IntSlice(a)) }

// Float64sAreSorted tests whether a slice of float64s is sorted in increasing order.
func Float64sAreSorted(a []float64) bool { return IsSorted(Float64Slice(a)) }

// StringsAreSorted tests whether a slice of strings is sorted in increasing order.
func StringsAreSorted(a []string) bool { return IsSorted(StringSlice(a)) }
<commit_msg>sort: fix computation of maxDepth to avoid infinite loop<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package sort provides primitives for sorting slices and user-defined
// collections.
package sort

import "math"

// A type, typically a collection, that satisfies sort.Interface can be
// sorted by the routines in this package.  The methods require that the
// elements of the collection be enumerated by an integer index.
type Interface interface {
	// Len is the number of elements in the collection.
	Len() int
	// Less returns whether the element with index i should sort
	// before the element with index j.
	Less(i, j int) bool
	// Swap swaps the elements with indexes i and j.
	Swap(i, j int)
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

// Insertion sort
func insertionSort(data Interface, a, b int) {
	for i := a + 1; i < b; i++ {
		for j := i; j > a && data.Less(j, j-1); j-- {
			data.Swap(j, j-1)
		}
	}
}

// siftDown implements the heap property on data[lo, hi).
// first is an offset into the array where the root of the heap lies.
func siftDown(data Interface, lo, hi, first int) {
	root := lo
	for {
		child := 2*root + 1
		if child >= hi {
			break
		}
		if child+1 < hi && data.Less(first+child, first+child+1) {
			child++
		}
		if !data.Less(first+root, first+child) {
			return
		}
		data.Swap(first+root, first+child)
		root = child
	}
}

func heapSort(data Interface, a, b int) {
	first := a
	lo := 0
	hi := b - a

	// Build heap with greatest element at top.
	for i := (hi - 1) / 2; i >= 0; i-- {
		siftDown(data, i, hi, first)
	}

	// Pop elements, largest first, into end of data.
	for i := hi - 1; i >= 0; i-- {
		data.Swap(first, first+i)
		siftDown(data, lo, i, first)
	}
}

// Quicksort, following Bentley and McIlroy,
// ``Engineering a Sort Function,'' SP&E November 1993.

// medianOfThree moves the median of the three values data[a], data[b], data[c] into data[a].
func medianOfThree(data Interface, a, b, c int) {
	m0 := b
	m1 := a
	m2 := c
	// bubble sort on 3 elements
	if data.Less(m1, m0) {
		data.Swap(m1, m0)
	}
	if data.Less(m2, m1) {
		data.Swap(m2, m1)
	}
	if data.Less(m1, m0) {
		data.Swap(m1, m0)
	}
	// now data[m0] <= data[m1] <= data[m2]
}

func swapRange(data Interface, a, b, n int) {
	for i := 0; i < n; i++ {
		data.Swap(a+i, b+i)
	}
}

func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
	m := lo + (hi-lo)/2 // Written like this to avoid integer overflow.
	if hi-lo > 40 {
		// Tukey's ``Ninther,'' median of three medians of three.
		s := (hi - lo) / 8
		medianOfThree(data, lo, lo+s, lo+2*s)
		medianOfThree(data, m, m-s, m+s)
		medianOfThree(data, hi-1, hi-1-s, hi-1-2*s)
	}
	medianOfThree(data, lo, m, hi-1)

	// Invariants are:
	//	data[lo] = pivot (set up by ChoosePivot)
	//	data[lo <= i < a] = pivot
	//	data[a <= i < b] < pivot
	//	data[b <= i < c] is unexamined
	//	data[c <= i < d] > pivot
	//	data[d <= i < hi] = pivot
	//
	// Once b meets c, can swap the "= pivot" sections
	// into the middle of the slice.
	pivot := lo
	a, b, c, d := lo+1, lo+1, hi, hi
	for b < c {
		if data.Less(b, pivot) { // data[b] < pivot
			b++
			continue
		}
		if !data.Less(pivot, b) { // data[b] = pivot
			data.Swap(a, b)
			a++
			b++
			continue
		}
		if data.Less(pivot, c-1) { // data[c-1] > pivot
			c--
			continue
		}
		if !data.Less(c-1, pivot) { // data[c-1] = pivot
			data.Swap(c-1, d-1)
			c--
			d--
			continue
		}
		// data[b] > pivot; data[c-1] < pivot
		data.Swap(b, c-1)
		b++
		c--
	}

	n := min(b-a, a-lo)
	swapRange(data, lo, b-n, n)

	n = min(hi-d, d-c)
	swapRange(data, c, hi-n, n)

	return lo + b - a, hi - (d - c)
}

func quickSort(data Interface, a, b, maxDepth int) {
	for b-a > 7 {
		if maxDepth == 0 {
			heapSort(data, a, b)
			return
		}
		maxDepth--
		mlo, mhi := doPivot(data, a, b)
		// Avoiding recursion on the larger subproblem guarantees
		// a stack depth of at most lg(b-a).
		if mlo-a < b-mhi {
			quickSort(data, a, mlo, maxDepth)
			a = mhi // i.e., quickSort(data, mhi, b)
		} else {
			quickSort(data, mhi, b, maxDepth)
			b = mlo // i.e., quickSort(data, a, mlo)
		}
	}
	if b-a > 1 {
		insertionSort(data, a, b)
	}
}

// Sort sorts data.
// The algorithm used is not guaranteed to be a stable sort.
func Sort(data Interface) {
	// Switch to heapsort if depth of 2*ceil(lg(n+1)) is reached.
	n := data.Len()
	maxDepth := 0
	for i := n; i > 0; i >>= 1 {
		maxDepth++
	}
	maxDepth *= 2
	quickSort(data, 0, n, maxDepth)
}

// IsSorted reports whether data is sorted.
func IsSorted(data Interface) bool {
	n := data.Len()
	for i := n - 1; i > 0; i-- {
		if data.Less(i, i-1) {
			return false
		}
	}
	return true
}

// Convenience types for common cases

// IntSlice attaches the methods of Interface to []int, sorting in increasing order.
type IntSlice []int

func (p IntSlice) Len() int           { return len(p) }
func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p IntSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// Sort is a convenience method.
func (p IntSlice) Sort() { Sort(p) }

// Float64Slice attaches the methods of Interface to []float64, sorting in increasing order.
type Float64Slice []float64

func (p Float64Slice) Len() int           { return len(p) }
func (p Float64Slice) Less(i, j int) bool { return p[i] < p[j] || math.IsNaN(p[i]) && !math.IsNaN(p[j]) }
func (p Float64Slice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// Sort is a convenience method.
func (p Float64Slice) Sort() { Sort(p) }

// StringSlice attaches the methods of Interface to []string, sorting in increasing order.
type StringSlice []string

func (p StringSlice) Len() int           { return len(p) }
func (p StringSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p StringSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// Sort is a convenience method.
func (p StringSlice) Sort() { Sort(p) }

// Convenience wrappers for common cases

// Ints sorts a slice of ints in increasing order.
func Ints(a []int) { Sort(IntSlice(a)) }

// Float64s sorts a slice of float64s in increasing order.
func Float64s(a []float64) { Sort(Float64Slice(a)) }

// Strings sorts a slice of strings in increasing order.
func Strings(a []string) { Sort(StringSlice(a)) }

// IntsAreSorted tests whether a slice of ints is sorted in increasing order.
func IntsAreSorted(a []int) bool { return IsSorted(IntSlice(a)) }

// Float64sAreSorted tests whether a slice of float64s is sorted in increasing order.
func Float64sAreSorted(a []float64) bool { return IsSorted(Float64Slice(a)) }

// StringsAreSorted tests whether a slice of strings is sorted in increasing order.
func StringsAreSorted(a []string) bool { return IsSorted(StringSlice(a)) }
<|endoftext|>


<commit_before>package primes

import (
	"sort"
)

// A natural number
type Number uint64

var PRIMES_100 []Number = []Number {
	2, 3, 5, 7, 11, 13, 17, 19, 23,
	29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
	71, 73, 79, 83, 89, 97, 101}

// Finds prime numbers below N
// Returns primes split in blocks for its convenience, they are sorted
func FindPrimes(N Number) (results [][]Number) {

	// fmt.Println("findNonPrimes(", N, nonPrimes, ")")
	// defer func() {
	// 	fmt.Println("    nonPrimes", nonPrimes)
	// }()

	// Primes below 100 are hard coded:
	if N <= 100 {
		var i int
		for PRIMES_100[i] < N { i++ }
		results = [][]Number{PRIMES_100[:i]}
		return
	}

	// Recursively finds non-primes below or equal to sqrt(N)
	n := (N.sqrt() + 1)
	results = FindPrimes(n)

	if n < 1000 {

		// Fills serially the buffer of non primes:
		primes := findPrimesInRange(n, N, results)
		if len(primes) > 0 {
			results = append(results, primes)
		}

	} else {
		// Fills on parallel the buffer of non primes:
		numResults := Number(len(results))
		newResults := make(chan []Number)
		numRoutines := 0
		for x := n; x < N; x += n {
			go func(x Number) {
				newResults <- findPrimesInRange(x, (x + n).min(N), results)
			}(x)
			numRoutines++
		}
		for i := 0; i < numRoutines; i++ {
			primes := <-newResults
			if len(primes) > 0 {
				results = append(results, primes)
			}
		}

		// Sorts only new results:
		sort.Sort(ByFirst(results[numResults:]))
	}

	return
}

// Finds prime numbers in the range [x0, x1) given all primes that are <= sqrt(x0)
func findPrimesInRange(x0, x1 Number, primes [][]Number) (newPrimes []Number) {

	// fmt.Println("findPrimesFrom", x0, x1, primes)
	// defer func() {
	//   	fmt.Println("    newPrimes", newPrimes)
	// }()

	flags := make([]bool, x1-x0)
	// numPrimes := len(flags)

	for _, primeGroup := range primes {
		for _, prime := range primeGroup {
			for i := int(x0.alignUp(prime) - x0); i < len(flags); i += int(prime) {
				flags[i] = true
				/*
				if !flags[i] {
					flags[i] = true
					numPrimes--
				}
				*/
			}
		}
	}
	// fmt.Println("    flags", flags)

	// Collects new prime numbers:
	estimatedNumPrimes := (x1 - x0) / (x1-x0).log10().max(1)
	newPrimes = make([]Number, 0, estimatedNumPrimes) // , numPrimes)
	for i, hasDividends := range flags {
		if !hasDividends {
			newPrimes = append(newPrimes, x0 + Number(i))
		}
	}

	return
}

// Returns the squared root of a number strictly positive
func (x Number) sqrt() (y Number) {

	for y = 1; y*y <= x; y++ {
	}
	y--

	return
}

// Aligns x to the closest multiple of k that is less or equal to x
func (x Number) align(k Number) (y Number) {
	y = x - (x % k)
	return
}

// Aligns x to the closest multiple of k that is greater or equal to x.
// k must be > 1
func (x Number) alignUp(k Number) (y Number) {
	x += (k - 1)
	y = x.align(k)
	return
}

// Min function
func (a Number) min(b Number) (y Number) {
	if a < b {
		y = a
	} else {
		y = b
	}
	return
}

// Max function
func (a Number) max(b Number) (y Number) {
	if a < b {
		y = b
	} else {
		y = a
	}
	return
}

func (x Number) isDerivedBy(k Number) bool {
	return x%k == 0
}

// Returns the 10 logarithm of x
func (x Number) log10() (y Number) {
	z := Number(10)
	for z <= x {
		z *= 10
		y += 1
	}
	return
}

// Used to sort result blocks using the first element
type ByFirst [][]Number

func (p ByFirst) Len() int           { return len(p) }
func (p ByFirst) Less(i, j int) bool { return p[i][0] < p[j][0] }
func (p ByFirst) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
<commit_msg>Improve algorithm<commit_after>package primes

import (
	"sort"
)

// A natural number
type Number uint64

var PRIMES_100 []Number = []Number {
	2, 3, 5, 7, 11, 13, 17, 19, 23,
	29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
	71, 73, 79, 83, 89, 97, 101}

// Finds prime numbers below N
// Returns primes split in blocks for its convenience, they are sorted
func FindPrimes(N Number) (results [][]Number) {

	// fmt.Println("findNonPrimes(", N, nonPrimes, ")")
	// defer func() {
	// 	fmt.Println("    nonPrimes", nonPrimes)
	// }()

	// Primes below 100 are hard coded:
	if N <= 100 {
		var i int
		for PRIMES_100[i] < N { i++ }
		results = [][]Number{PRIMES_100[:i]}
		return
	}

	// Recursively finds non-primes below or equal to sqrt(N)
	n := (N.sqrt() + 1)
	results = FindPrimes(n)

	if n < 1000 {

		// Fills serially the buffer of non primes:
		primes := findPrimesInRange(n, N, results)
		if len(primes) > 0 {
			results = append(results, primes)
		}

	} else {
		// Fills on parallel the buffer of non primes:
		numResults := Number(len(results))
		newResults := make(chan []Number)
		numRoutines := 0
		for x := n; x < N; x += n {
			go func(x Number) {
				newResults <- findPrimesInRange(x, (x + n).min(N), results)
			}(x)
			numRoutines++
		}
		for i := 0; i < numRoutines; i++ {
			primes := <-newResults
			if len(primes) > 0 {
				results = append(results, primes)
			}
		}

		// Sorts only new results:
		sort.Sort(ByFirst(results[numResults:]))
	}

	return
}

// Finds prime numbers in the range [x0, x1) given all primes that are <= sqrt(x0)
func findPrimesInRange(x0, x1 Number, primes [][]Number) (newPrimes []Number) {

	// fmt.Println("findPrimesFrom", x0, x1, primes)
	// defer func() {
	//   	fmt.Println("    newPrimes", newPrimes)
	// }()

	flags := make([]bool, x1-x0)

	for _, primeGroup := range primes {
		for _, prime := range primeGroup {
			for i := int(x0.alignUp(prime) - x0); i < len(flags); i += int(prime) {
				flags[i] = true
			}
		}
	}

	// Collects new prime numbers:
	estimatedNumPrimes := (x1 - x0) / (x1-x0).log10().max(1)
	newPrimes = make([]Number, 0, estimatedNumPrimes) // , numPrimes)
	for i, hasDividends := range flags {
		if !hasDividends {
			newPrimes = append(newPrimes, x0 + Number(i))
		}
	}

	return
}

// Returns the squared root of a number strictly positive
func (x Number) sqrt() (y Number) {

	for y = 1; y*y <= x; y++ {
	}
	y--

	return
}

// Aligns x to the closest multiple of k that is less or equal to x
func (x Number) align(k Number) (y Number) {
	y = x - (x % k)
	return
}

// Aligns x to the closest multiple of k that is greater or equal to x.
// k must be > 1
func (x Number) alignUp(k Number) (y Number) {
	x += (k - 1)
	y = x.align(k)
	return
}

// Min function
func (a Number) min(b Number) (y Number) {
	if a < b {
		y = a
	} else {
		y = b
	}
	return
}

// Max function
func (a Number) max(b Number) (y Number) {
	if a < b {
		y = b
	} else {
		y = a
	}
	return
}

func (x Number) isDerivedBy(k Number) bool {
	return x%k == 0
}

// Returns the 10 logarithm of x
func (x Number) log10() (y Number) {
	z := Number(10)
	for z <= x {
		z *= 10
		y += 1
	}
	return
}

// Used to sort result blocks using the first element
type ByFirst [][]Number

func (p ByFirst) Len() int           { return len(p) }
func (p ByFirst) Less(i, j int) bool { return p[i][0] < p[j][0] }
func (p ByFirst) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
<|endoftext|>


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

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file implements Json<->Lisp conversions using frames.

package golisp

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

func JsonToLispWithFrames(json interface{}) (result *Data) {
	mapValue, ok := json.(map[string]interface{})
	if ok {
		m := FrameMap{}
		m.Data = make(FrameMapData, len(mapValue))
		for key, val := range mapValue {
			value := JsonToLispWithFrames(val)
			m.Data[fmt.Sprintf("%s:", key)] = value
		}
		return FrameWithValue(&m)
	}

	arrayValue, ok := json.([]interface{})
	if ok {
		var ary *Data
		for _, val := range arrayValue {
			value := JsonToLispWithFrames(val)
			ary = Cons(value, ary)
		}
		return Reverse(ary)
	}

	numValue, ok := json.(float64)
	if ok {
		if math.Trunc(numValue) == numValue {
			return IntegerWithValue(int64(numValue))
		} else {
			return FloatWithValue(float32(numValue))
		}
	}

	floatValue, ok := json.(float64)
	if ok {
		if math.Mod(floatValue, 1) == 0 {
			return IntegerWithValue(int64(floatValue))
		} else {
			return FloatWithValue(float32(floatValue))
		}
	}

	strValue, ok := json.(string)
	if ok {
		return StringWithValue(strValue)
	}

	boolValue, ok := json.(bool)
	if ok {
		return BooleanWithValue(boolValue)
	}

	return
}

func JsonStringToLispWithFrames(jsonData string) (result *Data) {
	b := []byte(jsonData)
	var data interface{}
	err := json.Unmarshal(b, &data)
	if err != nil {
		fmt.Printf("Returning empty frame because of badly formed json: '%s'\n --> %v\n", jsonData, err)
		m := FrameMap{}
		m.Data = make(FrameMapData, 0)
		return FrameWithValue(&m)
	}
	return JsonToLispWithFrames(data)
}

func LispWithFramesToJson(d *Data) (result interface{}) {
	if d == nil {
		return ""
	}

	if IntegerP(d) {
		return IntegerValue(d)
	}

	if FloatP(d) {
		return FloatValue(d)
	}

	if StringP(d) || SymbolP(d) {
		return StringValue(d)
	}

	if BooleanP(d) {
		return BooleanValue(d)
	}

	if PairP(d) {
		ary := make([]interface{}, 0, Length(d))
		for c := d; NotNilP(c); c = Cdr(c) {
			ary = append(ary, LispWithFramesToJson(Car(c)))
		}
		return ary
	}

	if FrameP(d) {
		dict := make(map[string]interface{}, Length(d))
		frame := FrameValue(d)
		frame.Mutex.RLock()
		for k, v := range frame.Data {
			if !FunctionP(v) {
				dict[strings.TrimRight(k, ":")] = LispWithFramesToJson(v)
			}
		}
		frame.Mutex.RUnlock()
		return dict
	}

	return ""
}

func LispWithFramesToJsonString(d *Data) (result string) {
	temp := LispWithFramesToJson(d)
	j, err := json.Marshal(temp)
	if err == nil {
		return string(j)
	} else {
		return ""
	}
}
<commit_msg>support marshalling bytearrays to arrays of numbers in json<commit_after>// Copyright 2014 SteelSeries ApS.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file implements Json<->Lisp conversions using frames.

package golisp

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

func JsonToLispWithFrames(json interface{}) (result *Data) {
	mapValue, ok := json.(map[string]interface{})
	if ok {
		m := FrameMap{}
		m.Data = make(FrameMapData, len(mapValue))
		for key, val := range mapValue {
			value := JsonToLispWithFrames(val)
			m.Data[fmt.Sprintf("%s:", key)] = value
		}
		return FrameWithValue(&m)
	}

	arrayValue, ok := json.([]interface{})
	if ok {
		var ary *Data
		for _, val := range arrayValue {
			value := JsonToLispWithFrames(val)
			ary = Cons(value, ary)
		}
		return Reverse(ary)
	}

	numValue, ok := json.(float64)
	if ok {
		if math.Trunc(numValue) == numValue {
			return IntegerWithValue(int64(numValue))
		} else {
			return FloatWithValue(float32(numValue))
		}
	}

	floatValue, ok := json.(float64)
	if ok {
		if math.Mod(floatValue, 1) == 0 {
			return IntegerWithValue(int64(floatValue))
		} else {
			return FloatWithValue(float32(floatValue))
		}
	}

	strValue, ok := json.(string)
	if ok {
		return StringWithValue(strValue)
	}

	boolValue, ok := json.(bool)
	if ok {
		return BooleanWithValue(boolValue)
	}

	return
}

func JsonStringToLispWithFrames(jsonData string) (result *Data) {
	b := []byte(jsonData)
	var data interface{}
	err := json.Unmarshal(b, &data)
	if err != nil {
		fmt.Printf("Returning empty frame because of badly formed json: '%s'\n --> %v\n", jsonData, err)
		m := FrameMap{}
		m.Data = make(FrameMapData, 0)
		return FrameWithValue(&m)
	}
	return JsonToLispWithFrames(data)
}

func LispWithFramesToJson(d *Data) (result interface{}) {
	if d == nil {
		return ""
	}

	if IntegerP(d) {
		return IntegerValue(d)
	}

	if FloatP(d) {
		return FloatValue(d)
	}

	if StringP(d) || SymbolP(d) {
		return StringValue(d)
	}

	if BooleanP(d) {
		return BooleanValue(d)
	}

	if PairP(d) {
		ary := make([]interface{}, 0, Length(d))
		for c := d; NotNilP(c); c = Cdr(c) {
			ary = append(ary, LispWithFramesToJson(Car(c)))
		}
		return ary
	}

	if ObjectP(d) && ObjectType(d) == "[]byte" {
		ary := make([]interface{}, 0, Length(d))
		for _, b := range *(*[]byte)(ObjectValue(d)) {
			ary = append(ary, b)
		}
		return ary
	}

	if FrameP(d) {
		dict := make(map[string]interface{}, Length(d))
		frame := FrameValue(d)
		frame.Mutex.RLock()
		for k, v := range frame.Data {
			if !FunctionP(v) {
				dict[strings.TrimRight(k, ":")] = LispWithFramesToJson(v)
			}
		}
		frame.Mutex.RUnlock()
		return dict
	}

	return ""
}

func LispWithFramesToJsonString(d *Data) (result string) {
	temp := LispWithFramesToJson(d)
	j, err := json.Marshal(temp)
	if err == nil {
		return string(j)
	} else {
		return ""
	}
}
<|endoftext|>


<commit_before>package iterkernel

// KernelNext is responsible for loading the next value for the iterator.
//
// It is the partner of the Next method found in common iterators:
//
//	Next() bool
//
// (KernelNext does all the "book keeping" for a Next method.)
//
// Like Next, KernelNext will return true if there is a next value,
// and will return false is there is not a next value.
//
// Also, like Next, KernelNext returning false could be because of two different reasons.
//
// #1 because there are no more values in the iterator.
//
// Or #2 because an error occurred while trying to obain the next value.
//
// (KernelErr needs to be called to determine which was the case.)
//
// The parameter passed to KernelNext is a func with the signature:
//
//	func(int, interface{}) (bool, error)
//
// This func is what actually (potentially) gives KernelNext the next value.
//
// KernelNext calls this func, and passes it #1 the iteration number
// (which starts counting a zero), and #2 a pointer to where the func
// should store the next value.
//
// If the func loaded a next value successfully, then it should return like the following:
//
//	return true, nil
//
// If an error occurred while the func was trying to load a next value, then it should return like the following:
//
//	return false, err
//
// If there is no next value (and no errors occurred) then it should return like the following:
//
//	return false, nil
//
func (receiver *Kernel) KernelNext(fn func(int,interface{})(bool, error)) bool {
	if nil == receiver {
		return false
	}

	receiver.mutex.Lock()
	defer receiver.mutex.Unlock()

	if nil != receiver.err {
		return false
	}

	if receiver.closed {
		return false
	}

	index := receiver.index

	var datum interface{}

	next, err := fn(index, &datum)
	if nil != err {
		receiver.err = err
		return false
	}
	if !next {
		return false
	}

	receiver.datum = datum
	receiver.index++

	return true
}
<commit_msg>added more docs<commit_after>package iterkernel

// KernelNext is responsible for loading the next value for the iterator.
//
// It is the partner of the Next method found in common iterators:
//
//	Next() bool
//
// (KernelNext does all the "book keeping" for a Next method.)
//
// Like Next, KernelNext will return true if there is a next value,
// and will return false is there is not a next value.
//
// Also, like Next, KernelNext returning false could be because of two different reasons.
//
// #1 because there are no more values in the iterator.
//
// Or #2 because an error occurred while trying to obain the next value.
//
// (KernelErr needs to be called to determine which was the case.)
//
// The parameter passed to KernelNext is a func with the signature:
//
//	func(int, interface{}) (bool, error)
//
// This func is what actually (potentially) gives KernelNext the next value.
//
// KernelNext calls this func, and passes it #1 the iteration number
// (which starts counting a zero), and #2 a pointer to where the func
// should store the next value.
//
// If the func loaded a next value successfully, then it should return like the following:
//
//	return true, nil
//
// If an error occurred while the func was trying to load a next value, then it should return like the following:
//
//	return false, err
//
// If there is no next value (and no errors occurred) then it should return like the following:
//
//	return false, nil
//
// An example func might look like:
//
//	func (iterationNumber int, v interface{}) (bool, error) {
//		if 10 < index {
//			return false, nil
//		}
//
//		x := float64(index)
//
//		datum := x*x
//
//		p, ok := v.(*interface{})
//		if !ok {
//			return false, errInternalError
//		}
//
//		*p = datum
//
//		return true, nil
//	}
//
// That example would produce the sequence: 0.0, 1.0, 4.0, 9,0, 25,0, 36.0, 49.0, 64.0, 81.0.
func (receiver *Kernel) KernelNext(fn func(int,interface{})(bool, error)) bool {
	if nil == receiver {
		return false
	}

	receiver.mutex.Lock()
	defer receiver.mutex.Unlock()

	if nil != receiver.err {
		return false
	}

	if receiver.closed {
		return false
	}

	index := receiver.index

	var datum interface{}

	next, err := fn(index, &datum)
	if nil != err {
		receiver.err = err
		return false
	}
	if !next {
		return false
	}

	receiver.datum = datum
	receiver.index++

	return true
}
<|endoftext|>


<commit_before>package forest

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"io/ioutil"
	"net/http"
)

var verboseOnFailure = false

// VerboseOnFailure (default is false) will produce more information about the request and response when a failure is detected on an expectation.
// This setting is not the same but related to the value of testing.Verbose().
func VerboseOnFailure(verbose bool) {
	verboseOnFailure = verbose
}

// ExpectStatus inspects the response status code.
// If the value is not expected, the complete request, response is logged (iff verboseOnFailure) and the test is aborted.
// Return true if the status is as expected.
func ExpectStatus(t T, r *http.Response, status int) bool {
	if r == nil {
		logerror(t, serrorf("ExpectStatus: got nil but want Http response"))
		return false
	}
	if r.StatusCode != status {
		if verboseOnFailure {
			Dump(t, r)
		}
		logfatal(t, serrorf("ExpectStatus: got status %d but want %d, %s %v", r.StatusCode, status, r.Request.Method, r.Request.URL))
		return false
	}
	return true
}

// CheckError simply tests the error and fail is not undefined.
// This is implicity called after sending a Http request.
// Return true if there was an error.
func CheckError(t T, err error) bool {
	if err != nil {
		logerror(t, serrorf("CheckError: did not expect to receive err: %v", err))
	}
	return err != nil
}

// ExpectHeader inspects the header of the response.
// Return true if the header matches.
func ExpectHeader(t T, r *http.Response, name, value string) bool {
	if r == nil {
		logerror(t, serrorf("ExpectHeader: got nil but want a Http response"))
		return false
	}
	rname := r.Header.Get(name)
	if rname != value {
		logerror(t, serrorf("ExpectHeader: got header %s=%s but want %s", name, rname, value))
	}
	return rname == value
}

// ExpectJSONHash tries to unmarshal the response body into a Go map callback parameter.
// Fail if the body could not be read or if unmarshalling was not possible.
// Returns true if the callback was executed with a map.
func ExpectJSONHash(t T, r *http.Response, callback func(hash map[string]interface{})) bool {
	if r == nil {
		logerror(t, serrorf("ExpectJSONHash: no response available"))
		return false
	}
	if r.Body == nil {
		logerror(t, serrorf("ExpectJSONHash: no body to read"))
		return false
	}
	data, err := ioutil.ReadAll(r.Body)
	defer r.Body.Close()
	if err != nil {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectJSONHash: unable to read response body:%v", err))
		return false
	}
	// put the body back for re-reads
	r.Body = ioutil.NopCloser(bytes.NewReader(data))

	dict := map[string]interface{}{}
	err = json.Unmarshal(data, &dict)
	if err != nil {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectJSONHash: unable to unmarshal Json:%v", err))
		return false
	}
	callback(dict)
	return true
}

// ExpectJSONArray tries to unmarshal the response body into a Go slice callback parameter.
// Fail if the body could not be read or if unmarshalling was not possible.
// Returns true if the callback was executed with an array.
func ExpectJSONArray(t T, r *http.Response, callback func(array []interface{})) bool {
	if r == nil {
		logerror(t, serrorf("ExpectJSONArray: no response available"))
		return false
	}
	if r.Body == nil {
		logerror(t, serrorf("ExpectJSONArray: no body to read"))
		return false
	}
	data, err := ioutil.ReadAll(r.Body)
	defer r.Body.Close()
	if err != nil {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectJSONArray: unable to read response body:%v", err))
		return false
	}
	// put the body back for re-reads
	r.Body = ioutil.NopCloser(bytes.NewReader(data))

	slice := []interface{}{}
	err = json.Unmarshal(data, &slice)
	if err != nil {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectJSONArray: unable to unmarshal Json:%v", err))
		return false
	}
	callback(slice)
	return true
}

// ExpectString reads the response body into a Go string callback parameter.
// Fail if the body could not be read or unmarshalled.
// Returns true if a response body was read.
func ExpectString(t T, r *http.Response, callback func(content string)) bool {
	if r == nil {
		logerror(t, serrorf("ExpectString: no response available"))
		return false
	}
	if r.Body == nil {
		logerror(t, serrorf("ExpectString: no body to read"))
		return false
	}
	data, err := ioutil.ReadAll(r.Body)
	defer r.Body.Close()
	if err != nil {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectString: unable to read response body:%v", err))
		return false
	}
	// put the body back for re-reads
	r.Body = ioutil.NopCloser(bytes.NewReader(data))

	callback(string(data))
	return true
}

// ExpectXMLDocument tries to unmarshal the response body into fields of the provided document (struct).
// Fail if the body could not be read or unmarshalled.
// Returns true if a document could be unmarshalled.
func ExpectXMLDocument(t T, r *http.Response, doc interface{}) bool {
	if r == nil {
		logerror(t, serrorf("ExpectXMLDocument: no response available"))
		return false
	}
	if r.Body == nil {
		logerror(t, serrorf("ExpectXMLDocument: no body to read"))
		return false
	}
	data, err := ioutil.ReadAll(r.Body)
	defer r.Body.Close()
	if err != nil {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectXMLDocument: unable to read response body:%v", err))
		return false
	}
	// put the body back for re-reads
	r.Body = ioutil.NopCloser(bytes.NewReader(data))

	err = xml.Unmarshal(data, doc)
	if err != nil {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectXMLDocument: unable to unmarshal Xml:%v", err))
	}
	return err == nil
}

// ExpectJSONDocument tries to unmarshal the response body into fields of the provided document (struct).
// Fail if the body could not be read or unmarshalled.
// Returns true if a document could be unmarshalled.
func ExpectJSONDocument(t T, r *http.Response, doc interface{}) bool {
	if r == nil {
		logerror(t, serrorf("ExpectJSONDocument: no response available"))
		return false
	}
	if r.Body == nil {
		logerror(t, serrorf("ExpectJSONDocument: no body to read"))
		return false
	}
	data, err := ioutil.ReadAll(r.Body)
	defer r.Body.Close()
	if err != nil {
		logerror(t, serrorf("ExpectJSONDocument: unable to read response body :%v", err))
		return false
	}
	// put the body back for re-reads
	r.Body = ioutil.NopCloser(bytes.NewReader(data))

	err = json.Unmarshal(data, doc)
	if err != nil {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectJSONDocument: unable to unmarshal Json:%v", err))
	}
	return err == nil
}
<commit_msg>expect status no longer fatals<commit_after>package forest

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"io/ioutil"
	"net/http"
)

var verboseOnFailure = false

// VerboseOnFailure (default is false) will produce more information about the request and response when a failure is detected on an expectation.
// This setting is not the same but related to the value of testing.Verbose().
func VerboseOnFailure(verbose bool) {
	verboseOnFailure = verbose
}

// ExpectStatus inspects the response status code.
// If the value is not expected, the complete request, response is logged (iff verboseOnFailure) and the test is aborted.
// Return true if the status is as expected.
func ExpectStatus(t T, r *http.Response, status int) bool {
	if r == nil {
		logerror(t, serrorf("ExpectStatus: got nil but want Http response"))
		return false
	}
	if r.StatusCode != status {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectStatus: got status %d but want %d, %s %v", r.StatusCode, status, r.Request.Method, r.Request.URL))
		return false
	}
	return true
}

// CheckError simply tests the error and fail is not undefined.
// This is implicity called after sending a Http request.
// Return true if there was an error.
func CheckError(t T, err error) bool {
	if err != nil {
		logerror(t, serrorf("CheckError: did not expect to receive err: %v", err))
	}
	return err != nil
}

// ExpectHeader inspects the header of the response.
// Return true if the header matches.
func ExpectHeader(t T, r *http.Response, name, value string) bool {
	if r == nil {
		logerror(t, serrorf("ExpectHeader: got nil but want a Http response"))
		return false
	}
	rname := r.Header.Get(name)
	if rname != value {
		logerror(t, serrorf("ExpectHeader: got header %s=%s but want %s", name, rname, value))
	}
	return rname == value
}

// ExpectJSONHash tries to unmarshal the response body into a Go map callback parameter.
// Fail if the body could not be read or if unmarshalling was not possible.
// Returns true if the callback was executed with a map.
func ExpectJSONHash(t T, r *http.Response, callback func(hash map[string]interface{})) bool {
	if r == nil {
		logerror(t, serrorf("ExpectJSONHash: no response available"))
		return false
	}
	if r.Body == nil {
		logerror(t, serrorf("ExpectJSONHash: no body to read"))
		return false
	}
	data, err := ioutil.ReadAll(r.Body)
	defer r.Body.Close()
	if err != nil {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectJSONHash: unable to read response body:%v", err))
		return false
	}
	// put the body back for re-reads
	r.Body = ioutil.NopCloser(bytes.NewReader(data))

	dict := map[string]interface{}{}
	err = json.Unmarshal(data, &dict)
	if err != nil {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectJSONHash: unable to unmarshal Json:%v", err))
		return false
	}
	callback(dict)
	return true
}

// ExpectJSONArray tries to unmarshal the response body into a Go slice callback parameter.
// Fail if the body could not be read or if unmarshalling was not possible.
// Returns true if the callback was executed with an array.
func ExpectJSONArray(t T, r *http.Response, callback func(array []interface{})) bool {
	if r == nil {
		logerror(t, serrorf("ExpectJSONArray: no response available"))
		return false
	}
	if r.Body == nil {
		logerror(t, serrorf("ExpectJSONArray: no body to read"))
		return false
	}
	data, err := ioutil.ReadAll(r.Body)
	defer r.Body.Close()
	if err != nil {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectJSONArray: unable to read response body:%v", err))
		return false
	}
	// put the body back for re-reads
	r.Body = ioutil.NopCloser(bytes.NewReader(data))

	slice := []interface{}{}
	err = json.Unmarshal(data, &slice)
	if err != nil {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectJSONArray: unable to unmarshal Json:%v", err))
		return false
	}
	callback(slice)
	return true
}

// ExpectString reads the response body into a Go string callback parameter.
// Fail if the body could not be read or unmarshalled.
// Returns true if a response body was read.
func ExpectString(t T, r *http.Response, callback func(content string)) bool {
	if r == nil {
		logerror(t, serrorf("ExpectString: no response available"))
		return false
	}
	if r.Body == nil {
		logerror(t, serrorf("ExpectString: no body to read"))
		return false
	}
	data, err := ioutil.ReadAll(r.Body)
	defer r.Body.Close()
	if err != nil {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectString: unable to read response body:%v", err))
		return false
	}
	// put the body back for re-reads
	r.Body = ioutil.NopCloser(bytes.NewReader(data))

	callback(string(data))
	return true
}

// ExpectXMLDocument tries to unmarshal the response body into fields of the provided document (struct).
// Fail if the body could not be read or unmarshalled.
// Returns true if a document could be unmarshalled.
func ExpectXMLDocument(t T, r *http.Response, doc interface{}) bool {
	if r == nil {
		logerror(t, serrorf("ExpectXMLDocument: no response available"))
		return false
	}
	if r.Body == nil {
		logerror(t, serrorf("ExpectXMLDocument: no body to read"))
		return false
	}
	data, err := ioutil.ReadAll(r.Body)
	defer r.Body.Close()
	if err != nil {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectXMLDocument: unable to read response body:%v", err))
		return false
	}
	// put the body back for re-reads
	r.Body = ioutil.NopCloser(bytes.NewReader(data))

	err = xml.Unmarshal(data, doc)
	if err != nil {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectXMLDocument: unable to unmarshal Xml:%v", err))
	}
	return err == nil
}

// ExpectJSONDocument tries to unmarshal the response body into fields of the provided document (struct).
// Fail if the body could not be read or unmarshalled.
// Returns true if a document could be unmarshalled.
func ExpectJSONDocument(t T, r *http.Response, doc interface{}) bool {
	if r == nil {
		logerror(t, serrorf("ExpectJSONDocument: no response available"))
		return false
	}
	if r.Body == nil {
		logerror(t, serrorf("ExpectJSONDocument: no body to read"))
		return false
	}
	data, err := ioutil.ReadAll(r.Body)
	defer r.Body.Close()
	if err != nil {
		logerror(t, serrorf("ExpectJSONDocument: unable to read response body :%v", err))
		return false
	}
	// put the body back for re-reads
	r.Body = ioutil.NopCloser(bytes.NewReader(data))

	err = json.Unmarshal(data, doc)
	if err != nil {
		if verboseOnFailure {
			Dump(t, r)
		}
		logerror(t, serrorf("ExpectJSONDocument: unable to unmarshal Json:%v", err))
	}
	return err == nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"

	"github.com/parnurzeal/gorequest"
)

//URL to learn gorequest lib
var URL = "https://bitconnect.co/api/info/BTC_BCC"

//BitcoinInfo parse the response of the api
type BitcoinInfo struct {
	Bid            string `json:"bid"`
	LastPrice      string `json:"last_price"`
	Volume24h      string `json:"volume24h"`
	Currencystring string `json:"currency"`
	MarketName     string `json:"marketname"`
	Ask            string `json:"ask"`
	Low24h         string `json:"low24h"`
	Change24h      string `json:"change24h"`
	High24h        string `json:"high24h"`
	BaseCurrency   string `json:"basecurrency"`
}

//BitcoinInfoAPIResponse include the BitcoinInfo struct
type BitcoinInfoAPIResponse struct {
	Status  string        `json:"status"`
	Message string        `json:"message"`
	Markets []BitcoinInfo `json:"markets"`
}

func getBitCoinResponse(body []byte) (*BitcoinInfoAPIResponse, error) {
	var s = new(BitcoinInfoAPIResponse)
	err := json.Unmarshal(body, &s)
	if err != nil {
		fmt.Println("whoops...", err)
	}
	return s, err
}

func getR() string {
	resp, _ := http.Get(URL)

	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Println(string(body))
	return string(body)
}

func postForm() {
	resp, err := http.PostForm("http://example.com/form", url.Values{"key": {"Value"}, "id": {"123"}})
	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Println(string(body), err)
}

func withGorequest() {
	request := gorequest.New()
	_, body, err := request.Get(URL).End()
	if err != nil {
		panic(err)
	}
	s, err2 := getBitCoinResponse([]byte(body))
	if err2 != nil {
		panic(err2.Error())
	}
	fmt.Println(s.Status)
	fmt.Println(s.Message)
	fmt.Println(s.Markets[0].Ask)
	fmt.Println(s.Markets[0].MarketName)

}
func withOutGoRequestPost() {
	m := map[string]interface{}{
		"name":    "jacky",
		"species": "dog",
	}
	mJson, _ := json.Marshal(m)
	contentReader := bytes.NewReader(mJson)
	req, _ := http.NewRequest("POST", "http://example.com", contentReader)
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Notes", "Go request is coming! ")
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err.Error())
	}
	fmt.Println(resp.Body)
}

func withGoRequestPost() {
	request := gorequest.New()
	_, body, errs := request.Post("http://example.com").
		Set("Notes", "Go request is coming! ").Send(`{"name":"jacky","species":"dog"}`).End()
	if errs != nil {
		panic(errs)
	}
	fmt.Println("######")
	fmt.Println(body)
	fmt.Println("######")
}

func main() {
	// getR()
	// postForm()
	withGorequest()
	withGoRequestPost()
	withOutGoRequestPost()

}
<commit_msg>http request send browser version support<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"

	"github.com/parnurzeal/gorequest"
)

//URL to learn gorequest lib
var URL = "https://bitconnect.co/api/info/BTC_BCC"

//BitcoinInfo parse the response of the api
type BitcoinInfo struct {
	Bid            string `json:"bid"`
	LastPrice      string `json:"last_price"`
	Volume24h      string `json:"volume24h"`
	Currencystring string `json:"currency"`
	MarketName     string `json:"marketname"`
	Ask            string `json:"ask"`
	Low24h         string `json:"low24h"`
	Change24h      string `json:"change24h"`
	High24h        string `json:"high24h"`
	BaseCurrency   string `json:"basecurrency"`
}

//BrowserVersionSupport
type BrowserVersionSupport struct {
	Chrome  string
	Firefox string
}

//BitcoinInfoAPIResponse include the BitcoinInfo struct
type BitcoinInfoAPIResponse struct {
	Status  string        `json:"status"`
	Message string        `json:"message"`
	Markets []BitcoinInfo `json:"markets"`
}

func getBitCoinResponse(body []byte) (*BitcoinInfoAPIResponse, error) {
	var s = new(BitcoinInfoAPIResponse)
	err := json.Unmarshal(body, &s)
	if err != nil {
		fmt.Println("whoops...", err)
	}
	return s, err
}

func getR() string {
	resp, _ := http.Get(URL)

	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Println(string(body))
	return string(body)
}

func postForm() {
	resp, err := http.PostForm("http://example.com/form", url.Values{"key": {"Value"}, "id": {"123"}})
	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Println(string(body), err)
}

func withGorequest() {
	request := gorequest.New()
	_, body, err := request.Get(URL).End()
	if err != nil {
		panic(err)
	}
	s, err2 := getBitCoinResponse([]byte(body))
	if err2 != nil {
		panic(err2.Error())
	}
	fmt.Println(s.Status)
	fmt.Println(s.Message)
	fmt.Println(s.Markets[0].Ask)
	fmt.Println(s.Markets[0].MarketName)

}
func withOutGoRequestPost() {
	m := map[string]interface{}{
		"name":    "jacky",
		"species": "dog",
	}
	mJson, _ := json.Marshal(m)
	contentReader := bytes.NewReader(mJson)
	req, _ := http.NewRequest("POST", "http://example.com", contentReader)
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Notes", "Go request is coming! ")
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err.Error())
	}
	fmt.Println(resp.Body)
}

func withGoRequestPost() {
	request := gorequest.New()
	_, body, errs := request.Post("http://example.com").
		Set("Notes", "Go request is coming! ").Send(`{"name":"jacky","species":"dog"}`).End()
	if errs != nil {
		panic(errs)
	}
	fmt.Println("######")
	fmt.Println(body)
	fmt.Println("######")
}

func sendBrowserVersion() {
	browserVersion := BrowserVersionSupport{Chrome: "63.0", Firefox: "30.0"}
	request := gorequest.New()
	resp, body, err := request.Post("http://example.com").
		Send(browserVersion).
		Send(`Safari:"5.1.10"`).End()
	if err != nil {
		panic(err)
	}
	fmt.Println(resp, body)
}

func main() {
	// getR()
	// postForm()
	withGorequest()
	withGoRequestPost()
	withOutGoRequestPost()
	sendBrowserVersion()

}
<|endoftext|>


<commit_before>// Package zipkinhttp is an HTTP-based query transport that implements
// the Zipkin v1 API.
package zipkinhttp

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"sort"
	"strconv"
	"time"

	"path"

	"github.com/tracer/tracer"
	"github.com/tracer/tracer/server"
)

func init() {
	server.RegisterQueryTransport("zipkinhttp", setup)
}

func setup(srv *server.Server, conf map[string]interface{}) (server.QueryTransport, error) {
	listen, ok := conf["listen"].(string)
	if !ok {
		return nil, errors.New("missing listen setting for HTTP transport")
	}
	h := &HTTP{
		srv:    srv,
		listen: listen,
		mux:    http.NewServeMux(),
	}

	h.mux.HandleFunc("/api/v1/services", h.Services)
	h.mux.HandleFunc("/api/v1/spans", h.Spans)
	h.mux.HandleFunc("/api/v1/traces", h.Traces)
	h.mux.HandleFunc("/api/v1/trace/", h.Trace)
	h.mux.HandleFunc("/api/v1/dependencies", h.Dependencies)
	return h, nil
}

type HTTP struct {
	srv    *server.Server
	listen string
	mux    *http.ServeMux
}

// Start implements the server.QueryTransport interface.
func (h *HTTP) Start() error {
	return http.ListenAndServe(h.listen, h.mux)
}

func (h *HTTP) Services(w http.ResponseWriter, r *http.Request) {
	services, err := h.srv.Storage.Services()
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	_ = json.NewEncoder(w).Encode(services)
}

func (h *HTTP) Spans(w http.ResponseWriter, r *http.Request) {
	service := r.URL.Query().Get("serviceName")
	spans, err := h.srv.Storage.Operations(service)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	_ = json.NewEncoder(w).Encode(spans)
}

type zipkinTrace []zipkinSpan
type zipkinEndpoint struct {
	IPv4        string `json:"ipv4"`
	Port        int    `json:"port"`
	ServiceName string `json:"serviceName"`
}
type zipkinAnnotation struct {
	Endpoint  zipkinEndpoint `json:"endpoint"`
	Timestamp int            `json:"timestamp"`
	Value     string         `json:"value"`
}
type zipkinBinaryAnnotation struct {
	Endpoint zipkinEndpoint `json:"endpoint"`
	Key      string         `json:"key"`
	Value    string         `json:"value"`
}
type zipkinSpan struct {
	Annotations       []zipkinAnnotation       `json:"annotations"`
	BinaryAnnotations []zipkinBinaryAnnotation `json:"binaryAnnotations"`
	Debug             bool                     `json:"debug"`
	Duration          int                      `json:"duration"`
	ID                string                   `json:"id"`
	Name              string                   `json:"name"`
	ParentID          string                   `json:"parentId,omitempty"`
	Timestamp         int                      `json:"timestamp"`
	TraceID           string                   `json:"traceId"`
}

type zipkinBinaryAnnotations []zipkinBinaryAnnotation

func (s zipkinBinaryAnnotations) Len() int {
	return len(s)
}

func (s zipkinBinaryAnnotations) Less(i int, j int) bool {
	return s[i].Key < s[j].Key
}

func (s zipkinBinaryAnnotations) Swap(i int, j int) {
	s[i], s[j] = s[j], s[i]
}

func traceToZipkin(trace tracer.RawTrace) zipkinTrace {
	ztrace := zipkinTrace{}
	parents := map[uint64]uint64{}
	for _, rel := range trace.Relations {
		parents[rel.ChildID] = rel.ParentID
	}
	for _, span := range trace.Spans {
		var kind, opKind string
		switch span.Tags["span.kind"] {
		case "server":
			kind = "sr"
			opKind = "ss"
		case "client":
			kind = "cs"
			opKind = "cr"
		}
		zspan := zipkinSpan{
			Annotations: []zipkinAnnotation{
				{
					Endpoint: zipkinEndpoint{
						ServiceName: span.ServiceName,
					},
					Timestamp: int(span.StartTime.UnixNano()) / 1000,
					Value:     kind,
				},
				{
					Endpoint: zipkinEndpoint{
						ServiceName: span.ServiceName,
					},
					Timestamp: int(span.FinishTime.UnixNano()) / 1000,
					Value:     opKind,
				},
			},
			BinaryAnnotations: []zipkinBinaryAnnotation{},
			Debug:             false,
			Duration:          int(span.FinishTime.Sub(span.StartTime)) / 1000,
			ID:                fmt.Sprintf("%016x", span.SpanID),
			Name:              span.OperationName,
			ParentID:          fmt.Sprintf("%016x", parents[span.SpanID]),
			Timestamp:         int(span.StartTime.UnixNano() / 1000),
			TraceID:           fmt.Sprintf("%016x", trace.TraceID),
		}
		if parents[span.SpanID] == 0 {
			zspan.ParentID = ""
		}
		for k, v := range span.Tags {
			vs := fmt.Sprintf("%v", v)
			zspan.BinaryAnnotations = append(zspan.BinaryAnnotations, zipkinBinaryAnnotation{
				Key:   k,
				Value: vs,
			})
		}
		sort.Sort(zipkinBinaryAnnotations(zspan.BinaryAnnotations))
		ztrace = append(ztrace, zspan)
	}
	return ztrace
}

func atoi(s string) int {
	n, _ := strconv.Atoi(s)
	return n
}

func (h *HTTP) Traces(w http.ResponseWriter, r *http.Request) {
	limit := atoi(r.URL.Query().Get("limit"))
	if limit == 0 {
		limit = 10
	}
	minDuration := time.Duration(atoi(r.URL.Query().Get("minDuration"))) * time.Microsecond
	maxDuration := time.Duration(atoi(r.URL.Query().Get("maxDuration"))) * time.Microsecond
	msec := int64(atoi(r.URL.Query().Get("endTs")))
	endTs := time.Unix(msec/1000, (msec%1000)*1000)
	if msec == 0 {
		endTs = time.Now()
	}
	lookback := time.Duration(atoi(r.URL.Query().Get("lookback"))) * time.Millisecond

	traces, err := h.srv.Storage.QueryTraces(server.Query{
		StartTime:     endTs.Add(-lookback),
		FinishTime:    endTs,
		OperationName: "",
		MinDuration:   minDuration,
		MaxDuration:   maxDuration,
		AndTags:       nil,
		OrTags:        nil,
		Num:           limit,
	})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	out := []zipkinTrace{}
	for _, trace := range traces {
		ztrace := traceToZipkin(trace)
		out = append(out, ztrace)
	}
	_ = json.NewEncoder(w).Encode(out)
}

func (h *HTTP) Trace(w http.ResponseWriter, r *http.Request) {
	id, err := strconv.ParseUint(path.Base(r.URL.Path), 16, 64)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	trace, err := h.srv.Storage.TraceByID(id)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	_ = json.NewEncoder(w).Encode(traceToZipkin(trace))
}

func (h *HTTP) Dependencies(w http.ResponseWriter, r *http.Request) {
	type zipkinDependency struct {
		CallCount int    `json:"callCount"`
		Child     string `json:"child"`
		Parent    string `json:"parent"`
	}
	deps, err := h.srv.Storage.Dependencies()
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	out := []zipkinDependency{}
	for _, dep := range deps {
		out = append(out, zipkinDependency{
			CallCount: int(dep.Count),
			Child:     dep.Child,
			Parent:    dep.Parent,
		})
	}
	_ = json.NewEncoder(w).Encode(out)
}
<commit_msg>Include all log entries in zipkin API<commit_after>// Package zipkinhttp is an HTTP-based query transport that implements
// the Zipkin v1 API.
package zipkinhttp

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"sort"
	"strconv"
	"time"

	"path"

	"github.com/tracer/tracer"
	"github.com/tracer/tracer/server"
)

func init() {
	server.RegisterQueryTransport("zipkinhttp", setup)
}

func setup(srv *server.Server, conf map[string]interface{}) (server.QueryTransport, error) {
	listen, ok := conf["listen"].(string)
	if !ok {
		return nil, errors.New("missing listen setting for HTTP transport")
	}
	h := &HTTP{
		srv:    srv,
		listen: listen,
		mux:    http.NewServeMux(),
	}

	h.mux.HandleFunc("/api/v1/services", h.Services)
	h.mux.HandleFunc("/api/v1/spans", h.Spans)
	h.mux.HandleFunc("/api/v1/traces", h.Traces)
	h.mux.HandleFunc("/api/v1/trace/", h.Trace)
	h.mux.HandleFunc("/api/v1/dependencies", h.Dependencies)
	return h, nil
}

type HTTP struct {
	srv    *server.Server
	listen string
	mux    *http.ServeMux
}

// Start implements the server.QueryTransport interface.
func (h *HTTP) Start() error {
	return http.ListenAndServe(h.listen, h.mux)
}

func (h *HTTP) Services(w http.ResponseWriter, r *http.Request) {
	services, err := h.srv.Storage.Services()
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	_ = json.NewEncoder(w).Encode(services)
}

func (h *HTTP) Spans(w http.ResponseWriter, r *http.Request) {
	service := r.URL.Query().Get("serviceName")
	spans, err := h.srv.Storage.Operations(service)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	_ = json.NewEncoder(w).Encode(spans)
}

type zipkinTrace []zipkinSpan
type zipkinEndpoint struct {
	IPv4        string `json:"ipv4"`
	Port        int    `json:"port"`
	ServiceName string `json:"serviceName"`
}
type zipkinAnnotation struct {
	Endpoint  zipkinEndpoint `json:"endpoint"`
	Timestamp int            `json:"timestamp"`
	Value     string         `json:"value"`
}
type zipkinBinaryAnnotation struct {
	Endpoint zipkinEndpoint `json:"endpoint"`
	Key      string         `json:"key"`
	Value    string         `json:"value"`
}
type zipkinSpan struct {
	Annotations       []zipkinAnnotation       `json:"annotations"`
	BinaryAnnotations []zipkinBinaryAnnotation `json:"binaryAnnotations"`
	Debug             bool                     `json:"debug"`
	Duration          int                      `json:"duration"`
	ID                string                   `json:"id"`
	Name              string                   `json:"name"`
	ParentID          string                   `json:"parentId,omitempty"`
	Timestamp         int                      `json:"timestamp"`
	TraceID           string                   `json:"traceId"`
}

type zipkinBinaryAnnotations []zipkinBinaryAnnotation

func (s zipkinBinaryAnnotations) Len() int {
	return len(s)
}

func (s zipkinBinaryAnnotations) Less(i int, j int) bool {
	return s[i].Key < s[j].Key
}

func (s zipkinBinaryAnnotations) Swap(i int, j int) {
	s[i], s[j] = s[j], s[i]
}

func traceToZipkin(trace tracer.RawTrace) zipkinTrace {
	ztrace := zipkinTrace{}
	parents := map[uint64]uint64{}
	for _, rel := range trace.Relations {
		parents[rel.ChildID] = rel.ParentID
	}
	for _, span := range trace.Spans {
		var kind, opKind string
		switch span.Tags["span.kind"] {
		case "server":
			kind = "sr"
			opKind = "ss"
		case "client":
			kind = "cs"
			opKind = "cr"
		}
		zspan := zipkinSpan{
			Annotations: []zipkinAnnotation{
				{
					Endpoint: zipkinEndpoint{
						ServiceName: span.ServiceName,
					},
					Timestamp: int(span.StartTime.UnixNano()) / 1000,
					Value:     kind,
				},
			},
			BinaryAnnotations: []zipkinBinaryAnnotation{},
			Debug:             false,
			Duration:          int(span.FinishTime.Sub(span.StartTime)) / 1000,
			ID:                fmt.Sprintf("%016x", span.SpanID),
			Name:              span.OperationName,
			ParentID:          fmt.Sprintf("%016x", parents[span.SpanID]),
			Timestamp:         int(span.StartTime.UnixNano() / 1000),
			TraceID:           fmt.Sprintf("%016x", trace.TraceID),
		}
		if parents[span.SpanID] == 0 {
			zspan.ParentID = ""
		}
		for k, v := range span.Tags {
			vs := fmt.Sprintf("%v", v)
			zspan.BinaryAnnotations = append(zspan.BinaryAnnotations, zipkinBinaryAnnotation{
				Key:   k,
				Value: vs,
			})
		}
		for _, log := range span.Logs {
			zspan.Annotations = append(zspan.Annotations,
				zipkinAnnotation{
					Endpoint: zipkinEndpoint{
						ServiceName: span.ServiceName,
					},
					Timestamp: int(log.Timestamp.UnixNano()) / 1000,
					Value:     log.Event,
				})
		}
		zspan.Annotations = append(zspan.Annotations,
			zipkinAnnotation{
				Endpoint: zipkinEndpoint{
					ServiceName: span.ServiceName,
				},
				Timestamp: int(span.FinishTime.UnixNano()) / 1000,
				Value:     opKind,
			})
		sort.Sort(zipkinBinaryAnnotations(zspan.BinaryAnnotations))
		ztrace = append(ztrace, zspan)
	}
	return ztrace
}

func atoi(s string) int {
	n, _ := strconv.Atoi(s)
	return n
}

func (h *HTTP) Traces(w http.ResponseWriter, r *http.Request) {
	limit := atoi(r.URL.Query().Get("limit"))
	if limit == 0 {
		limit = 10
	}
	minDuration := time.Duration(atoi(r.URL.Query().Get("minDuration"))) * time.Microsecond
	maxDuration := time.Duration(atoi(r.URL.Query().Get("maxDuration"))) * time.Microsecond
	msec := int64(atoi(r.URL.Query().Get("endTs")))
	endTs := time.Unix(msec/1000, (msec%1000)*1000)
	if msec == 0 {
		endTs = time.Now()
	}
	lookback := time.Duration(atoi(r.URL.Query().Get("lookback"))) * time.Millisecond

	traces, err := h.srv.Storage.QueryTraces(server.Query{
		StartTime:     endTs.Add(-lookback),
		FinishTime:    endTs,
		OperationName: "",
		MinDuration:   minDuration,
		MaxDuration:   maxDuration,
		AndTags:       nil,
		OrTags:        nil,
		Num:           limit,
	})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	out := []zipkinTrace{}
	for _, trace := range traces {
		ztrace := traceToZipkin(trace)
		out = append(out, ztrace)
	}
	_ = json.NewEncoder(w).Encode(out)
}

func (h *HTTP) Trace(w http.ResponseWriter, r *http.Request) {
	id, err := strconv.ParseUint(path.Base(r.URL.Path), 16, 64)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	trace, err := h.srv.Storage.TraceByID(id)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	_ = json.NewEncoder(w).Encode(traceToZipkin(trace))
}

func (h *HTTP) Dependencies(w http.ResponseWriter, r *http.Request) {
	type zipkinDependency struct {
		CallCount int    `json:"callCount"`
		Child     string `json:"child"`
		Parent    string `json:"parent"`
	}
	deps, err := h.srv.Storage.Dependencies()
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	out := []zipkinDependency{}
	for _, dep := range deps {
		out = append(out, zipkinDependency{
			CallCount: int(dep.Count),
			Child:     dep.Child,
			Parent:    dep.Parent,
		})
	}
	_ = json.NewEncoder(w).Encode(out)
}
<|endoftext|>


<commit_before><commit_msg>10/08/2019 08:33:26 PM	modified:   regex/regex.go<commit_after><|endoftext|>


<commit_before><commit_msg>Close db in tests<commit_after><|endoftext|>


<commit_before>package main

import (
	"net"
	"net/http"
	"strings"
	"testing"
)

// Should set an `X-Forwarded-For` header for requests that don't already
// have one and append to requests that already have the header. This test
// will not work if run from behind a proxy that also sets XFF.
func TestReqHeaderXFFCreateAndAppend(t *testing.T) {
	ResetBackends(backendsByPriority)

	const headerName = "X-Forwarded-For"
	const sentHeaderVal = "203.0.113.99"
	var ourReportedIP net.IP
	var receivedHeaderVal string

	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		receivedHeaderVal = r.Header.Get(headerName)
	})

	// First request with no existing XFF.
	req := NewUniqueEdgeGET(t)
	resp := RoundTripCheckError(t, req)
	defer resp.Body.Close()

	if receivedHeaderVal == "" {
		t.Fatalf("Origin didn't receive request with %q header", headerName)
	}

	ourReportedIP = net.ParseIP(receivedHeaderVal)
	if ourReportedIP == nil {
		t.Fatalf(
			"Expected origin to receive %q header with single IP. Got %q",
			headerName,
			receivedHeaderVal,
		)
	}

	// Use the IP returned by the first response to predict the second.
	expectedHeaderVals := []string{sentHeaderVal, ourReportedIP.String()}

	// Second request with existing XFF.
	req = NewUniqueEdgeGET(t)
	req.Header.Set(headerName, sentHeaderVal)

	resp = RoundTripCheckError(t, req)
	defer resp.Body.Close()

	receivedHeaderVals := strings.Split(receivedHeaderVal, ",")
	if count := len(receivedHeaderVals); count != len(expectedHeaderVals) {
		t.Fatalf(
			"Origin received %q header with wrong count of IPs. Expected %d, got %d: %q",
			headerName,
			expectedHeaderVals,
			count,
			receivedHeaderVal,
		)
	}

	for count, expectedVal := range expectedHeaderVals {
		receivedVal := strings.TrimSpace(receivedHeaderVals[count])
		if receivedVal != expectedVal {
			t.Errorf(
				"Origin received %q header with wrong IP #%d. Expected %q, got %q",
				headerName,
				count+1,
				expectedVal,
				receivedVal,
			)
		}
	}
}

// Should create a True-Client-IP header containing the client's IP
// address, discarding the value provided in the original request.
func TestReqHeaderUnspoofableClientIP(t *testing.T) {
	ResetBackends(backendsByPriority)

	const sentHeaderVal = "203.0.113.99"
	var headerName string
	var receivedHeaderVal string

	switch {
	case vendorCloudflare:
		t.Skip(notSupportedByVendor)
	case vendorFastly:
		headerName = "True-Client-IP"
	default:
		t.Fatal(notImplementedForVendor)
	}

	sentHeaderIP := net.ParseIP(sentHeaderVal)

	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		receivedHeaderVal = r.Header.Get(headerName)
	})

	req := NewUniqueEdgeGET(t)
	req.Header.Set(headerName, sentHeaderVal)

	resp := RoundTripCheckError(t, req)
	defer resp.Body.Close()

	receivedHeaderIP := net.ParseIP(receivedHeaderVal)
	if receivedHeaderIP == nil {
		t.Fatalf("Origin received %q header with non-IP value %q", headerName, receivedHeaderVal)
	}
	if receivedHeaderIP.Equal(sentHeaderIP) {
		t.Errorf("Origin received %q header with unmodified value %q", headerName, receivedHeaderIP)
	}
}

// Should not modify `Host` header from original request.
func TestReqHeaderHostUnmodified(t *testing.T) {
	const headerName = "Host"
	var sentHeaderVal = *edgeHost
	var receivedHeaderVal string

	ResetBackends(backendsByPriority)
	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		receivedHeaderVal = r.Host
	})

	req := NewUniqueEdgeGET(t)

	if req.Host != sentHeaderVal {
		t.Errorf(
			"Constructed request contains wrong %q header. Expected %q, got %q",
			headerName,
			sentHeaderVal,
			req.Host,
		)
	}

	resp := RoundTripCheckError(t, req)
	defer resp.Body.Close()

	if receivedHeaderVal != sentHeaderVal {
		t.Errorf(
			"Origin received %q header with modified value. Expected %q, got %q",
			headerName,
			sentHeaderVal,
			receivedHeaderVal,
		)
	}
}
<commit_msg>Don't skip Cloudflare unspoofable client IP test<commit_after>package main

import (
	"net"
	"net/http"
	"strings"
	"testing"
)

// Should set an `X-Forwarded-For` header for requests that don't already
// have one and append to requests that already have the header. This test
// will not work if run from behind a proxy that also sets XFF.
func TestReqHeaderXFFCreateAndAppend(t *testing.T) {
	ResetBackends(backendsByPriority)

	const headerName = "X-Forwarded-For"
	const sentHeaderVal = "203.0.113.99"
	var ourReportedIP net.IP
	var receivedHeaderVal string

	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		receivedHeaderVal = r.Header.Get(headerName)
	})

	// First request with no existing XFF.
	req := NewUniqueEdgeGET(t)
	resp := RoundTripCheckError(t, req)
	defer resp.Body.Close()

	if receivedHeaderVal == "" {
		t.Fatalf("Origin didn't receive request with %q header", headerName)
	}

	ourReportedIP = net.ParseIP(receivedHeaderVal)
	if ourReportedIP == nil {
		t.Fatalf(
			"Expected origin to receive %q header with single IP. Got %q",
			headerName,
			receivedHeaderVal,
		)
	}

	// Use the IP returned by the first response to predict the second.
	expectedHeaderVals := []string{sentHeaderVal, ourReportedIP.String()}

	// Second request with existing XFF.
	req = NewUniqueEdgeGET(t)
	req.Header.Set(headerName, sentHeaderVal)

	resp = RoundTripCheckError(t, req)
	defer resp.Body.Close()

	receivedHeaderVals := strings.Split(receivedHeaderVal, ",")
	if count := len(receivedHeaderVals); count != len(expectedHeaderVals) {
		t.Fatalf(
			"Origin received %q header with wrong count of IPs. Expected %d, got %d: %q",
			headerName,
			expectedHeaderVals,
			count,
			receivedHeaderVal,
		)
	}

	for count, expectedVal := range expectedHeaderVals {
		receivedVal := strings.TrimSpace(receivedHeaderVals[count])
		if receivedVal != expectedVal {
			t.Errorf(
				"Origin received %q header with wrong IP #%d. Expected %q, got %q",
				headerName,
				count+1,
				expectedVal,
				receivedVal,
			)
		}
	}
}

// Should create a True-Client-IP header containing the client's IP
// address, discarding the value provided in the original request.
func TestReqHeaderUnspoofableClientIP(t *testing.T) {
	ResetBackends(backendsByPriority)

	const sentHeaderVal = "203.0.113.99"
	var headerName string
	var receivedHeaderVal string

	switch {
	case vendorCloudflare, vendorFastly:
		headerName = "True-Client-IP"
	default:
		t.Fatal(notImplementedForVendor)
	}

	sentHeaderIP := net.ParseIP(sentHeaderVal)

	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		receivedHeaderVal = r.Header.Get(headerName)
	})

	req := NewUniqueEdgeGET(t)
	req.Header.Set(headerName, sentHeaderVal)

	resp := RoundTripCheckError(t, req)
	defer resp.Body.Close()

	receivedHeaderIP := net.ParseIP(receivedHeaderVal)
	if receivedHeaderIP == nil {
		t.Fatalf("Origin received %q header with non-IP value %q", headerName, receivedHeaderVal)
	}
	if receivedHeaderIP.Equal(sentHeaderIP) {
		t.Errorf("Origin received %q header with unmodified value %q", headerName, receivedHeaderIP)
	}
}

// Should not modify `Host` header from original request.
func TestReqHeaderHostUnmodified(t *testing.T) {
	const headerName = "Host"
	var sentHeaderVal = *edgeHost
	var receivedHeaderVal string

	ResetBackends(backendsByPriority)
	originServer.SwitchHandler(func(w http.ResponseWriter, r *http.Request) {
		receivedHeaderVal = r.Host
	})

	req := NewUniqueEdgeGET(t)

	if req.Host != sentHeaderVal {
		t.Errorf(
			"Constructed request contains wrong %q header. Expected %q, got %q",
			headerName,
			sentHeaderVal,
			req.Host,
		)
	}

	resp := RoundTripCheckError(t, req)
	defer resp.Body.Close()

	if receivedHeaderVal != sentHeaderVal {
		t.Errorf(
			"Origin received %q header with modified value. Expected %q, got %q",
			headerName,
			sentHeaderVal,
			receivedHeaderVal,
		)
	}
}
<|endoftext|>