dbg.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  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. "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. self := &Dbgr{}
  117. return self
  118. }
  119. /*
  120. New will create and return a pair of debugging functions. You can customize where
  121. they output to by passing in an (optional) customization function:
  122. import (
  123. Dbg "github.com/robertkrimen/dbg"
  124. "os"
  125. )
  126. # dbg to os.Stderr
  127. dbg, dbgf := Dbg.New(func(dbgr *Dbgr) {
  128. dbgr.SetOutput(os.Stderr)
  129. })
  130. */
  131. func New(options ...interface{}) (dbg DbgFunction, dbgf DbgFunction) {
  132. dbgr := NewDbgr()
  133. if len(options) > 0 {
  134. if fn, ok := options[0].(func(*Dbgr)); ok {
  135. fn(dbgr)
  136. }
  137. }
  138. return dbgr.DbgDbgf()
  139. }
  140. func (self Dbgr) Dbg(values ...interface{}) {
  141. self.getEmit().emit(_frmt{}, "", values...)
  142. }
  143. func (self Dbgr) Dbgf(values ...interface{}) {
  144. self.dbgf(values...)
  145. }
  146. func (self Dbgr) DbgDbgf() (dbg DbgFunction, dbgf DbgFunction) {
  147. dbg = func(vl ...interface{}) {
  148. self.Dbg(vl...)
  149. }
  150. dbgf = func(vl ...interface{}) {
  151. self.dbgf(vl...)
  152. }
  153. return dbg, dbgf // Redundant, but...
  154. }
  155. func (self Dbgr) dbgf(values ...interface{}) {
  156. var frmt _frmt
  157. if len(values) > 0 {
  158. tmp := fmt.Sprint(values[0])
  159. frmt = parseFormat(tmp)
  160. values = values[1:]
  161. }
  162. buffer_f := bytes.Buffer{}
  163. format := frmt.format
  164. end := len(format)
  165. for at := 0; at < end; {
  166. last := at
  167. for at < end && format[at] != '%' {
  168. at++
  169. }
  170. if at > last {
  171. buffer_f.WriteString(format[last:at])
  172. }
  173. if at >= end {
  174. break
  175. }
  176. // format[at] == '%'
  177. at++
  178. // format[at] == ?
  179. if format[at] == '@' {
  180. depth := 2
  181. pc, _, _, _ := runtime.Caller(depth)
  182. name := runtime.FuncForPC(pc).Name()
  183. buffer_f.WriteString(name)
  184. } else {
  185. buffer_f.WriteString(format[at-1 : at+1])
  186. }
  187. at++
  188. }
  189. //values_f := append([]interface{}{}, values[0:frmt.operandCount]...)
  190. values_f := values[0:frmt.operandCount]
  191. values_dbg := values[frmt.operandCount:]
  192. if len(values_dbg) > 0 {
  193. // Adjust frmt.format:
  194. // (%v instead of %s because: frmt.check)
  195. {
  196. tmp := format
  197. if len(tmp) > 0 {
  198. if unicode.IsSpace(rune(tmp[len(tmp)-1])) {
  199. buffer_f.WriteString("%v")
  200. } else {
  201. buffer_f.WriteString(" %v")
  202. }
  203. } else if frmt.check {
  204. // Performing a check, so no output
  205. } else {
  206. buffer_f.WriteString("%v")
  207. }
  208. }
  209. // Adjust values_f:
  210. if !frmt.check {
  211. tmp := []string{}
  212. for _, value := range values_dbg {
  213. tmp = append(tmp, fmt.Sprintf("%v", value))
  214. }
  215. // First, make a copy of values_f, so we avoid overwriting values_dbg when appending
  216. values_f = append([]interface{}{}, values_f...)
  217. values_f = append(values_f, strings.Join(tmp, " "))
  218. }
  219. }
  220. format = buffer_f.String()
  221. if frmt.check {
  222. // We do not actually emit to the log, but panic if
  223. // a non-nil value is detected (e.g. a non-nil error)
  224. for _, value := range values_dbg {
  225. if value != nil {
  226. if format == "" {
  227. panic(value)
  228. } else {
  229. panic(fmt.Sprintf(format, append(values_f, value)...))
  230. }
  231. }
  232. }
  233. } else {
  234. self.getEmit().emit(frmt, format, values_f...)
  235. }
  236. }
  237. // Idiot-proof &Dbgr{}, etc.
  238. func (self *Dbgr) getEmit() _emit {
  239. if self.emit == nil {
  240. self.emit = standardEmit()
  241. }
  242. return self.emit
  243. }
  244. // SetOutput will accept the following as a destination for output:
  245. //
  246. // *log.Logger Print*/Panic*/Fatal* of the logger
  247. // io.Writer -
  248. // nil Reset to the default output (os.Stderr)
  249. // "log" Print*/Panic*/Fatal* via the "log" package
  250. //
  251. func (self *Dbgr) SetOutput(output interface{}) {
  252. if output == nil {
  253. self.emit = standardEmit()
  254. return
  255. }
  256. switch output := output.(type) {
  257. case *log.Logger:
  258. self.emit = _emitLogger{
  259. logger: output,
  260. }
  261. return
  262. case io.Writer:
  263. self.emit = _emitWriter{
  264. writer: output,
  265. }
  266. return
  267. case string:
  268. if output == "log" {
  269. self.emit = _emitLog{}
  270. return
  271. }
  272. }
  273. panic(output)
  274. }
  275. // ======== //
  276. // = emit = //
  277. // ======== //
  278. func standardEmit() _emit {
  279. return _emitWriter{
  280. writer: os.Stderr,
  281. }
  282. }
  283. func ln(tmp string) string {
  284. length := len(tmp)
  285. if length > 0 && tmp[length-1] != '\n' {
  286. return tmp + "\n"
  287. }
  288. return tmp
  289. }
  290. type _emit interface {
  291. emit(_frmt, string, ...interface{})
  292. }
  293. type _emitWriter struct {
  294. writer io.Writer
  295. }
  296. func (self _emitWriter) emit(frmt _frmt, format string, values ...interface{}) {
  297. if format == "" {
  298. fmt.Fprintln(self.writer, values...)
  299. } else {
  300. if frmt.panic {
  301. panic(fmt.Sprintf(format, values...))
  302. }
  303. fmt.Fprintf(self.writer, ln(format), values...)
  304. if frmt.fatal {
  305. os.Exit(1)
  306. }
  307. }
  308. }
  309. type _emitLogger struct {
  310. logger *log.Logger
  311. }
  312. func (self _emitLogger) emit(frmt _frmt, format string, values ...interface{}) {
  313. if format == "" {
  314. self.logger.Println(values...)
  315. } else {
  316. if frmt.panic {
  317. self.logger.Panicf(format, values...)
  318. } else if frmt.fatal {
  319. self.logger.Fatalf(format, values...)
  320. } else {
  321. self.logger.Printf(format, values...)
  322. }
  323. }
  324. }
  325. type _emitLog struct {
  326. }
  327. func (self _emitLog) emit(frmt _frmt, format string, values ...interface{}) {
  328. if format == "" {
  329. log.Println(values...)
  330. } else {
  331. if frmt.panic {
  332. log.Panicf(format, values...)
  333. } else if frmt.fatal {
  334. log.Fatalf(format, values...)
  335. } else {
  336. log.Printf(format, values...)
  337. }
  338. }
  339. }