<commit_before>/*
    MP3Cat is a fast command line utility for concatenating MP3 files
    without re-encoding. It supports both constant bit rate (CBR) and
    variable bit rate (VBR) files.
*/
package main

import (
    "fmt"
    "io"
    "os"
    "path"
    "path/filepath"
    "golang.org/x/crypto/ssh/terminal"
    "github.com/dmulholland/mp3lib"
    "github.com/dmulholland/janus-go/janus"
)

const version = "3.0.3"

var helptext = fmt.Sprintf(`
Usage: %s [FLAGS] [OPTIONS] [ARGUMENTS]

  This tool concatenates MP3 files without re-encoding. It can join constant
  bit-rate (CBR) files, variable bit-rate (VBR) files, or a mixture of both.

  If a set of input CBR files share the same bit-rate, the output file will
  also be CBR; if the input files have different bit-rates, the output file
  will be VBR.

  Files to be merged can be specified as a list of filenames:

    $ mp3cat one.mp3 two.mp3 three.mp3

  Alternatively, an entire directory of .mp3 files can be merged:

    $ mp3cat --dir /path/to/directory

Arguments:
  [files]                 List of files to merge.

Options:
  -d, --dir <path>        Directory of files to merge.
  -i, --interlace <path>  Interlace a spacer file between each input file.
  -o, --out <path>        Output filename. Defaults to 'output.mp3'.

Flags:
  -f, --force             Overwrite an existing output file.
  -h, --help              Display this help text and exit.
  -q, --quiet             Run in quiet mode.
  -t, --tag               Copy the ID3 tag from the first input file.
  -v, --version           Display the application's version number and exit.
`, filepath.Base(os.Args[0]))

func main() {

    // Parse the command line arguments.
    parser := janus.NewParser()
    parser.Helptext = helptext
    parser.Version = version
    parser.NewFlag("force f")
    parser.NewFlag("quiet q")
    parser.NewFlag("debug")
    parser.NewFlag("tag t")
    parser.NewString("out o", "output.mp3")
    parser.NewString("dir d")
    parser.NewString("interlace i")
    parser.Parse()

    // Make sure we have a list of files to merge.
    var files []string
    if parser.Found("dir") {
        pattern := "*.[Mm][Pp]3"
        globs, err := filepath.Glob(path.Join(parser.GetString("dir"), pattern))
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }
        if globs == nil || len(globs) == 0 {
            fmt.Fprintln(os.Stderr, "Error: no files found.")
            os.Exit(1)
        }
        files = globs
    } else if parser.HasArgs() {
        files = parser.GetArgs()
    } else {
        fmt.Fprintln(os.Stderr, "Error: you must specify files to merge.")
        os.Exit(1)
    }

    // Are we interlacing a spacer file?
    if parser.Found("interlace") {
        files = interlace(files, parser.GetString("interlace"))
    }

    // Make sure all the files in the list actually exist.
    validateFiles(files)

    // Set debug mode if the user supplied a --debug flag.
    if parser.GetFlag("debug") {
        mp3lib.DebugMode = true
    }

    // Merge the input files.
    merge(
        parser.GetString("out"),
        files,
        parser.GetFlag("force"),
        parser.GetFlag("quiet"),
        parser.GetFlag("tag"))
}

// Check that all the files in the list exist.
func validateFiles(files []string) {
    for _, file := range files {
        if _, err := os.Stat(file); err != nil {
            fmt.Fprintf(
                os.Stderr,
                "Error: the file '%v' does not exist.\n", file)
            os.Exit(1)
        }
    }
}

// Interlace a spacer file between each file in the list.
func interlace(files []string, spacer string) []string {
    var interlaced []string
    for _, file := range files {
        interlaced = append(interlaced, file)
        interlaced = append(interlaced, spacer)
    }
    return interlaced[:len(interlaced) - 1]
}

// Create a new file at the specified output path containing the merged
// contents of the list of input files.
func merge(outpath string, inpaths []string, force, quiet, tag bool) {

    var totalFrames uint32
    var totalBytes uint32
    var totalFiles int
    var firstBitRate int
    var isVBR bool

    // Only overwrite an existing file if the --force flag has been used.
    if _, err := os.Stat(outpath); err == nil {
        if !force {
            fmt.Fprintf(
                os.Stderr,
                "Error: the file '%v' already exists.\n", outpath)
            os.Exit(1)
        }
    }

    // If the list of input files includes the output file we'll end up in an
    // infinite loop.
    for _, filepath := range inpaths {
        if filepath == outpath {
            fmt.Fprintln(
                os.Stderr,
                "Error: the list of input files includes the output file.")
            os.Exit(1)
        }
    }

    // Create the output file.
    outfile, err := os.Create(outpath)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }

    if !quiet {
        line()
    }

    // Loop over the input files and append their MP3 frames to the output
    // file.
    for _, inpath := range inpaths {

        if !quiet {
            fmt.Println("+", inpath)
        }

        infile, err := os.Open(inpath)
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }

        isFirstFrame := true

        for {

            // Read the next frame from the input file.
            frame := mp3lib.NextFrame(infile)
            if frame == nil {
                break
            }

            // Skip the first frame if it's a VBR header.
            if isFirstFrame {
                isFirstFrame = false
                if mp3lib.IsXingHeader(frame) || mp3lib.IsVbriHeader(frame) {
                    continue
                }
            }

            // If we detect more than one bitrate we'll need to add a VBR
            // header to the output file.
            if firstBitRate == 0 {
                firstBitRate = frame.BitRate
            } else if frame.BitRate != firstBitRate {
                isVBR = true
            }

            // Write the frame to the output file.
            _, err := outfile.Write(frame.RawBytes)
            if err != nil {
                fmt.Fprintln(os.Stderr, err)
                os.Exit(1)
            }

            totalFrames += 1
            totalBytes += uint32(len(frame.RawBytes))
        }

        infile.Close()
        totalFiles += 1
    }

    outfile.Close()
    if !quiet {
        line()
    }

    // If we detected multiple bitrates, prepend a VBR header to the file.
    if isVBR {
        if !quiet {
            fmt.Println("• Multiple bitrates detected. Adding VBR header.")
        }
        addXingHeader(outpath, totalFrames, totalBytes)
    }

    // Copy the ID3v2 tag from the first input file if requested. Order of
    // operations is important here. The ID3 tag must be the first item in
    // the file - in particular, it must come *before* any VBR header.
    if tag {
        if !quiet {
            fmt.Println("• Adding ID3 tag.")
        }
        addID3v2Tag(outpath, inpaths[0])
    }

    // Print a count of the number of files merged.
    if !quiet {
        fmt.Printf("• %v files merged.\n", totalFiles)
        line()
    }
}

// Prepend an Xing VBR header to the specified MP3 file.
func addXingHeader(filepath string, totalFrames, totalBytes uint32) {

    outputFile, err := os.Create(filepath + ".mp3cat.tmp")
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }

    inputFile, err := os.Open(filepath)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }

    templateFrame := mp3lib.NextFrame(inputFile)
    inputFile.Seek(0, 0)

    xingHeader := mp3lib.NewXingHeader(templateFrame, totalFrames, totalBytes)

    _, err = outputFile.Write(xingHeader.RawBytes)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }

    _, err = io.Copy(outputFile, inputFile)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }

    outputFile.Close()
    inputFile.Close()

    err = os.Remove(filepath)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }

    err = os.Rename(filepath + ".mp3cat.tmp", filepath)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
}

// Prepend an ID3v2 tag to the MP3 file at mp3Path, copying from tagPath.
func addID3v2Tag(mp3Path, tagPath string) {

    tagFile, err := os.Open(tagPath)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }

    id3tag := mp3lib.NextID3v2Tag(tagFile)
    tagFile.Close()

    if id3tag != nil {
        outputFile, err := os.Create(mp3Path + ".mp3cat.tmp")
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }

        inputFile, err := os.Open(mp3Path)
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }

        _, err = outputFile.Write(id3tag.RawBytes)
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }

        _, err = io.Copy(outputFile, inputFile)
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }

        outputFile.Close()
        inputFile.Close()

        err = os.Remove(mp3Path)
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }

        err = os.Rename(mp3Path + ".mp3cat.tmp", mp3Path)
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }
    }
}

// Print a line to stdout if we're running in a terminal.
func line() {
    if terminal.IsTerminal(int(os.Stdout.Fd())) {
        width, _, err := terminal.GetSize(int(os.Stdout.Fd()))
        if err == nil {
            for i := 0; i < width; i++ {
                fmt.Print("─")
            }
            fmt.Println()
        }
    }
}
<commit_msg>Fix bounds check bug<commit_after>/*
    MP3Cat is a fast command line utility for concatenating MP3 files
    without re-encoding. It supports both constant bit rate (CBR) and
    variable bit rate (VBR) files.
*/
package main

import (
    "fmt"
    "io"
    "os"
    "path"
    "path/filepath"
    "golang.org/x/crypto/ssh/terminal"
    "github.com/dmulholland/mp3lib"
    "github.com/dmulholland/janus-go/janus"
)

const version = "3.0.4"

var helptext = fmt.Sprintf(`
Usage: %s [FLAGS] [OPTIONS] [ARGUMENTS]

  This tool concatenates MP3 files without re-encoding. It can join constant
  bit-rate (CBR) files, variable bit-rate (VBR) files, or a mixture of both.

  If a set of input CBR files share the same bit-rate, the output file will
  also be CBR; if the input files have different bit-rates, the output file
  will be VBR.

  Files to be merged can be specified as a list of filenames:

    $ mp3cat one.mp3 two.mp3 three.mp3

  Alternatively, an entire directory of .mp3 files can be merged:

    $ mp3cat --dir /path/to/directory

Arguments:
  [files]                 List of files to merge.

Options:
  -d, --dir <path>        Directory of files to merge.
  -i, --interlace <path>  Interlace a spacer file between each input file.
  -o, --out <path>        Output filename. Defaults to 'output.mp3'.

Flags:
  -f, --force             Overwrite an existing output file.
  -h, --help              Display this help text and exit.
  -q, --quiet             Run in quiet mode.
  -t, --tag               Copy the ID3 tag from the first input file.
  -v, --version           Display the application's version number and exit.
`, filepath.Base(os.Args[0]))

func main() {

    // Parse the command line arguments.
    parser := janus.NewParser()
    parser.Helptext = helptext
    parser.Version = version
    parser.NewFlag("force f")
    parser.NewFlag("quiet q")
    parser.NewFlag("debug")
    parser.NewFlag("tag t")
    parser.NewString("out o", "output.mp3")
    parser.NewString("dir d")
    parser.NewString("interlace i")
    parser.Parse()

    // Make sure we have a list of files to merge.
    var files []string
    if parser.Found("dir") {
        pattern := "*.[Mm][Pp]3"
        globs, err := filepath.Glob(path.Join(parser.GetString("dir"), pattern))
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }
        if globs == nil || len(globs) == 0 {
            fmt.Fprintln(os.Stderr, "Error: no files found.")
            os.Exit(1)
        }
        files = globs
    } else if parser.HasArgs() {
        files = parser.GetArgs()
    } else {
        fmt.Fprintln(os.Stderr, "Error: you must specify files to merge.")
        os.Exit(1)
    }

    // Are we interlacing a spacer file?
    if parser.Found("interlace") {
        files = interlace(files, parser.GetString("interlace"))
    }

    // Make sure all the files in the list actually exist.
    validateFiles(files)

    // Set debug mode if the user supplied a --debug flag.
    if parser.GetFlag("debug") {
        mp3lib.DebugMode = true
    }

    // Merge the input files.
    merge(
        parser.GetString("out"),
        files,
        parser.GetFlag("force"),
        parser.GetFlag("quiet"),
        parser.GetFlag("tag"))
}

// Check that all the files in the list exist.
func validateFiles(files []string) {
    for _, file := range files {
        if _, err := os.Stat(file); err != nil {
            fmt.Fprintf(
                os.Stderr,
                "Error: the file '%v' does not exist.\n", file)
            os.Exit(1)
        }
    }
}

// Interlace a spacer file between each file in the list.
func interlace(files []string, spacer string) []string {
    var interlaced []string
    for _, file := range files {
        interlaced = append(interlaced, file)
        interlaced = append(interlaced, spacer)
    }
    return interlaced[:len(interlaced) - 1]
}

