Skip to content

Commit

Permalink
Add new reading / parsing functions that take a Context object.
Browse files Browse the repository at this point in the history
This will allow the caller to optionally cancel long-running parsing calls.
  • Loading branch information
fancycode committed Jan 23, 2024
1 parent b89d7b1 commit f2e4421
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 97 deletions.
33 changes: 22 additions & 11 deletions pkg/pdfcpu/model/parse.go
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package model

import (
"context"
"encoding/hex"
"strconv"
"strings"
Expand Down Expand Up @@ -292,7 +293,7 @@ func ParseObjectAttributes(line *string) (objectNumber *int, generationNumber *i
return objectNumber, generationNumber, nil
}

func parseArray(line *string) (*types.Array, error) {
func parseArray(c context.Context, line *string) (*types.Array, error) {
if log.ParseEnabled() {
log.Parse.Println("ParseObject: value = Array")
}
Expand Down Expand Up @@ -329,7 +330,7 @@ func parseArray(line *string) (*types.Array, error) {

for !strings.HasPrefix(l, "]") {

obj, err := ParseObject(&l)
obj, err := ParseObjectContext(c, &l)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -527,11 +528,15 @@ func parseName(line *string) (*types.Name, error) {
return &nameObj, nil
}

func processDictKeys(line *string, relaxed bool) (types.Dict, error) {
func processDictKeys(c context.Context, line *string, relaxed bool) (types.Dict, error) {
l := *line
var eol bool
d := types.NewDict()
for !strings.HasPrefix(l, ">>") {
if err := c.Err(); err != nil {
return nil, err
}

key, err := parseName(&l)
if err != nil {
return nil, err
Expand Down Expand Up @@ -564,7 +569,7 @@ func processDictKeys(line *string, relaxed bool) (types.Dict, error) {
continue
}

obj, err := ParseObject(&l)
obj, err := ParseObjectContext(c, &l)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -597,7 +602,7 @@ func processDictKeys(line *string, relaxed bool) (types.Dict, error) {
return d, nil
}

func parseDict(line *string, relaxed bool) (types.Dict, error) {
func parseDict(c context.Context, line *string, relaxed bool) (types.Dict, error) {
if line == nil || len(*line) == 0 {
return nil, errNoDictionary
}
Expand All @@ -623,7 +628,7 @@ func parseDict(line *string, relaxed bool) (types.Dict, error) {
return nil, errDictionaryNotTerminated
}

d, err := processDictKeys(&l, relaxed)
d, err := processDictKeys(c, &l, relaxed)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -829,7 +834,7 @@ func parseNumericOrIndRef(line *string) (types.Object, error) {
return parseIndRef(s, l, l1, line, i, i2, rangeErr)
}

func parseHexLiteralOrDict(l *string) (val types.Object, err error) {
func parseHexLiteralOrDict(c context.Context, l *string) (val types.Object, err error) {
if len(*l) < 2 {
return nil, errBufNotAvailable
}
Expand All @@ -843,8 +848,8 @@ func parseHexLiteralOrDict(l *string) (val types.Object, err error) {
d types.Dict
err error
)
if d, err = parseDict(l, false); err != nil {
if d, err = parseDict(l, true); err != nil {
if d, err = parseDict(c, l, false); err != nil {
if d, err = parseDict(c, l, true); err != nil {
return nil, err
}
}
Expand Down Expand Up @@ -892,6 +897,12 @@ func parseBooleanOrNull(l string) (val types.Object, s string, ok bool) {

// ParseObject parses next Object from string buffer and returns the updated (left clipped) buffer.
func ParseObject(line *string) (types.Object, error) {
return ParseObjectContext(context.Background(), line)
}

// ParseObjectContext parses next Object from string buffer and returns the updated (left clipped) buffer.
// If the passed context is cancelled, parsing will be interrupted.
func ParseObjectContext(c context.Context, line *string) (types.Object, error) {
if noBuf(line) {
return nil, errBufNotAvailable
}
Expand All @@ -915,7 +926,7 @@ func ParseObject(line *string) (types.Object, error) {
switch l[0] {

case '[': // array
a, err := parseArray(&l)
a, err := parseArray(c, &l)
if err != nil {
return nil, err
}
Expand All @@ -929,7 +940,7 @@ func ParseObject(line *string) (types.Object, error) {
value = *nameObj

case '<': // hex literal or dict
value, err = parseHexLiteralOrDict(&l)
value, err = parseHexLiteralOrDict(c, &l)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit f2e4421

Please sign in to comment.