<commit_before>/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
	p := new(ListNode)
	dump := p
	l1_val, l2_val, c, sum := 0, 0, 0, 0

	for l1 != nil || l2 != nil {
		if l1 != nil {
			l1_val = l1.Val
			l1 = l1.Next
		}

		if l2 != nil {
			l2_val = l2.Val
			l2 = l2.Next
		}

		sum = l1_val + l2_val + c
		p.Next = new(ListNode)
		p = p.Next
		p.Val, c = sum % 10, sum / 10

		l1_val, l2_val = 0, 0
	}

	return dump.Next
}
<commit_msg>[LEETCODE] Add Two Numbers - go - check if the leftmost int exists<commit_after>package _go

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
	p := new(ListNode)
	dump := p
	l1_val, l2_val, c, sum := 0, 0, 0, 0

	for l1 != nil || l2 != nil {
		if l1 != nil {
			l1_val = l1.Val
			l1 = l1.Next
		}

		if l2 != nil {
			l2_val = l2.Val
			l2 = l2.Next
		}

		sum = l1_val + l2_val + c
		p.Next = new(ListNode)
		p = p.Next
		p.Val, c = sum % 10, sum / 10

		l1_val, l2_val = 0, 0
	}

	if c == 1 {
		p.Next = &ListNode{1, nil}
	}

	return dump.Next
}

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}<|endoftext|>


<commit_before>// Package core contains some debugging/dumping variable functions
package core

import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"reflect"
	"runtime"
	"runtime/debug"
	"strings"
	"sync"
	"time"

	"github.com/DanielRenne/GoCore/core/extensions"
	"github.com/DanielRenne/GoCore/core/serverSettings"
	"github.com/davidrenne/reflections"
	"github.com/go-errors/errors"
)

type core_debug struct{}

var core_logger = log.New(os.Stdout, "", 0)

// TransactionLog provides a thread-safe buffer/string if you have serverSettings.WebConfig.Application.ReleaseMode == "development" you can call something like core.Debug.GetDump in many places and then read the TransactionLog when you need to (note you must manually clear it as it will just increase your memory usage the more logs are sent)
var TransactionLog string

// Debug is a base struct for all debug functions.
var Debug = core_debug{}

// Logger can be overridden with log.New(os.Stdout, "", 0) to log to stdout or some other writer
var Logger = core_logger

// TransactionLogMutex is a mutex for the TransactionLog which should be used on your end to clear the value safely
var TransactionLogMutex *sync.RWMutex

func init() {
	TransactionLogMutex = &sync.RWMutex{}
}

// Nop is a dummy function that can be called in source files where
// other debug functions are constantly added and removed.
// That way import "github.com/ungerik/go-start/debug" won't cause an error when
// no other debug function is currently used.
// Arbitrary objects can be passed as arguments to avoid "declared and not used"
// error messages when commenting code out and in.
// The result is a nil interface{} dummy value.
func (self *core_debug) Nop(dummiesIn ...interface{}) (dummyOut interface{}) {
	return nil
}

// CallStackInfo returns a string with the call stack info.
func (self *core_debug) CallStackInfo(skip int) (info string) {
	pc, file, line, ok := runtime.Caller(skip)
	if ok {
		funcName := runtime.FuncForPC(pc).Name()
		info += fmt.Sprintf("In function %s()", funcName)
	}
	for i := 0; ok; i++ {
		info += fmt.Sprintf("\n%s:%d", file, line)
		_, file, line, ok = runtime.Caller(skip + i)
	}
	return info
}

// PrintCallStack prints the call stack info.
func (self *core_debug) PrintCallStack() {
	debug.PrintStack()
}

// LogCallStack logs the call stack info.
func (self *core_debug) LogCallStack() {
	log.Print(self.Stack())
}

func (self *core_debug) Stack() string {
	return string(debug.Stack())
}

func (self *core_debug) formatValue(value interface{}) string {
	return fmt.Sprintf("\n     Type: %T\n    Value: %v\nGo Syntax: %#v", value, value, value)
}

func (self *core_debug) formatCallstack(skip int) string {
	return fmt.Sprintf("\nCallstack: %s", self.CallStackInfo(skip+1))
}

// FormatSkip formats a value with callstack info.
func (self *core_debug) FormatSkip(skip int, value interface{}) string {
	return self.formatValue(value) + self.formatCallstack(skip+1)
}

// Format formats a value with callstack info.
func (self *core_debug) Format(value interface{}) string {
	return self.FormatSkip(2, value)
}

// IsZeroOfUnderlyingType returns true if the value is the zero value (nil) for its type.
func IsZeroOfUnderlyingType(x interface{}) bool {
	return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface())
}

// IsZeroOfUnderlyingType2 returns true if the value is the zero value (nil) for its type.
func IsZeroOfUnderlyingType2(x interface{}) bool {
	return x == reflect.Zero(reflect.TypeOf(x)).Interface()
}

// HandleError is a helper function that will log an error and return it with the callers line and file.
func (self *core_debug) HandleError(err error) (s string) {
	if err != nil {
		// notice that we're using 1, so it will actually log the where
		// the error happened, 0 = this function, we don't want that.
		_, fn, line, _ := runtime.Caller(1)
		fileNameParts := strings.Split(fn, "/")
		return fmt.Sprintf("  Error Info: %s Line %d. ErrorType: %v", fileNameParts[len(fileNameParts)-1], line, err)
	}
	return ""
}

// ErrLineAndFile returns the line and file of the error.
func (self *core_debug) ErrLineAndFile(err error) (s string) {
	if err != nil {
		// notice that we're using 1, so it will actually log the where
		// the error happened, 0 = this function, we don't want that.
		_, fn, line, _ := runtime.Caller(1)
		fileNameParts := strings.Split(fn, "/")
		return fmt.Sprintf("%s Line %d", fileNameParts[len(fileNameParts)-1], line)
	}
	return ""
}

// Dump is a helper function that will log unlimited values to print to stdout or however you have log setup if you overload core/Logger
func (self *core_debug) Dump(valuesOriginal ...interface{}) {
	t := time.Now()
	l := "!!!!!!!!!!!!! DEBUG " + t.Format("2006-01-02 15:04:05.000000") + "!!!!!!!!!!!!!\n\n"
	Logger.Println(l)

	serverSettings.WebConfigMutex.RLock()
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	serverSettings.WebConfigMutex.RUnlock()
	for _, value := range valuesOriginal {
		l := self.dumpBase(value)
		Logger.Print(l)
		serverSettings.WebConfigMutex.RLock()
		if serverSettings.WebConfig.Application.ReleaseMode == "development" {
			TransactionLogMutex.Lock()
			TransactionLog += l
			TransactionLogMutex.Unlock()
		}
		serverSettings.WebConfigMutex.RUnlock()
	}
	l = self.ThrowAndPrintError()
	Logger.Print(l)

	serverSettings.WebConfigMutex.RLock()
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	serverSettings.WebConfigMutex.RUnlock()
	l = "!!!!!!!!!!!!! ENDDEBUG " + t.Format("2006-01-02 15:04:05.000000") + "!!!!!!!!!!!!!"
	Logger.Println(l)
	serverSettings.WebConfigMutex.RLock()
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	serverSettings.WebConfigMutex.RUnlock()
}

// GetDump is a helper function that will log unlimited values which will return a string representation of what was logged
func (self *core_debug) GetDump(valuesOriginal ...interface{}) (output string) {
	for _, value := range valuesOriginal {
		output += self.dumpBase(value)
	}
	//output += self.ThrowAndPrintError()
	return output
}

func (self *core_debug) GetDumpWithInfo(valuesOriginal ...interface{}) (output string) {
	t := time.Now()
	return self.GetDumpWithInfoAndTimeString(t.String(), valuesOriginal...)
}

// GetDumpWithInfoAndTimeString is a helper function that will log unlimited values which will return a string representation of what was logged but allows you to pass your own time string in a case of timezone offsets
func (self *core_debug) GetDumpWithInfoAndTimeString(timeStr string, valuesOriginal ...interface{}) (output string) {
	l := "\n!!!!!!!!!!!!! DEBUG " + timeStr + "!!!!!!!!!!!!!\n\n"
	output += l

	serverSettings.WebConfigMutex.RLock()
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	serverSettings.WebConfigMutex.RUnlock()

	for _, value := range valuesOriginal {
		output += self.dumpBase(value) + "\n"
	}

	serverSettings.WebConfigMutex.RLock()
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		TransactionLogMutex.Lock()
		TransactionLog += output
		TransactionLogMutex.Unlock()
	}
	serverSettings.WebConfigMutex.RUnlock()

	l = self.ThrowAndPrintError()
	output += l
	serverSettings.WebConfigMutex.RLock()
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	serverSettings.WebConfigMutex.RUnlock()
	l = "!!!!!!!!!!!!! ENDDEBUG " + timeStr + "!!!!!!!!!!!!!\n"
	output += l
	serverSettings.WebConfigMutex.RLock()
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	serverSettings.WebConfigMutex.RUnlock()
	return output
}

func (self *core_debug) dumpBase(values ...interface{}) (output string) {
	var jsonString string
	var err error
	var structKeys []string
	if Logger != nil {
		for _, value := range values {
			isAllJSON := true
			var kind string
			kind = strings.TrimSpace(fmt.Sprintf("%T", value))
			if !IsZeroOfUnderlyingType(value) {
				kind = reflections.ReflectKind(value)
				structKeys, err = reflections.FieldsDeep(value)
				if err == nil {
					for _, field := range structKeys {
						jsonString, err = reflections.GetFieldTag(value, field, "json")
						if err != nil {
							isAllJSON = false
						}
						if jsonString == "" {
							isAllJSON = false
						}
					}
				} else {
					isAllJSON = false
				}
			} else {
				isAllJSON = false
			}

			if isAllJSON || kind == "map" || kind == "bson.M" || kind == "slice" {
				var rawBytes []byte
				rawBytes, err = json.MarshalIndent(value, "", "\t")
				if err == nil {
					if kind == "slice" || kind[:2] == "[]" {
						valReflected := reflect.ValueOf(value)
						output += fmt.Sprintf("#### %-39s [len:%s]####\n%+v", kind, extensions.IntToString(valReflected.Len()), string(rawBytes[:]))
					} else {
						output += fmt.Sprintf("#### %-39s ####\n%+v", kind, string(rawBytes[:]))
					}
				}
			} else {
				if strings.TrimSpace(kind) == "string" {
					var stringVal = value.(string)
					position := strings.Index(stringVal, "Desc->")
					if position == -1 {
						if !extensions.IsPrintable(stringVal) {
							kind += " (non printables -> dump hex)"
							stringVal = hex.Dump([]byte(stringVal))
						}
						valReflected := reflect.ValueOf(value)
						output += fmt.Sprintf("#### %-39s [len:%s]####\n%s", kind, extensions.IntToString(valReflected.Len()), stringVal)
					} else {
						output += stringVal[6:] + " --> "
					}
				} else if kind[:2] == "[]" || strings.TrimSpace(kind) == "array" {
					valReflected := reflect.ValueOf(value)
					output += fmt.Sprintf("#### %-39s [len:%s]####\n%+v", kind, extensions.IntToString(valReflected.Len()), value)
				} else {
					output += fmt.Sprintf("#### %-39s ####\n%+v", kind, value)
				}
			}
		}
	}
	return output
}

// ThrowAndPrintError is a helper function that will throw a fake error and get the callstack and return it as a string (you probably shouldnt use this)
func (self *core_debug) ThrowAndPrintError() (output string) {

	serverSettings.WebConfigMutex.RLock()
	ok := serverSettings.WebConfig.Application.CoreDebugStackTrace
	serverSettings.WebConfigMutex.RUnlock()
	if ok {
		output += "\n"
		errorInfo := self.ThrowError()
		stack := strings.Split(errorInfo.ErrorStack(), "\n")
		if len(stack) >= 8 {
			output += "\nDump Caller:"
			output += "\n---------------"
			//output += strings.Join(stack, ",")
			output += "\n golines ==> " + strings.TrimSpace(stack[6])
			output += "\n         ==> " + strings.TrimSpace(stack[7])
			output += "\n         ==> " + strings.TrimSpace(stack[8])
			output += "\n         ==> " + strings.TrimSpace(stack[9])
			output += "\n         ==> " + strings.TrimSpace(stack[10])
			if len(stack) >= 12 {
				output += "\n         ==> " + strings.TrimSpace(stack[11])
			}
			if len(stack) >= 13 {
				output += "\n         ==> " + strings.TrimSpace(stack[12])
			}
			if len(stack) >= 14 {
				output += "\n         ==> " + strings.TrimSpace(stack[13])
			}
			if len(stack) >= 15 {
				output += "\n         ==> " + strings.TrimSpace(stack[14])
			}
			if len(stack) >= 16 {
				output += "\n         ==> " + strings.TrimSpace(stack[15])
			}
			output += "\n---------------"
			output += "\n"
			output += "\n"
		}
	}
	return output
}

// ThrowError is a helper function that will throw a fake error and get the callstack and return it as an error (you probably shouldnt use this)
func (self *core_debug) ThrowError() *errors.Error {
	return errors.Errorf("Debug Dump")
}

