github.com/boki/go-xmp@v1.0.1/xmp/reader.go (about)

     1  // Copyright (c) 2017-2018 Alexander Eichhorn
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"): you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    11  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    12  // License for the specific language governing permissions and limitations
    13  // under the License.
    14  
    15  package xmp
    16  
    17  import (
    18  	"bufio"
    19  	"bytes"
    20  	"io"
    21  )
    22  
    23  func Read(r io.Reader) (*Document, error) {
    24  	x := &Document{}
    25  	d := NewDecoder(r)
    26  	if err := d.Decode(x); err != nil {
    27  		return nil, err
    28  	}
    29  	return x, nil
    30  }
    31  
    32  func Scan(r io.Reader) (*Document, error) {
    33  	pp, err := ScanPackets(r)
    34  	if err != nil {
    35  		return nil, err
    36  	}
    37  	x := &Document{}
    38  	if err := Unmarshal(pp[0], x); err != nil {
    39  		return nil, err
    40  	}
    41  	return x, nil
    42  }
    43  
    44  func ScanPackets(r io.Reader) ([][]byte, error) {
    45  	packets := make([][]byte, 0)
    46  	s := bufio.NewScanner(r)
    47  	s.Split(splitPacket)
    48  	for s.Scan() {
    49  		b := s.Bytes()
    50  		if isXmpPacket(b) {
    51  			x := make([]byte, len(b))
    52  			copy(x, b)
    53  			packets = append(packets, x)
    54  		}
    55  	}
    56  	if err := s.Err(); err != nil {
    57  		return nil, err
    58  	}
    59  	if len(packets) == 0 {
    60  		return nil, io.EOF
    61  	}
    62  	return packets, nil
    63  }
    64  
    65  var packet_start = []byte("<?xpacket begin")
    66  var packet_end = []byte("<?xpacket end")       // plus suffix `"w"?>`
    67  var magic = []byte("W5M0MpCehiHzreSzNTczkc9d") // len 24
    68  
    69  func isXmpPacket(b []byte) bool {
    70  	return bytes.Index(b[:51], magic) > -1
    71  }
    72  
    73  func splitPacket(data []byte, atEOF bool) (advance int, token []byte, err error) {
    74  	start := bytes.Index(data, packet_start)
    75  	if start == -1 {
    76  		ofs := len(data) - len(packet_start)
    77  		if ofs > 0 {
    78  			return ofs, nil, nil
    79  		}
    80  		return len(data), nil, nil
    81  	}
    82  	end := bytes.Index(data[start:], packet_end)
    83  	last := start + end + len(packet_end) + 6
    84  	if end == -1 || last > len(data) {
    85  		if atEOF {
    86  			return len(data), nil, nil
    87  		}
    88  		return 0, nil, nil
    89  	}
    90  	return last, data[start:last], nil
    91  }