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  }