// GetDump is a helper function that will return a string of the dump of the values passed in
func GetDump(valuesOriginal ...interface{}) string {
	return Debug.GetDump(valuesOriginal...)
}

// Dump is a helper function that will dump the values passed to it
func Dump(valuesOriginal ...interface{}) {
	Debug.Dump(valuesOriginal...)
}
<commit_msg>Add better package desc for core<commit_after>// Package core is the core package of GoCore.
// Also contains some debugging/dumping variable functions
package core

import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"reflect"
	"runtime"
	"runtime/debug"
	"strings"
	"sync"
	"time"

	"github.com/DanielRenne/GoCore/core/extensions"
	"github.com/DanielRenne/GoCore/core/serverSettings"
	"github.com/davidrenne/reflections"
	"github.com/go-errors/errors"
)

type core_debug struct{}

var core_logger = log.New(os.Stdout, "", 0)

// TransactionLog provides a thread-safe buffer/string if you have serverSettings.WebConfig.Application.ReleaseMode == "development" you can call something like core.Debug.GetDump in many places and then read the TransactionLog when you need to (note you must manually clear it as it will just increase your memory usage the more logs are sent)
var TransactionLog string

// Debug is a base struct for all debug functions.
var Debug = core_debug{}

// Logger can be overridden with log.New(os.Stdout, "", 0) to log to stdout or some other writer
var Logger = core_logger

// TransactionLogMutex is a mutex for the TransactionLog which should be used on your end to clear the value safely
var TransactionLogMutex *sync.RWMutex

func init() {
	TransactionLogMutex = &sync.RWMutex{}
}

// Nop is a dummy function that can be called in source files where
// other debug functions are constantly added and removed.
// That way import "github.com/ungerik/go-start/debug" won't cause an error when
// no other debug function is currently used.
// Arbitrary objects can be passed as arguments to avoid "declared and not used"
// error messages when commenting code out and in.
// The result is a nil interface{} dummy value.
func (self *core_debug) Nop(dummiesIn ...interface{}) (dummyOut interface{}) {
	return nil
}

// CallStackInfo returns a string with the call stack info.
func (self *core_debug) CallStackInfo(skip int) (info string) {
	pc, file, line, ok := runtime.Caller(skip)
	if ok {
		funcName := runtime.FuncForPC(pc).Name()
		info += fmt.Sprintf("In function %s()", funcName)
	}
	for i := 0; ok; i++ {
		info += fmt.Sprintf("\n%s:%d", file, line)
		_, file, line, ok = runtime.Caller(skip + i)
	}
	return info
}

// PrintCallStack prints the call stack info.
func (self *core_debug) PrintCallStack() {
	debug.PrintStack()
}

// LogCallStack logs the call stack info.
func (self *core_debug) LogCallStack() {
	log.Print(self.Stack())
}

func (self *core_debug) Stack() string {
	return string(debug.Stack())
}

func (self *core_debug) formatValue(value interface{}) string {
	return fmt.Sprintf("\n     Type: %T\n    Value: %v\nGo Syntax: %#v", value, value, value)
}

func (self *core_debug) formatCallstack(skip int) string {
	return fmt.Sprintf("\nCallstack: %s", self.CallStackInfo(skip+1))
}

// FormatSkip formats a value with callstack info.
func (self *core_debug) FormatSkip(skip int, value interface{}) string {
	return self.formatValue(value) + self.formatCallstack(skip+1)
}

// Format formats a value with callstack info.
func (self *core_debug) Format(value interface{}) string {
	return self.FormatSkip(2, value)
}

// IsZeroOfUnderlyingType returns true if the value is the zero value (nil) for its type.
func IsZeroOfUnderlyingType(x interface{}) bool {
	return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface())
}

// IsZeroOfUnderlyingType2 returns true if the value is the zero value (nil) for its type.
func IsZeroOfUnderlyingType2(x interface{}) bool {
	return x == reflect.Zero(reflect.TypeOf(x)).Interface()
}

// HandleError is a helper function that will log an error and return it with the callers line and file.
func (self *core_debug) HandleError(err error) (s string) {
	if err != nil {
		// notice that we're using 1, so it will actually log the where
		// the error happened, 0 = this function, we don't want that.
		_, fn, line, _ := runtime.Caller(1)
		fileNameParts := strings.Split(fn, "/")
		return fmt.Sprintf("  Error Info: %s Line %d. ErrorType: %v", fileNameParts[len(fileNameParts)-1], line, err)
	}
	return ""
}

// ErrLineAndFile returns the line and file of the error.
func (self *core_debug) ErrLineAndFile(err error) (s string) {
	if err != nil {
		// notice that we're using 1, so it will actually log the where
		// the error happened, 0 = this function, we don't want that.
		_, fn, line, _ := runtime.Caller(1)
		fileNameParts := strings.Split(fn, "/")
		return fmt.Sprintf("%s Line %d", fileNameParts[len(fileNameParts)-1], line)
	}
	return ""
}

// Dump is a helper function that will log unlimited values to print to stdout or however you have log setup if you overload core/Logger
func (self *core_debug) Dump(valuesOriginal ...interface{}) {
	t := time.Now()
	l := "!!!!!!!!!!!!! DEBUG " + t.Format("2006-01-02 15:04:05.000000") + "!!!!!!!!!!!!!\n\n"
	Logger.Println(l)

	serverSettings.WebConfigMutex.RLock()
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	serverSettings.WebConfigMutex.RUnlock()
	for _, value := range valuesOriginal {
		l := self.dumpBase(value)
		Logger.Print(l)
		serverSettings.WebConfigMutex.RLock()
		if serverSettings.WebConfig.Application.ReleaseMode == "development" {
			TransactionLogMutex.Lock()
			TransactionLog += l
			TransactionLogMutex.Unlock()
		}
		serverSettings.WebConfigMutex.RUnlock()
	}
	l = self.ThrowAndPrintError()
	Logger.Print(l)

	serverSettings.WebConfigMutex.RLock()
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	serverSettings.WebConfigMutex.RUnlock()
	l = "!!!!!!!!!!!!! ENDDEBUG " + t.Format("2006-01-02 15:04:05.000000") + "!!!!!!!!!!!!!"
	Logger.Println(l)
	serverSettings.WebConfigMutex.RLock()
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	serverSettings.WebConfigMutex.RUnlock()
}

// GetDump is a helper function that will log unlimited values which will return a string representation of what was logged
func (self *core_debug) GetDump(valuesOriginal ...interface{}) (output string) {
	for _, value := range valuesOriginal {
		output += self.dumpBase(value)
	}
	//output += self.ThrowAndPrintError()
	return output
}

func (self *core_debug) GetDumpWithInfo(valuesOriginal ...interface{}) (output string) {
	t := time.Now()
	return self.GetDumpWithInfoAndTimeString(t.String(), valuesOriginal...)
}

// GetDumpWithInfoAndTimeString is a helper function that will log unlimited values which will return a string representation of what was logged but allows you to pass your own time string in a case of timezone offsets
func (self *core_debug) GetDumpWithInfoAndTimeString(timeStr string, valuesOriginal ...interface{}) (output string) {
	l := "\n!!!!!!!!!!!!! DEBUG " + timeStr + "!!!!!!!!!!!!!\n\n"
	output += l

	serverSettings.WebConfigMutex.RLock()
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	serverSettings.WebConfigMutex.RUnlock()

	for _, value := range valuesOriginal {
		output += self.dumpBase(value) + "\n"
	}

	serverSettings.WebConfigMutex.RLock()
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		TransactionLogMutex.Lock()
		TransactionLog += output
		TransactionLogMutex.Unlock()
	}
	serverSettings.WebConfigMutex.RUnlock()

	l = self.ThrowAndPrintError()
	output += l
	serverSettings.WebConfigMutex.RLock()
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	serverSettings.WebConfigMutex.RUnlock()
	l = "!!!!!!!!!!!!! ENDDEBUG " + timeStr + "!!!!!!!!!!!!!\n"
	output += l
	serverSettings.WebConfigMutex.RLock()
	if serverSettings.WebConfig.Application.ReleaseMode == "development" {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	serverSettings.WebConfigMutex.RUnlock()
	return output
}

func (self *core_debug) dumpBase(values ...interface{}) (output string) {
	var jsonString string
	var err error
	var structKeys []string
	if Logger != nil {
		for _, value := range values {
			isAllJSON := true
			var kind string
			kind = strings.TrimSpace(fmt.Sprintf("%T", value))
			if !IsZeroOfUnderlyingType(value) {
				kind = reflections.ReflectKind(value)
				structKeys, err = reflections.FieldsDeep(value)
				if err == nil {
					for _, field := range structKeys {
						jsonString, err = reflections.GetFieldTag(value, field, "json")
						if err != nil {
							isAllJSON = false
						}
						if jsonString == "" {
							isAllJSON = false
						}
					}
				} else {
					isAllJSON = false
				}
			} else {
				isAllJSON = false
			}

			if isAllJSON || kind == "map" || kind == "bson.M" || kind == "slice" {
				var rawBytes []byte
				rawBytes, err = json.MarshalIndent(value, "", "\t")
				if err == nil {
					if kind == "slice" || kind[:2] == "[]" {
						valReflected := reflect.ValueOf(value)
						output += fmt.Sprintf("#### %-39s [len:%s]####\n%+v", kind, extensions.IntToString(valReflected.Len()), string(rawBytes[:]))
					} else {
						output += fmt.Sprintf("#### %-39s ####\n%+v", kind, string(rawBytes[:]))
					}
				}
			} else {
				if strings.TrimSpace(kind) == "string" {
					var stringVal = value.(string)
					position := strings.Index(stringVal, "Desc->")
					if position == -1 {
						if !extensions.IsPrintable(stringVal) {
							kind += " (non printables -> dump hex)"
							stringVal = hex.Dump([]byte(stringVal))
						}
						valReflected := reflect.ValueOf(value)
						output += fmt.Sprintf("#### %-39s [len:%s]####\n%s", kind, extensions.IntToString(valReflected.Len()), stringVal)
					} else {
						output += stringVal[6:] + " --> "
					}
				} else if kind[:2] == "[]" || strings.TrimSpace(kind) == "array" {
					valReflected := reflect.ValueOf(value)
					output += fmt.Sprintf("#### %-39s [len:%s]####\n%+v", kind, extensions.IntToString(valReflected.Len()), value)
				} else {
					output += fmt.Sprintf("#### %-39s ####\n%+v", kind, value)
				}
			}
		}
	}
	return output
}

// ThrowAndPrintError is a helper function that will throw a fake error and get the callstack and return it as a string (you probably shouldnt use this)
func (self *core_debug) ThrowAndPrintError() (output string) {

	serverSettings.WebConfigMutex.RLock()
	ok := serverSettings.WebConfig.Application.CoreDebugStackTrace
	serverSettings.WebConfigMutex.RUnlock()
	if ok {
		output += "\n"
		errorInfo := self.ThrowError()
		stack := strings.Split(errorInfo.ErrorStack(), "\n")
		if len(stack) >= 8 {
			output += "\nDump Caller:"
			output += "\n---------------"
			//output += strings.Join(stack, ",")
			output += "\n golines ==> " + strings.TrimSpace(stack[6])
			output += "\n         ==> " + strings.TrimSpace(stack[7])
			output += "\n         ==> " + strings.TrimSpace(stack[8])
			output += "\n         ==> " + strings.TrimSpace(stack[9])
			output += "\n         ==> " + strings.TrimSpace(stack[10])
			if len(stack) >= 12 {
				output += "\n         ==> " + strings.TrimSpace(stack[11])
			}
			if len(stack) >= 13 {
				output += "\n         ==> " + strings.TrimSpace(stack[12])
			}
			if len(stack) >= 14 {
				output += "\n         ==> " + strings.TrimSpace(stack[13])
			}
			if len(stack) >= 15 {
				output += "\n         ==> " + strings.TrimSpace(stack[14])
			}
			if len(stack) >= 16 {
				output += "\n         ==> " + strings.TrimSpace(stack[15])
			}
			output += "\n---------------"
			output += "\n"
			output += "\n"
		}
	}
	return output
}

// ThrowError is a helper function that will throw a fake error and get the callstack and return it as an error (you probably shouldnt use this)
func (self *core_debug) ThrowError() *errors.Error {
	return errors.Errorf("Debug Dump")
}

// GetDump is a helper function that will return a string of the dump of the values passed in
func GetDump(valuesOriginal ...interface{}) string {
	return Debug.GetDump(valuesOriginal...)
}

// Dump is a helper function that will dump the values passed to it
func Dump(valuesOriginal ...interface{}) {
	Debug.Dump(valuesOriginal...)
}
<|endoftext|>


<commit_before>// Package core is the main package contents of the GoCore application collection of packages and utilities
// Also the root contains some debugging/dumping variable functions
package core

import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"reflect"
	"runtime"
	"runtime/debug"
	"strings"
	"sync"
	"time"

	"github.com/DanielRenne/GoCore/core/extensions"
	"github.com/DanielRenne/GoCore/core/serverSettings"
	"github.com/davidrenne/reflections"
	"github.com/go-errors/errors"
)

type core_debug struct{}

var core_logger = log.New(os.Stdout, "", 0)