// Create a new file at the specified output path containing the merged
// contents of the list of input files.
func merge(outpath string, inpaths []string, force, quiet, tag bool) {

    var totalFrames uint32
    var totalBytes uint32
    var totalFiles int
    var firstBitRate int
    var isVBR bool

    // Only overwrite an existing file if the --force flag has been used.
    if _, err := os.Stat(outpath); err == nil {
        if !force {
            fmt.Fprintf(
                os.Stderr,
                "Error: the file '%v' already exists.\n", outpath)
            os.Exit(1)
        }
    }

    // If the list of input files includes the output file we'll end up in an
    // infinite loop.
    for _, filepath := range inpaths {
        if filepath == outpath {
            fmt.Fprintln(
                os.Stderr,
                "Error: the list of input files includes the output file.")
            os.Exit(1)
        }
    }

    // Create the output file.
    outfile, err := os.Create(outpath)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }

    if !quiet {
        line()
    }

    // Loop over the input files and append their MP3 frames to the output
    // file.
    for _, inpath := range inpaths {

        if !quiet {
            fmt.Println("+", inpath)
        }

        infile, err := os.Open(inpath)
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }

        isFirstFrame := true

        for {

            // Read the next frame from the input file.
            frame := mp3lib.NextFrame(infile)
            if frame == nil {
                break
            }

            // Skip the first frame if it's a VBR header.
            if isFirstFrame {
                isFirstFrame = false
                if mp3lib.IsXingHeader(frame) || mp3lib.IsVbriHeader(frame) {
                    continue
                }
            }

            // If we detect more than one bitrate we'll need to add a VBR
            // header to the output file.
            if firstBitRate == 0 {
                firstBitRate = frame.BitRate
            } else if frame.BitRate != firstBitRate {
                isVBR = true
            }

            // Write the frame to the output file.
            _, err := outfile.Write(frame.RawBytes)
            if err != nil {
                fmt.Fprintln(os.Stderr, err)
                os.Exit(1)
            }

            totalFrames += 1
            totalBytes += uint32(len(frame.RawBytes))
        }

        infile.Close()
        totalFiles += 1
    }

    outfile.Close()
    if !quiet {
        line()
    }

    // If we detected multiple bitrates, prepend a VBR header to the file.
    if isVBR {
        if !quiet {
            fmt.Println("• Multiple bitrates detected. Adding VBR header.")
        }
        addXingHeader(outpath, totalFrames, totalBytes)
    }

    // Copy the ID3v2 tag from the first input file if requested. Order of
    // operations is important here. The ID3 tag must be the first item in
    // the file - in particular, it must come *before* any VBR header.
    if tag {
        if !quiet {
            fmt.Println("• Adding ID3 tag.")
        }
        addID3v2Tag(outpath, inpaths[0])
    }

    // Print a count of the number of files merged.
    if !quiet {
        fmt.Printf("• %v files merged.\n", totalFiles)
        line()
    }
}

// Prepend an Xing VBR header to the specified MP3 file.
func addXingHeader(filepath string, totalFrames, totalBytes uint32) {

    outputFile, err := os.Create(filepath + ".mp3cat.tmp")
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }

    inputFile, err := os.Open(filepath)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }

    templateFrame := mp3lib.NextFrame(inputFile)
    inputFile.Seek(0, 0)

    xingHeader := mp3lib.NewXingHeader(templateFrame, totalFrames, totalBytes)

    _, err = outputFile.Write(xingHeader.RawBytes)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }

    _, err = io.Copy(outputFile, inputFile)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }

    outputFile.Close()
    inputFile.Close()

    err = os.Remove(filepath)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }

    err = os.Rename(filepath + ".mp3cat.tmp", filepath)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
}

// Prepend an ID3v2 tag to the MP3 file at mp3Path, copying from tagPath.
func addID3v2Tag(mp3Path, tagPath string) {

    tagFile, err := os.Open(tagPath)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }

    id3tag := mp3lib.NextID3v2Tag(tagFile)
    tagFile.Close()

    if id3tag != nil {
        outputFile, err := os.Create(mp3Path + ".mp3cat.tmp")
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }

        inputFile, err := os.Open(mp3Path)
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }

        _, err = outputFile.Write(id3tag.RawBytes)
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }

        _, err = io.Copy(outputFile, inputFile)
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }

        outputFile.Close()
        inputFile.Close()

        err = os.Remove(mp3Path)
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }

        err = os.Rename(mp3Path + ".mp3cat.tmp", mp3Path)
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }
    }
}

// Print a line to stdout if we're running in a terminal.
func line() {
    if terminal.IsTerminal(int(os.Stdout.Fd())) {
        width, _, err := terminal.GetSize(int(os.Stdout.Fd()))
        if err == nil {
            for i := 0; i < width; i++ {
                fmt.Print("─")
            }
            fmt.Println()
        }
    }
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"context"
	"encoding/json"
	"html/template"
	"net/http"
	"net/http/pprof"
	"os"

	"github.com/elazarl/go-bindata-assetfs"
	"github.com/gorilla/websocket"
	"github.com/nicksnyder/go-i18n/i18n"
	bloomsky "github.com/patrickalin/bloomsky-api-go"
	"github.com/patrickalin/bloomsky-client-go/assembly-assetfs"
)

type httpServer struct {
	bloomskyMessageToHTTP chan bloomsky.Bloomsky
	httpServ              *http.Server
	conn                  *websocket.Conn
	msgJSON               []byte
	templates             map[string]*template.Template
	store                 store
}
type pageHome struct {
	Websockerurl string
}

type logStru struct {
	Time  string `json:"time"`
	Msg   string `json:"msg"`
	Level string `json:"level"`
	Param string `json:"param"`
	Fct   string `json:"fct"`
}

const logfile = "bloomsky.log"

//listen
func (httpServ *httpServer) listen(context context.Context) {
	go func() {
		for {
			mybloomsky := <-httpServ.bloomskyMessageToHTTP
			var err error

			httpServ.msgJSON, err = json.Marshal(mybloomsky.GetBloomskyStruct())
			checkErr(err, funcName(), "Marshal json Error")

			if httpServ.msgJSON == nil {
				logFatal(err, funcName(), "JSON Empty")
			}

			if httpServ.conn != nil {
				httpServ.refreshWebsocket()
			}

			logDebug(funcName(), "Listen", string(httpServ.msgJSON))
		}
	}()
}

func (httpServ *httpServer) refreshWebsocket() {
	t := append(httpServ.msgJSON, []byte("SEPARATOR"+httpServ.store.String("temperatureCelsius"))...)
	t = append(t, []byte("SEPARATOR"+httpServ.store.String("windGustkmh"))...)
	err := httpServ.conn.WriteMessage(websocket.TextMessage, t)
	checkErr(err, funcName(), "Impossible to write to websocket")
}

// Websocket handler to send data
func (httpServ *httpServer) refreshdata(w http.ResponseWriter, r *http.Request) {
	logDebug(funcName(), "Refresh data Websocket handle")

	upgrader := websocket.Upgrader{}

	var err error

	httpServ.conn, err = upgrader.Upgrade(w, r, nil)
	checkErr(err, funcName(), "Upgrade upgrader")

	if err = httpServ.conn.WriteMessage(websocket.TextMessage, httpServ.msgJSON); err != nil {
		logFatal(err, funcName(), "Impossible to write to websocket")
	}
}

// Websocket handler to send data
func (httpServ *httpServer) refreshHistory(w http.ResponseWriter, r *http.Request) {
	logDebug(funcName(), "Refresh history Websocket handle")

	upgrader := websocket.Upgrader{}

	var err error

	httpServ.conn, err = upgrader.Upgrade(w, r, nil)
	checkErr(err, funcName(), "Upgrade upgrader")

	httpServ.refreshWebsocket()
}

func getWs(r *http.Request) string {
	if r.TLS == nil {
		return "ws://"
	}
	return "wss://"
}

// Home bloomsky handler
func (httpServ *httpServer) home(w http.ResponseWriter, r *http.Request) {
	logDebug(funcName(), "Home Http handle")

	p := pageHome{Websockerurl: getWs(r) + r.Host + "/refreshdata"}
	if err := httpServ.templates["home"].Execute(w, p); err != nil {
		logFatal(err, funcName(), "Execute template home")
	}
}

// Home bloomsky handler
func (httpServ *httpServer) history(w http.ResponseWriter, r *http.Request) {
	logDebug(funcName(), "Home History handle")

	p := pageHome{Websockerurl: getWs(r) + r.Host + "/refreshhistory"}
	if err := httpServ.templates["history"].Execute(w, p); err != nil {
		logFatal(err, funcName(), "Execute template history")
	}
}

// Log handler
func (httpServ *httpServer) log(w http.ResponseWriter, r *http.Request) {
	logDebug(funcName(), "Log Http handle")

	p := map[string]interface{}{"logRange": createArrayLog(logfile)}

	err := httpServ.templates["log"].Execute(w, p)
	checkErr(err, funcName(), "Compile template log")
}

func getFileServer(dev bool) http.FileSystem {
	if dev {
		return http.Dir("static")
	}
	return &assetfs.AssetFS{Asset: assemblyAssetfs.Asset, AssetDir: assemblyAssetfs.AssetDir, AssetInfo: assemblyAssetfs.AssetInfo, Prefix: "static"}
}

//createWebServer create web server
func createWebServer(in chan bloomsky.Bloomsky, HTTPPort string, HTTPSPort string, translate i18n.TranslateFunc, devel bool, store store) (*httpServer, error) {

	t := make(map[string]*template.Template)
	t["home"] = GetHTMLTemplate("bloomsky", []string{"tmpl/index.html", "tmpl/bloomsky/script.html", "tmpl/bloomsky/body.html", "tmpl/bloomsky/menu.html", "tmpl/header.html", "tmpl/endScript.html"}, map[string]interface{}{"T": translate}, devel)
	t["history"] = GetHTMLTemplate("bloomsky", []string{"tmpl/index.html", "tmpl/history/script.html", "tmpl/history/body.html", "tmpl/history/menu.html", "tmpl/header.html", "tmpl/endScript.html"}, map[string]interface{}{"T": translate}, devel)
	t["log"] = GetHTMLTemplate("bloomsky", []string{"tmpl/index.html", "tmpl/log/script.html", "tmpl/log/body.html", "tmpl/log/menu.html", "tmpl/header.html", "tmpl/endScript.html"}, map[string]interface{}{"T": translate}, devel)

	server := &httpServer{bloomskyMessageToHTTP: in,
		templates: t,
		store:     store}

	fs := http.FileServer(getFileServer(devel))

	s := http.NewServeMux()

	s.Handle("/static/", http.StripPrefix("/static/", fs))
	s.Handle("/favicon.ico", fs)
	s.HandleFunc("/", server.home)
	s.HandleFunc("/refreshdata", server.refreshdata)
	s.HandleFunc("/refreshhistory", server.refreshHistory)
	s.HandleFunc("/log", server.log)
	s.HandleFunc("/history", server.history)
	s.HandleFunc("/debug/pprof/", pprof.Index)
	s.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
	s.HandleFunc("/debug/pprof/profile", pprof.Profile)
	s.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
	s.HandleFunc("/debug/pprof/trace", pprof.Trace)

	h := &http.Server{Addr: HTTPPort, Handler: s}
	go func() {
		err := h.ListenAndServe()
		checkErr(err, funcName(), "Error when I create the server HTTP (don't forget ':')")
	}()

	hs := &http.Server{Addr: HTTPSPort, Handler: s}
	go func() {
		err := hs.ListenAndServeTLS("server.crt", "server.key")
		checkErr(err, funcName(), "Error when I create the server HTTPS (don't forget ':')")
	}()

	logInfo(funcName(), "Server HTTP listen on port", HTTPPort)
	logInfo(funcName(), "Server HTTPS listen on port", HTTPSPort)

	server.httpServ = h
	return server, nil
}

func createArrayLog(logFile string) (logRange []logStru) {
	file, err := os.Open(logFile)
	checkErr(err, funcName(), "Imposible to open file", "bloomsky.log")

	defer file.Close()
	scanner := bufio.NewScanner(file)

	var tt logStru
	for scanner.Scan() {
		json.Unmarshal([]byte(scanner.Text()), &tt)
		checkErr(err, funcName(), "Impossible to unmarshall log", scanner.Text())

		logRange = append(logRange, tt)
	}

	scanner.Err()
	checkErr(err, funcName(), "Scanner Err")

	return logRange
}
<commit_msg>catch all errors<commit_after>package main

import (
	"bufio"
	"context"
	"encoding/json"
	"html/template"
	"net/http"
	"net/http/pprof"
	"os"

	"github.com/elazarl/go-bindata-assetfs"
	"github.com/gorilla/websocket"
	"github.com/nicksnyder/go-i18n/i18n"
	bloomsky "github.com/patrickalin/bloomsky-api-go"
	"github.com/patrickalin/bloomsky-client-go/assembly-assetfs"
)

type httpServer struct {
	bloomskyMessageToHTTP chan bloomsky.Bloomsky
	httpServ              *http.Server
	conn                  *websocket.Conn
	msgJSON               []byte
	templates             map[string]*template.Template
	store                 store
}
type pageHome struct {
	Websockerurl string
}

type logStru struct {
	Time  string `json:"time"`
	Msg   string `json:"msg"`
	Level string `json:"level"`
	Param string `json:"param"`
	Fct   string `json:"fct"`
}

const logfile = "bloomsky.log"

