More detailed logging

This commit is contained in:
Peter Williams 2017-01-26 20:20:13 +11:00
parent 7dc32baa20
commit 9edc2a8970
6 changed files with 179 additions and 37 deletions

View File

@ -41,6 +41,8 @@ func (this DummyLogger) Debug(format string, args ...interface{}) {
// Simple Console Logger that the tests use. // Simple Console Logger that the tests use.
type ConsoleLogger struct{} type ConsoleLogger struct{}
const DebugOutput = false
func (this ConsoleLogger) Error(format string, args ...interface{}) { func (this ConsoleLogger) Error(format string, args ...interface{}) {
this.output(os.Stderr, "[ERROR] ", format, args...) this.output(os.Stderr, "[ERROR] ", format, args...)
} }
@ -58,7 +60,9 @@ func (this ConsoleLogger) Info(format string, args ...interface{}) {
} }
func (this ConsoleLogger) Debug(format string, args ...interface{}) { func (this ConsoleLogger) Debug(format string, args ...interface{}) {
if DebugOutput {
this.output(os.Stdout, "[DEBUG] ", format, args...) this.output(os.Stdout, "[DEBUG] ", format, args...)
}
} }
func (this ConsoleLogger) output(f *os.File, prefix, format string, args ...interface{}) { func (this ConsoleLogger) output(f *os.File, prefix, format string, args ...interface{}) {

View File

@ -15,6 +15,7 @@ package pdf
import ( import (
"errors" "errors"
"fmt" "fmt"
"os"
"regexp" "regexp"
"strconv" "strconv"
@ -220,6 +221,16 @@ type PdfPage struct {
pageDict *PdfObjectDictionary pageDict *PdfObjectDictionary
} }
func (this *PdfPage) Show(pageNum int) {
this.GetPageDict()
common.Log.Info("-PdfPage.Show page %d ========================================", pageNum)
fmt.Printf("BoxColorInfo=%s\n", Trace(this.BoxColorInfo))
fmt.Printf("Contents=%s\n", Trace(this.Contents))
ShowDict(os.Stdout, "PdfPage.pageDict", this.pageDict)
this.Resources.Show()
common.Log.Info("+PdfPage.Show page %d ========================================", pageNum)
}
func NewPdfPage() *PdfPage { func NewPdfPage() *PdfPage {
page := PdfPage{} page := PdfPage{}
page.pageDict = &PdfObjectDictionary{} page.pageDict = &PdfObjectDictionary{}
@ -696,6 +707,20 @@ type PdfPageResources struct {
ProcSet PdfObject ProcSet PdfObject
} }
func (this *PdfPageResources) Show() {
common.Log.Info("-PdfPageResources.Show ========================================")
fmt.Printf("ExtGState=%s\n", Trace(this.ExtGState))
fmt.Printf("ColorSpace=%s\n", Trace(this.ColorSpace))
fmt.Printf("Pattern=%s\n", Trace(this.Pattern))
fmt.Printf("Shading=%s\n", Trace(this.Shading))
ShowDict(os.Stdout, "PdfPageResources.XObject", this.XObject)
ShowDict(os.Stdout, "PdfPageResources.Font", this.Font)
// fmt.Printf("Font=%s\n", Trace(this.Font))
fmt.Printf("ProcSet=%s\n", Trace(this.ProcSet))
common.Log.Info("+PdfPageResources.Show ========================================")
}
func NewPdfPageResourcesFromDict(dict *PdfObjectDictionary) (*PdfPageResources, error) { func NewPdfPageResourcesFromDict(dict *PdfObjectDictionary) (*PdfPageResources, error) {
r := PdfPageResources{} r := PdfPageResources{}

View File

@ -1199,14 +1199,14 @@ func (this *PdfParser) parseIndirectObjectBase(isIndirect bool) (PdfObject, erro
hb := make([]byte, hlen) hb := make([]byte, hlen)
_, err = this.ReadAtLeast(hb, hlen) _, err = this.ReadAtLeast(hb, hlen)
if err != nil { if err != nil {
common.Log.Debug("ERROR: unable to read - %s", err) common.Log.Error("unable to read - %s", err)
return nil, err return nil, err
} }
common.Log.Debug("textline: %s", hb) common.Log.Debug("textline: %s", hb)
result := reIndirectObject.FindStringSubmatch(string(hb)) result := reIndirectObject.FindStringSubmatch(string(hb))
if len(result) < 3 { if len(result) < 3 {
common.Log.Debug("ERROR: Unable to find object signature (%s)", string(hb)) common.Log.Error("Unable to find object signature (%s)", string(hb))
return &indirect, errors.New("Unable to detect indirect object signature") return &indirect, errors.New("Unable to detect indirect object signature")
} }
@ -1280,18 +1280,18 @@ func (this *PdfParser) parseIndirectObjectBase(isIndirect bool) (PdfObject, erro
return nil, errors.New("Stream length needs to be an integer") return nil, errors.New("Stream length needs to be an integer")
} }
streamLength := *pstreamLength streamLength := *pstreamLength
if streamLength < 0 { if streamLength < 0 { // !@#$ < 1 ?
return nil, errors.New("Stream needs to be longer than 0") return nil, errors.New("Stream needs to be longer than 0")
} }
stream := make([]byte, streamLength) stream := make([]byte, streamLength)
_, err = this.ReadAtLeast(stream, int(streamLength)) _, err = this.ReadAtLeast(stream, int(streamLength))
if err != nil { if err != nil {
common.Log.Debug("ERROR stream (%d): %X", len(stream), stream) common.Log.Error("stream (%d): %X", len(stream), stream)
return nil, err return nil, err
} }
streamobj := PdfObjectStream{} streamobj := PdfObjectStream{} // !@#$
streamobj.Stream = stream streamobj.Stream = stream
streamobj.PdfObjectDictionary = indirect.PdfObject.(*PdfObjectDictionary) streamobj.PdfObjectDictionary = indirect.PdfObject.(*PdfObjectDictionary)
streamobj.ObjectNumber = indirect.ObjectNumber streamobj.ObjectNumber = indirect.ObjectNumber

View File

@ -467,7 +467,7 @@ func (this *PdfReader) buildPageList(node *PdfIndirectObject, parent *PdfIndirec
return nil return nil
} }
if *objType != "Pages" { if *objType != "Pages" {
common.Log.Debug("ERROR: Table of content containing non Page/Pages object! (%s)", objType) common.Log.Error("Table of content containing non Page/Pages object! (%s)", objType)
return errors.New("Table of content containing non Page/Pages object!") return errors.New("Table of content containing non Page/Pages object!")
} }
@ -484,7 +484,7 @@ func (this *PdfReader) buildPageList(node *PdfIndirectObject, parent *PdfIndirec
kidsObj, err := this.parser.Trace((*nodeDict)["Kids"]) kidsObj, err := this.parser.Trace((*nodeDict)["Kids"])
if err != nil { if err != nil {
common.Log.Debug("ERROR: Failed loading Kids object") common.Log.Error("Failed loading Kids object")
return err return err
} }
@ -505,7 +505,7 @@ func (this *PdfReader) buildPageList(node *PdfIndirectObject, parent *PdfIndirec
common.Log.Debug("**Child: %d - %s", idx, child) common.Log.Debug("**Child: %d - %s", idx, child)
child, ok := child.(*PdfIndirectObject) child, ok := child.(*PdfIndirectObject)
if !ok { if !ok {
common.Log.Debug("ERROR: Page not indirect object - (%s)", child) common.Log.Error("Page not indirect object - (%s)", child)
panic(errors.New("Page not indirect object")) panic(errors.New("Page not indirect object"))
return errors.New("Page not indirect object") return errors.New("Page not indirect object")
} }

View File

@ -146,12 +146,7 @@ func (this *PdfParser) inspect() (map[string]int, error) {
return objTypes, nil return objTypes, nil
} }
func ShowDict(w *os.File, name string, d *PdfObjectDictionary) { func ShowDict(w *os.File, name string, o PdfObject) {
keys := []string{}
for k := range *d {
keys = append(keys, string(k))
}
sort.Strings(keys)
_, file, line, ok := runtime.Caller(1) _, file, line, ok := runtime.Caller(1)
if !ok { if !ok {
file = "???" file = "???"
@ -159,10 +154,44 @@ func ShowDict(w *os.File, name string, d *PdfObjectDictionary) {
} else { } else {
file = filepath.Base(file) file = filepath.Base(file)
} }
fmt.Fprintf(w, "ShowDict: %s:%d %q %d\n", file, line, name, len(*d))
for i, k := range keys { if o == nil {
v := (*d)[PdfObjectName(k)] fmt.Fprintf(w, "ShowDict: %s:%d %q nil\n", file, line, name)
return
}
ref := "" ref := ""
if io, isIndirect := o.(*PdfIndirectObject); isIndirect {
o = io.PdfObject
ref = (*io).PdfObjectReference.String()
}
d := o.(*PdfObjectDictionary)
fmt.Fprintf(w, "ShowDict: %s:%d %q %d %s\n", file, line, name, len(*d), ref)
showDict(w, d, "")
}
func showDict(w *os.File, d *PdfObjectDictionary, indent string) {
for i, k := range sortedKeys(d) {
v := (*d)[PdfObjectName(k)]
if e, ok := v.(*PdfObjectDictionary); ok {
fmt.Fprintf(w, indent+"%4d: %#10q:\n", i, k)
showDict(w, e, indent+" ")
} else {
fmt.Fprintf(w, indent+"%4d: %#10q: %s\n", i, k, ObjStr(v))
}
}
}
func sortedKeys(d *PdfObjectDictionary) []string {
keys := []string{}
for k := range *d {
keys = append(keys, string(k))
}
sort.Strings(keys)
return keys
}
func ObjStr(v PdfObject) string {
ref := "--- ---"
if io, ok := v.(*PdfIndirectObject); ok { if io, ok := v.(*PdfIndirectObject); ok {
v = (*io).PdfObject v = (*io).PdfObject
ref = (*io).PdfObjectReference.String() ref = (*io).PdfObjectReference.String()
@ -178,9 +207,15 @@ func ShowDict(w *os.File, name string, d *PdfObjectDictionary) {
s = fmt.Sprintf("%f", *x) s = fmt.Sprintf("%f", *x)
} else if b, ok := v.(*PdfObjectBool); ok { } else if b, ok := v.(*PdfObjectBool); ok {
s = fmt.Sprintf("%t", *b) s = fmt.Sprintf("%t", *b)
} else if x, ok := v.(*PdfObjectStream); ok {
s = fmt.Sprintf("%s %s", s, (*x).PdfObjectDictionary)
} else if d, ok := v.(*PdfObjectDictionary); ok {
s = fmt.Sprintf("%s %s", s, *d)
} else if d, ok := v.(*PdfObjectArray); ok {
s = fmt.Sprintf("%s %s", s, *d)
} }
fmt.Fprintf(w, "%4d: %#20q: %10s %s\n", i, k, s, ref)
} return fmt.Sprintf("%-9s %s", ref, s)
} }
func Trace(obj PdfObject) PdfObject { func Trace(obj PdfObject) PdfObject {

View File

@ -16,6 +16,7 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"sort"
"time" "time"
"github.com/unidoc/unidoc/common" "github.com/unidoc/unidoc/common"
@ -77,6 +78,83 @@ type PdfWriter struct {
ids *PdfObjectArray ids *PdfObjectArray
} }
// Show prints information about a PdfWriter's contents
func (this *PdfWriter) Show() {
typeCounts := map[string]int{}
common.Log.Info("-PdfWriter.Show ========================================")
fmt.Printf("root=%s\n", Trace(this.root))
fmt.Printf("catalog=%s\n", Trace(this.pages))
fmt.Printf("infoObj=%s\n", Trace(this.infoObj))
fmt.Printf("pages=%s\n", Trace(this.pages))
fmt.Printf("objects=%d\n", len(this.objects))
sort.Stable(byObject(this.objects))
for i, o := range this.objects {
_, _, t, u := ObjStreamType(o)
fmt.Printf("%10d: [%s:%s] %s\n", i, t, u, ObjStr(o))
typeCounts[t]++
}
fmt.Printf("ids=%s\n", Trace(this.ids))
common.Log.Info("+PdfWriter.Show ========================================")
for t, n := range typeCounts {
fmt.Printf("%#20q: %3d\n", t, n)
}
}
// byObject sorts slices of PdfObject by "Type" and "Subtype" keys. See ObjStreamType
type byObject []PdfObject
func (x byObject) Len() int { return len(x) }
func (x byObject) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x byObject) Less(i, j int) bool {
si, di, ti, ui := ObjStreamType(x[i])
sj, dj, tj, uj := ObjStreamType(x[j])
if ti != tj {
return ti > tj
}
if ui != uj {
return ui > uj
}
if si != sj {
return si
}
if di != dj {
return si
}
return false
}
// ObjStreamType returns information about streams and dicts: isStream, isDict, typ, subtyp
// isStream: is `o`a PdfObjectStream?
// isDict: is `o`a PdfObjectDictionary?
// type: "Type" value of dict or stream
// type: "Subtype" value of dict or stream
func ObjStreamType(o PdfObject) (isStream, isDict bool, typ, subtyp string) {
if io, ok := o.(*PdfIndirectObject); ok {
o = (*io).PdfObject
}
var d *PdfObjectDictionary = nil
if s, ok := o.(*PdfObjectStream); ok {
d = (*s).PdfObjectDictionary
isStream = true
} else if s, ok := o.(*PdfObjectDictionary); ok {
d = s
isDict = true
}
if d != nil {
if v, ok := (*d)["Type"]; ok {
typ = string(*(v.(*PdfObjectName)))
}
if v, ok := (*d)["Subtype"]; ok {
subtyp = string(*(v.(*PdfObjectName)))
}
}
return
}
func NewPdfWriter() PdfWriter { func NewPdfWriter() PdfWriter {
w := PdfWriter{} w := PdfWriter{}
@ -211,7 +289,7 @@ func (this *PdfWriter) addObjects(obj PdfObject) error {
if _, isReference := obj.(*PdfObjectReference); isReference { if _, isReference := obj.(*PdfObjectReference); isReference {
// Should never be a reference, should already be resolved. // Should never be a reference, should already be resolved.
common.Log.Debug("ERROR: Cannot be a reference!") common.Log.Error("Cannot be a reference!")
return errors.New("Reference not allowed") return errors.New("Reference not allowed")
} }