// No one will ever use this, but TransactionLog provides a thread-safe buffer/string if you have debug.EnableTransactionLog set to true you can call something like core.Debug.GetDump in many places and then eventually read the core.TransactionLog value when you need to (note you must manually clear it as it will just increase your memory usage the more logs are sent).  And always remember to use TransactionLogMutex.RLock and unlock when you are trying to read it in a busy system logging lots of stuff
var TransactionLog string

// See TransactionLog documentation
var EnableTransactionLog bool

// Debug is a base struct for all debug functions.
var Debug = core_debug{}

// LogStackTraces will show you where your logs are coming from in the stack.  Alternatively if you are using a GoCore full web app with a webConfig.json you can set CoreDebugStackTrace to true if you dont override this to false or true.  The default is true.
var LogStackTraces bool

// Logger can be overridden with log.New(os.Stdout, "", 0) to log to stdout or some other writer
var Logger = core_logger

// TransactionLogMutex is a mutex for the TransactionLog which should be used on your end to clear the value safely
var TransactionLogMutex *sync.RWMutex

func init() {
	LogStackTraces = true
	TransactionLogMutex = &sync.RWMutex{}
}

// Nop is a dummy function that can be called in source files where
// other debug functions are constantly added and removed.
// That way import "github.com/ungerik/go-start/debug" won't cause an error when
// no other debug function is currently used.
// Arbitrary objects can be passed as arguments to avoid "declared and not used"
// error messages when commenting code out and in.
// The result is a nil interface{} dummy value.
func (self *core_debug) Nop(dummiesIn ...interface{}) (dummyOut interface{}) {
	return nil
}

// CallStackInfo returns a string with the call stack info.
func (self *core_debug) CallStackInfo(skip int) (info string) {
	pc, file, line, ok := runtime.Caller(skip)
	if ok {
		funcName := runtime.FuncForPC(pc).Name()
		info += fmt.Sprintf("In function %s()", funcName)
	}
	for i := 0; ok; i++ {
		info += fmt.Sprintf("\n%s:%d", file, line)
		_, file, line, ok = runtime.Caller(skip + i)
	}
	return info
}

// PrintCallStack prints the call stack info.
func (self *core_debug) PrintCallStack() {
	debug.PrintStack()
}

// LogCallStack logs the call stack info.
func (self *core_debug) LogCallStack() {
	log.Print(self.Stack())
}

func (self *core_debug) Stack() string {
	return string(debug.Stack())
}

func (self *core_debug) formatValue(value interface{}) string {
	return fmt.Sprintf("\n     Type: %T\n    Value: %v\nGo Syntax: %#v", value, value, value)
}

func (self *core_debug) formatCallstack(skip int) string {
	return fmt.Sprintf("\nCallstack: %s", self.CallStackInfo(skip+1))
}

// FormatSkip formats a value with callstack info.
func (self *core_debug) FormatSkip(skip int, value interface{}) string {
	return self.formatValue(value) + self.formatCallstack(skip+1)
}

// Format formats a value with callstack info.
func (self *core_debug) Format(value interface{}) string {
	return self.FormatSkip(2, value)
}

// IsZeroOfUnderlyingType returns true if the value is the zero value (nil) for its type.
func IsZeroOfUnderlyingType(x interface{}) bool {
	return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface())
}

// IsZeroOfUnderlyingType2 returns true if the value is the zero value (nil) for its type.
func IsZeroOfUnderlyingType2(x interface{}) bool {
	return x == reflect.Zero(reflect.TypeOf(x)).Interface()
}

// HandleError is a helper function that will log an error and return it with the callers line and file.
func (self *core_debug) HandleError(err error) (s string) {
	if err != nil {
		// notice that we're using 1, so it will actually log the where
		// the error happened, 0 = this function, we don't want that.
		_, fn, line, _ := runtime.Caller(1)
		fileNameParts := strings.Split(fn, "/")
		return fmt.Sprintf("  Error Info: %s Line %d. ErrorType: %v", fileNameParts[len(fileNameParts)-1], line, err)
	}
	return ""
}

// ErrLineAndFile returns the line and file of the error.
func (self *core_debug) ErrLineAndFile(err error) (s string) {
	if err != nil {
		// notice that we're using 1, so it will actually log the where
		// the error happened, 0 = this function, we don't want that.
		_, fn, line, _ := runtime.Caller(1)
		fileNameParts := strings.Split(fn, "/")
		return fmt.Sprintf("%s Line %d", fileNameParts[len(fileNameParts)-1], line)
	}
	return ""
}

// Dump is a helper function that will log unlimited values to print to stdout or however you have log setup if you overload core/Logger
func (self *core_debug) Dump(valuesOriginal ...interface{}) {
	t := time.Now()
	l := "!!!!!!!!!!!!! DEBUG " + t.Format("2006-01-02 15:04:05.000000") + "!!!!!!!!!!!!!\n\n"
	Logger.Println(l)

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	for _, value := range valuesOriginal {
		l := self.dumpBase(value)
		Logger.Print(l)
		if EnableTransactionLog {
			TransactionLogMutex.Lock()
			TransactionLog += l
			TransactionLogMutex.Unlock()
		}
	}
	l = self.ThrowAndPrintError()
	Logger.Print(l)

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	l = "!!!!!!!!!!!!! ENDDEBUG " + t.Format("2006-01-02 15:04:05.000000") + "!!!!!!!!!!!!!"
	Logger.Println(l)
	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
}

// GetDump is a helper function that will log unlimited values which will return a string representation of what was logged
func (self *core_debug) GetDump(valuesOriginal ...interface{}) (output string) {
	for _, value := range valuesOriginal {
		output += self.dumpBase(value)
	}
	//output += self.ThrowAndPrintError()
	return output
}

func (self *core_debug) GetDumpWithInfo(valuesOriginal ...interface{}) (output string) {
	t := time.Now()
	return self.GetDumpWithInfoAndTimeString(t.String(), valuesOriginal...)
}

// GetDumpWithInfoAndTimeString is a helper function that will log unlimited values which will return a string representation of what was logged but allows you to pass your own time string in a case of timezone offsets
func (self *core_debug) GetDumpWithInfoAndTimeString(timeStr string, valuesOriginal ...interface{}) (output string) {
	l := "\n!!!!!!!!!!!!! DEBUG " + timeStr + "!!!!!!!!!!!!!\n\n"
	output += l

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}

	for _, value := range valuesOriginal {
		output += self.dumpBase(value) + "\n"
	}

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += output
		TransactionLogMutex.Unlock()
	}

	l = self.ThrowAndPrintError()
	output += l

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}

	l = "!!!!!!!!!!!!! ENDDEBUG " + timeStr + "!!!!!!!!!!!!!\n"
	output += l
	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	return output
}

func (self *core_debug) dumpBase(values ...interface{}) (output string) {
	var jsonString string
	var err error
	var structKeys []string
	if Logger != nil {
		for _, value := range values {
			isAllJSON := true
			var kind string
			kind = strings.TrimSpace(fmt.Sprintf("%T", value))
			kindFormatted := strings.TrimSpace(fmt.Sprintf("%T", value))
			// var pieces = strings.Split(kind, " ")
			// if pieces[0] == "struct" || strings.Index(pieces[0], "model.") != -1 || strings.Index(pieces[0], "viewModel.") != -1 {
			if !IsZeroOfUnderlyingType(value) {
				kind = reflections.ReflectKind(value)
				structKeys, err = reflections.FieldsDeep(value)
				if err == nil {
					for _, field := range structKeys {
						jsonString, err = reflections.GetFieldTag(value, field, "json")
						if err != nil {
							isAllJSON = false
						}
						if jsonString == "" {
							isAllJSON = false
						}
					}
				} else {
					isAllJSON = false
				}
			} else {
				isAllJSON = false
			}

			if kindFormatted != "[]uint8" && (isAllJSON || kind == "map" || kind == "bson.M" || kind == "slice") {
				var rawBytes []byte
				rawBytes, err = json.MarshalIndent(value, "", "\t")
				if err == nil {
					if kind == "slice" || kind[:2] == "[]" {
						valReflected := reflect.ValueOf(value)
						output += fmt.Sprintf("#### %-39s [len:%s]####\n%+v", kindFormatted, extensions.IntToString(valReflected.Len()), string(rawBytes[:]))
						output += "\n\nOr Go Slice Code\n\n" + fmt.Sprintf("%#v", value)
					} else {
						output += fmt.Sprintf("#### %-39s ####\n%+v", kindFormatted, string(rawBytes[:]))
						output += "\n\nOr Go Struct Code\n\n" + fmt.Sprintf("%#v", value)
					}
				}
			} else {
				if strings.TrimSpace(kind) == "string" {
					var stringVal = fmt.Sprintf("%+v", value)
					position := strings.Index(stringVal, "Desc->")
					if position == -1 {
						if !extensions.IsPrintable(stringVal) {
							kind += " (non printables -> dump hex)"
							stringVal = hex.Dump([]byte(stringVal))
						}
						valReflected := reflect.ValueOf(value)
						output += fmt.Sprintf("#### %-39s [len:%s]####\n%s", kindFormatted, extensions.IntToString(valReflected.Len()), stringVal)
					} else {
						output += stringVal[6:] + " --> "
					}
				} else if kindFormatted == "[]uint8" || kind[:2] == "[]" || strings.TrimSpace(kind) == "array" {
					if kindFormatted == "[]uint8" {
						val, ok := value.([]uint8)
						if ok {
							if !extensions.IsPrintable(string(val)) {
								kind += " (non printables -> dump hex of a []byte)"
								output = hex.Dump(value.([]uint8))
							} else {
								valReflected := reflect.ValueOf(value)
								output += fmt.Sprintf("#### %-39s [len:%s]####\n%s", kindFormatted, extensions.IntToString(valReflected.Len()), string(val))
							}
						}
					} else {
						valReflected := reflect.ValueOf(value)
						output += fmt.Sprintf("#### %-39s [len:%s]####\n%#v", kindFormatted, extensions.IntToString(valReflected.Len()), value)
					}
				} else {
					output += fmt.Sprintf("#### %-39s ####\n%#v", kindFormatted, value)
				}
			}
		}
	}
	return output
}

// ThrowAndPrintError is a helper function that will throw a fake error and get the callstack and return it as a string (you probably shouldnt use this)
func (self *core_debug) ThrowAndPrintError() (output string) {

	serverSettings.WebConfigMutex.RLock()
	ok := serverSettings.WebConfig.Application.CoreDebugStackTrace
	serverSettings.WebConfigMutex.RUnlock()
	if ok || LogStackTraces {
		output += "\n"
		errorInfo := self.ThrowError()
		stack := strings.Split(errorInfo.ErrorStack(), "\n")
		if len(stack) >= 8 {
			output += "\nDump Caller:"
			output += "\n---------------"
			//output += strings.Join(stack, ",")
			output += "\n golines ==> " + strings.TrimSpace(stack[6])
			output += "\n         ==> " + strings.TrimSpace(stack[7])
			output += "\n         ==> " + strings.TrimSpace(stack[8])
			output += "\n         ==> " + strings.TrimSpace(stack[9])
			output += "\n         ==> " + strings.TrimSpace(stack[10])
			if len(stack) >= 12 {
				output += "\n         ==> " + strings.TrimSpace(stack[11])
			}
			if len(stack) >= 13 {
				output += "\n         ==> " + strings.TrimSpace(stack[12])
			}
			if len(stack) >= 14 {
				output += "\n         ==> " + strings.TrimSpace(stack[13])
			}
			if len(stack) >= 15 {
				output += "\n         ==> " + strings.TrimSpace(stack[14])
			}
			if len(stack) >= 16 {
				output += "\n         ==> " + strings.TrimSpace(stack[15])
			}
			output += "\n---------------"
			output += "\n"
			output += "\n"
		}
	}
	return output
}

// ThrowError is a helper function that will throw a fake error and get the callstack and return it as an error (you probably shouldnt use this)
func (self *core_debug) ThrowError() *errors.Error {
	return errors.Errorf("Debug Dump")
}

// GetDump is a helper function that will return a string of the dump of the values passed in
func GetDump(valuesOriginal ...interface{}) string {
	return Debug.GetDump(valuesOriginal...)
}

// Dump is a helper function that will dump the values passed to it
func Dump(valuesOriginal ...interface{}) {
	Debug.Dump(valuesOriginal...)
}
<commit_msg>Stack trace issues<commit_after>// Package core is the main package contents of the GoCore application collection of packages and utilities
// Also the root contains some debugging/dumping variable functions
package core

import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"reflect"
	"runtime"
	"runtime/debug"
	"strings"
	"sync"
	"time"

	"github.com/DanielRenne/GoCore/core/extensions"
	"github.com/DanielRenne/GoCore/core/serverSettings"
	"github.com/davidrenne/reflections"
	"github.com/go-errors/errors"
)

type core_debug struct{}

var core_logger = log.New(os.Stdout, "", 0)

// No one will ever use this, but TransactionLog provides a thread-safe buffer/string if you have debug.EnableTransactionLog set to true you can call something like core.Debug.GetDump in many places and then eventually read the core.TransactionLog value when you need to (note you must manually clear it as it will just increase your memory usage the more logs are sent).  And always remember to use TransactionLogMutex.RLock and unlock when you are trying to read it in a busy system logging lots of stuff
var TransactionLog string