//listen
func (httpServ *httpServer) listen(context context.Context) {
	go func() {
		for {
			mybloomsky := <-httpServ.bloomskyMessageToHTTP
			var err error

			httpServ.msgJSON, err = json.Marshal(mybloomsky.GetBloomskyStruct())
			checkErr(err, funcName(), "Marshal json Error")

			if httpServ.msgJSON == nil {
				logFatal(err, funcName(), "JSON Empty")
			}

			if httpServ.conn != nil {
				httpServ.refreshWebsocket()
			}

			logDebug(funcName(), "Listen", string(httpServ.msgJSON))
		}
	}()
}

func (httpServ *httpServer) refreshWebsocket() {
	t := append(httpServ.msgJSON, []byte("SEPARATOR"+httpServ.store.String("temperatureCelsius"))...)
	t = append(t, []byte("SEPARATOR"+httpServ.store.String("windGustkmh"))...)
	err := httpServ.conn.WriteMessage(websocket.TextMessage, t)
	checkErr(err, funcName(), "Impossible to write to websocket")
}

// Websocket handler to send data
func (httpServ *httpServer) refreshdata(w http.ResponseWriter, r *http.Request) {
	logDebug(funcName(), "Refresh data Websocket handle")

	upgrader := websocket.Upgrader{}

	var err error

	httpServ.conn, err = upgrader.Upgrade(w, r, nil)
	checkErr(err, funcName(), "Upgrade upgrader")

	if err = httpServ.conn.WriteMessage(websocket.TextMessage, httpServ.msgJSON); err != nil {
		logFatal(err, funcName(), "Impossible to write to websocket")
	}
}

// Websocket handler to send data
func (httpServ *httpServer) refreshHistory(w http.ResponseWriter, r *http.Request) {
	logDebug(funcName(), "Refresh history Websocket handle")

	upgrader := websocket.Upgrader{}

	var err error

	httpServ.conn, err = upgrader.Upgrade(w, r, nil)
	checkErr(err, funcName(), "Upgrade upgrader")

	httpServ.refreshWebsocket()
}

func getWs(r *http.Request) string {
	if r.TLS == nil {
		return "ws://"
	}
	return "wss://"
}

// Home bloomsky handler
func (httpServ *httpServer) home(w http.ResponseWriter, r *http.Request) {
	logDebug(funcName(), "Home Http handle")

	p := pageHome{Websockerurl: getWs(r) + r.Host + "/refreshdata"}
	if err := httpServ.templates["home"].Execute(w, p); err != nil {
		logFatal(err, funcName(), "Execute template home")
	}
}

// Home bloomsky handler
func (httpServ *httpServer) history(w http.ResponseWriter, r *http.Request) {
	logDebug(funcName(), "Home History handle")

	p := pageHome{Websockerurl: getWs(r) + r.Host + "/refreshhistory"}
	if err := httpServ.templates["history"].Execute(w, p); err != nil {
		logFatal(err, funcName(), "Execute template history")
	}
}

// Log handler
func (httpServ *httpServer) log(w http.ResponseWriter, r *http.Request) {
	logDebug(funcName(), "Log Http handle")

	p := map[string]interface{}{"logRange": createArrayLog(logfile)}

	err := httpServ.templates["log"].Execute(w, p)
	checkErr(err, funcName(), "Compile template log")
}

func getFileServer(dev bool) http.FileSystem {
	if dev {
		return http.Dir("static")
	}
	return &assetfs.AssetFS{Asset: assemblyAssetfs.Asset, AssetDir: assemblyAssetfs.AssetDir, AssetInfo: assemblyAssetfs.AssetInfo, Prefix: "static"}
}

//createWebServer create web server
func createWebServer(in chan bloomsky.Bloomsky, HTTPPort string, HTTPSPort string, translate i18n.TranslateFunc, devel bool, store store) (*httpServer, error) {

	t := make(map[string]*template.Template)
	t["home"] = GetHTMLTemplate("bloomsky", []string{"tmpl/index.html", "tmpl/bloomsky/script.html", "tmpl/bloomsky/body.html", "tmpl/bloomsky/menu.html", "tmpl/header.html", "tmpl/endScript.html"}, map[string]interface{}{"T": translate}, devel)
	t["history"] = GetHTMLTemplate("bloomsky", []string{"tmpl/index.html", "tmpl/history/script.html", "tmpl/history/body.html", "tmpl/history/menu.html", "tmpl/header.html", "tmpl/endScript.html"}, map[string]interface{}{"T": translate}, devel)
	t["log"] = GetHTMLTemplate("bloomsky", []string{"tmpl/index.html", "tmpl/log/script.html", "tmpl/log/body.html", "tmpl/log/menu.html", "tmpl/header.html", "tmpl/endScript.html"}, map[string]interface{}{"T": translate}, devel)

	server := &httpServer{bloomskyMessageToHTTP: in,
		templates: t,
		store:     store}

	fs := http.FileServer(getFileServer(devel))

	s := http.NewServeMux()

	s.Handle("/static/", http.StripPrefix("/static/", fs))
	s.Handle("/favicon.ico", fs)
	s.HandleFunc("/", server.home)
	s.HandleFunc("/refreshdata", server.refreshdata)
	s.HandleFunc("/refreshhistory", server.refreshHistory)
	s.HandleFunc("/log", server.log)
	s.HandleFunc("/history", server.history)
	s.HandleFunc("/debug/pprof/", pprof.Index)
	s.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
	s.HandleFunc("/debug/pprof/profile", pprof.Profile)
	s.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
	s.HandleFunc("/debug/pprof/trace", pprof.Trace)

	h := &http.Server{Addr: HTTPPort, Handler: s}
	go func() {
		err := h.ListenAndServe()
		checkErr(err, funcName(), "Error when I create the server HTTP (don't forget ':')")
	}()

	hs := &http.Server{Addr: HTTPSPort, Handler: s}
	go func() {
		err := hs.ListenAndServeTLS("server.crt", "server.key")
		checkErr(err, funcName(), "Error when I create the server HTTPS (don't forget ':')")
	}()

	logInfo(funcName(), "Server HTTP listen on port", HTTPPort)
	logInfo(funcName(), "Server HTTPS listen on port", HTTPSPort)

	server.httpServ = h
	return server, nil
}

func createArrayLog(logFile string) (logRange []logStru) {
	file, err := os.Open(logFile)
	checkErr(err, funcName(), "Imposible to open file", logFile)

	defer func() {
		err = file.Close()
		checkErr(err, funcName(), "Imposible to close file", logFile)
	}()
	scanner := bufio.NewScanner(file)

	var tt logStru
	for scanner.Scan() {
		err = json.Unmarshal([]byte(scanner.Text()), &tt)
		checkErr(err, funcName(), "Impossible to unmarshall log", scanner.Text())

		logRange = append(logRange, tt)
	}

	err = scanner.Err()
	checkErr(err, funcName(), "Scanner Err")

	return logRange
}
<|endoftext|>


<commit_before>/*
Copyright 2016 - 2017 Huawei Technologies Co., Ltd. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cmd

import (
	"context"
	"crypto/tls"
	"fmt"
	"net"
	"net/http"
	"os"
	"os/signal"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/spf13/cobra"
	"gopkg.in/macaron.v1"

	"github.com/Huawei/containerops/common"
	"github.com/Huawei/containerops/common/utils"
	"github.com/Huawei/containerops/dockyard/model"
	"github.com/Huawei/containerops/dockyard/web"
)

var addressOption string
var portOption int

// webCmd is sub command which start/stop/monitor Dockyard's REST API daemon.
var daemonCmd = &cobra.Command{
	Use:   "daemon",
	Short: "Web sub command start/stop/monitor Dockyard's REST API daemon.",
	Long:  ``,
}

// start Dockyard deamon sub command
var startDaemonCmd = &cobra.Command{
	Use:   "start",
	Short: "Start Dockyard's REST API daemon.",
	Long:  ``,
	Run:   startDeamon,
}

// stop Dockyard deamon sub command
var stopDaemonCmd = &cobra.Command{
	Use:   "stop",
	Short: "stop Dockyard's REST API daemon.",
	Long:  ``,
	Run:   stopDaemon,
}

// monitor Dockyard deamon sub command
var monitorDeamonCmd = &cobra.Command{
	Use:   "monitor",
	Short: "monitor Dockyard's REST API daemon.",
	Long:  ``,
	Run:   monitorDaemon,
}

// init()
func init() {
	RootCmd.AddCommand(daemonCmd)

	// Add start sub command
	daemonCmd.AddCommand(startDaemonCmd)
	startDaemonCmd.Flags().StringVarP(&addressOption, "address", "a", "", "http or https listen address.")
	startDaemonCmd.Flags().IntVarP(&portOption, "port", "p", 0, "the port of http.")

	// Add stop sub command
	daemonCmd.AddCommand(stopDaemonCmd)
	// Add daemon sub command
	daemonCmd.AddCommand(monitorDeamonCmd)
}

// startDeamon() start Dockyard's REST API daemon.
func startDeamon(cmd *cobra.Command, args []string) {
	model.OpenDatabase(&common.Database)
	m := macaron.New()

	// Set Macaron Web Middleware And Routers
	web.SetDockyardMacaron(m, cfgFile)

	var server *http.Server
	stopChan := make(chan os.Signal)

	signal.Notify(stopChan, os.Interrupt)

	address := common.Web.Address
	if addressOption != "" {
		address = addressOption
	}
	port := common.Web.Port
	if portOption != 0 {
		port = portOption
	}

	go func() {
		switch common.Web.Mode {
		case "https":
			listenAddr := fmt.Sprintf("%s:%d", address, port)
			server = &http.Server{Addr: listenAddr, TLSConfig: &tls.Config{MinVersion: tls.VersionTLS10}, Handler: m}
			if err := server.ListenAndServeTLS(common.Web.Cert, common.Web.Key); err != nil {
				log.Errorf("Start Dockyard https service error: %s\n", err.Error())
			}

			break
		case "unix":
			listenAddr := fmt.Sprintf("%s", address)
			if utils.IsFileExist(listenAddr) {
				os.Remove(listenAddr)
			}

			if listener, err := net.Listen("unix", listenAddr); err != nil {
				log.Errorf("Start Dockyard unix socket error: %s\n", err.Error())
			} else {
				server = &http.Server{Handler: m}
				if err := server.Serve(listener); err != nil {
					log.Errorf("Start Dockyard unix socket error: %s\n", err.Error())
				}
			}
			break
		default:
			log.Fatalf("Invalid listen mode: %s\n", common.Web.Mode)
			os.Exit(1)
			break
		}
	}()

	// Graceful shutdown
	<-stopChan // wait for SIGINT
	log.Errorln("Shutting down server...")

	if server != nil {
		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
		defer cancel()
		server.Shutdown(ctx)
	}

	log.Errorln("Server gracefully stopped")
}

// stopDaemon() stop Dockyard's REST API daemon.
func stopDaemon(cmd *cobra.Command, args []string) {

}

// monitordAemon() monitor Dockyard's REST API deamon.
func monitorDaemon(cmd *cobra.Command, args []string) {

}
<commit_msg>Fix typo errors.<commit_after>/*
Copyright 2016 - 2017 Huawei Technologies Co., Ltd. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cmd

import (
	"context"
	"crypto/tls"
	"fmt"
	"net"
	"net/http"
	"os"
	"os/signal"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/spf13/cobra"
	"gopkg.in/macaron.v1"

	"github.com/Huawei/containerops/common"
	"github.com/Huawei/containerops/common/utils"
	"github.com/Huawei/containerops/dockyard/model"
	"github.com/Huawei/containerops/dockyard/web"
)

var addressOption string
var portOption int

// webCmd is sub command which start/stop/monitor Dockyard's REST API daemon.
var daemonCmd = &cobra.Command{
	Use:   "daemon",
	Short: "Web sub command start/stop/monitor Dockyard's REST API daemon.",
	Long:  ``,
}

// start Dockyard daemon sub command
var startDaemonCmd = &cobra.Command{
	Use:   "start",
	Short: "Start Dockyard's REST API daemon.",
	Long:  ``,
	Run:   startDeamon,
}

// stop Dockyard daemon sub command
var stopDaemonCmd = &cobra.Command{
	Use:   "stop",
	Short: "stop Dockyard's REST API daemon.",
	Long:  ``,
	Run:   stopDaemon,
}

// monitor Dockyard daemon sub command
var monitorDaemonCmd = &cobra.Command{
	Use:   "monitor",
	Short: "monitor Dockyard's REST API daemon.",
	Long:  ``,
	Run:   monitorDaemon,
}

// init()
func init() {
	RootCmd.AddCommand(daemonCmd)

	// Add start sub command
	daemonCmd.AddCommand(startDaemonCmd)
	startDaemonCmd.Flags().StringVarP(&addressOption, "address", "a", "", "http or https listen address.")
	startDaemonCmd.Flags().IntVarP(&portOption, "port", "p", 0, "the port of http.")

	// Add stop sub command
	daemonCmd.AddCommand(stopDaemonCmd)
	// Add daemon sub command
	daemonCmd.AddCommand(monitorDaemonCmd)
}

// startDeamon() start Dockyard's REST API daemon.
func startDeamon(cmd *cobra.Command, args []string) {
	model.OpenDatabase(&common.Database)
	m := macaron.New()

	// Set Macaron Web Middleware And Routers
	web.SetDockyardMacaron(m, cfgFile)

	var server *http.Server
	stopChan := make(chan os.Signal)

	signal.Notify(stopChan, os.Interrupt)

	address := common.Web.Address
	if addressOption != "" {
		address = addressOption
	}
	port := common.Web.Port
	if portOption != 0 {
		port = portOption
	}

	go func() {
		switch common.Web.Mode {
		case "https":
			listenAddr := fmt.Sprintf("%s:%d", address, port)
			server = &http.Server{Addr: listenAddr, TLSConfig: &tls.Config{MinVersion: tls.VersionTLS10}, Handler: m}
			if err := server.ListenAndServeTLS(common.Web.Cert, common.Web.Key); err != nil {
				log.Errorf("Start Dockyard https service error: %s\n", err.Error())
			}

			break
		case "unix":
			listenAddr := fmt.Sprintf("%s", address)
			if utils.IsFileExist(listenAddr) {
				os.Remove(listenAddr)
			}

			if listener, err := net.Listen("unix", listenAddr); err != nil {
				log.Errorf("Start Dockyard unix socket error: %s\n", err.Error())
			} else {
				server = &http.Server{Handler: m}
				if err := server.Serve(listener); err != nil {
					log.Errorf("Start Dockyard unix socket error: %s\n", err.Error())
				}
			}
			break
		default:
			log.Fatalf("Invalid listen mode: %s\n", common.Web.Mode)
			os.Exit(1)
			break
		}
	}()

	// Graceful shutdown
	<-stopChan // wait for SIGINT
	log.Errorln("Shutting down server...")

	if server != nil {
		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
		defer cancel()
		server.Shutdown(ctx)
	}

	log.Errorln("Server gracefully stopped")
}

// stopDaemon() stop Dockyard's REST API daemon.
func stopDaemon(cmd *cobra.Command, args []string) {

}

// monitorDaemon() monitor Dockyard's REST API deamon.
func monitorDaemon(cmd *cobra.Command, args []string) {

}
<|endoftext|>


<commit_before>package nk

/*
#include "nuklear.h"
*/
import "C"
import "unsafe"

