aboutsummaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/github.com/obscuren/qml/log.go
diff options
context:
space:
mode:
Diffstat (limited to 'Godeps/_workspace/src/github.com/obscuren/qml/log.go')
-rw-r--r--Godeps/_workspace/src/github.com/obscuren/qml/log.go157
1 files changed, 157 insertions, 0 deletions
diff --git a/Godeps/_workspace/src/github.com/obscuren/qml/log.go b/Godeps/_workspace/src/github.com/obscuren/qml/log.go
new file mode 100644
index 000000000..5301e63b0
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/obscuren/qml/log.go
@@ -0,0 +1,157 @@
+package qml
+
+// #include "capi.h"
+//
+import "C"
+
+import (
+ "fmt"
+ "log"
+ "path/filepath"
+ "strings"
+)
+
+// SetLogger sets the target for messages logged by the qml package,
+// including console.log and related calls from within qml code.
+//
+// The logger value must implement either the StdLogger interface,
+// which is satisfied by the standard *log.Logger type, or the QmlLogger
+// interface, which offers more control over the logged message.
+//
+// If no logger is provided, the qml package will send messages to the
+// default log package logger. This behavior may also be restored by
+// providing a nil logger to this function.
+func SetLogger(logger interface{}) {
+ if logger == nil {
+ logHandler = defaultLogger{}
+ return
+ }
+ if qmll, ok := logger.(QmlLogger); ok {
+ logHandler = qmll
+ return
+ }
+ if stdl, ok := logger.(StdLogger); ok {
+ logHandler = wrappedStdLogger{stdl}
+ return
+ }
+ panic("unsupported logger interface")
+}
+
+// The QmlLogger interface may be implemented to better control how
+// log messages from the qml package are handled. Values that
+// implement either StdLogger or QmlLogger may be provided to the
+// SetLogger function.
+type QmlLogger interface {
+ // QmlOutput is called whenever a new message is available for logging.
+ // The message value must not be used after the method returns.
+ QmlOutput(message LogMessage) error
+}
+
+// The StdLogger interface is implemented by standard *log.Logger values.
+// Values that implement either StdLogger or QmlLogger may be provided
+// to the SetLogger function.
+type StdLogger interface {
+ // Output is called whenever a new message is available for logging.
+ // See the standard log.Logger type for more details.
+ Output(calldepth int, s string) error
+}
+
+// NOTE: LogMessage is an interface to avoid allocating and copying
+// several strings for each logged message.
+
+// LogMessage is implemented by values provided to QmlLogger.QmlOutput.
+type LogMessage interface {
+ Severity() LogSeverity
+ Text() string
+ File() string
+ Line() int
+
+ String() string // returns "file:line: text"
+
+ privateMarker()
+}
+
+type LogSeverity int
+
+const (
+ LogDebug LogSeverity = iota
+ LogWarning
+ LogCritical
+ LogFatal
+)
+
+var logHandler QmlLogger = defaultLogger{}
+
+type defaultLogger struct{}
+
+func (defaultLogger) QmlOutput(msg LogMessage) error {
+ log.Println(msg.String())
+ return nil
+}
+
+func init() {
+ // Install the C++ log handler that diverts calls to the hook below.
+ C.installLogHandler()
+}
+
+//export hookLogHandler
+func hookLogHandler(cmsg *C.LogMessage) {
+ // Workarund for QTBUG-35943
+ text := unsafeString(cmsg.text, cmsg.textLen)
+ if strings.HasPrefix(text, `"Qt Warning: Compose file:`) {
+ return
+ }
+ msg := logMessage{c: cmsg}
+ logHandler.QmlOutput(&msg)
+ msg.invalid = true
+}
+
+type wrappedStdLogger struct {
+ StdLogger
+}
+
+func (l wrappedStdLogger) QmlOutput(msg LogMessage) error {
+ return l.Output(0, msg.String())
+}
+
+type logMessage struct {
+ c *C.LogMessage
+
+ // invalid flags that cmsg points to unreliable memory,
+ // since the log hook has already returned.
+ invalid bool
+}
+
+func (m *logMessage) assertValid() {
+ if m.invalid {
+ panic("attempted to use log message outside of log hook")
+ }
+}
+
+func (m *logMessage) Severity() LogSeverity {
+ return LogSeverity(m.c.severity)
+}
+
+func (m *logMessage) Line() int {
+ m.assertValid()
+ return int(m.c.line)
+}
+
+func (m *logMessage) String() string {
+ m.assertValid()
+ file := unsafeString(m.c.file, m.c.fileLen)
+ text := unsafeString(m.c.text, m.c.textLen)
+ return fmt.Sprintf("%s:%d: %s", filepath.Base(file), m.c.line, text)
+}
+
+func (m *logMessage) File() string {
+ m.assertValid()
+ return C.GoStringN(m.c.file, m.c.fileLen)
+}
+
+func (m *logMessage) Text() string {
+ m.assertValid()
+ return C.GoStringN(m.c.text, m.c.line)
+}
+
+func (*logMessage) privateMarker() {}