// See TransactionLog documentation
var EnableTransactionLog bool

// Debug is a base struct for all debug functions.
var Debug = core_debug{}

// LogStackTraces will show you where your logs are coming from in the stack.  Alternatively if you are using a GoCore full web app with a webConfig.json you can set CoreDebugStackTrace to true if you dont override this to false or true.  The default is true.
var LogStackTraces bool

// Logger can be overridden with log.New(os.Stdout, "", 0) to log to stdout or some other writer
var Logger = core_logger

// TransactionLogMutex is a mutex for the TransactionLog which should be used on your end to clear the value safely
var TransactionLogMutex *sync.RWMutex

func init() {
	LogStackTraces = false
	TransactionLogMutex = &sync.RWMutex{}
}

// Nop is a dummy function that can be called in source files where
// other debug functions are constantly added and removed.
// That way import "github.com/ungerik/go-start/debug" won't cause an error when
// no other debug function is currently used.
// Arbitrary objects can be passed as arguments to avoid "declared and not used"
// error messages when commenting code out and in.
// The result is a nil interface{} dummy value.
func (self *core_debug) Nop(dummiesIn ...interface{}) (dummyOut interface{}) {
	return nil
}

// CallStackInfo returns a string with the call stack info.
func (self *core_debug) CallStackInfo(skip int) (info string) {
	pc, file, line, ok := runtime.Caller(skip)
	if ok {
		funcName := runtime.FuncForPC(pc).Name()
		info += fmt.Sprintf("In function %s()", funcName)
	}
	for i := 0; ok; i++ {
		info += fmt.Sprintf("\n%s:%d", file, line)
		_, file, line, ok = runtime.Caller(skip + i)
	}
	return info
}

// PrintCallStack prints the call stack info.
func (self *core_debug) PrintCallStack() {
	debug.PrintStack()
}

// LogCallStack logs the call stack info.
func (self *core_debug) LogCallStack() {
	log.Print(self.Stack())
}

func (self *core_debug) Stack() string {
	return string(debug.Stack())
}

func (self *core_debug) formatValue(value interface{}) string {
	return fmt.Sprintf("\n     Type: %T\n    Value: %v\nGo Syntax: %#v", value, value, value)
}

func (self *core_debug) formatCallstack(skip int) string {
	return fmt.Sprintf("\nCallstack: %s", self.CallStackInfo(skip+1))
}

// FormatSkip formats a value with callstack info.
func (self *core_debug) FormatSkip(skip int, value interface{}) string {
	return self.formatValue(value) + self.formatCallstack(skip+1)
}

// Format formats a value with callstack info.
func (self *core_debug) Format(value interface{}) string {
	return self.FormatSkip(2, value)
}

// IsZeroOfUnderlyingType returns true if the value is the zero value (nil) for its type.
func IsZeroOfUnderlyingType(x interface{}) bool {
	return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface())
}

// IsZeroOfUnderlyingType2 returns true if the value is the zero value (nil) for its type.
func IsZeroOfUnderlyingType2(x interface{}) bool {
	return x == reflect.Zero(reflect.TypeOf(x)).Interface()
}

// HandleError is a helper function that will log an error and return it with the callers line and file.
func (self *core_debug) HandleError(err error) (s string) {
	if err != nil {
		// notice that we're using 1, so it will actually log the where
		// the error happened, 0 = this function, we don't want that.
		_, fn, line, _ := runtime.Caller(1)
		fileNameParts := strings.Split(fn, "/")
		return fmt.Sprintf("  Error Info: %s Line %d. ErrorType: %v", fileNameParts[len(fileNameParts)-1], line, err)
	}
	return ""
}

// ErrLineAndFile returns the line and file of the error.
func (self *core_debug) ErrLineAndFile(err error) (s string) {
	if err != nil {
		// notice that we're using 1, so it will actually log the where
		// the error happened, 0 = this function, we don't want that.
		_, fn, line, _ := runtime.Caller(1)
		fileNameParts := strings.Split(fn, "/")
		return fmt.Sprintf("%s Line %d", fileNameParts[len(fileNameParts)-1], line)
	}
	return ""
}

// Dump is a helper function that will log unlimited values to print to stdout or however you have log setup if you overload core/Logger
func (self *core_debug) Dump(valuesOriginal ...interface{}) {
	t := time.Now()
	l := "!!!!!!!!!!!!! DEBUG " + t.Format("2006-01-02 15:04:05.000000") + "!!!!!!!!!!!!!\n\n"
	Logger.Println(l)

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	for _, value := range valuesOriginal {
		l := self.dumpBase(value)
		Logger.Print(l)
		if EnableTransactionLog {
			TransactionLogMutex.Lock()
			TransactionLog += l
			TransactionLogMutex.Unlock()
		}
	}
	l = self.ThrowAndPrintError()
	Logger.Print(l)

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	l = "!!!!!!!!!!!!! ENDDEBUG " + t.Format("2006-01-02 15:04:05.000000") + "!!!!!!!!!!!!!"
	Logger.Println(l)
	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
}

// GetDump is a helper function that will log unlimited values which will return a string representation of what was logged
func (self *core_debug) GetDump(valuesOriginal ...interface{}) (output string) {
	for _, value := range valuesOriginal {
		output += self.dumpBase(value)
	}
	//output += self.ThrowAndPrintError()
	return output
}

func (self *core_debug) GetDumpWithInfo(valuesOriginal ...interface{}) (output string) {
	t := time.Now()
	return self.GetDumpWithInfoAndTimeString(t.String(), valuesOriginal...)
}

// GetDumpWithInfoAndTimeString is a helper function that will log unlimited values which will return a string representation of what was logged but allows you to pass your own time string in a case of timezone offsets
func (self *core_debug) GetDumpWithInfoAndTimeString(timeStr string, valuesOriginal ...interface{}) (output string) {
	l := "\n!!!!!!!!!!!!! DEBUG " + timeStr + "!!!!!!!!!!!!!\n\n"
	output += l

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}

	for _, value := range valuesOriginal {
		output += self.dumpBase(value) + "\n"
	}

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += output
		TransactionLogMutex.Unlock()
	}

	l = self.ThrowAndPrintError()
	output += l

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}

	l = "!!!!!!!!!!!!! ENDDEBUG " + timeStr + "!!!!!!!!!!!!!\n"
	output += l
	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	return output
}

func (self *core_debug) dumpBase(values ...interface{}) (output string) {
	var jsonString string
	var err error
	var structKeys []string
	if Logger != nil {
		for _, value := range values {
			isAllJSON := true
			var kind string
			kind = strings.TrimSpace(fmt.Sprintf("%T", value))
			kindFormatted := strings.TrimSpace(fmt.Sprintf("%T", value))
			// var pieces = strings.Split(kind, " ")
			// if pieces[0] == "struct" || strings.Index(pieces[0], "model.") != -1 || strings.Index(pieces[0], "viewModel.") != -1 {
			if !IsZeroOfUnderlyingType(value) {
				kind = reflections.ReflectKind(value)
				structKeys, err = reflections.FieldsDeep(value)
				if err == nil {
					for _, field := range structKeys {
						jsonString, err = reflections.GetFieldTag(value, field, "json")
						if err != nil {
							isAllJSON = false
						}
						if jsonString == "" {
							isAllJSON = false
						}
					}
				} else {
					isAllJSON = false
				}
			} else {
				isAllJSON = false
			}

			if kindFormatted != "[]uint8" && (isAllJSON || kind == "map" || kind == "bson.M" || kind == "slice") {
				var rawBytes []byte
				rawBytes, err = json.MarshalIndent(value, "", "\t")
				if err == nil {
					if kind == "slice" || kind[:2] == "[]" {
						valReflected := reflect.ValueOf(value)
						output += fmt.Sprintf("#### %-39s [len:%s]####\n%+v", kindFormatted, extensions.IntToString(valReflected.Len()), string(rawBytes[:]))
						output += "\n\nOr Go Slice Code\n\n" + fmt.Sprintf("%#v", value)
					} else {
						output += fmt.Sprintf("#### %-39s ####\n%+v", kindFormatted, string(rawBytes[:]))
						output += "\n\nOr Go Struct Code\n\n" + fmt.Sprintf("%#v", value)
					}
				}
			} else {
				if strings.TrimSpace(kind) == "string" {
					var stringVal = fmt.Sprintf("%+v", value)
					position := strings.Index(stringVal, "Desc->")
					if position == -1 {
						if !extensions.IsPrintable(stringVal) {
							kind += " (non printables -> dump hex)"
							stringVal = hex.Dump([]byte(stringVal))
						}
						valReflected := reflect.ValueOf(value)
						output += fmt.Sprintf("#### %-39s [len:%s]####\n%s", kindFormatted, extensions.IntToString(valReflected.Len()), stringVal)
					} else {
						output += stringVal[6:] + " --> "
					}
				} else if kindFormatted == "[]uint8" || kind[:2] == "[]" || strings.TrimSpace(kind) == "array" {
					if kindFormatted == "[]uint8" {
						val, ok := value.([]uint8)
						if ok {
							if !extensions.IsPrintable(string(val)) {
								kind += " (non printables -> dump hex of a []byte)"
								output = hex.Dump(value.([]uint8))
							} else {
								valReflected := reflect.ValueOf(value)
								output += fmt.Sprintf("#### %-39s [len:%s]####\n%s", kindFormatted, extensions.IntToString(valReflected.Len()), string(val))
							}
						}
					} else {
						valReflected := reflect.ValueOf(value)
						output += fmt.Sprintf("#### %-39s [len:%s]####\n%#v", kindFormatted, extensions.IntToString(valReflected.Len()), value)
					}
				} else {
					output += fmt.Sprintf("#### %-39s ####\n%#v", kindFormatted, value)
				}
			}
		}
	}
	return output
}

// ThrowAndPrintError is a helper function that will throw a fake error and get the callstack and return it as a string (you probably shouldnt use this)
func (self *core_debug) ThrowAndPrintError() (output string) {

	serverSettings.WebConfigMutex.RLock()
	ok := serverSettings.WebConfig.Application.CoreDebugStackTrace
	serverSettings.WebConfigMutex.RUnlock()
	if ok || LogStackTraces {
		output += "\n"
		errorInfo := self.ThrowError()
		stack := strings.Split(errorInfo.ErrorStack(), "\n")
		if len(stack) >= 8 {
			output += "\nDump Caller:"
			output += "\n---------------"
			//output += strings.Join(stack, ",")
			if len(stack) >= 7 {
				output += "\n golines ==> " + strings.TrimSpace(stack[6])
			}
			if len(stack) >= 8 {
				output += "\n         ==> " + strings.TrimSpace(stack[7])
			}
			if len(stack) >= 9 {
				output += "\n         ==> " + strings.TrimSpace(stack[8])
			}
			if len(stack) >= 10 {
				output += "\n         ==> " + strings.TrimSpace(stack[9])
			}
			if len(stack) >= 11 {
				output += "\n         ==> " + strings.TrimSpace(stack[10])
			}
			if len(stack) >= 12 {
				output += "\n         ==> " + strings.TrimSpace(stack[11])
			}
			if len(stack) >= 13 {
				output += "\n         ==> " + strings.TrimSpace(stack[12])
			}
			if len(stack) >= 14 {
				output += "\n         ==> " + strings.TrimSpace(stack[13])
			}
			if len(stack) >= 15 {
				output += "\n         ==> " + strings.TrimSpace(stack[14])
			}
			if len(stack) >= 16 {
				output += "\n         ==> " + strings.TrimSpace(stack[15])
			}
			output += "\n---------------"
			output += "\n"
			output += "\n"
		}
	}
	return output
}

// ThrowError is a helper function that will throw a fake error and get the callstack and return it as an error (you probably shouldnt use this)
func (self *core_debug) ThrowError() *errors.Error {
	return errors.Errorf("Debug Dump")
}

// GetDump is a helper function that will return a string of the dump of the values passed in
func GetDump(valuesOriginal ...interface{}) string {
	return Debug.GetDump(valuesOriginal...)
}

// Dump is a helper function that will dump the values passed to it
func Dump(valuesOriginal ...interface{}) {
	Debug.Dump(valuesOriginal...)
}
<|endoftext|>


<commit_before>package dbf

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

const (
	_BENCH_TYPE_CPU     = 0
	_BENCH_TYPE_GPU_AMD = 1
	_BENCH_TYPE_GPU_NV  = 2

	_VENDOR_TYPE_GENERATOR = "generator"
	_VENDOR_TYPE_CRACKER   = "cracker"
)

var (
	confDbf      *ConfigDbf
	pathCurrent  string
	pathConfDir  string
	pathConfFile string
	pathVendor   string
	pathCrack    string
)

func InitConfig() {
	initConfigPlatform()

	// Set current path
	var err error
	pathCurrent, err = filepath.Abs(filepath.Dir(os.Args[0]))
	if err == nil {
		pathCurrent += string(os.PathSeparator)
	} else {
		Log.Printf("%s\n", err)
		panic(1)
	}

	pathConfDir = pathCurrent + "config" + string(os.PathSeparator)
	pathConfFile = pathConfDir + "dbf.json"
	pathVendor = pathCurrent + "vendor" + string(os.PathSeparator)
	pathCrack = pathCurrent + "crack" + string(os.PathSeparator)

	check()
}