func (ctx *Context) Input() *Input {
	return (*Input)(&ctx.input)
}

func (ctx *Context) Style() *Style {
	return (*Style)(&ctx.style)
}

func (ctx *Context) Memory() *Buffer {
	return (*Buffer)(&ctx.memory)
}

func (ctx *Context) Clip() *Clipboard {
	return (*Clipboard)(&ctx.clip)
}

func (ctx *Context) LastWidgetState() Flags {
	return (Flags)(ctx.last_widget_state)
}

func (ctx *Context) DeltaTimeSeconds() float32 {
	return (float32)(ctx.delta_time_seconds)
}

func (ctx *Context) ButtonBehavior() ButtonBehavior {
	return (ButtonBehavior)(ctx.button_behavior)
}

func (ctx *Context) Stacks() *ConfigurationStacks {
	return (*ConfigurationStacks)(&ctx.stacks)
}

func (input *Input) Mouse() *Mouse {
	return (*Mouse)(&input.mouse)
}

func (mouse *Mouse) Grab() bool {
	return mouse.grab == True
}

func (mouse *Mouse) Grabbed() bool {
	return mouse.grabbed == True
}

func (mouse *Mouse) Ungrab() bool {
	return mouse.ungrab == True
}

func (mouse *Mouse) ScrollDelta() Vec2 {
	return (Vec2)(mouse.scroll_delta)
}

func (mouse *Mouse) Pos() (int32, int32) {
	return (int32)(mouse.pos.x), (int32)(mouse.pos.y)
}

func (mouse *Mouse) SetPos(x, y int32) {
	mouse.pos.x = (C.float)(x)
	mouse.pos.y = (C.float)(y)
}

func (mouse *Mouse) Prev() (int32, int32) {
	return (int32)(mouse.prev.x), (int32)(mouse.prev.y)
}

func (mouse *Mouse) Delta() (int32, int32) {
	return (int32)(mouse.delta.x), (int32)(mouse.delta.y)
}

var VertexLayoutEnd = DrawVertexLayoutElement{
	Attribute: VertexAttributeCount,
	Format:    FormatCount,
	Offset:    0,
}

func NkDrawForeach(ctx *Context, b *Buffer, fn func(cmd *DrawCommand)) {
	cmd := Nk_DrawBegin(ctx, b)
	for {
		if cmd == nil {
			break
		}
		fn(cmd)
		cmd = Nk_DrawNext(cmd, b, ctx)
	}
}

func NkFontAtlasAddFromBytes(atlas *FontAtlas, data []byte, height float32, config *FontConfig) *Font {
	dataPtr := unsafe.Pointer((*sliceHeader)(unsafe.Pointer(&data)).Data)
	return NkFontAtlasAddFromMemory(atlas, dataPtr, Size(len(data)), height, config)
}

func (fc *FontConfig) SetRange(r *Rune) {
	fc._range = (*C.nk_rune)(r)
}

func (fc *FontConfig) SetOversample(v, h int) {
	fc.oversample_v = (C.uchar)(v)
	fc.oversample_h = (C.uchar)(h)
}

func (h Handle) ID() int {
	return int(*(*int64)(unsafe.Pointer(&h)))
}

func (h Handle) Ptr() uintptr {
	return *(*uintptr)(unsafe.Pointer(&h))
}

func (atlas *FontAtlas) DefaultFont() *Font {
	return (*Font)(atlas.default_font)
}

func (c Color) R() Byte {
	return Byte(c.r)
}

func (c Color) G() Byte {
	return Byte(c.g)
}

func (c Color) B() Byte {
	return Byte(c.b)
}

func (c Color) A() Byte {
	return Byte(c.a)
}

func (c Color) RGBA() (Byte, Byte, Byte, Byte) {
	return Byte(c.r), Byte(c.g), Byte(c.b), Byte(c.a)
}

func (c Color) RGBAi() (int32, int32, int32, int32) {
	return int32(c.r), int32(c.g), int32(c.b), int32(c.a)
}

func (c *Color) SetR(r Byte) {
	c.r = (C.nk_byte)(r)
}

func (c *Color) SetG(g Byte) {
	c.g = (C.nk_byte)(g)
}

func (c *Color) SetB(b Byte) {
	c.b = (C.nk_byte)(b)
}

func (c *Color) SetA(a Byte) {
	c.a = (C.nk_byte)(a)
}

func (c *Color) SetRGBA(r, g, b, a Byte) {
	c.r = (C.nk_byte)(r)
	c.g = (C.nk_byte)(g)
	c.b = (C.nk_byte)(b)
	c.a = (C.nk_byte)(a)
}

func (c *Color) SetRGBAi(r, g, b, a int32) {
	c.r = (C.nk_byte)(r)
	c.g = (C.nk_byte)(g)
	c.b = (C.nk_byte)(b)
	c.a = (C.nk_byte)(a)
}

func (cmd *DrawCommand) ElemCount() int {
	return (int)(cmd.elem_count)
}

func (cmd *DrawCommand) Texture() Handle {
	return (Handle)(cmd.texture)
}

func (cmd *DrawCommand) ClipRect() *Rect {
	return (*Rect)(&cmd.clip_rect)
}

func (f Font) Handle() *UserFont {
	return NewUserFontRef(unsafe.Pointer(&f.handle))
}

func (r *Rect) X() float32 {
	return (float32)(r.x)
}

func (r *Rect) Y() float32 {
	return (float32)(r.y)
}

func (r *Rect) W() float32 {
	return (float32)(r.w)
}

func (r *Rect) H() float32 {
	return (float32)(r.h)
}

func (v *Vec2) X() float32 {
	return (float32)(v.x)
}

func (v *Vec2) Y() float32 {
	return (float32)(v.y)
}

func (v *Vec2) SetX(x float32) {
	v.x = (C.float)(x)
}

func (v *Vec2) SetY(y float32) {
	v.y = (C.float)(y)
}

func (v *Vec2) Reset() {
	v.x = 0
	v.y = 0
}

// Allocated is the total amount of memory allocated.
func (b *Buffer) Allocated() int {
	return (int)(b.allocated)
}

// Size is the current size of the buffer.
func (b *Buffer) Size() int {
	return (int)(b.size)
}

// Type is the memory management type of the buffer.
func (b *Buffer) Type() AllocationType {
	return (AllocationType)(b._type)
}

func (l *ListView) Begin() int {
	return (int)(l.begin)
}

func (l *ListView) End() int {
	return (int)(l.end)
}

func (l *ListView) Count() int {
	return (int)(l.count)
}

func (panel *Panel) Bounds() *Rect {
	return (*Rect)(&panel.bounds)
}
<commit_msg>Add FontConfig-related stuff<commit_after>package nk

/*
#include "nuklear.h"

const nk_rune nk_font_japanese_glyph_ranges[] = {
    0x0020, 0x00FF,
    0x2200, 0x22FF, // Mathematical Operators
    0x3000, 0x303F, // CJK Symbols and Punctuation
    0x3040, 0x309F, // Hiragana
    0x30A0, 0x30FF, // Katakana
    0x0370, 0x03FF, // Greek and Coptic
    0xFF00, 0xFFEF, // Halfwidth and Fullwidth Forms
    0x4E00, 0x9FFF, // CJK Unified Ideographs
    0
};
*/
import "C"
import "unsafe"

func (ctx *Context) Input() *Input {
	return (*Input)(&ctx.input)
}

func (ctx *Context) Style() *Style {
	return (*Style)(&ctx.style)
}

func (ctx *Context) Memory() *Buffer {
	return (*Buffer)(&ctx.memory)
}

func (ctx *Context) Clip() *Clipboard {
	return (*Clipboard)(&ctx.clip)
}

func (ctx *Context) LastWidgetState() Flags {
	return (Flags)(ctx.last_widget_state)
}

func (ctx *Context) DeltaTimeSeconds() float32 {
	return (float32)(ctx.delta_time_seconds)
}

func (ctx *Context) ButtonBehavior() ButtonBehavior {
	return (ButtonBehavior)(ctx.button_behavior)
}

func (ctx *Context) Stacks() *ConfigurationStacks {
	return (*ConfigurationStacks)(&ctx.stacks)
}

func (input *Input) Mouse() *Mouse {
	return (*Mouse)(&input.mouse)
}

func (mouse *Mouse) Grab() bool {
	return mouse.grab == True
}

func (mouse *Mouse) Grabbed() bool {
	return mouse.grabbed == True
}

func (mouse *Mouse) Ungrab() bool {
	return mouse.ungrab == True
}

func (mouse *Mouse) ScrollDelta() Vec2 {
	return (Vec2)(mouse.scroll_delta)
}

func (mouse *Mouse) Pos() (int32, int32) {
	return (int32)(mouse.pos.x), (int32)(mouse.pos.y)
}

func (mouse *Mouse) SetPos(x, y int32) {
	mouse.pos.x = (C.float)(x)
	mouse.pos.y = (C.float)(y)
}

func (mouse *Mouse) Prev() (int32, int32) {
	return (int32)(mouse.prev.x), (int32)(mouse.prev.y)
}

func (mouse *Mouse) Delta() (int32, int32) {
	return (int32)(mouse.delta.x), (int32)(mouse.delta.y)
}

var VertexLayoutEnd = DrawVertexLayoutElement{
	Attribute: VertexAttributeCount,
	Format:    FormatCount,
	Offset:    0,
}

func NkDrawForeach(ctx *Context, b *Buffer, fn func(cmd *DrawCommand)) {
	cmd := Nk_DrawBegin(ctx, b)
	for {
		if cmd == nil {
			break
		}
		fn(cmd)
		cmd = Nk_DrawNext(cmd, b, ctx)
	}
}

func NkFontAtlasAddFromBytes(atlas *FontAtlas, data []byte, height float32, config *FontConfig) *Font {
	dataPtr := unsafe.Pointer((*sliceHeader)(unsafe.Pointer(&data)).Data)
	return NkFontAtlasAddFromMemory(atlas, dataPtr, Size(len(data)), height, config)
}

func NkFontJapaneseGlyphRanges() *Rune {
	__ret := &(C.nk_font_japanese_glyph_ranges[0])
	__v := *(**Rune)(unsafe.Pointer(&__ret))
	return __v
}

func (fc *FontConfig) SetPixelSnap(b bool) {
	var i int
	if b {
		i = 1
	} else {
		i = 0
	}
	fc.pixel_snap = (C.uchar)(i)
}

func (fc *FontConfig) SetOversample(v, h int) {
	fc.oversample_v = (C.uchar)(v)
	fc.oversample_h = (C.uchar)(h)
}

func (fc *FontConfig) SetRange(r *Rune) {
	fc._range = (*C.nk_rune)(r)
}

func (h Handle) ID() int {
	return int(*(*int64)(unsafe.Pointer(&h)))
}

func (h Handle) Ptr() uintptr {
	return *(*uintptr)(unsafe.Pointer(&h))
}

