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 }