// checkDir checks if dir exists and is accessible, otherwise tries to create it
func checkDir(path string) error {
	if _, err := os.Stat(path); err != nil {
		if os.IsNotExist(err) { // Does not exist, so create it
			if err = os.MkdirAll(path, 0775); err != nil {
				Log.Printf("%s\n", err) // Error in creating
				return err
			}
		} else {
			Log.Printf("%s\n", err) // Error in accessing
			return err
		}
	}

	return nil
}

func check() {
	err := checkDir(pathConfDir)
	if err != nil {
		Log.Printf("%s\n", err)
		panic(1)
	}

	// Check config file
	if _, err := os.Stat(pathConfFile); err != nil {
		if os.IsNotExist(err) { // Does not exist, so create it
			// Create initial config file
			err = createConfDbf()
			if err == nil {
				fmt.Printf("Please enter server's URL in url_api in config file: %s\n", pathConfFile)
				panic(0)
			} else { // Can't create
				Log.Printf("%s\n", err)
				panic(1)
			}
		} else {
			Log.Printf("%s\n", err) // Error in accessing
			panic(1)
		}
	} else { // Sync config file
		err := checkDir(pathVendor)
		if err != nil {
			Log.Printf("%s\n", err)
			panic(1)
		}

		err = checkDir(pathCrack)
		if err != nil {
			Log.Printf("%s\n", err)
			panic(1)
		}

		confDbf = readConfDbf()

		initServer()

		// Check default vendor files and update benchmarks
		for i, platform := range *confDbf.Platform {
			if strings.HasPrefix(platform.Id, "cpu") { // CPU
				if platform.Active != 0 { // Is active
					(*confDbf.Platform)[i].Benchmark = getBench(_BENCH_TYPE_CPU, &platform.Id)
				}
			} else if strings.HasSuffix(platform.Id, "_amd") { // GPU AMD
				if platform.Active != 0 { // Is active
					(*confDbf.Platform)[i].Benchmark = getBench(_BENCH_TYPE_GPU_AMD, &platform.Id)
				}
			} else if strings.HasSuffix(platform.Id, "_nv") { // GPU Nvidia
				if platform.Active != 0 { // Is active
					(*confDbf.Platform)[i].Benchmark = getBench(_BENCH_TYPE_GPU_NV, &platform.Id)
				}
			}
		}

		// Update config file
		saveConfDbf(confDbf)
	}
}

func getBench(benchType int, platformId *string) int {
	// Check vendor file
	var vendorBench string
	switch benchType {
	case _BENCH_TYPE_CPU:
		vendorBench = "hashcat"
	case _BENCH_TYPE_GPU_AMD:
		vendorBench = "oclHashcat"
	case _BENCH_TYPE_GPU_NV:
		vendorBench = "cudaHashcat"
	default:
		return 0
	}

	pathVendorBench := pathVendor + "cracker" + string(os.PathSeparator) + vendorBench + string(os.PathSeparator) + *platformId + string(os.PathSeparator)
	err := checkDir(pathVendorBench)
	if err != nil {
		Log.Printf("%s\n", err)
		panic(1)
	}
	pathVendorBench += *platformId

	if _, err := os.Stat(pathVendorBench); os.IsNotExist(err) {
		if getVendor(_VENDOR_TYPE_CRACKER, &vendorBench, platformId, &pathVendorBench) == false {
			return 0
		}
	}

	// Preform benchmark

	/*
	out, err := exec.Command(pathVendorBench, "-b -m 0").Output()
	if err != nil {
		Log.Fatal(err)
	}
	fmt.Printf("STDOUT: %s\n", out)
	*/

	cmd := exec.Command(pathVendorBench, "-b -m 0")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		Log.Println("a")
		Log.Fatal(err)
	}
	if err := cmd.Start(); err != nil {
		Log.Println("b")
		Log.Fatal(err)
	}

	var b []byte
	stdout.Read(b)

	if err := cmd.Wait(); err != nil {
		Log.Println("c")
		Log.Fatal(err)
	}
	fmt.Printf("STDOUT: %s\n", b)

	return 1
}
<commit_msg>Preparing command execution!!!<commit_after>package dbf

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	//	"bytes"
	"strings"
)

const (
	_BENCH_TYPE_CPU     = 0
	_BENCH_TYPE_GPU_AMD = 1
	_BENCH_TYPE_GPU_NV  = 2

	_VENDOR_TYPE_GENERATOR = "generator"
	_VENDOR_TYPE_CRACKER   = "cracker"
)

var (
	confDbf      *ConfigDbf
	pathCurrent  string
	pathConfDir  string
	pathConfFile string
	pathVendor   string
	pathCrack    string
)

func InitConfig() {
	initConfigPlatform()

	// Set current path
	var err error
	pathCurrent, err = filepath.Abs(filepath.Dir(os.Args[0]))
	if err == nil {
		pathCurrent += string(os.PathSeparator)
	} else {
		Log.Printf("%s\n", err)
		panic(1)
	}

	pathConfDir = pathCurrent + "config" + string(os.PathSeparator)
	pathConfFile = pathConfDir + "dbf.json"
	pathVendor = pathCurrent + "vendor" + string(os.PathSeparator)
	pathCrack = pathCurrent + "crack" + string(os.PathSeparator)

	check()
}

// checkDir checks if dir exists and is accessible, otherwise tries to create it
func checkDir(path string) error {
	if _, err := os.Stat(path); err != nil {
		if os.IsNotExist(err) { // Does not exist, so create it
			if err = os.MkdirAll(path, 0775); err != nil {
				Log.Printf("%s\n", err) // Error in creating
				return err
			}
		} else {
			Log.Printf("%s\n", err) // Error in accessing
			return err
		}
	}

	return nil
}

func check() {
	err := checkDir(pathConfDir)
	if err != nil {
		Log.Printf("%s\n", err)
		panic(1)
	}

	// Check config file
	if _, err := os.Stat(pathConfFile); err != nil {
		if os.IsNotExist(err) { // Does not exist, so create it
			// Create initial config file
			err = createConfDbf()
			if err == nil {
				fmt.Printf("Please enter server's URL in url_api in config file: %s\n", pathConfFile)
				panic(0)
			} else { // Can't create
				Log.Printf("%s\n", err)
				panic(1)
			}
		} else {
			Log.Printf("%s\n", err) // Error in accessing
			panic(1)
		}
	} else { // Sync config file
		err := checkDir(pathVendor)
		if err != nil {
			Log.Printf("%s\n", err)
			panic(1)
		}

		err = checkDir(pathCrack)
		if err != nil {
			Log.Printf("%s\n", err)
			panic(1)
		}

		confDbf = readConfDbf()

		initServer()

		// Check default vendor files and update benchmarks
		for i, platform := range *confDbf.Platform {
			if strings.HasPrefix(platform.Id, "cpu") { // CPU
				if platform.Active != 0 { // Is active
					(*confDbf.Platform)[i].Benchmark = getBench(_BENCH_TYPE_CPU, &platform.Id)
				}
			} else if strings.HasSuffix(platform.Id, "_amd") { // GPU AMD
				if platform.Active != 0 { // Is active
					(*confDbf.Platform)[i].Benchmark = getBench(_BENCH_TYPE_GPU_AMD, &platform.Id)
				}
			} else if strings.HasSuffix(platform.Id, "_nv") { // GPU Nvidia
				if platform.Active != 0 { // Is active
					(*confDbf.Platform)[i].Benchmark = getBench(_BENCH_TYPE_GPU_NV, &platform.Id)
				}
			}
		}

		// Update config file
		saveConfDbf(confDbf)
	}
}

func getBench(benchType int, platformId *string) int {
	// Check vendor file
	var vendorBench string
	switch benchType {
	case _BENCH_TYPE_CPU:
		vendorBench = "hashcat"
	case _BENCH_TYPE_GPU_AMD:
		vendorBench = "oclHashcat"
	case _BENCH_TYPE_GPU_NV:
		vendorBench = "cudaHashcat"
	default:
		return 0
	}

	pathVendorBench := pathVendor + "cracker" + string(os.PathSeparator) + vendorBench + string(os.PathSeparator) + *platformId + string(os.PathSeparator)
	err := checkDir(pathVendorBench)
	if err != nil {
		Log.Printf("%s\n", err)
		panic(1)
	}
	pathVendorBench += *platformId

	if _, err := os.Stat(pathVendorBench); os.IsNotExist(err) {
		if getVendor(_VENDOR_TYPE_CRACKER, &vendorBench, platformId, &pathVendorBench) == false {
			return 0
		}
	}

	// Preform benchmark
	cmd := exec.Command(pathVendorBench, "-b", "-m 0")

	//	var cmdOut, cmdErr bytes.Buffer
	//	cmd.Stdout = &cmdOut
	//	cmd.Stderr = &cmdErr
	//	cmd.Run()
	//	fmt.Printf("STDOUT: %s\n", cmd.Stdout)
	//	fmt.Printf("STDERR: %s\n", cmd.Stderr)

	stdout, _ := cmd.StdoutPipe()
	stderr, _ := cmd.StderrPipe()
	cmd.Start()
	b, _ := ioutil.ReadAll(stdout)
	fmt.Printf("STDOUT: %s\n", string(b))
	b, _ = ioutil.ReadAll(stderr)
	fmt.Printf("STDERR: %s\n", string(b))
	cmd.Wait()

	return 1
}
<|endoftext|>


<commit_before>// A memcached binary protocol client.
package memcached

import (
	"encoding/binary"
	"fmt"
	"io"
	"log"
	"net"
	"strings"
	"sync"

	"github.com/dustin/gomemcached"
)

const bufsize = 1024

// The Client itself.
type Client struct {
	conn    io.ReadWriteCloser
	healthy bool

	hdrBuf []byte
}

// Connect to a memcached server.
func Connect(prot, dest string) (rv *Client, err error) {
	conn, err := net.Dial(prot, dest)
	if err != nil {
		return nil, err
	}
	return Wrap(conn)
}

// Wrap an existing transport.
func Wrap(rwc io.ReadWriteCloser) (rv *Client, err error) {
	return &Client{
		conn:    rwc,
		healthy: true,
		hdrBuf:  make([]byte, gomemcached.HDR_LEN),
	}, nil
}

// Close the connection when you're done.
func (c *Client) Close() {
	c.conn.Close()
}

// Return false if this client has had issues communicating.
//
// This is useful for connection pools where we want to
// non-destructively determine that a connection may be reused.
func (c Client) IsHealthy() bool {
	return c.healthy
}

// Send a custom request and get the response.
func (client *Client) Send(req *gomemcached.MCRequest) (rv *gomemcached.MCResponse, err error) {
	err = transmitRequest(client.conn, req)
	if err != nil {
		client.healthy = false
		return
	}
	resp, err := getResponse(client.conn, client.hdrBuf)
	if err != nil {
		client.healthy = false
	}
	return resp, err
}

// Send a request, but do not wait for a response.
func (client *Client) Transmit(req *gomemcached.MCRequest) error {
	err := transmitRequest(client.conn, req)
	if err != nil {
		client.healthy = false
	}
	return err
}

// Receive a response
func (client *Client) Receive() (*gomemcached.MCResponse, error) {
	resp, err := getResponse(client.conn, client.hdrBuf)
	if err != nil {
		client.healthy = false
	}
	return resp, err
}

// Get the value for a key.
func (client *Client) Get(vb uint16, key string) (*gomemcached.MCResponse, error) {
	return client.Send(&gomemcached.MCRequest{
		Opcode:  gomemcached.GET,
		VBucket: vb,
		Key:     []byte(key),
		Cas:     0,
		Opaque:  0,
		Extras:  []byte{},
		Body:    []byte{}})
}

// Delete a key.
func (client *Client) Del(vb uint16, key string) (*gomemcached.MCResponse, error) {
	return client.Send(&gomemcached.MCRequest{
		Opcode:  gomemcached.DELETE,
		VBucket: vb,
		Key:     []byte(key),
		Cas:     0,
		Opaque:  0,
		Extras:  []byte{},
		Body:    []byte{}})
}

// List auth mechanisms
func (client *Client) AuthList() (*gomemcached.MCResponse, error) {
	return client.Send(&gomemcached.MCRequest{
		Opcode:  gomemcached.SASL_LIST_MECHS,
		VBucket: 0,
		Key:     []byte{},
		Cas:     0,
		Opaque:  0,
		Extras:  []byte{},
		Body:    []byte{}})
}

func (client *Client) Auth(user, pass string) (*gomemcached.MCResponse, error) {
	res, err := client.AuthList()

	if err != nil {
		return res, err
	}

	authMech := string(res.Body)
	if strings.Index(authMech, "PLAIN") != -1 {
		return client.Send(&gomemcached.MCRequest{
			Opcode:  gomemcached.SASL_AUTH,
			VBucket: 0,
			Key:     []byte("PLAIN"),
			Cas:     0,
			Opaque:  0,
			Extras:  []byte{},
			Body:    []byte(fmt.Sprintf("\x00%s\x00%s", user, pass))})
	}
	return res, fmt.Errorf("Auth mechanism PLAIN not supported")
}