func (atlas *FontAtlas) DefaultFont() *Font {
	return (*Font)(atlas.default_font)
}

func (c Color) R() Byte {
	return Byte(c.r)
}

func (c Color) G() Byte {
	return Byte(c.g)
}

func (c Color) B() Byte {
	return Byte(c.b)
}

func (c Color) A() Byte {
	return Byte(c.a)
}

func (c Color) RGBA() (Byte, Byte, Byte, Byte) {
	return Byte(c.r), Byte(c.g), Byte(c.b), Byte(c.a)
}

func (c Color) RGBAi() (int32, int32, int32, int32) {
	return int32(c.r), int32(c.g), int32(c.b), int32(c.a)
}

func (c *Color) SetR(r Byte) {
	c.r = (C.nk_byte)(r)
}

func (c *Color) SetG(g Byte) {
	c.g = (C.nk_byte)(g)
}

func (c *Color) SetB(b Byte) {
	c.b = (C.nk_byte)(b)
}

func (c *Color) SetA(a Byte) {
	c.a = (C.nk_byte)(a)
}

func (c *Color) SetRGBA(r, g, b, a Byte) {
	c.r = (C.nk_byte)(r)
	c.g = (C.nk_byte)(g)
	c.b = (C.nk_byte)(b)
	c.a = (C.nk_byte)(a)
}

func (c *Color) SetRGBAi(r, g, b, a int32) {
	c.r = (C.nk_byte)(r)
	c.g = (C.nk_byte)(g)
	c.b = (C.nk_byte)(b)
	c.a = (C.nk_byte)(a)
}

func (cmd *DrawCommand) ElemCount() int {
	return (int)(cmd.elem_count)
}

func (cmd *DrawCommand) Texture() Handle {
	return (Handle)(cmd.texture)
}

func (cmd *DrawCommand) ClipRect() *Rect {
	return (*Rect)(&cmd.clip_rect)
}

func (f Font) Handle() *UserFont {
	return NewUserFontRef(unsafe.Pointer(&f.handle))
}

func (r *Rect) X() float32 {
	return (float32)(r.x)
}

func (r *Rect) Y() float32 {
	return (float32)(r.y)
}

func (r *Rect) W() float32 {
	return (float32)(r.w)
}

func (r *Rect) H() float32 {
	return (float32)(r.h)
}

func (v *Vec2) X() float32 {
	return (float32)(v.x)
}

func (v *Vec2) Y() float32 {
	return (float32)(v.y)
}

func (v *Vec2) SetX(x float32) {
	v.x = (C.float)(x)
}

func (v *Vec2) SetY(y float32) {
	v.y = (C.float)(y)
}

func (v *Vec2) Reset() {
	v.x = 0
	v.y = 0
}

// Allocated is the total amount of memory allocated.
func (b *Buffer) Allocated() int {
	return (int)(b.allocated)
}

// Size is the current size of the buffer.
func (b *Buffer) Size() int {
	return (int)(b.size)
}

// Type is the memory management type of the buffer.
func (b *Buffer) Type() AllocationType {
	return (AllocationType)(b._type)
}

func (l *ListView) Begin() int {
	return (int)(l.begin)
}

func (l *ListView) End() int {
	return (int)(l.end)
}

func (l *ListView) Count() int {
	return (int)(l.count)
}

func (panel *Panel) Bounds() *Rect {
	return (*Rect)(&panel.bounds)
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"testing"

	capnp "zombiezen.com/go/capnproto2"

	"github.com/gorilla/mux"
	. "github.com/smartystreets/goconvey/convey"
)

func TestPolicy(t *testing.T) {

	Convey("Policy", t, func() {

		Convey("test my knowledge of mux", func() {
			r := mux.NewRouter()
			r.Path("/something/{(1|2)}")

			req, _ := http.NewRequest("GET", "http://localhost:1234/something/1", nil)

			var routeMatch mux.RouteMatch

			result := r.Match(req, &routeMatch)

			So(result, ShouldEqual, true)
		})

		Convey("validates", func() {

			Convey("false", func() {
				Convey("when the request path does not match the policy exact path", func() {
					_, seg, _ := capnp.NewMessage(capnp.SingleSegment(nil))

					policy, _ := NewPolicy(seg)

					policy.SetPath("/some/path")

					request, _ := NewHTTPRequest(seg)

					request.SetPath("/some/other/path")

					So(policy.validate(request), ShouldEqual, false)

				})
				Convey("when the request path does not match the policy templated path", func() {
					_, seg, _ := capnp.NewMessage(capnp.SingleSegment(nil))

					policy, _ := NewPolicy(seg)

					policy.SetPath("/some/path/{id:(1|2)}")

					request, _ := NewHTTPRequest(seg)

					request.SetPath("/some/path/3")

					result := policy.validate(request)
					So(result, ShouldEqual, false)

				})
				Convey("when the request verb does not match a single policy verb", func() {
					_, seg, _ := capnp.NewMessage(capnp.SingleSegment(nil))

					policy, _ := NewPolicy(seg)

					verbs, _ := capnp.NewTextList(seg, 1)

					verbs.Set(0, "PUT")

					policy.SetVerbs(verbs)

					request, _ := NewHTTPRequest(seg)

					request.SetVerb("GET")

					So(policy.validate(request), ShouldEqual, false)

				})
				Convey("when the request verb does not match a any policy verbs", func() {

				})
				Convey("when the request has a header key which is not present in the header policy", func() {

				})
				Convey("when the request has a header value which does not match a header policy value for the specified key", func() {

				})
				Convey("when the request has a query string key which is not present in the query policy", func() {

				})
				Convey("when the request has a query value which does not match a query policy value for the specified key", func() {

				})
			})

			Convey("true", func() {
				Convey("when the request path does match the policy exact path", func() {

				})
				Convey("when the request path does match the policy templated path", func() {

				})
				Convey("when the request verb does match a single policy verb", func() {

				})
				Convey("when the request verb does match one of many policy verbs", func() {

				})
				Convey("when the request has a header key which is present in the header policy", func() {

				})
				Convey("when the request has a header value which does match a header policy value for the specified key", func() {

				})
				Convey("when the request has a query string key which is present in the query policy", func() {

				})
				Convey("when the request has a query value which does match a query policy value for the specified key", func() {

				})
			})

		})

	})

}
<commit_msg>when the request verb does not match a any policy verbs ✔<commit_after>package main

import (
	"net/http"
	"testing"

	capnp "zombiezen.com/go/capnproto2"

	"github.com/gorilla/mux"
	. "github.com/smartystreets/goconvey/convey"
)

func TestPolicy(t *testing.T) {

	Convey("Policy", t, func() {

		Convey("test my knowledge of mux", func() {
			r := mux.NewRouter()
			r.Path("/something/{(1|2)}")

			req, _ := http.NewRequest("GET", "http://localhost:1234/something/1", nil)

			var routeMatch mux.RouteMatch

			result := r.Match(req, &routeMatch)

			So(result, ShouldEqual, true)
		})

		Convey("validates", func() {

			Convey("false", func() {
				Convey("when the request path does not match the policy exact path", func() {
					_, seg, _ := capnp.NewMessage(capnp.SingleSegment(nil))

					policy, _ := NewPolicy(seg)

					policy.SetPath("/some/path")

					request, _ := NewHTTPRequest(seg)

					request.SetPath("/some/other/path")

					So(policy.validate(request), ShouldEqual, false)

				})
				Convey("when the request path does not match the policy templated path", func() {
					_, seg, _ := capnp.NewMessage(capnp.SingleSegment(nil))

					policy, _ := NewPolicy(seg)

					policy.SetPath("/some/path/{id:(1|2)}")

					request, _ := NewHTTPRequest(seg)

					request.SetPath("/some/path/3")

					result := policy.validate(request)
					So(result, ShouldEqual, false)

				})
				Convey("when the request verb does not match a single policy verb", func() {
					_, seg, _ := capnp.NewMessage(capnp.SingleSegment(nil))

					policy, _ := NewPolicy(seg)

					verbs, _ := capnp.NewTextList(seg, 1)

					verbs.Set(0, "PUT")

					policy.SetVerbs(verbs)

					request, _ := NewHTTPRequest(seg)

					request.SetVerb("GET")

					So(policy.validate(request), ShouldEqual, false)
				})
				Convey("when the request verb does not match a any policy verbs", func() {
					_, seg, _ := capnp.NewMessage(capnp.SingleSegment(nil))

					policy, _ := NewPolicy(seg)

					verbs, _ := capnp.NewTextList(seg, 2)

					verbs.Set(0, "PUT")
					verbs.Set(1, "POST")

					policy.SetVerbs(verbs)

					request, _ := NewHTTPRequest(seg)

					request.SetVerb("GET")

					So(policy.validate(request), ShouldEqual, false)

				})
				Convey("when the request has a header key which is not present in the header policy", func() {

				})
				Convey("when the request has a header value which does not match a header policy value for the specified key", func() {

				})
				Convey("when the request has a query string key which is not present in the query policy", func() {

				})
				Convey("when the request has a query value which does not match a query policy value for the specified key", func() {

				})
			})

			Convey("true", func() {
				Convey("when the request path does match the policy exact path", func() {

				})
				Convey("when the request path does match the policy templated path", func() {

				})
				Convey("when the request verb does match a single policy verb", func() {

				})
				Convey("when the request verb does match one of many policy verbs", func() {

				})
				Convey("when the request has a header key which is present in the header policy", func() {

				})
				Convey("when the request has a header value which does match a header policy value for the specified key", func() {

				})
				Convey("when the request has a query string key which is present in the query policy", func() {

				})
				Convey("when the request has a query value which does match a query policy value for the specified key", func() {

				})
			})

		})

	})

}
<|endoftext|>


<commit_before>package honeybadger

import (
	"code.google.com/p/go-uuid/uuid"
	"encoding/json"
	"regexp"
)

type hash map[string]interface{}

type Notice struct {
	APIKey       string
	Error        Error
	Token        string
	ErrorMessage string
	ErrorClass   string
	Hostname     string
	Env          string
	Backtrace    []*Frame
	ProjectRoot  string
}

func (n *Notice) asJSON() *hash {
	return &hash{
		"api_key": n.APIKey,
		"notifier": &hash{
			"name":    "honeybadger",
			"url":     "https://github.com/honeybadger-io/honeybadger-go",
			"version": "0.0.0",
		},
		"error": &hash{
			"token":     n.Token,
			"message":   n.ErrorMessage,
			"class":     n.ErrorClass,
			"backtrace": n.Backtrace,
		},
		"server": &hash{
			"project_root":     n.ProjectRoot,
			"environment_name": n.Env,
			"hostname":         n.Hostname,
		},
	}
}

func (n *Notice) toJSON() []byte {
	if out, err := json.Marshal(n.asJSON()); err == nil {
		return out
	} else {
		panic(err)
	}
}

func composeStack(stack []*Frame, root string) (frames []*Frame) {
	if root == "" {
		return stack
	}

	re, err := regexp.Compile("^" + regexp.QuoteMeta(root))
	if err != nil {
		return stack
	}

	for _, frame := range stack {
		file := re.ReplaceAllString(frame.File, "[PROJECT_ROOT]")
		frames = append(frames, &Frame{
			File:   file,
			Number: frame.Number,
			Method: frame.Method,
		})
	}
	return
}

func newNotice(config *Configuration, err Error) *Notice {
	notice := Notice{
		APIKey:       config.APIKey,
		Error:        err,
		Token:        uuid.NewRandom().String(),
		ErrorMessage: err.Message,
		ErrorClass:   err.Class,
		Env:          config.Env,
		Hostname:     config.Hostname,
		Backtrace:    composeStack(err.Stack, config.Root),
		ProjectRoot:  config.Root,
	}

	return &notice
}
<commit_msg>Send time.<commit_after>package honeybadger

import (
	"code.google.com/p/go-uuid/uuid"
	"encoding/json"
	"regexp"
	"time"
)

type hash map[string]interface{}

type Notice struct {
	APIKey       string
	Error        Error
	Token        string
	ErrorMessage string
	ErrorClass   string
	Hostname     string
	Env          string
	Backtrace    []*Frame
	ProjectRoot  string
}

func (n *Notice) asJSON() *hash {
	return &hash{
		"api_key": n.APIKey,
		"notifier": &hash{
			"name":    "honeybadger",
			"url":     "https://github.com/honeybadger-io/honeybadger-go",
			"version": "0.0.0",
		},
		"error": &hash{
			"token":     n.Token,
			"message":   n.ErrorMessage,
			"class":     n.ErrorClass,
			"backtrace": n.Backtrace,
		},
		"server": &hash{
			"project_root":     n.ProjectRoot,
			"environment_name": n.Env,
			"hostname":         n.Hostname,
			"time":             time.Now().UTC(),
		},
	}
}

func (n *Notice) toJSON() []byte {
	if out, err := json.Marshal(n.asJSON()); err == nil {
		return out
	} else {
		panic(err)
	}
}

