dbg.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. // This file was AUTOMATICALLY GENERATED by dbg-import (smuggol) from github.com/robertkrimen/dbg
  2. /*
  3. Package dbg is a println/printf/log-debugging utility library.
  4. import (
  5. Dbg "github.com/robertkrimen/dbg"
  6. )
  7. dbg, dbgf := Dbg.New()
  8. dbg("Emit some debug stuff", []byte{120, 121, 122, 122, 121}, math.Pi)
  9. # "2013/01/28 16:50:03 Emit some debug stuff [120 121 122 122 121] 3.141592653589793"
  10. dbgf("With a %s formatting %.2f", "little", math.Pi)
  11. # "2013/01/28 16:51:55 With a little formatting (3.14)"
  12. dbgf("%/fatal//A fatal debug statement: should not be here")
  13. # "A fatal debug statement: should not be here"
  14. # ...and then, os.Exit(1)
  15. dbgf("%/panic//Can also panic %s", "this")
  16. # "Can also panic this"
  17. # ...as a panic, equivalent to: panic("Can also panic this")
  18. dbgf("Any %s arguments without a corresponding %%", "extra", "are treated like arguments to dbg()")
  19. # "2013/01/28 17:14:40 Any extra arguments (without a corresponding %) are treated like arguments to dbg()"
  20. dbgf("%d %d", 1, 2, 3, 4, 5)
  21. # "2013/01/28 17:16:32 Another example: 1 2 3 4 5"
  22. dbgf("%@: Include the function name for a little context (via %s)", "%@")
  23. # "2013... github.com/robertkrimen/dbg.TestSynopsis: Include the function name for a little context (via %@)"
  24. By default, dbg uses log (log.Println, log.Printf, log.Panic, etc.) for output.
  25. However, you can also provide your own output destination by invoking dbg.New with
  26. a customization function:
  27. import (
  28. "bytes"
  29. Dbg "github.com/robertkrimen/dbg"
  30. "os"
  31. )
  32. # dbg to os.Stderr
  33. dbg, dbgf := Dbg.New(func(dbgr *Dbgr) {
  34. dbgr.SetOutput(os.Stderr)
  35. })
  36. # A slightly contrived example:
  37. var buffer bytes.Buffer
  38. dbg, dbgf := New(func(dbgr *Dbgr) {
  39. dbgr.SetOutput(&buffer)
  40. })
  41. */
  42. package dbg
  43. import (
  44. "bytes"
  45. "fmt"
  46. "io"
  47. "log"
  48. "os"
  49. "regexp"
  50. goruntime "runtime"
  51. "strings"
  52. "unicode"
  53. )
  54. type _frmt struct {
  55. ctl string
  56. format string
  57. operandCount int
  58. panic bool
  59. fatal bool
  60. check bool
  61. }
  62. var (
  63. ctlTest = regexp.MustCompile(`^\s*%/`)
  64. ctlScan = regexp.MustCompile(`%?/(panic|fatal|check)(?:\s|$)`)
  65. )
  66. func operandCount(format string) int {
  67. count := 0
  68. end := len(format)
  69. for at := 0; at < end; {
  70. for at < end && format[at] != '%' {
  71. at++
  72. }
  73. at++
  74. if at < end {
  75. if format[at] != '%' && format[at] != '@' {
  76. count++
  77. }
  78. at++
  79. }
  80. }
  81. return count
  82. }
  83. func parseFormat(format string) (frmt _frmt) {
  84. if ctlTest.MatchString(format) {
  85. format = strings.TrimLeftFunc(format, unicode.IsSpace)
  86. index := strings.Index(format, "//")
  87. if index != -1 {
  88. frmt.ctl = format[0:index]
  89. format = format[index+2:] // Skip the second slash via +2 (instead of +1)
  90. } else {
  91. frmt.ctl = format
  92. format = ""
  93. }
  94. for _, tmp := range ctlScan.FindAllStringSubmatch(frmt.ctl, -1) {
  95. for _, value := range tmp[1:] {
  96. switch value {
  97. case "panic":
  98. frmt.panic = true
  99. case "fatal":
  100. frmt.fatal = true
  101. case "check":
  102. frmt.check = true
  103. }
  104. }
  105. }
  106. }
  107. frmt.format = format
  108. frmt.operandCount = operandCount(format)
  109. return
  110. }
  111. type Dbgr struct {
  112. emit emit
  113. }
  114. type DbgFunction func(values ...interface{})
  115. func NewDbgr() *Dbgr {
  116. return &Dbgr{}
  117. }
  118. /*
  119. New will create and return a pair of debugging functions. You can customize where
  120. they output to by passing in an (optional) customization function:
  121. import (
  122. Dbg "github.com/robertkrimen/dbg"
  123. "os"
  124. )
  125. # dbg to os.Stderr
  126. dbg, dbgf := Dbg.New(func(dbgr *Dbgr) {
  127. dbgr.SetOutput(os.Stderr)
  128. })
  129. */
  130. func New(options ...interface{}) (dbg DbgFunction, dbgf DbgFunction) {
  131. dbgr := NewDbgr()
  132. if len(options) > 0 {
  133. if fn, ok := options[0].(func(*Dbgr)); ok {
  134. fn(dbgr)
  135. }
  136. }
  137. return dbgr.DbgDbgf()
  138. }
  139. func (d Dbgr) Dbg(values ...interface{}) {
  140. d.getEmit().emit(_frmt{}, "", values...)
  141. }
  142. func (d Dbgr) Dbgf(values ...interface{}) {
  143. d.dbgf(values...)
  144. }
  145. func (d Dbgr) DbgDbgf() (dbg DbgFunction, dbgf DbgFunction) {
  146. dbg = func(vl ...interface{}) {
  147. d.Dbg(vl...)
  148. }
  149. dbgf = func(vl ...interface{}) {
  150. d.dbgf(vl...)
  151. }
  152. return dbg, dbgf // Redundant, but...
  153. }
  154. func (d Dbgr) dbgf(values ...interface{}) {
  155. var frmt _frmt
  156. if len(values) > 0 {
  157. tmp := fmt.Sprint(values[0])
  158. frmt = parseFormat(tmp)
  159. values = values[1:]
  160. }
  161. buf := bytes.Buffer{}
  162. format := frmt.format
  163. end := len(format)
  164. for at := 0; at < end; {
  165. last := at
  166. for at < end && format[at] != '%' {
  167. at++
  168. }
  169. if at > last {
  170. buf.WriteString(format[last:at])
  171. }
  172. if at >= end {
  173. break
  174. }
  175. // format[at] == '%'
  176. at++
  177. // format[at] == ?
  178. if format[at] == '@' {
  179. depth := 2
  180. pc, _, _, _ := goruntime.Caller(depth)
  181. name := goruntime.FuncForPC(pc).Name()
  182. buf.WriteString(name)
  183. } else {
  184. buf.WriteString(format[at-1 : at+1])
  185. }
  186. at++
  187. }
  188. //valuesF := append([]interface{}{}, values[0:frmt.operandCount]...)
  189. valuesF := values[0:frmt.operandCount]
  190. valuesDbg := values[frmt.operandCount:]
  191. if len(valuesDbg) > 0 {
  192. // Adjust frmt.format:
  193. // (%v instead of %s because: frmt.check)
  194. tmp := format
  195. if len(tmp) > 0 {
  196. if unicode.IsSpace(rune(tmp[len(tmp)-1])) {
  197. buf.WriteString("%v")
  198. } else {
  199. buf.WriteString(" %v")
  200. }
  201. } else if frmt.check {
  202. // Performing a check, so no output
  203. } else {
  204. buf.WriteString("%v")
  205. }
  206. // Adjust valuesF:
  207. if !frmt.check {
  208. tmp := []string{}
  209. for _, value := range valuesDbg {
  210. tmp = append(tmp, fmt.Sprintf("%v", value))
  211. }
  212. // First, make a copy of valuesF, so we avoid overwriting valuesDbg when appending
  213. valuesF = append([]interface{}{}, valuesF...)
  214. valuesF = append(valuesF, strings.Join(tmp, " "))
  215. }
  216. }
  217. format = buf.String()
  218. if frmt.check {
  219. // We do not actually emit to the log, but panic if
  220. // a non-nil value is detected (e.g. a non-nil error)
  221. for _, value := range valuesDbg {
  222. if value != nil {
  223. if format == "" {
  224. panic(value)
  225. } else {
  226. panic(fmt.Sprintf(format, append(valuesF, value)...))
  227. }
  228. }
  229. }
  230. } else {
  231. d.getEmit().emit(frmt, format, valuesF...)
  232. }
  233. }
  234. // Idiot-proof &Dbgr{}, etc.
  235. func (d *Dbgr) getEmit() emit {
  236. if d.emit == nil {
  237. d.emit = standardEmit()
  238. }
  239. return d.emit
  240. }
  241. // SetOutput will accept the following as a destination for output:
  242. //
  243. // *log.Logger Print*/Panic*/Fatal* of the logger
  244. // io.Writer -
  245. // nil Reset to the default output (os.Stderr)
  246. // "log" Print*/Panic*/Fatal* via the "log" package
  247. func (d *Dbgr) SetOutput(output interface{}) {
  248. if output == nil {
  249. d.emit = standardEmit()
  250. return
  251. }
  252. switch output := output.(type) {
  253. case *log.Logger:
  254. d.emit = emitLogger{
  255. logger: output,
  256. }
  257. return
  258. case io.Writer:
  259. d.emit = emitWriter{
  260. writer: output,
  261. }
  262. return
  263. case string:
  264. if output == "log" {
  265. d.emit = emitLog{}
  266. return
  267. }
  268. }
  269. panic(output)
  270. }
  271. // ======== //
  272. // = emit = //
  273. // ======== //
  274. func standardEmit() emit {
  275. return emitWriter{
  276. writer: os.Stderr,
  277. }
  278. }
  279. func ln(tmp string) string {
  280. length := len(tmp)
  281. if length > 0 && tmp[length-1] != '\n' {
  282. return tmp + "\n"
  283. }
  284. return tmp
  285. }
  286. type emit interface {
  287. emit(_frmt, string, ...interface{})
  288. }
  289. type emitWriter struct {
  290. writer io.Writer
  291. }
  292. func (ew emitWriter) emit(frmt _frmt, format string, values ...interface{}) {
  293. if format == "" {
  294. fmt.Fprintln(ew.writer, values...)
  295. } else {
  296. if frmt.panic {
  297. panic(fmt.Sprintf(format, values...))
  298. }
  299. fmt.Fprintf(ew.writer, ln(format), values...)
  300. if frmt.fatal {
  301. os.Exit(1)
  302. }
  303. }
  304. }
  305. type emitLogger struct {
  306. logger *log.Logger
  307. }
  308. func (el emitLogger) emit(frmt _frmt, format string, values ...interface{}) {
  309. if format == "" {
  310. el.logger.Println(values...)
  311. } else {
  312. if frmt.panic {
  313. el.logger.Panicf(format, values...)
  314. } else if frmt.fatal {
  315. el.logger.Fatalf(format, values...)
  316. } else {
  317. el.logger.Printf(format, values...)
  318. }
  319. }
  320. }
  321. type emitLog struct {
  322. }
  323. func (el emitLog) emit(frmt _frmt, format string, values ...interface{}) {
  324. if format == "" {
  325. log.Println(values...)
  326. } else {
  327. if frmt.panic {
  328. log.Panicf(format, values...)
  329. } else if frmt.fatal {
  330. log.Fatalf(format, values...)
  331. } else {
  332. log.Printf(format, values...)
  333. }
  334. }
  335. }