func (client *Client) store(opcode gomemcached.CommandCode, vb uint16,
	key string, flags int, exp int, body []byte) (*gomemcached.MCResponse, error) {

	req := &gomemcached.MCRequest{
		Opcode:  opcode,
		VBucket: vb,
		Key:     []byte(key),
		Cas:     0,
		Opaque:  0,
		Extras:  []byte{0, 0, 0, 0, 0, 0, 0, 0},
		Body:    body}

	binary.BigEndian.PutUint64(req.Extras, uint64(flags)<<32|uint64(exp))
	return client.Send(req)
}

// Increment a value.
func (client *Client) Incr(vb uint16, key string,
	amt, def uint64, exp int) (uint64, error) {

	req := &gomemcached.MCRequest{
		Opcode:  gomemcached.INCREMENT,
		VBucket: vb,
		Key:     []byte(key),
		Cas:     0,
		Opaque:  0,
		Extras:  make([]byte, 8+8+4),
		Body:    []byte{}}
	binary.BigEndian.PutUint64(req.Extras[:8], amt)
	binary.BigEndian.PutUint64(req.Extras[8:16], def)
	binary.BigEndian.PutUint32(req.Extras[16:20], uint32(exp))

	resp, err := client.Send(req)
	if err != nil {
		return 0, err
	}

	return binary.BigEndian.Uint64(resp.Body), nil
}

// Add a value for a key (store if not exists).
func (client *Client) Add(vb uint16, key string, flags int, exp int,
	body []byte) (*gomemcached.MCResponse, error) {
	return client.store(gomemcached.ADD, vb, key, flags, exp, body)
}

// Set the value for a key.
func (client *Client) Set(vb uint16, key string, flags int, exp int,
	body []byte) (*gomemcached.MCResponse, error) {
	return client.store(gomemcached.SET, vb, key, flags, exp, body)
}

// Get keys in bulk
func (client *Client) GetBulk(vb uint16, keys []string) (map[string]*gomemcached.MCResponse, error) {
	terminalOpaque := uint32(len(keys) + 5)
	rv := map[string]*gomemcached.MCResponse{}
	wg := sync.WaitGroup{}
	going := true

	defer func() {
		going = false
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		for going {
			res, err := client.Receive()
			if err != nil {
				return
			}
			if res.Opaque == terminalOpaque {
				return
			}
			if res.Opcode != gomemcached.GETQ {
				log.Panicf("Unexpected opcode in GETQ response: %+v",
					res)
			}
			rv[keys[res.Opaque]] = res
		}
	}()

	for i, k := range keys {
		err := client.Transmit(&gomemcached.MCRequest{
			Opcode:  gomemcached.GETQ,
			VBucket: vb,
			Key:     []byte(k),
			Cas:     0,
			Opaque:  uint32(i),
			Extras:  []byte{},
			Body:    []byte{}})
		if err != nil {
			return rv, err
		}
	}

	err := client.Transmit(&gomemcached.MCRequest{
		Opcode: gomemcached.NOOP,
		Key:    []byte{},
		Cas:    0,
		Extras: []byte{},
		Body:   []byte{},
		Opaque: terminalOpaque})
	if err != nil {
		return rv, err
	}

	wg.Wait()

	return rv, nil
}

// Operation to perform on this CAS loop.
type CasOp uint8

const (
	// Store the new value normally
	CASStore = CasOp(iota)
	// Stop attempting to CAS, leave value untouched
	CASQuit
	// Delete the current value
	CASDelete
)

// User specified termination is returned as an error.
func (c CasOp) Error() string {
	switch c {
	case CASStore:
		return "CAS store"
	case CASQuit:
		return "CAS quit"
	case CASDelete:
		return "CAS delete"
	}
	panic("Unhandled value")
}

// A function to perform a CAS transform.
// Input is the current value, or nil if no value exists.
// The function should return the new value (if any) to set, and the store/quit/delete operation.
type CasFunc func(current []byte) ([]byte, CasOp)

// Perform a CAS transform with the given function.
//
// If the value does not exist, a nil current value will be sent to f.
func (client *Client) CAS(vb uint16, k string, f CasFunc,
	initexp int) (*gomemcached.MCResponse, error) {

	flags := 0
	exp := 0

	for {
		orig, err := client.Get(vb, k)
		if err != nil && (orig == nil || orig.Status != gomemcached.KEY_ENOENT) {
			return orig, err
		}

		if orig.Status == gomemcached.KEY_ENOENT {
			init, operation := f(nil)
			if operation == CASQuit || operation == CASDelete {
				return nil, operation
			}
			// If it doesn't exist, add it
			resp, err := UnwrapMemcachedError(client.Add(vb, k, 0, initexp, init))
			if err == nil && resp.Status != gomemcached.KEY_EEXISTS {
				return nil, resp
			}
		} else {
			var req *gomemcached.MCRequest
			newValue, operation := f(orig.Body)

			switch operation {
			case CASQuit:
				return nil, operation
			case CASStore:
				req = &gomemcached.MCRequest{
					Opcode:  gomemcached.SET,
					VBucket: vb,
					Key:     []byte(k),
					Cas:     orig.Cas,
					Opaque:  0,
					Extras:  []byte{0, 0, 0, 0, 0, 0, 0, 0},
					Body:    newValue}

				binary.BigEndian.PutUint64(req.Extras,
					uint64(flags)<<32|uint64(exp))
			case CASDelete:
				req = &gomemcached.MCRequest{
					Opcode:  gomemcached.DELETE,
					VBucket: vb,
					Key:     []byte(k),
					Cas:     orig.Cas}
			}
			resp, err := client.Send(req)
			if err == nil {
				return resp, nil
			}
		}
	}
	panic("Unreachable")
}

// Stats returns a slice of these.
type StatValue struct {
	// The stat key
	Key string
	// The stat value
	Val string
}

// Get stats from the server
// use "" as the stat key for toplevel stats.
func (client *Client) Stats(key string) ([]StatValue, error) {
	rv := make([]StatValue, 0, 128)

	req := &gomemcached.MCRequest{
		Opcode:  gomemcached.STAT,
		VBucket: 0,
		Key:     []byte(key),
		Cas:     0,
		Opaque:  918494,
		Extras:  []byte{}}

	err := transmitRequest(client.conn, req)
	if err != nil {
		return rv, err
	}

	for {
		res, err := getResponse(client.conn, client.hdrBuf)
		if err != nil {
			return rv, err
		}
		k := string(res.Key)
		if k == "" {
			break
		}
		rv = append(rv, StatValue{
			Key: k,
			Val: string(res.Body),
		})
	}

	return rv, nil
}

// Get the stats from the server as a map
func (client *Client) StatsMap(key string) (map[string]string, error) {
	rv := make(map[string]string)
	st, err := client.Stats(key)
	if err != nil {
		return rv, err
	}
	for _, sv := range st {
		rv[sv.Key] = sv.Val
	}
	return rv, nil
}
<commit_msg>Correct return value when a CAS success on an Add.<commit_after>// A memcached binary protocol client.
package memcached

import (
	"encoding/binary"
	"fmt"
	"io"
	"log"
	"net"
	"strings"
	"sync"

	"github.com/dustin/gomemcached"
)

const bufsize = 1024

// The Client itself.
type Client struct {
	conn    io.ReadWriteCloser
	healthy bool

	hdrBuf []byte
}

// Connect to a memcached server.
func Connect(prot, dest string) (rv *Client, err error) {
	conn, err := net.Dial(prot, dest)
	if err != nil {
		return nil, err
	}
	return Wrap(conn)
}

// Wrap an existing transport.
func Wrap(rwc io.ReadWriteCloser) (rv *Client, err error) {
	return &Client{
		conn:    rwc,
		healthy: true,
		hdrBuf:  make([]byte, gomemcached.HDR_LEN),
	}, nil
}

// Close the connection when you're done.
func (c *Client) Close() {
	c.conn.Close()
}

// Return false if this client has had issues communicating.
//
// This is useful for connection pools where we want to
// non-destructively determine that a connection may be reused.
func (c Client) IsHealthy() bool {
	return c.healthy
}

// Send a custom request and get the response.
func (client *Client) Send(req *gomemcached.MCRequest) (rv *gomemcached.MCResponse, err error) {
	err = transmitRequest(client.conn, req)
	if err != nil {
		client.healthy = false
		return
	}
	resp, err := getResponse(client.conn, client.hdrBuf)
	if err != nil {
		client.healthy = false
	}
	return resp, err
}

// Send a request, but do not wait for a response.
func (client *Client) Transmit(req *gomemcached.MCRequest) error {
	err := transmitRequest(client.conn, req)
	if err != nil {
		client.healthy = false
	}
	return err
}

// Receive a response
func (client *Client) Receive() (*gomemcached.MCResponse, error) {
	resp, err := getResponse(client.conn, client.hdrBuf)
	if err != nil {
		client.healthy = false
	}
	return resp, err
}

// Get the value for a key.
func (client *Client) Get(vb uint16, key string) (*gomemcached.MCResponse, error) {
	return client.Send(&gomemcached.MCRequest{
		Opcode:  gomemcached.GET,
		VBucket: vb,
		Key:     []byte(key),
		Cas:     0,
		Opaque:  0,
		Extras:  []byte{},
		Body:    []byte{}})
}

// Delete a key.
func (client *Client) Del(vb uint16, key string) (*gomemcached.MCResponse, error) {
	return client.Send(&gomemcached.MCRequest{
		Opcode:  gomemcached.DELETE,
		VBucket: vb,
		Key:     []byte(key),
		Cas:     0,
		Opaque:  0,
		Extras:  []byte{},
		Body:    []byte{}})
}

// List auth mechanisms
func (client *Client) AuthList() (*gomemcached.MCResponse, error) {
	return client.Send(&gomemcached.MCRequest{
		Opcode:  gomemcached.SASL_LIST_MECHS,
		VBucket: 0,
		Key:     []byte{},
		Cas:     0,
		Opaque:  0,
		Extras:  []byte{},
		Body:    []byte{}})
}

func (client *Client) Auth(user, pass string) (*gomemcached.MCResponse, error) {
	res, err := client.AuthList()

	if err != nil {
		return res, err
	}

	authMech := string(res.Body)
	if strings.Index(authMech, "PLAIN") != -1 {
		return client.Send(&gomemcached.MCRequest{
			Opcode:  gomemcached.SASL_AUTH,
			VBucket: 0,
			Key:     []byte("PLAIN"),
			Cas:     0,
			Opaque:  0,
			Extras:  []byte{},
			Body:    []byte(fmt.Sprintf("\x00%s\x00%s", user, pass))})
	}
	return res, fmt.Errorf("Auth mechanism PLAIN not supported")
}

func (client *Client) store(opcode gomemcached.CommandCode, vb uint16,
	key string, flags int, exp int, body []byte) (*gomemcached.MCResponse, error) {

	req := &gomemcached.MCRequest{
		Opcode:  opcode,
		VBucket: vb,
		Key:     []byte(key),
		Cas:     0,
		Opaque:  0,
		Extras:  []byte{0, 0, 0, 0, 0, 0, 0, 0},
		Body:    body}

	binary.BigEndian.PutUint64(req.Extras, uint64(flags)<<32|uint64(exp))
	return client.Send(req)
}

// Increment a value.
func (client *Client) Incr(vb uint16, key string,
	amt, def uint64, exp int) (uint64, error) {

	req := &gomemcached.MCRequest{
		Opcode:  gomemcached.INCREMENT,
		VBucket: vb,
		Key:     []byte(key),
		Cas:     0,
		Opaque:  0,
		Extras:  make([]byte, 8+8+4),
		Body:    []byte{}}
	binary.BigEndian.PutUint64(req.Extras[:8], amt)
	binary.BigEndian.PutUint64(req.Extras[8:16], def)
	binary.BigEndian.PutUint32(req.Extras[16:20], uint32(exp))

	resp, err := client.Send(req)
	if err != nil {
		return 0, err
	}

	return binary.BigEndian.Uint64(resp.Body), nil
}

// Add a value for a key (store if not exists).
func (client *Client) Add(vb uint16, key string, flags int, exp int,
	body []byte) (*gomemcached.MCResponse, error) {
	return client.store(gomemcached.ADD, vb, key, flags, exp, body)
}

// Set the value for a key.
func (client *Client) Set(vb uint16, key string, flags int, exp int,
	body []byte) (*gomemcached.MCResponse, error) {
	return client.store(gomemcached.SET, vb, key, flags, exp, body)
}

// Get keys in bulk
func (client *Client) GetBulk(vb uint16, keys []string) (map[string]*gomemcached.MCResponse, error) {
	terminalOpaque := uint32(len(keys) + 5)
	rv := map[string]*gomemcached.MCResponse{}
	wg := sync.WaitGroup{}
	going := true

	defer func() {
		going = false
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		for going {
			res, err := client.Receive()
			if err != nil {
				return
			}
			if res.Opaque == terminalOpaque {
				return
			}
			if res.Opcode != gomemcached.GETQ {
				log.Panicf("Unexpected opcode in GETQ response: %+v",
					res)
			}
			rv[keys[res.Opaque]] = res
		}
	}()

	for i, k := range keys {
		err := client.Transmit(&gomemcached.MCRequest{
			Opcode:  gomemcached.GETQ,
			VBucket: vb,
			Key:     []byte(k),
			Cas:     0,
			Opaque:  uint32(i),
			Extras:  []byte{},
			Body:    []byte{}})
		if err != nil {
			return rv, err
		}
	}

	err := client.Transmit(&gomemcached.MCRequest{
		Opcode: gomemcached.NOOP,
		Key:    []byte{},
		Cas:    0,
		Extras: []byte{},
		Body:   []byte{},
		Opaque: terminalOpaque})
	if err != nil {
		return rv, err
	}

	wg.Wait()

	return rv, nil
}

