-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathtypes.go
More file actions
272 lines (243 loc) · 5.19 KB
/
types.go
File metadata and controls
272 lines (243 loc) · 5.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package pdf
import (
"bytes"
"io"
"io/ioutil"
"sort"
)
// Kind represents the kind of value stored in an Object.
type Kind int
const (
Null Kind = iota
Bool
Integer
Real
String
Name
Dict
Array
Stream
Indirect // Reference: 1 0 R; renamed from Ptr to avoid collision with Ptr struct
Keyword // Internal: obj, endobj, etc.
)
// Object represents a PDF object using a tagged union approach to avoid interface{} boxing.
type Object struct {
Kind Kind
BoolVal bool
Int64Val int64
Float64Val float64
NameVal string
StringVal string
KeywordVal string
ArrayVal []Object
DictVal map[string]Object
PtrVal objptr
StreamOffset int64 // For Stream, DictVal holds the header
}
// Internal types
type objptr struct {
id uint32
gen uint16
}
type objdef struct {
ptr objptr
obj Object
}
// A Value represents a value in a PDF file.
type Value struct {
r *Reader // the reader, for resolving references
ptr objptr // the pointer to the object, if any
obj Object // the actual data
err error // if non-nil, the error that occurred during resolution or access
}
// Err returns the error associated with the value, if any.
func (v Value) Err() error {
return v.err
}
// Kind returns the kind of value v is.
func (v Value) Kind() Kind {
if v.err != nil {
return Null
}
return v.obj.Kind
}
// IsNull reports whether v is a null value.
func (v Value) IsNull() bool {
return v.Kind() == Null
}
// Bool returns v's boolean value.
func (v Value) Bool() bool {
if v.err != nil {
return false
}
return v.obj.BoolVal
}
// Int64 returns v's integer value.
func (v Value) Int64() int64 {
if v.err != nil {
return 0
}
if v.obj.Kind == Integer {
return v.obj.Int64Val
}
if v.obj.Kind == Real {
return int64(v.obj.Float64Val)
}
return 0
}
// Float64 returns v's float value.
func (v Value) Float64() float64 {
if v.err != nil {
return 0
}
if v.obj.Kind == Real {
return v.obj.Float64Val
}
if v.obj.Kind == Integer {
return float64(v.obj.Int64Val)
}
return 0
}
// RawString returns v's string value.
func (v Value) RawString() string {
if v.err != nil {
return ""
}
return v.obj.StringVal
}
// String returns a textual representation of the value v.
func (v Value) String() string {
if v.err != nil {
return ""
}
return objfmt(v.obj)
}
// Text returns v's string value interpreted as a “text string” (defined in the PDF spec)
// and converted to UTF-8.
func (v Value) Text() string {
if v.err != nil {
return ""
}
s := v.obj.StringVal
if isPDFDocEncoded(s) {
return pdfDocDecode(s)
}
if isUTF16(s) {
return utf16Decode(s[2:])
}
return s
}
// Reader returns a reader for the stream v.
func (v Value) Reader() io.ReadCloser {
if v.err != nil {
return &errorReadCloser{v.err}
}
if v.obj.Kind == Stream {
return newStreamReader(v.obj, v.r)
}
return ioutil.NopCloser(bytes.NewReader(nil))
}
// Data returns the raw data of the stream v.
func (v Value) Data() []byte {
if v.err != nil {
return nil
}
if v.obj.Kind == Stream {
data, _ := io.ReadAll(newStreamReader(v.obj, v.r))
return data
}
return nil
}
// Ptr represents a PDF Object Reference (Indirect Object)
// This is the public API struct.
type Ptr struct {
id uint32
gen uint16
}
// GetID returns the object number.
func (p Ptr) GetID() uint32 {
return p.id
}
// GetGen returns the generation number.
func (p Ptr) GetGen() uint16 {
return p.gen
}
// Name returns v's name value.
func (v Value) Name() string {
if v.err != nil {
return ""
}
return v.obj.NameVal
}
// Len returns the number of elements in the array v.
func (v Value) Len() int {
if v.err != nil {
return 0
}
if v.obj.Kind == Array {
return len(v.obj.ArrayVal)
}
return 0
}
// Index returns the i'th element of the array v.
func (v Value) Index(i int) Value {
if v.err != nil {
return Value{err: v.err}
}
if v.obj.Kind != Array {
return Value{}
}
a := v.obj.ArrayVal
if i < 0 || i >= len(a) {
return Value{}
}
return v.r.resolve(v.ptr, a[i])
}
// Keys returns the keys of the dictionary v, sorted alphabetically.
func (v Value) Keys() []string {
if v.err != nil {
return nil
}
var keys []string
if v.obj.Kind == Dict || v.obj.Kind == Stream {
for k := range v.obj.DictVal {
keys = append(keys, k)
}
}
sort.Strings(keys)
return keys
}
// Key returns the value associated with the key k in the dictionary v.
func (v Value) Key(key string) Value {
if v.err != nil {
return Value{err: v.err}
}
if v.obj.Kind == Dict || v.obj.Kind == Stream {
if val, ok := v.obj.DictVal[key]; ok {
return v.r.resolve(v.ptr, val)
}
}
return Value{}
}
// GetPtr returns the object reference for the value.
func (v Value) GetPtr() Ptr {
return Ptr{id: v.ptr.id, gen: v.ptr.gen}
}
// Header returns the header dictionary for the stream v.
func (v Value) Header() Value {
if v.err != nil {
return Value{err: v.err}
}
if v.obj.Kind == Stream {
// Create a Value for the header (which is a Dict)
hdrObj := Object{
Kind: Dict,
DictVal: v.obj.DictVal,
}
return v.r.createValue(objptr{}, hdrObj)
}
return Value{}
}