codeberg.org/go-pdf/fpdf@v0.11.1/compare.go (about) 1 // Copyright ©2023 The go-pdf Authors. All rights reserved. 2 // Use of this source code is governed by a MIT-style 3 // license that can be found in the LICENSE file. 4 5 /* 6 * Copyright (c) 2015 Kurt Jung (Gmail: kurt.w.jung) 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 package fpdf 22 23 import ( 24 "bytes" 25 "fmt" 26 "io" 27 "os" 28 "sort" 29 ) 30 31 type sortType struct { 32 length int 33 less func(int, int) bool 34 swap func(int, int) 35 } 36 37 func (s *sortType) Len() int { 38 return s.length 39 } 40 41 func (s *sortType) Less(i, j int) bool { 42 return s.less(i, j) 43 } 44 45 func (s *sortType) Swap(i, j int) { 46 s.swap(i, j) 47 } 48 49 func gensort(Len int, Less func(int, int) bool, Swap func(int, int)) { 50 sort.Sort(&sortType{length: Len, less: Less, swap: Swap}) 51 } 52 53 func writeBytes(leadStr string, startPos int, sl []byte) { 54 var pos, max int 55 var b byte 56 fmt.Printf("%s %07x", leadStr, startPos) 57 max = len(sl) 58 for pos < max { 59 fmt.Printf(" ") 60 for k := 0; k < 8; k++ { 61 if pos < max { 62 fmt.Printf(" %02x", sl[pos]) 63 } else { 64 fmt.Printf(" ") 65 } 66 pos++ 67 } 68 } 69 fmt.Printf(" |") 70 pos = 0 71 for pos < max { 72 b = sl[pos] 73 if b < 32 || b >= 128 { 74 b = '.' 75 } 76 fmt.Printf("%c", b) 77 pos++ 78 } 79 fmt.Printf("|\n") 80 } 81 82 func checkBytes(pos int, sl1, sl2 []byte, printDiff bool) (eq bool) { 83 eq = bytes.Equal(sl1, sl2) 84 if !eq && printDiff { 85 writeBytes("<", pos, sl1) 86 writeBytes(">", pos, sl2) 87 } 88 return 89 } 90 91 // CompareBytes compares the bytes referred to by sl1 with those referred to by 92 // sl2. Nil is returned if the buffers are equal, otherwise an error. 93 func CompareBytes(sl1, sl2 []byte, printDiff bool) (err error) { 94 var posStart, posEnd, len1, len2, length int 95 var diffs bool 96 97 len1 = len(sl1) 98 len2 = len(sl2) 99 length = len1 100 if length > len2 { 101 length = len2 102 } 103 for posStart < length-1 { 104 posEnd = posStart + 16 105 if posEnd > length { 106 posEnd = length 107 } 108 if !checkBytes(posStart, sl1[posStart:posEnd], sl2[posStart:posEnd], printDiff) { 109 diffs = true 110 } 111 posStart = posEnd 112 } 113 if diffs { 114 err = fmt.Errorf("documents are different") 115 } 116 return 117 } 118 119 // ComparePDFs reads and compares the full contents of the two specified 120 // readers byte-for-byte. Nil is returned if the buffers are equal, otherwise 121 // an error. 122 func ComparePDFs(rdr1, rdr2 io.Reader, printDiff bool) (err error) { 123 var b1, b2 *bytes.Buffer 124 _, err = b1.ReadFrom(rdr1) 125 if err == nil { 126 _, err = b2.ReadFrom(rdr2) 127 if err == nil { 128 err = CompareBytes(b1.Bytes(), b2.Bytes(), printDiff) 129 } 130 } 131 return 132 } 133 134 // ComparePDFFiles reads and compares the full contents of the two specified 135 // files byte-for-byte. Nil is returned if the file contents are equal, or if 136 // the second file is missing, otherwise an error. 137 func ComparePDFFiles(file1Str, file2Str string, printDiff bool) (err error) { 138 var sl1, sl2 []byte 139 sl1, err = os.ReadFile(file1Str) 140 if err == nil { 141 sl2, err = os.ReadFile(file2Str) 142 if err == nil { 143 err = CompareBytes(sl1, sl2, printDiff) 144 } else { 145 // Second file is missing; treat this as success 146 err = nil 147 } 148 } 149 return 150 }