// Operation to perform on this CAS loop.
type CasOp uint8

const (
	// Store the new value normally
	CASStore = CasOp(iota)
	// Stop attempting to CAS, leave value untouched
	CASQuit
	// Delete the current value
	CASDelete
)

// User specified termination is returned as an error.
func (c CasOp) Error() string {
	switch c {
	case CASStore:
		return "CAS store"
	case CASQuit:
		return "CAS quit"
	case CASDelete:
		return "CAS delete"
	}
	panic("Unhandled value")
}

// A function to perform a CAS transform.
// Input is the current value, or nil if no value exists.
// The function should return the new value (if any) to set, and the store/quit/delete operation.
type CasFunc func(current []byte) ([]byte, CasOp)

// Perform a CAS transform with the given function.
//
// If the value does not exist, a nil current value will be sent to f.
func (client *Client) CAS(vb uint16, k string, f CasFunc,
	initexp int) (*gomemcached.MCResponse, error) {

	flags := 0
	exp := 0

	for {
		orig, err := client.Get(vb, k)
		if err != nil && (orig == nil || orig.Status != gomemcached.KEY_ENOENT) {
			return orig, err
		}

		if orig.Status == gomemcached.KEY_ENOENT {
			init, operation := f(nil)
			if operation == CASQuit || operation == CASDelete {
				return nil, operation
			}
			// If it doesn't exist, add it
			resp, err := UnwrapMemcachedError(client.Add(vb, k, 0, initexp, init))
			if err == nil && resp.Status != gomemcached.KEY_EEXISTS {
				if resp.Status != gomemcached.SUCCESS {
					return nil, resp
				}
				return nil, nil
			}
		} else {
			var req *gomemcached.MCRequest
			newValue, operation := f(orig.Body)

			switch operation {
			case CASQuit:
				return nil, operation
			case CASStore:
				req = &gomemcached.MCRequest{
					Opcode:  gomemcached.SET,
					VBucket: vb,
					Key:     []byte(k),
					Cas:     orig.Cas,
					Opaque:  0,
					Extras:  []byte{0, 0, 0, 0, 0, 0, 0, 0},
					Body:    newValue}

				binary.BigEndian.PutUint64(req.Extras,
					uint64(flags)<<32|uint64(exp))
			case CASDelete:
				req = &gomemcached.MCRequest{
					Opcode:  gomemcached.DELETE,
					VBucket: vb,
					Key:     []byte(k),
					Cas:     orig.Cas}
			}
			resp, err := client.Send(req)
			if err == nil {
				return resp, nil
			}
		}
	}
	panic("Unreachable")
}

// Stats returns a slice of these.
type StatValue struct {
	// The stat key
	Key string
	// The stat value
	Val string
}

// Get stats from the server
// use "" as the stat key for toplevel stats.
func (client *Client) Stats(key string) ([]StatValue, error) {
	rv := make([]StatValue, 0, 128)

	req := &gomemcached.MCRequest{
		Opcode:  gomemcached.STAT,
		VBucket: 0,
		Key:     []byte(key),
		Cas:     0,
		Opaque:  918494,
		Extras:  []byte{}}

	err := transmitRequest(client.conn, req)
	if err != nil {
		return rv, err
	}

	for {
		res, err := getResponse(client.conn, client.hdrBuf)
		if err != nil {
			return rv, err
		}
		k := string(res.Key)
		if k == "" {
			break
		}
		rv = append(rv, StatValue{
			Key: k,
			Val: string(res.Body),
		})
	}

	return rv, nil
}

// Get the stats from the server as a map
func (client *Client) StatsMap(key string) (map[string]string, error) {
	rv := make(map[string]string)
	st, err := client.Stats(key)
	if err != nil {
		return rv, err
	}
	for _, sv := range st {
		rv[sv.Key] = sv.Val
	}
	return rv, nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"time"

	"github.com/ecc1/medtronic"
)

var (
	numHours = flag.Int("n", 6, "number of `hours`")
	earliest = time.Now()
)

func main() {
	flag.Parse()
	pump := medtronic.Open()
	pump.Wakeup()
	newer := pump.Family() >= 23
	numPages := pump.HistoryPageCount()
	cutoff := earliest.Add(-time.Duration(*numHours) * time.Hour)
	log.Printf("scanning for records since %v", cutoff)
	for page := 0; page < numPages && !earliest.Before(cutoff) && pump.Error() == nil; page++ {
		data := pump.HistoryPage(page)
		records, err := medtronic.DecodeHistoryRecords(data, newer)
		if err != nil {
			pump.SetError(err)
		}
		for _, r := range records {
			handleRecord(r)
		}
	}
	if pump.Error() != nil {
		log.Fatal(pump.Error())
	}
}

func handleRecord(r medtronic.HistoryRecord) {
	t := r.Time
	if !t.IsZero() && t.Before(earliest) {
		earliest = t
	}
	b, err := json.MarshalIndent(r, "", "  ")
	if err != nil {
		fmt.Printf("%v %v\n", r.Type(), err)
	} else {
		fmt.Printf("%v %s\n", r.Type(), string(b))
	}
}
<commit_msg>Print results as single JSON array<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"time"

	"github.com/ecc1/medtronic"
)

var (
	numHours = flag.Int("n", 6, "number of `hours`")
)

func main() {
	flag.Parse()
	pump := medtronic.Open()
	pump.Wakeup()
	newer := pump.Family() >= 23
	numPages := pump.HistoryPageCount()
	cutoff := medtronic.TimeNow().Add(-time.Duration(*numHours) * time.Hour)
	log.Printf("retrieving records since %s", cutoff.Format(medtronic.TimeLayout))
	results := []medtronic.HistoryRecord{}
loop:
	for page := 0; page < numPages && pump.Error() == nil; page++ {
		log.Printf("scanning page %d", page)
		data := pump.HistoryPage(page)
		records, err := medtronic.DecodeHistoryRecords(data, newer)
		if err != nil {
			pump.SetError(err)
		}
		for _, r := range records {
			t := r.Time
			if !t.IsZero() && t.Before(cutoff) {
				log.Printf("stopping at timestamp %s", t.Format(medtronic.TimeLayout))
				break loop
			}
			results = append(results, r)
		}
	}
	if pump.Error() != nil {
		log.Fatal(pump.Error())
	}
	b, err := json.MarshalIndent(results, "", "  ")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(b))
}
<|endoftext|>


<commit_before>package pythonast

import (
	"fmt"
	"io"
)

type Writer struct {
	out         io.Writer
	indentLevel int
}

func NewWriter(w io.Writer) *Writer {
	return &Writer{out: w}
}

func (w *Writer) WriteModule(m *Module) {
	for _, bodyStmt := range m.Body {
		w.writeStmt(bodyStmt)
		w.newline()
	}
}

func (w *Writer) writeStmts(stmts []Stmt) {
	for i, stmt := range stmts {
		if i > 0 {
			w.newline()
		}
		w.writeStmt(stmt)
	}
}

func (w *Writer) writeStmt(stmt Stmt) {
	switch s := stmt.(type) {
	case *FunctionDef:
		w.functionDef(s)
	case *ClassDef:
		w.classDef(s)
	case *While:
		w.write("while ")
		w.writeExpr(s.Test)
		w.write(":")
		w.indent()
		w.writeStmts(s.Body)
		w.dedent()
	case *Assign:
		for i, target := range s.Targets {
			if i > 0 {
				w.comma()
			}
			w.writeExpr(target)
		}
		w.write(" = ")
		w.writeExpr(s.Value)
	case *Return:
		w.write("return ")
		w.writeExpr(s.Value)
	case *Pass:
		w.write("pass")
	case *ExprStmt:
		w.writeExpr(s.Value)
	case *If:
		w.write("if ")
		w.writeExpr(s.Test)
		w.write(":")
		w.indent()
		w.writeStmts(s.Body)
		w.dedent()
		if s.Orelse != nil {
			if elif, ok := s.Orelse[0].(*If); ok {
				w.write("el")
				w.writeStmt(elif)
			} else {
				w.write("else:")
				w.indent()
				w.writeStmts(s.Orelse)
				w.dedent()
			}
		}
	case *AugAssign:
		w.augAssign(s)
	case *For:
		w.write("for ")
		w.writeExpr(s.Target)
		w.write(" in ")
		w.writeExpr(s.Iter)
		w.write(":")
		w.indent()
		for i, bodyStmt := range s.Body {
			if i > 0 {
				w.newline()
			}
			w.writeStmt(bodyStmt)
		}
		w.dedent()
	case *Break:
		w.write("break")
	case *Continue:
		w.write("continue")
	default:
		panic(fmt.Sprintf("unknown Stmt: %T", stmt))
	}
}

func (w *Writer) augAssign(s *AugAssign) {
	w.writeExpr(s.Target)
	w.write(" ")
	w.writeOp(s.Op)
	w.write("=")
	w.write(" ")
	w.writeExpr(s.Value)
}

func (w *Writer) writeExprPrec(expr Expr, parentPrec int) {
	if expr == nil {
		panic("nil expr")
	}
	prec := expr.Precedence()
	paren := prec < parentPrec
	if paren {
		w.beginParen()
	}
	switch e := expr.(type) {
	case *BinOp:
		w.writeExprPrec(e.Left, prec)
		w.writeOp(e.Op)
		w.writeExprPrec(e.Right, prec)
	case *Name:
		w.identifier(e.Id)
	case *Num:
		w.write(e.N)
	case *Str:
		w.write(e.S)
	case *Compare:
		w.writeExprPrec(e.Left, prec)
		for i := range e.Ops {
			w.writeCmpOp(e.Ops[i])
			w.writeExprPrec(e.Comparators[i], prec)
		}
	case *Tuple:
		for i, elt := range e.Elts {
			if i > 0 {
				w.comma()
			}
			w.writeExprPrec(elt, prec)
		}
	case *Call:
		w.writeExprPrec(e.Func, prec)
		w.beginParen()
		i := 0
		for _, arg := range e.Args {
			if i != 0 {
				w.comma()
			}
			w.writeExprPrec(arg, prec)
			i++
		}
		for _, kw := range e.Keywords {
			if i != 0 {
				w.comma()
			}
			w.identifier(*kw.Arg)
			w.write("=")
			w.writeExprPrec(kw.Value, prec)
			i++
		}
		w.endParen()
	case *Attribute:
		w.writeExprPrec(e.Value, prec)
		w.write(".")
		w.identifier(e.Attr)
	case *NameConstant:
		w.nameConstant(e)
	case *List:
		w.list(e)
	case *Subscript:
		w.writeExprPrec(e.Value, prec)
		w.write("[")
		w.slice(e.Slice)
		w.write("]")
	case *BoolOpExpr:
		w.boolOpExpr(e)
	case *UnaryOpExpr:
		w.unaryOpExpr(e)
	default:
		panic(fmt.Sprintf("unknown Expr: %T", expr))
	}
	if paren {
		w.endParen()
	}
}

func (w *Writer) boolOpExpr(e *BoolOpExpr) {
	w.writeExprPrec(e.Values[0], e.Precedence())
	switch e.Op {
	case Or:
		w.write(" or ")
	case And:
		w.write(" and ")
	}
	w.writeExprPrec(e.Values[1], e.Precedence())
}

func (w *Writer) unaryOpExpr(e *UnaryOpExpr) {
	switch e.Op {
	case Invert:
		w.write("~")
	case Not:
		w.write("not ")
	case UAdd:
		w.write("+")
	case USub:
		w.write("-")
	}
	w.writeExprPrec(e.Operand, e.Precedence())
}

func (w *Writer) slice(s Slice) {
	switch s := s.(type) {
	case *Index:
		w.writeExpr(s.Value)
	case *RangeSlice:
		w.writeExpr(s.Lower)
		w.write(":")
		w.writeExpr(s.Upper)
	default:
		panic(fmt.Sprintf("unknown Slice: %T", s))
	}
}

func (w *Writer) list(l *List) {
	w.write("[")
	for i, elt := range l.Elts {
		if i > 0 {
			w.comma()
		}
		w.writeExprPrec(elt, l.Precedence())
	}
	w.write("]")
}

func (w *Writer) nameConstant(nc *NameConstant) {
	switch nc.Value {
	case None:
		w.write("None")
	case True:
		w.write("True")
	case False:
		w.write("False")
	default:
		panic(fmt.Sprintf("unknown NameConstant %v", nc.Value))
	}
}

func (w *Writer) writeExpr(expr Expr) {
	w.writeExprPrec(expr, 0)
}

