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