blob: 78eee53073fd5f7385f6fe49f4040d58b613e332 [file] [log] [blame]
// Copyright 2003, 2004 Colin Percival
// All rights reserved
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted providing that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// For the terms under which this work may be distributed, please see
// the adjoining file "LICENSE".
//
// ChangeLog:
// 2005-05-05 - Use the modified header struct from bspatch.h; use 32-bit
// values throughout.
// --Benjamin Smedberg <benjamin@smedbergs.us>
// 2015-08-03 - Change search() to template to allow PagedArray usage.
// --Samuel Huang <huangs@chromium.org>
// 2015-08-19 - Optimized search() to be non-recursive.
// --Samuel Huang <huangs@chromium.org>
// 2016-06-28 - Moved matchlen() and search() to a new file; format; changed
// search() use std::lexicographical_compare().
// 2016-06-30 - Changed matchlen() input; changed search() to return struct.
// --Samuel Huang <huangs@chromium.org>
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COURGETTE_THIRD_PARTY_BSDIFF_BSDIFF_SEARCH_H_
#define COURGETTE_THIRD_PARTY_BSDIFF_BSDIFF_SEARCH_H_
#include <algorithm>
namespace bsdiff {
// Return values of search().
struct SearchResult {
SearchResult(int pos_in, int size_in) : pos(pos_in), size(size_in) {}
int pos;
int size;
};
// Similar to ::memcmp(), but assumes equal |size| and returns match length.
inline int matchlen(const unsigned char* buf1,
const unsigned char* buf2,
int size) {
for (int i = 0; i < size; ++i)
if (buf1[i] != buf2[i])
return i;
return size;
}
// Finds a suffix in |old| that has the longest common prefix with |keybuf|,
// aided by suffix array |I| of |old|. Returns the match length, and writes to
// |pos| a position of best match in |old|. If multiple such positions exist,
// |pos| would take an arbitrary one.
template <class T>
SearchResult search(T I,
const unsigned char* srcbuf,
int srcsize,
const unsigned char* keybuf,
int keysize) {
int lo = 0;
int hi = srcsize;
while (hi - lo >= 2) {
int mid = (lo + hi) / 2;
if (std::lexicographical_compare(
srcbuf + I[mid], srcbuf + srcsize, keybuf, keybuf + keysize)) {
lo = mid;
} else {
hi = mid;
}
}
int x = matchlen(srcbuf + I[lo], keybuf, std::min(srcsize - I[lo], keysize));
int y = matchlen(srcbuf + I[hi], keybuf, std::min(srcsize - I[hi], keysize));
return (x > y) ? SearchResult(I[lo], x) : SearchResult(I[hi], y);
}
} // namespace bsdiff
#endif // COURGETTE_THIRD_PARTY_BSDIFF_BSDIFF_SEARCH_H_