func composeStack(stack []*Frame, root string) (frames []*Frame) {
	if root == "" {
		return stack
	}

	re, err := regexp.Compile("^" + regexp.QuoteMeta(root))
	if err != nil {
		return stack
	}

	for _, frame := range stack {
		file := re.ReplaceAllString(frame.File, "[PROJECT_ROOT]")
		frames = append(frames, &Frame{
			File:   file,
			Number: frame.Number,
			Method: frame.Method,
		})
	}
	return
}

func newNotice(config *Configuration, err Error) *Notice {
	notice := Notice{
		APIKey:       config.APIKey,
		Error:        err,
		Token:        uuid.NewRandom().String(),
		ErrorMessage: err.Message,
		ErrorClass:   err.Class,
		Env:          config.Env,
		Hostname:     config.Hostname,
		Backtrace:    composeStack(err.Stack, config.Root),
		ProjectRoot:  config.Root,
	}

	return &notice
}
<|endoftext|>


<commit_before>package fluentd_forwarder

import (
	"bytes"
	"github.com/ugorji/go/codec"
	logging "github.com/op/go-logging"
	"net"
	"reflect"
	"sync"
	"sync/atomic"
	"time"
	"io"
	"os"
	"math/rand"
	"unsafe"
)

var randSource = rand.NewSource(time.Now().UnixNano())

type ForwardOutput struct {
	logger            *logging.Logger
	codec             *codec.MsgpackHandle
	bind              string
	retryInterval     time.Duration
	connectionTimeout time.Duration
	writeTimeout      time.Duration
	enc               *codec.Encoder
	conn              net.Conn
	flushInterval     time.Duration
	wg                sync.WaitGroup
	journalGroup      JournalGroup
	journal           Journal
	emitterChan       chan FluentRecordSet
	spoolerShutdownChan chan struct{}
	isShuttingDown    unsafe.Pointer
}

func encodeRecordSet(encoder *codec.Encoder, recordSet FluentRecordSet) error {
	v := []interface{}{recordSet.Tag, recordSet.Records}
	err := encoder.Encode(v)
	if err != nil {
		return err
	}
	return err
}

func (output *ForwardOutput) ensureConnected() error {
	if output.conn == nil {
		output.logger.Notice("Connecting to %s...", output.bind)
		conn, err := net.DialTimeout("tcp", output.bind, output.connectionTimeout)
		if err != nil {
			output.logger.Error("Failed to connect to %s (reason: %s)", output.bind, err.Error())
			return err
		} else {
			output.conn = conn
		}
	}
	return nil
}

func (output *ForwardOutput) sendBuffer(buf []byte) error {
	for len(buf) > 0 {
		if atomic.LoadPointer(&output.isShuttingDown) != unsafe.Pointer(uintptr(0)) {
			break
		}
		err := output.ensureConnected()
		if err != nil {
			output.logger.Info("Will be retried in %s", output.retryInterval.String())
			time.Sleep(output.retryInterval)
			continue
		}
		startTime := time.Now()
		if output.writeTimeout == 0 {
			output.conn.SetWriteDeadline(time.Time {})
		} else {
			output.conn.SetWriteDeadline(startTime.Add(output.writeTimeout))
		}
		n, err := output.conn.Write(buf)
		buf = buf[n:]
		if err != nil {
			output.logger.Error("Failed to flush buffer (reason: %s, left: %d bytes)", err.Error(), len(buf))
			err_, ok := err.(net.Error)
			if !ok || (!err_.Timeout() && !err_.Temporary()) {
				return err
			}
		}
		if n > 0 {
			elapsed := time.Now().Sub(startTime)
			output.logger.Info("Forwarded %d bytes in %f seconds (%d bytes left)\n", n, elapsed.Seconds(), len(buf))
		}
	}
	return nil
}

func (output *ForwardOutput) spawnSpooler() {
	output.logger.Notice("Spawning spooler")
	output.wg.Add(1)
	go func() {
		ticker := time.NewTicker(output.flushInterval)
		defer func () {
			ticker.Stop()
			output.journal.Dispose()
			if output.conn != nil {
				output.conn.Close()
			}
			output.conn = nil
			output.wg.Done()
		}()
		output.logger.Notice("Spooler started")
		outer: for {
			select {
			case <-ticker.C:
				buf := make([]byte, 16777216)
				output.logger.Notice("Flushing...")
				err := output.journal.Flush(func(chunk JournalChunk) error {
					defer chunk.Dispose()
					output.logger.Info("Flushing chunk %s", chunk.String())
					reader, err := chunk.GetReader()
					if err != nil {
						return err
					}
					for {
						n, err := reader.Read(buf)
						if n > 0 {
							err_ :=output.sendBuffer(buf[:n])
							if err_ != nil {
								return err
							}
						}
						if err != nil {
							if err == io.EOF {
								break
							} else {
								return err
							}
						}
					}
					return nil
				})
				if err != nil {
					output.logger.Error("Error during reading from the journal: %s", err.Error())
				}
			case <-output.spoolerShutdownChan:
				break outer
			}
		}
		output.logger.Notice("Spooler ended")
	}()
}

func (output *ForwardOutput) spawnEmitter() {
	output.logger.Notice("Spawning emitter")
	output.wg.Add(1)
	go func() {
		defer func() {
			output.spoolerShutdownChan <- struct{}{}
			output.wg.Done()
		}()
		output.logger.Notice("Emitter started")
		buffer := bytes.Buffer{}
		for recordSet := range output.emitterChan {
			buffer.Reset()
			encoder := codec.NewEncoder(&buffer, output.codec)
			err := encodeRecordSet(encoder, recordSet)
			if err != nil {
				output.logger.Error("%s", err.Error())
				continue
			}
			output.logger.Debug("Emitter processed %d entries", len(recordSet.Records))
			output.journal.Write(buffer.Bytes())
		}
		output.logger.Notice("Emitter ended")
	}()
}

func (output *ForwardOutput) Emit(recordSets []FluentRecordSet) error {
	defer func() {
		recover()
	}()
	for _, recordSet := range recordSets {
		output.emitterChan <- recordSet
	}
	return nil
}

func (output *ForwardOutput) String() string {
	return "output"
}

func (output *ForwardOutput) Stop() {
	if atomic.CompareAndSwapPointer(&output.isShuttingDown, unsafe.Pointer(uintptr(0)), unsafe.Pointer(uintptr(1))) {
		close(output.emitterChan)
	}
}

func (output *ForwardOutput) WaitForShutdown() {
	output.wg.Wait()
}

func (output *ForwardOutput) Start() {
	output.spawnSpooler()
	output.spawnEmitter()
}

func NewForwardOutput(logger *logging.Logger, bind string, retryInterval time.Duration, connectionTimeout time.Duration, writeTimeout time.Duration, flushInterval time.Duration, journalGroupPath string, maxJournalChunkSize int64) (*ForwardOutput, error) {
	_codec := codec.MsgpackHandle{}
	_codec.MapType = reflect.TypeOf(map[string]interface{}(nil))
	_codec.RawToString = false
	_codec.StructToArray = true

	journalFactory := NewFileJournalGroupFactory(
		logger,
		randSource,
		time.Now,
		".log",
		os.FileMode(0600),
		maxJournalChunkSize,
	)
	output := &ForwardOutput{
		logger:            logger,
		codec:             &_codec,
		bind:              bind,
		retryInterval:     retryInterval,
		connectionTimeout: connectionTimeout,
		writeTimeout:      writeTimeout,
		wg:                sync.WaitGroup{},
		flushInterval:     flushInterval,
		emitterChan:       make(chan FluentRecordSet),
		spoolerShutdownChan: make(chan struct{}),
		isShuttingDown:    unsafe.Pointer(uintptr(0)),
	}
	journalGroup, err := journalFactory.GetJournalGroup(journalGroupPath, output)
	if err != nil {
		return nil, err
	}
	defer func () {
		err := journalGroup.Dispose()
		if err != nil {
			logger.Error("%#v", err)
		}
	}()
	output.journalGroup  = journalGroup
	output.journal       = journalGroup.GetJournal("output")
	return output, nil
}
<commit_msg>Fix error recovery scheme of the emitter.<commit_after>package fluentd_forwarder

import (
	"bytes"
	"github.com/ugorji/go/codec"
	logging "github.com/op/go-logging"
	"net"
	"reflect"
	"sync"
	"sync/atomic"
	"time"
	"io"
	"os"
	"math/rand"
	"unsafe"
)

var randSource = rand.NewSource(time.Now().UnixNano())

type ForwardOutput struct {
	logger            *logging.Logger
	codec             *codec.MsgpackHandle
	bind              string
	retryInterval     time.Duration
	connectionTimeout time.Duration
	writeTimeout      time.Duration
	enc               *codec.Encoder
	conn              net.Conn
	flushInterval     time.Duration
	wg                sync.WaitGroup
	journalGroup      JournalGroup
	journal           Journal
	emitterChan       chan FluentRecordSet
	spoolerShutdownChan chan struct{}
	isShuttingDown    unsafe.Pointer
}

func encodeRecordSet(encoder *codec.Encoder, recordSet FluentRecordSet) error {
	v := []interface{}{recordSet.Tag, recordSet.Records}
	err := encoder.Encode(v)
	if err != nil {
		return err
	}
	return err
}

func (output *ForwardOutput) ensureConnected() error {
	if output.conn == nil {
		output.logger.Notice("Connecting to %s...", output.bind)
		conn, err := net.DialTimeout("tcp", output.bind, output.connectionTimeout)
		if err != nil {
			output.logger.Error("Failed to connect to %s (reason: %s)", output.bind, err.Error())
			return err
		} else {
			output.conn = conn
		}
	}
	return nil
}

func (output *ForwardOutput) sendBuffer(buf []byte) error {
	for len(buf) > 0 {
		if atomic.LoadPointer(&output.isShuttingDown) != unsafe.Pointer(uintptr(0)) {
			break
		}
		err := output.ensureConnected()
		if err != nil {
			output.logger.Info("Will be retried in %s", output.retryInterval.String())
			time.Sleep(output.retryInterval)
			continue
		}
		startTime := time.Now()
		if output.writeTimeout == 0 {
			output.conn.SetWriteDeadline(time.Time {})
		} else {
			output.conn.SetWriteDeadline(startTime.Add(output.writeTimeout))
		}
		n, err := output.conn.Write(buf)
		buf = buf[n:]
		if err != nil {
			output.logger.Error("Failed to flush buffer (reason: %s, left: %d bytes)", err.Error(), len(buf))
			err_, ok := err.(net.Error)
			if !ok || (!err_.Timeout() && !err_.Temporary()) {
				output.conn.Close()
				output.conn = nil
				continue
			}
		}
		if n > 0 {
			elapsed := time.Now().Sub(startTime)
			output.logger.Info("Forwarded %d bytes in %f seconds (%d bytes left)\n", n, elapsed.Seconds(), len(buf))
		}
	}
	return nil
}

func (output *ForwardOutput) spawnSpooler() {
	output.logger.Notice("Spawning spooler")
	output.wg.Add(1)
	go func() {
		ticker := time.NewTicker(output.flushInterval)
		defer func () {
			ticker.Stop()
			output.journal.Dispose()
			if output.conn != nil {
				output.conn.Close()
			}
			output.conn = nil
			output.wg.Done()
		}()
		output.logger.Notice("Spooler started")
		outer: for {
			select {
			case <-ticker.C:
				buf := make([]byte, 16777216)
				output.logger.Notice("Flushing...")
				err := output.journal.Flush(func(chunk JournalChunk) error {
					defer chunk.Dispose()
					output.logger.Info("Flushing chunk %s", chunk.String())
					reader, err := chunk.GetReader()
					if err != nil {
						return err
					}
					for {
						n, err := reader.Read(buf)
						if n > 0 {
							err_ :=output.sendBuffer(buf[:n])
							if err_ != nil {
								return err
							}
						}
						if err != nil {
							if err == io.EOF {
								break
							} else {
								return err
							}
						}
					}
					return nil
				})
				if err != nil {
					output.logger.Error("Error during reading from the journal: %s", err.Error())
				}
			case <-output.spoolerShutdownChan:
				break outer
			}
		}
		output.logger.Notice("Spooler ended")
	}()
}

func (output *ForwardOutput) spawnEmitter() {
	output.logger.Notice("Spawning emitter")
	output.wg.Add(1)
	go func() {
		defer func() {
			output.spoolerShutdownChan <- struct{}{}
			output.wg.Done()
		}()
		output.logger.Notice("Emitter started")
		buffer := bytes.Buffer{}
		for recordSet := range output.emitterChan {
			buffer.Reset()
			encoder := codec.NewEncoder(&buffer, output.codec)
			err := encodeRecordSet(encoder, recordSet)
			if err != nil {
				output.logger.Error("%s", err.Error())
				continue
			}
			output.logger.Debug("Emitter processed %d entries", len(recordSet.Records))
			output.journal.Write(buffer.Bytes())
		}
		output.logger.Notice("Emitter ended")
	}()
}

