@Override
	public void setBytes(Address address, byte[] source, int sIndex, int size)
			throws MemoryAccessException {
		lock.acquire();
		try {
			Address addr = address;
			int n = size;
			// loop first just to make sure the operation can complete before making any changes
			while (n > 0) {
				MemoryBlock block = getBlock(addr);
				if (block == null) {
					throw new MemoryAccessException(
						"Address " + addr.toString(true) + " does not exist in memory");
				}
				long advanced = block.getSize() - addr.subtract(block.getStart());
				if (advanced >= n) {
					break;
				}
				n -= advanced;
				try {
					addr = block.getEnd().addNoWrap(1);
				}
				catch (AddressOverflowException e) {
					throw new MemoryAccessException("Attempted to write beyond address space");
				}
			}

			addr = address;
			n = size;
			int offset = sIndex;
			while (n > 0) {
				MemoryBlock block = getBlock(addr);
				int cnt = block.putBytes(addr, source, offset, n);
				offset += cnt;
				n -= cnt;
				if (n <= 0) {
					break;
				}
				addr = block.getEnd().add(1);
			}

		}
		finally {
			lock.release();
		}

	}
Tests if the memory contains a sequence of contiguous bytes that match the given byte array
at all bit positions where the mask contains an "on" bit. The test will be something like

<PRE>
 for(int i = 0; i &lt; bytes.length; i++) {
    if (bytes[i] != memory.getByte(addr+i) &amp; masks[i]) {
        return false;
    }
}
</PRE>

@param addr The beginning address in memory to test against.
@param bytes the array of bytes to test for.
@param masks the array of masks. (One for each byte in the byte array)
@param forward if true, the matching is going forward, otherwise backward

@return 1 if there is a match 0 if there is no match -i if no match is found, this is the
        number of bytes that can be safely skipped
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDB.java