func (w *Writer) writeOp(op Operator) {
	switch op {
	case Add:
		w.write("+")
	case Sub:
		w.write("-")
	case Mult:
		w.write("*")
	case MatMult:
		w.write("@")
	case Div:
		w.write("/")
	case Mod:
		w.write("%")
	case Pow:
		w.write("**")
	case LShift:
		w.write("<<")
	case RShift:
		w.write(">>")
	case BitOr:
		w.write("|")
	case BitXor:
		w.write("^")
	case BitAnd:
		w.write("&")
	case FloorDiv:
		w.write("//")
	}
}

func (w *Writer) writeCmpOp(op CmpOp) {
	switch op {
	case Eq:
		w.write("==")
	case NotEq:
		w.write("!=")
	case Lt:
		w.write("<")
	case LtE:
		w.write("<=")
	case Gt:
		w.write(">")
	case GtE:
		w.write(">=")
	case Is:
		w.write(" is ")
	case IsNot:
		w.write(" is not ")
	case In:
		w.write(" in ")
	case NotIn:
		w.write(" not in ")
	}
}

func (w *Writer) functionDef(s *FunctionDef) {
	w.write("def ")
	w.identifier(s.Name)
	w.beginParen()
	defaultOffset := len(s.Args.Args) - len(s.Args.Defaults)
	for i, arg := range s.Args.Args {
		if i > 0 {
			w.comma()
		}
		w.identifier(arg.Arg)
		if i >= defaultOffset {
			w.write("=")
			w.writeExpr(s.Args.Defaults[i-defaultOffset])
		}
	}
	w.endParen()
	w.write(":")
	w.indent()
	for i, bodyStmt := range s.Body {
		if i > 0 {
			w.newline()
		}
		w.writeStmt(bodyStmt)
	}
	w.dedent()
}

func (w *Writer) classDef(s *ClassDef) {
	w.write("class ")
	w.identifier(s.Name)
	if len(s.Bases) > 0 {
		w.beginParen()
		for i, base := range s.Bases {
			if i > 0 {
				w.comma()
			}
			w.writeExpr(base)
		}
		w.endParen()
	}
	w.write(":")
	w.indent()
	for i, bodyStmt := range s.Body {
		if i > 0 {
			w.newline()
		}
		w.writeStmt(bodyStmt)
	}
	w.dedent()
}

func (w *Writer) identifier(i Identifier) {
	w.write(string(i))
}

func (w *Writer) comma() {
	w.write(", ")
}

func (w *Writer) beginParen() {
	w.write("(")
}

func (w *Writer) endParen() {
	w.write(")")
}

func (w *Writer) indent() {
	w.indentLevel++
	w.newline()
}

func (w *Writer) newline() {
	w.write("\n")
	for i := 0; i < w.indentLevel; i++ {
		w.write("    ")
	}
}

func (w *Writer) dedent() {
	w.indentLevel--
	w.newline()
}

func (w *Writer) write(s string) {
	w.out.Write([]byte(s))
}
<commit_msg>Python writer: fix nil bounds in slice<commit_after>package pythonast

import (
	"fmt"
	"io"
)

type Writer struct {
	out         io.Writer
	indentLevel int
}

func NewWriter(w io.Writer) *Writer {
	return &Writer{out: w}
}

func (w *Writer) WriteModule(m *Module) {
	for _, bodyStmt := range m.Body {
		w.writeStmt(bodyStmt)
		w.newline()
	}
}

func (w *Writer) writeStmts(stmts []Stmt) {
	for i, stmt := range stmts {
		if i > 0 {
			w.newline()
		}
		w.writeStmt(stmt)
	}
}

func (w *Writer) writeStmt(stmt Stmt) {
	switch s := stmt.(type) {
	case *FunctionDef:
		w.functionDef(s)
	case *ClassDef:
		w.classDef(s)
	case *While:
		w.write("while ")
		w.writeExpr(s.Test)
		w.write(":")
		w.indent()
		w.writeStmts(s.Body)
		w.dedent()
	case *Assign:
		for i, target := range s.Targets {
			if i > 0 {
				w.comma()
			}
			w.writeExpr(target)
		}
		w.write(" = ")
		w.writeExpr(s.Value)
	case *Return:
		w.write("return ")
		w.writeExpr(s.Value)
	case *Pass:
		w.write("pass")
	case *ExprStmt:
		w.writeExpr(s.Value)
	case *If:
		w.write("if ")
		w.writeExpr(s.Test)
		w.write(":")
		w.indent()
		w.writeStmts(s.Body)
		w.dedent()
		if s.Orelse != nil {
			if elif, ok := s.Orelse[0].(*If); ok {
				w.write("el")
				w.writeStmt(elif)
			} else {
				w.write("else:")
				w.indent()
				w.writeStmts(s.Orelse)
				w.dedent()
			}
		}
	case *AugAssign:
		w.augAssign(s)
	case *For:
		w.write("for ")
		w.writeExpr(s.Target)
		w.write(" in ")
		w.writeExpr(s.Iter)
		w.write(":")
		w.indent()
		for i, bodyStmt := range s.Body {
			if i > 0 {
				w.newline()
			}
			w.writeStmt(bodyStmt)
		}
		w.dedent()
	case *Break:
		w.write("break")
	case *Continue:
		w.write("continue")
	default:
		panic(fmt.Sprintf("unknown Stmt: %T", stmt))
	}
}

func (w *Writer) augAssign(s *AugAssign) {
	w.writeExpr(s.Target)
	w.write(" ")
	w.writeOp(s.Op)
	w.write("=")
	w.write(" ")
	w.writeExpr(s.Value)
}

func (w *Writer) writeExprPrec(expr Expr, parentPrec int) {
	if expr == nil {
		panic("nil expr")
	}
	prec := expr.Precedence()
	paren := prec < parentPrec
	if paren {
		w.beginParen()
	}
	switch e := expr.(type) {
	case *BinOp:
		w.writeExprPrec(e.Left, prec)
		w.writeOp(e.Op)
		w.writeExprPrec(e.Right, prec)
	case *Name:
		w.identifier(e.Id)
	case *Num:
		w.write(e.N)
	case *Str:
		w.write(e.S)
	case *Compare:
		w.writeExprPrec(e.Left, prec)
		for i := range e.Ops {
			w.writeCmpOp(e.Ops[i])
			w.writeExprPrec(e.Comparators[i], prec)
		}
	case *Tuple:
		for i, elt := range e.Elts {
			if i > 0 {
				w.comma()
			}
			w.writeExprPrec(elt, prec)
		}
	case *Call:
		w.writeExprPrec(e.Func, prec)
		w.beginParen()
		i := 0
		for _, arg := range e.Args {
			if i != 0 {
				w.comma()
			}
			w.writeExprPrec(arg, prec)
			i++
		}
		for _, kw := range e.Keywords {
			if i != 0 {
				w.comma()
			}
			w.identifier(*kw.Arg)
			w.write("=")
			w.writeExprPrec(kw.Value, prec)
			i++
		}
		w.endParen()
	case *Attribute:
		w.writeExprPrec(e.Value, prec)
		w.write(".")
		w.identifier(e.Attr)
	case *NameConstant:
		w.nameConstant(e)
	case *List:
		w.list(e)
	case *Subscript:
		w.writeExprPrec(e.Value, prec)
		w.write("[")
		w.slice(e.Slice)
		w.write("]")
	case *BoolOpExpr:
		w.boolOpExpr(e)
	case *UnaryOpExpr:
		w.unaryOpExpr(e)
	default:
		panic(fmt.Sprintf("unknown Expr: %T", expr))
	}
	if paren {
		w.endParen()
	}
}

func (w *Writer) boolOpExpr(e *BoolOpExpr) {
	w.writeExprPrec(e.Values[0], e.Precedence())
	switch e.Op {
	case Or:
		w.write(" or ")
	case And:
		w.write(" and ")
	}
	w.writeExprPrec(e.Values[1], e.Precedence())
}

func (w *Writer) unaryOpExpr(e *UnaryOpExpr) {
	switch e.Op {
	case Invert:
		w.write("~")
	case Not:
		w.write("not ")
	case UAdd:
		w.write("+")
	case USub:
		w.write("-")
	}
	w.writeExprPrec(e.Operand, e.Precedence())
}

func (w *Writer) slice(s Slice) {
	switch s := s.(type) {
	case *Index:
		w.writeExpr(s.Value)
	case *RangeSlice:
		if s.Lower != nil {
			w.writeExpr(s.Lower)
		}
		w.write(":")
		if s.Upper != nil {
			w.writeExpr(s.Upper)
		}
	default:
		panic(fmt.Sprintf("unknown Slice: %T", s))
	}
}

func (w *Writer) list(l *List) {
	w.write("[")
	for i, elt := range l.Elts {
		if i > 0 {
			w.comma()
		}
		w.writeExprPrec(elt, l.Precedence())
	}
	w.write("]")
}

func (w *Writer) nameConstant(nc *NameConstant) {
	switch nc.Value {
	case None:
		w.write("None")
	case True:
		w.write("True")
	case False:
		w.write("False")
	default:
		panic(fmt.Sprintf("unknown NameConstant %v", nc.Value))
	}
}

func (w *Writer) writeExpr(expr Expr) {
	w.writeExprPrec(expr, 0)
}

func (w *Writer) writeOp(op Operator) {
	switch op {
	case Add:
		w.write("+")
	case Sub:
		w.write("-")
	case Mult:
		w.write("*")
	case MatMult:
		w.write("@")
	case Div:
		w.write("/")
	case Mod:
		w.write("%")
	case Pow:
		w.write("**")
	case LShift:
		w.write("<<")
	case RShift:
		w.write(">>")
	case BitOr:
		w.write("|")
	case BitXor:
		w.write("^")
	case BitAnd:
		w.write("&")
	case FloorDiv:
		w.write("//")
	}
}

func (w *Writer) writeCmpOp(op CmpOp) {
	switch op {
	case Eq:
		w.write("==")
	case NotEq:
		w.write("!=")
	case Lt:
		w.write("<")
	case LtE:
		w.write("<=")
	case Gt:
		w.write(">")
	case GtE:
		w.write(">=")
	case Is:
		w.write(" is ")
	case IsNot:
		w.write(" is not ")
	case In:
		w.write(" in ")
	case NotIn:
		w.write(" not in ")
	}
}

func (w *Writer) functionDef(s *FunctionDef) {
	w.write("def ")
	w.identifier(s.Name)
	w.beginParen()
	defaultOffset := len(s.Args.Args) - len(s.Args.Defaults)
	for i, arg := range s.Args.Args {
		if i > 0 {
			w.comma()
		}
		w.identifier(arg.Arg)
		if i >= defaultOffset {
			w.write("=")
			w.writeExpr(s.Args.Defaults[i-defaultOffset])
		}
	}
	w.endParen()
	w.write(":")
	w.indent()
	for i, bodyStmt := range s.Body {
		if i > 0 {
			w.newline()
		}
		w.writeStmt(bodyStmt)
	}
	w.dedent()
}

func (w *Writer) classDef(s *ClassDef) {
	w.write("class ")
	w.identifier(s.Name)
	if len(s.Bases) > 0 {
		w.beginParen()
		for i, base := range s.Bases {
			if i > 0 {
				w.comma()
			}
			w.writeExpr(base)
		}
		w.endParen()
	}
	w.write(":")
	w.indent()
	for i, bodyStmt := range s.Body {
		if i > 0 {
			w.newline()
		}
		w.writeStmt(bodyStmt)
	}
	w.dedent()
}

func (w *Writer) identifier(i Identifier) {
	w.write(string(i))
}

func (w *Writer) comma() {
	w.write(", ")
}

func (w *Writer) beginParen() {
	w.write("(")
}

func (w *Writer) endParen() {
	w.write(")")
}

func (w *Writer) indent() {
	w.indentLevel++
	w.newline()
}

func (w *Writer) newline() {
	w.write("\n")
	for i := 0; i < w.indentLevel; i++ {
		w.write("    ")
	}
}

func (w *Writer) dedent() {
	w.indentLevel--
	w.newline()
}

func (w *Writer) write(s string) {
	w.out.Write([]byte(s))
}
<|endoftext|>


<commit_before>// +build windows

package ole

import "testing"

func TestIUnknown(t *testing.T) {
	defer func() {
		if r := recover(); r != nil {
			t.Error(r)
		}
	}()

	var err error

	err = CoInitialize(0)
	if err != nil {
		t.Fatal(err)
	}

	defer CoUninitialize()

	var unknown *IUnknown

	// oleutil.CreateObject()
	unknown, err = CreateInstance(CLSID_COMEchoTestObject, IID_IUnknown)
	if err != nil {
		t.Fatal(err)
		return
	}
}
<commit_msg>Release iunknown object.<commit_after>// +build windows

package ole

import "testing"

func TestIUnknown(t *testing.T) {
	defer func() {
		if r := recover(); r != nil {
			t.Error(r)
		}
	}()

	var err error

	err = CoInitialize(0)
	if err != nil {
		t.Fatal(err)
	}

	defer CoUninitialize()

	var unknown *IUnknown

	// oleutil.CreateObject()
	unknown, err = CreateInstance(CLSID_COMEchoTestObject, IID_IUnknown)
	if err != nil {
		t.Fatal(err)
		return
	}
	unknown.Release()
}
<|endoftext|>