func (output *ForwardOutput) Emit(recordSets []FluentRecordSet) error {
	defer func() {
		recover()
	}()
	for _, recordSet := range recordSets {
		output.emitterChan <- recordSet
	}
	return nil
}

func (output *ForwardOutput) String() string {
	return "output"
}

func (output *ForwardOutput) Stop() {
	if atomic.CompareAndSwapPointer(&output.isShuttingDown, unsafe.Pointer(uintptr(0)), unsafe.Pointer(uintptr(1))) {
		close(output.emitterChan)
	}
}

func (output *ForwardOutput) WaitForShutdown() {
	output.wg.Wait()
}

func (output *ForwardOutput) Start() {
	output.spawnSpooler()
	output.spawnEmitter()
}

func NewForwardOutput(logger *logging.Logger, bind string, retryInterval time.Duration, connectionTimeout time.Duration, writeTimeout time.Duration, flushInterval time.Duration, journalGroupPath string, maxJournalChunkSize int64) (*ForwardOutput, error) {
	_codec := codec.MsgpackHandle{}
	_codec.MapType = reflect.TypeOf(map[string]interface{}(nil))
	_codec.RawToString = false
	_codec.StructToArray = true

	journalFactory := NewFileJournalGroupFactory(
		logger,
		randSource,
		time.Now,
		".log",
		os.FileMode(0600),
		maxJournalChunkSize,
	)
	output := &ForwardOutput{
		logger:            logger,
		codec:             &_codec,
		bind:              bind,
		retryInterval:     retryInterval,
		connectionTimeout: connectionTimeout,
		writeTimeout:      writeTimeout,
		wg:                sync.WaitGroup{},
		flushInterval:     flushInterval,
		emitterChan:       make(chan FluentRecordSet),
		spoolerShutdownChan: make(chan struct{}),
		isShuttingDown:    unsafe.Pointer(uintptr(0)),
	}
	journalGroup, err := journalFactory.GetJournalGroup(journalGroupPath, output)
	if err != nil {
		return nil, err
	}
	defer func () {
		err := journalGroup.Dispose()
		if err != nil {
			logger.Error("%#v", err)
		}
	}()
	output.journalGroup  = journalGroup
	output.journal       = journalGroup.GetJournal("output")
	return output, nil
}
<|endoftext|>


<commit_before>package kami

import (
	"golang.org/x/net/context"
)

type key int

const (
	paramsKey key = iota
	panicKey
)

// Param returns a request URL parameter, or a blank string if it doesn't exist.
// For example, with the path /v2/papers/:page
// use kami.Param(ctx, "page") to access the :page variable.
func Param(ctx context.Context, name string) string {
	params, ok := ctx.Value(paramsKey).(map[string]string)
	if !ok {
		return ""
	}
	return params[name]
}

// SetParameter will set the value of a path parameter in a given context.
func SetParameter(ctx context.Context, name string, value string) context.Context {
	params, ok := ctx.Value(paramsKey).(map[string]string)
	if !ok {
		params = make(map[string]string)
	}
	params[name] = value
	return context.WithValue(ctx, paramsKey, params)
}

// Exception gets the "v" in panic(v). The panic details.
// Only PanicHandler will receive a context you can use this with.
func Exception(ctx context.Context) interface{} {
	return ctx.Value(panicKey)
}

func newContextWithParams(ctx context.Context, params map[string]string) context.Context {
	return context.WithValue(ctx, paramsKey, params)
}

func mergeParams(ctx context.Context, params map[string]string) context.Context {
	current, _ := ctx.Value(paramsKey).(map[string]string)
	if current == nil {
		return context.WithValue(ctx, paramsKey, params)
	}

	for k, v := range params {
		current[k] = v
	}
	return ctx
}

func newContextWithException(ctx context.Context, exception interface{}) context.Context {
	return context.WithValue(ctx, panicKey, exception)
}
<commit_msg>update SetParameter -> SetParam<commit_after>package kami

import (
	"golang.org/x/net/context"
)

type key int

const (
	paramsKey key = iota
	panicKey
)

// Param returns a request URL parameter, or a blank string if it doesn't exist.
// For example, with the path /v2/papers/:page
// use kami.Param(ctx, "page") to access the :page variable.
func Param(ctx context.Context, name string) string {
	params, ok := ctx.Value(paramsKey).(map[string]string)
	if !ok {
		return ""
	}
	return params[name]
}

// SetParam will set the value of a path parameter in a given context.
func SetParam(ctx context.Context, name string, value string) context.Context {
	params, ok := ctx.Value(paramsKey).(map[string]string)
	if !ok {
		params = make(map[string]string)
	}
	params[name] = value
	return context.WithValue(ctx, paramsKey, params)
}

// Exception gets the "v" in panic(v). The panic details.
// Only PanicHandler will receive a context you can use this with.
func Exception(ctx context.Context) interface{} {
	return ctx.Value(panicKey)
}

func newContextWithParams(ctx context.Context, params map[string]string) context.Context {
	return context.WithValue(ctx, paramsKey, params)
}

func mergeParams(ctx context.Context, params map[string]string) context.Context {
	current, _ := ctx.Value(paramsKey).(map[string]string)
	if current == nil {
		return context.WithValue(ctx, paramsKey, params)
	}

	for k, v := range params {
		current[k] = v
	}
	return ctx
}

func newContextWithException(ctx context.Context, exception interface{}) context.Context {
	return context.WithValue(ctx, panicKey, exception)
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 Leon Dang, Nahanni Systems Inc
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer
 *    in this position and unchanged.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

package ucl

import (
	"fmt"
	"io"
)

// The order of the keys as they appear in the file; this allows the user to
// have their own order for items.
const KeyOrder = "--ucl-keyorder--"

var Ucldebug bool = true
func debug(a... interface{}) {
	if Ucldebug {
		fmt.Println(a)
	}
}

type Parser struct {
	scanner *scanner

	ucl     map[string] interface{}

	tags    []*tag
	tagsi   int

	done    bool
	err     error
}

func NewParser(r io.Reader) *Parser {
	p := &Parser{
		scanner: newScanner(r),
		ucl: make(map[string] interface{}),
	}

	return p
}

func (p *Parser) nexttag() (*tag, error) {
	var err error

	if p.done {
		return nil, io.EOF
	}

	for {
		if p.tagsi >= len(p.tags) {
			p.tags, err = p.scanner.nexttags()
			if err != nil {
				return nil, err
			}
			p.tagsi = 0
		}
		for ; p.tagsi < len(p.tags); p.tagsi++ {
			m := p.tags[p.tagsi]
			if m.state == WHITESPACE || m.state == LCOMMENT ||
			   m.state == HCOMMENT {
				continue
			}
			p.tagsi++

			return m, nil
		}
	}

	return nil, fmt.Errorf("end of input line %d", p.scanner.line)
}

func (p *Parser) parsevalue(t *tag, parent interface{}) (interface{}, error) {
	var err error

restart:
	if t == nil {
		t, err = p.nexttag()
		if err != nil {
			return nil, err
		}
	}

	switch t.state {
	case TAG, QUOTE, VQUOTE, SLASH:
		// this could be either a value or a new key
		// have to see if the followon tags exist
		nt, err := p.nexttag()
		if err != nil {
			return nil, err
		}

		if nt == nil || nt.state == SEMICOL || nt.state == COMMA {
			return string(t.val), nil;  // leaf value; done
		}
		if nt.state == BRACECLOSE || nt.state == BRACKETCLOSE {
			nt.val = t.val
			return nt, nil
		}

		// "t" is a new key tag
		themap := make(map[string] interface{})
		res, err := p.parsevalue(nt, parent)

		if err != nil {
			debug("Error:", err)
			return nil, err
		}

		korder := make([]string, 1, 16)
		korder[0] = string(t.val)
		themap[KeyOrder] = korder
		themap[string(t.val)] = res
		return themap, nil

	case SEMICOL:
		// no value, let parent handle it
		if parent == nil {
			return t, fmt.Errorf("unexpected ';' at line %d", p.scanner.line)
		}
		return parent, nil

	case COMMA:
		// no value, let parent handle it
		if parent == nil {
			return t, fmt.Errorf("unexpected ',' at line %d", p.scanner.line)
		}
		return parent, nil

	case MLSTRING:
		// this must only be a value
		return string(t.val), nil

	case BRACEOPEN:
		// {, new map
		res, err := p.parse(t, parent)
		if err != nil {
			debug("parse error:", err)
		}
		return res, err

	case BRACECLOSE:
		// return until we hit the stack that has BRACEOPEN
		return parent, nil

	case BRACKETOPEN:
		thelist := make([]interface{}, 0, 32)
		res, err := p.parselist(nil, thelist)
		return res, err

	case BRACKETCLOSE:
		// list finished
		return parent, nil

	case EQUAL, COLON:
		t = nil
		goto restart
	}

	return nil, nil
}

func (p *Parser) parselist(t *tag, parent []interface{}) (ret interface{}, err error) {
	// Parse until bracket close
restart:
	if t == nil {
		t, err = p.nexttag()
		if err != nil {
			return nil, err
		}
	}

	switch t.state {
	case BRACKETCLOSE:
		// list finished
		return parent, nil

	case SEMICOL, COLON, EQUAL:
		// no value, let parent handle it
		return nil, fmt.Errorf("Invalid tag %s line %d",
		                       string(t.val), p.scanner.line)
	case COMMA:
		t = nil
		goto restart

	default:
		// append child
		res, err := p.parsevalue(t, nil)
		if err != nil {
			debug("error parsing value:", err)
			return nil, err
		} else {
			if restag, ok := res.(*tag); ok {
				// result is a tag; parsevalue didn't handle it
				if restag.state == BRACKETCLOSE {
					parent = append(parent, string(restag.val))
					return parent, nil
				} else {
					return nil, fmt.Errorf("Unexpected tag %s, line %d\n",
					               string(restag.val), p.scanner.line)
				}
			}

			parent = append(parent, res)
		}
		t = nil
		goto restart
	}
	return parent, err
}

func (p *Parser) parse(t *tag, parent interface{}) (ret interface{}, err error) {
	defer func() {
		p.err = err
	}()

restart:
	if t == nil {
		t, err = p.nexttag()
		if err != nil {
			return nil, err
		}
	}

	switch t.state {
	case TAG, QUOTE, VQUOTE, SLASH:
		// new key
		k := string(t.val)

		themap, ok := parent.(map[string] interface{})
		if !ok {
			debug("not a map at tag:", k)
			panic("...")
		}

		korder_intf, ok := themap[KeyOrder]
		var korder []string
		if !ok {
			korder = make([]string, 0, 16)
		} else {
			korder, ok = korder_intf.([]string)
			if !ok {
				debug("key order is not slice")
				return nil, fmt.Errorf("map[--keyorder--] is not slice")
			}
		}

		res, err := p.parsevalue(nil, nil)
		if err != nil {
			if restag, ok := res.(*tag); ok {
				if restag.state == SEMICOL {
					// no value for key, make it == null
					res = nil
				}
			} else {
				debug("parsevalue error:", err)
				return nil, err
			}
		} else if restag, ok := res.(*tag); ok {
			// result is a tag; parsevalue didn't handle it
			if restag.state != BRACECLOSE {
				t = restag
				goto restart
			}
			res = string(restag.val)
			t = restag
		}

		if mapitems, ok := themap[k]; ok {
			if childarray, ok := mapitems.([]interface{}); ok {
				// already an array, so append
				childarray = append(childarray, res)
				themap[k] = childarray
			} else {
				childarray := make([]interface{}, 1, 2)
				childarray[0] = themap[k]
				childarray = append(childarray, res)
				themap[k] = childarray
			}
		} else {
			// doesn't exist
			korder = append(korder, k)
			themap[KeyOrder] = korder
			themap[k] = res
		}
		if t.state == BRACECLOSE {
			// map completed
			return parent, nil
		}

		// done for this tag; go to next
		t = nil
		goto restart

	case SEMICOL:
		t = nil
		goto restart

	case MLSTRING:
		// shouldn't happen
		return nil, fmt.Errorf("Unexpected multi-line string")

	case BRACEOPEN:
		// {
		// If parent is not a map and not nil, then error

		var theparent interface{}
		var ok bool
		if parent == nil {
			theparent = make(map[string] interface{})
		} else if theparent, ok = parent.(map[string] interface{}); !ok {
			if theparent, ok = parent.([]interface{}); !ok {
				debug("Error braceopen - parent is not a map/list/nil")
				return nil, fmt.Errorf("Invalid {, parent not nil|map|list")
			}
		}
		res, err := p.parse(nil, theparent)
		if err != nil {
			debug("Error parsing brace", err)
		}
		return res, err

	case BRACECLOSE:
		// map finished
		return parent, nil

	case BRACKETOPEN:
		thelist := make([]interface{}, 0, 32)
		res, err := p.parselist(nil, thelist)
		return res, err

	case BRACKETCLOSE:
		// list finished
		return parent, nil
	}

	return nil, nil
}

func (p *Parser) Ucl() (map[string] interface{}, error) {
	p.parse(nil, p.ucl)

	if p.err == io.EOF {
		p.err = nil
	}
	return p.ucl, p.err
}
<commit_msg>Add toggle to suppress KeyOrder element in maps<commit_after>/*
 * Copyright (c) 2015 Leon Dang, Nahanni Systems Inc
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer
 *    in this position and unchanged.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

package ucl

import (
	"fmt"
	"io"
)

// The order of the keys as they appear in the file; this allows the user to
// have their own order for items.
const KeyOrder = "--ucl-keyorder--"

var UclExportKeyOrder bool = true

var Ucldebug bool = true
func debug(a... interface{}) {
	if Ucldebug {
		fmt.Println(a)
	}
}

type Parser struct {
	scanner *scanner

	ucl     map[string] interface{}

	tags    []*tag
	tagsi   int

	done    bool
	err     error
}

func NewParser(r io.Reader) *Parser {
	p := &Parser{
		scanner: newScanner(r),
		ucl: make(map[string] interface{}),
	}

	return p
}

func (p *Parser) nexttag() (*tag, error) {
	var err error

	if p.done {
		return nil, io.EOF
	}

	for {
		if p.tagsi >= len(p.tags) {
			p.tags, err = p.scanner.nexttags()
			if err != nil {
				return nil, err
			}
			p.tagsi = 0
		}
		for ; p.tagsi < len(p.tags); p.tagsi++ {
			m := p.tags[p.tagsi]
			if m.state == WHITESPACE || m.state == LCOMMENT ||
			   m.state == HCOMMENT {
				continue
			}
			p.tagsi++

			return m, nil
		}
	}

	return nil, fmt.Errorf("end of input line %d", p.scanner.line)
}

func (p *Parser) parsevalue(t *tag, parent interface{}) (interface{}, error) {
	var err error

restart:
	if t == nil {
		t, err = p.nexttag()
		if err != nil {
			return nil, err
		}
	}

	switch t.state {
	case TAG, QUOTE, VQUOTE, SLASH:
		// this could be either a value or a new key
		// have to see if the followon tags exist
		nt, err := p.nexttag()
		if err != nil {
			return nil, err
		}

		if nt == nil || nt.state == SEMICOL || nt.state == COMMA {
			return string(t.val), nil;  // leaf value; done
		}
		if nt.state == BRACECLOSE || nt.state == BRACKETCLOSE {
			nt.val = t.val
			return nt, nil
		}

		// "t" is a new key tag
		themap := make(map[string] interface{})
		res, err := p.parsevalue(nt, parent)

		if err != nil {
			debug("Error:", err)
			return nil, err
		}

		korder := make([]string, 1, 16)
		korder[0] = string(t.val)
		themap[KeyOrder] = korder
		themap[string(t.val)] = res
		return themap, nil

	case SEMICOL:
		// no value, let parent handle it
		if parent == nil {
			return t, fmt.Errorf("unexpected ';' at line %d", p.scanner.line)
		}
		return parent, nil

	case COMMA:
		// no value, let parent handle it
		if parent == nil {
			return t, fmt.Errorf("unexpected ',' at line %d", p.scanner.line)
		}
		return parent, nil

	case MLSTRING:
		// this must only be a value
		return string(t.val), nil

	case BRACEOPEN:
		// {, new map
		res, err := p.parse(t, parent)
		if err != nil {
			debug("parse error:", err)
		}
		return res, err

	case BRACECLOSE:
		// return until we hit the stack that has BRACEOPEN
		return parent, nil

	case BRACKETOPEN:
		thelist := make([]interface{}, 0, 32)
		res, err := p.parselist(nil, thelist)
		return res, err

	case BRACKETCLOSE:
		// list finished
		return parent, nil

	case EQUAL, COLON:
		t = nil
		goto restart
	}

	return nil, nil
}

func (p *Parser) parselist(t *tag, parent []interface{}) (ret interface{}, err error) {
	// Parse until bracket close
restart:
	if t == nil {
		t, err = p.nexttag()
		if err != nil {
			return nil, err
		}
	}

	switch t.state {
	case BRACKETCLOSE:
		// list finished
		return parent, nil

	case SEMICOL, COLON, EQUAL:
		// no value, let parent handle it
		return nil, fmt.Errorf("Invalid tag %s line %d",
		                       string(t.val), p.scanner.line)
	case COMMA:
		t = nil
		goto restart

	default:
		// append child
		res, err := p.parsevalue(t, nil)
		if err != nil {
			debug("error parsing value:", err)
			return nil, err
		} else {
			if restag, ok := res.(*tag); ok {
				// result is a tag; parsevalue didn't handle it
				if restag.state == BRACKETCLOSE {
					parent = append(parent, string(restag.val))
					return parent, nil
				} else {
					return nil, fmt.Errorf("Unexpected tag %s, line %d\n",
					               string(restag.val), p.scanner.line)
				}
			}

			parent = append(parent, res)
		}
		t = nil
		goto restart
	}
	return parent, err
}

func (p *Parser) parse(t *tag, parent interface{}) (ret interface{}, err error) {
	defer func() {
		p.err = err
	}()

restart:
	if t == nil {
		t, err = p.nexttag()
		if err != nil {
			return nil, err
		}
	}

	switch t.state {
	case TAG, QUOTE, VQUOTE, SLASH:
		// new key
		k := string(t.val)

		themap, ok := parent.(map[string] interface{})
		if !ok {
			debug("not a map at tag:", k)
			panic("...")
		}

		korder_intf, ok := themap[KeyOrder]
		var korder []string
		if !ok {
			korder = make([]string, 0, 16)
		} else {
			korder, ok = korder_intf.([]string)
			if !ok {
				debug("key order is not slice")
				return nil, fmt.Errorf("map[--keyorder--] is not slice")
			}
		}

		res, err := p.parsevalue(nil, nil)
		if err != nil {
			if restag, ok := res.(*tag); ok {
				if restag.state == SEMICOL {
					// no value for key, make it == null
					res = nil
				}
			} else {
				debug("parsevalue error:", err)
				return nil, err
			}
		} else if restag, ok := res.(*tag); ok {
			// result is a tag; parsevalue didn't handle it
			if restag.state != BRACECLOSE {
				t = restag
				goto restart
			}
			res = string(restag.val)
			t = restag
		}

		if mapitems, ok := themap[k]; ok {
			if childarray, ok := mapitems.([]interface{}); ok {
				// already an array, so append
				childarray = append(childarray, res)
				themap[k] = childarray
			} else {
				childarray := make([]interface{}, 1, 2)
				childarray[0] = themap[k]
				childarray = append(childarray, res)
				themap[k] = childarray
			}
		} else {
			// doesn't exist
			korder = append(korder, k)
			if UclExportKeyOrder {
				themap[KeyOrder] = korder
			}
			themap[k] = res
		}
		if t.state == BRACECLOSE {
			// map completed
			return parent, nil
		}

		// done for this tag; go to next
		t = nil
		goto restart

	case SEMICOL:
		t = nil
		goto restart

	case MLSTRING:
		// shouldn't happen
		return nil, fmt.Errorf("Unexpected multi-line string")

	case BRACEOPEN:
		// {
		// If parent is not a map and not nil, then error

		var theparent interface{}
		var ok bool
		if parent == nil {
			theparent = make(map[string] interface{})
		} else if theparent, ok = parent.(map[string] interface{}); !ok {
			if theparent, ok = parent.([]interface{}); !ok {
				debug("Error braceopen - parent is not a map/list/nil")
				return nil, fmt.Errorf("Invalid {, parent not nil|map|list")
			}
		}
		res, err := p.parse(nil, theparent)
		if err != nil {
			debug("Error parsing brace", err)
		}
		return res, err

	case BRACECLOSE:
		// map finished
		return parent, nil

	case BRACKETOPEN:
		thelist := make([]interface{}, 0, 32)
		res, err := p.parselist(nil, thelist)
		return res, err

	case BRACKETCLOSE:
		// list finished
		return parent, nil
	}

	return nil, nil
}

func (p *Parser) Ucl() (map[string] interface{}, error) {
	p.parse(nil, p.ucl)

	if p.err == io.EOF {
		p.err = nil
	}
	return p.ucl, p.err
}
<|endoftext|>


<commit_before>package remote

import (
	"bytes/buffer"
	"event"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
)

var port = func() string {
	tmpport := os.Getenv("PORT")
	if tmpport == "" {
		tmpport = "5000"
	}

	return tmpport
}

type ProxySession struct {
	serv     *UserProxyService
	conn     net.Conn
	addr     string
	recv_evs chan event.Event
}

type UserProxyService struct {
	name        string
	recv_evs    chan event.Event
	send_evs    chan event.Event
	session_map map[uint32]*ProxySession
}

func (serv *UserProxyService) eventLoop() {
	for {
		ev := <-serv.recv_evs
		ev = event.ExtractEvent(ev)
		switch ev.GetType() {
		case event.HTTP_REQUEST_EVENT_TYPE:
			req := ev.(*event.HTTPRequestEvent)
		case event.EVENT_SEQUNCEIAL_CHUNK_TYPE:
			chunk := ev.(*event.SequentialChunkEvent)

		}
	}
}

var userProxyServiceMap map[string]*UserProxyService

func getUserProxyService(name string) *UserProxyService {
	serv, exist := userProxyServiceMap[name]
	if !exist {
		serv = &UserProxyService{}
		serv.name = name
		serv.recv_evs = make(chan event.Event, 4096)
		serv.send_evs = make(chan event.Event, 4096)
		go serv.eventLoop()
	}
	return serv
}

func InvokeCallback(w http.ResponseWriter, req *http.Request) {
	body, err := ioutil.ReadAll(req.Body)
	if nil != err {
	}
	user := ""
	buf := bytes.NewBuffer(body)
	for {
		if buf.Len() == 0 {
			break
		}
		ev, err := event.DecodeEvent(buf)
		if nil != err {
			break
		}
		getUserProxyService(user).recv_evs <- ev
	}

}

// hello world, the web server
func IndexCallback(w http.ResponseWriter, req *http.Request) {
	io.WriteString(w, html)
}

func LaunchC4HttpServer() {
	http.HandleFunc("/", IndexCallback)
	http.HandleFunc("/invoke", InvokeCallback)
	err := http.ListenAndServe(":"+port(), nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err.Error())
	}
}

const html = `
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
	<title>GSnova C4 Server</title>

GSnova
      by @yinqiwen

      Welcome to use GSnova C4 Server(V0.15.0)!

Code

You can clone the project with Git
      by running:

$ git clone git://github.com/yinqiwen/gsnova.git

      get the source code on GitHub : yinqiwen/gsnova

`
<commit_msg>C4 Update<commit_after>package remote

import (
	"bytes/buffer"
	"event"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
)

var port = func() string {
	tmpport := os.Getenv("PORT")
	if tmpport == "" {
		tmpport = "5000"
	}

	return tmpport
}

type ProxySession struct {
	serv     *UserProxyService
	conn     net.Conn
	addr     string
	recv_evs chan event.Event
}

type UserProxyService struct {
	name        string
	recv_evs    chan event.Event
	send_evs    chan event.Event
	session_map map[uint32]*ProxySession
}

func (serv *UserProxyService) eventLoop() {
	for {
		ev := <-serv.recv_evs
		ev = event.ExtractEvent(ev)
		switch ev.GetType() {
		case event.HTTP_REQUEST_EVENT_TYPE:
			req := ev.(*event.HTTPRequestEvent)
		case event.EVENT_SEQUNCEIAL_CHUNK_TYPE:
			chunk := ev.(*event.SequentialChunkEvent)

		}
	}
}

var userProxyServiceMap map[string]*UserProxyService

func getUserProxyService(name string) *UserProxyService {
	serv, exist := userProxyServiceMap[name]
	if !exist {
		serv = &UserProxyService{}
		serv.name = name
		serv.recv_evs = make(chan event.Event, 4096)
		serv.send_evs = make(chan event.Event, 4096)
		go serv.eventLoop()
	}
	return serv
}

func InvokeCallback(w http.ResponseWriter, req *http.Request) {
	body, err := ioutil.ReadAll(req.Body)
	if nil != err {
	}
	user := ""
	buf := bytes.NewBuffer(body)
	for {
		if buf.Len() == 0 {
			break
		}
		ev, err := event.DecodeEvent(buf)
		if nil != err {
			break
		}
		getUserProxyService(user).recv_evs <- ev
	}

}

// hello world, the web server
func IndexCallback(w http.ResponseWriter, req *http.Request) {
	io.WriteString(w, html)
}

func LaunchC4HttpServer() {
	http.HandleFunc("/", IndexCallback)
	http.HandleFunc("/invoke", InvokeCallback)
	err := http.ListenAndServe(":"+port(), nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err.Error())
	}
}

const html = `
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
	<title>GSnova C4 Server</title>

GSnova
      by @yinqiwen

      Welcome to use GSnova C4 Server(V0.15.0)!

Code

You can clone the project with Git
      by running:

$ git clone git://github.com/yinqiwen/gsnova.git

      get the source code on GitHub : yinqiwen/gsnova

`
<|endoftext|>