initial commit
This commit is contained in:
commit
6fcbbfbab2
|
@ -0,0 +1,98 @@
|
|||
version: '{build}'
|
||||
|
||||
cache:
|
||||
- x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z -> .appveyor.yml
|
||||
- i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z -> .appveyor.yml
|
||||
- Nim -> .appveyor.yml
|
||||
|
||||
matrix:
|
||||
# We always want 32 and 64-bit compilation
|
||||
fast_finish: false
|
||||
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
|
||||
install:
|
||||
- setlocal EnableExtensions EnableDelayedExpansion
|
||||
|
||||
- IF "%PLATFORM%" == "x86" (
|
||||
SET "MINGW_ARCHIVE=i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z" &
|
||||
SET "MINGW_URL=https://sourceforge.net/projects/mingw-w64/files/Toolchains%%20targetting%%20Win32/Personal%%20Builds/mingw-builds/4.9.2/threads-win32/dwarf/i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z" &
|
||||
SET "MINGW_DIR=mingw32"
|
||||
) ELSE (
|
||||
IF "%PLATFORM%" == "x64" (
|
||||
SET "MINGW_ARCHIVE=x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z" &
|
||||
SET "MINGW_URL=https://sourceforge.net/projects/mingw-w64/files/Toolchains%%20targetting%%20Win64/Personal%%20Builds/mingw-builds/4.9.2/threads-win32/seh/x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z" &
|
||||
SET "MINGW_DIR=mingw64"
|
||||
) else (
|
||||
echo "Unknown platform"
|
||||
)
|
||||
)
|
||||
|
||||
- SET PATH=%CD%\%MINGW_DIR%\bin;%CD%\Nim\bin;%PATH%
|
||||
|
||||
# Unpack mingw
|
||||
- IF NOT EXIST "%MINGW_ARCHIVE%" appveyor DownloadFile "%MINGW_URL%" -FileName "%MINGW_ARCHIVE%"
|
||||
- 7z x -y "%MINGW_ARCHIVE%" > nul
|
||||
|
||||
# build nim from our own branch - this to avoid the day-to-day churn and
|
||||
# regressions of the fast-paced Nim development while maintaining the
|
||||
# flexibility to apply patches
|
||||
- SET "NEED_REBUILD="
|
||||
|
||||
- IF NOT EXIST "Nim\\.git\\" (
|
||||
git clone https://github.com/nim-lang/Nim.git
|
||||
) ELSE (
|
||||
( cd Nim ) &
|
||||
( git pull ) &
|
||||
( cd .. )
|
||||
)
|
||||
|
||||
# Rebuild Nim if HEAD has moved or if we don't yet have a cached version
|
||||
- IF NOT EXIST "Nim\\ver.txt" (
|
||||
SET NEED_REBUILD=1
|
||||
) ELSE (
|
||||
( CD Nim ) &
|
||||
( git rev-parse HEAD > ..\\cur_ver.txt ) &
|
||||
( fc ver.txt ..\\cur_ver.txt > nul ) &
|
||||
( IF NOT ERRORLEVEL == 0 SET NEED_REBUILD=1 ) &
|
||||
( cd .. )
|
||||
)
|
||||
|
||||
- IF NOT EXIST "Nim\\bin\\nim.exe" SET NEED_REBUILD=1
|
||||
- IF NOT EXIST "Nim\\bin\\nimble.exe" SET NEED_REBUILD=1
|
||||
|
||||
# after building nim, wipe csources to save on cache space
|
||||
- IF DEFINED NEED_REBUILD (
|
||||
cd Nim &
|
||||
( IF EXIST "csources" rmdir /s /q csources ) &
|
||||
git clone --depth 1 https://github.com/nim-lang/csources &
|
||||
cd csources &
|
||||
( IF "%PLATFORM%" == "x64" ( build64.bat > nul ) else ( build.bat > nul ) ) &
|
||||
cd .. &
|
||||
bin\nim c --verbosity:0 --hints:off koch &
|
||||
koch boot -d:release --verbosity:0 --hints:off &
|
||||
koch nimble > nul &
|
||||
git rev-parse HEAD > ver.txt &
|
||||
rmdir /s /q csources &
|
||||
cd ..
|
||||
)
|
||||
|
||||
- git clone --depth 1 https://github.com/google/snappy
|
||||
|
||||
build_script:
|
||||
- cd snappy
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake .. -G "MinGW Makefiles"
|
||||
- mingw32-make
|
||||
- copy libsnappy.a C:\projects\%APPVEYOR_PROJECT_SLUG%\tests
|
||||
|
||||
- cd C:\projects\%APPVEYOR_PROJECT_SLUG%
|
||||
- nimble install -y > nul
|
||||
|
||||
test_script:
|
||||
- nimble test
|
||||
|
||||
deploy: off
|
|
@ -0,0 +1,3 @@
|
|||
master
|
||||
*.exe
|
||||
libsnappy.a
|
|
@ -0,0 +1,46 @@
|
|||
language: c # or other C/C++ variants
|
||||
|
||||
sudo: false
|
||||
|
||||
# https://docs.travis-ci.com/user/caching/
|
||||
#
|
||||
# Caching the whole nim folder is better than relying on ccache - this way, we
|
||||
# skip the expensive bootstrap process and linking
|
||||
cache:
|
||||
directories:
|
||||
- nim
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
install:
|
||||
# build nim from our own branch - this to avoid the day-to-day churn and
|
||||
# regressions of the fast-paced Nim development while maintaining the
|
||||
# flexibility to apply patches
|
||||
#
|
||||
# check version of remote branch
|
||||
- "export NIMVER=$(git ls-remote https://github.com/nim-lang/nim.git HEAD | cut -f 1)"
|
||||
|
||||
# after building nim, wipe csources to save on cache space
|
||||
- "{ [ -f nim/$NIMVER/bin/nim ] && [ -f nim/$NIMVER/bin/nimble ] ; } ||
|
||||
{ rm -rf nim ;
|
||||
mkdir -p nim ;
|
||||
git clone --depth=1 https://github.com/nim-lang/nim.git nim/$NIMVER ;
|
||||
cd nim/$NIMVER ;
|
||||
sh build_all.sh > /dev/null;
|
||||
rm -rf csources ;
|
||||
cd ../.. ;
|
||||
}"
|
||||
- "export PATH=$PWD/nim/$NIMVER/bin:$PATH"
|
||||
- git clone --depth 1 https://github.com/google/snappy
|
||||
|
||||
script:
|
||||
- cd snappy
|
||||
- mkdir build
|
||||
- cd build && cmake ../ && make
|
||||
- cd ../..
|
||||
- cp snappy/build/libsnappy.a tests/libsnappy.a
|
||||
|
||||
- nimble install -y > /dev/null
|
||||
- nimble test
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018 andri lim
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,498 @@
|
|||
const
|
||||
tagLiteral* = 0x00
|
||||
tagCopy1* = 0x01
|
||||
tagCopy2* = 0x02
|
||||
tagCopy4* = 0x03
|
||||
|
||||
inputMargin = 16 - 1
|
||||
|
||||
# PutUvarint encodes a uint64 into buf and returns the number of bytes written.
|
||||
func putUvarint(buf: var openArray[byte], x: uint64): int =
|
||||
var
|
||||
i = 0
|
||||
x = x
|
||||
|
||||
while x >= 0x80'u64:
|
||||
buf[i] = byte(x and 0xFF) or 0x80
|
||||
x = x shr 7
|
||||
inc i
|
||||
buf[i] = byte(x and 0xFF)
|
||||
result = i + 1
|
||||
|
||||
# Uvarint decodes a uint64 from buf and returns that value and the
|
||||
# number of bytes read (> 0). If an error occurred, the value is 0
|
||||
# and the number of bytes n is <= 0 meaning:
|
||||
#
|
||||
# n == 0: buf too small
|
||||
# n < 0: value larger than 64 bits (overflow)
|
||||
# and -n is the number of bytes read
|
||||
#
|
||||
func uvarint(buf: openArray[byte]): (uint64, int) =
|
||||
var x: uint64
|
||||
var s: uint
|
||||
for i, b in buf:
|
||||
if int(b) < 0x80:
|
||||
if (i > 9) or (i == 9) and (int(b) > 1):
|
||||
return (0'u64, -(i + 1)) # overflow
|
||||
return (x or (uint64(b) shl s), i + 1)
|
||||
x = x or (uint64(b and 0x7F) shl s)
|
||||
inc(s, 7)
|
||||
result = (0'u64, 0)
|
||||
|
||||
template sliceImpl(r: openArray[byte], a, b: int): auto =
|
||||
toOpenArray(cast[ptr array[0, byte]](r[0].unsafeAddr)[], a, b)
|
||||
|
||||
template `%`(s, i: untyped): untyped =
|
||||
(when i is BackwardsIndex: s.len - int(i) else: int(i))
|
||||
|
||||
template `[]`[U, V](r: openArray[byte], s: HSlice[U, V]): auto =
|
||||
sliceImpl(r, r % s.a, r % s.b)
|
||||
|
||||
func load32(b: openArray[byte]): uint32 {.inline.} =
|
||||
result = uint32(b[0]) or
|
||||
(uint32(b[1]) shl 8 ) or
|
||||
(uint32(b[2]) shl 16) or
|
||||
(uint32(b[3]) shl 24)
|
||||
|
||||
func load32(b: openArray[byte], i: int): uint32 =
|
||||
result = load32(b[i..<i+4])
|
||||
|
||||
func load64(b: openArray[byte]): uint64 {.inline.} =
|
||||
result = uint64(b[0]) or
|
||||
(uint64(b[1]) shl 8 ) or
|
||||
(uint64(b[2]) shl 16) or
|
||||
(uint64(b[3]) shl 24) or
|
||||
(uint64(b[4]) shl 32) or
|
||||
(uint64(b[5]) shl 40) or
|
||||
(uint64(b[6]) shl 48) or
|
||||
(uint64(b[7]) shl 56)
|
||||
|
||||
func load64(b: openArray[byte], i: int): uint64 =
|
||||
result = load64(b[i..<i+8])
|
||||
|
||||
# emitLiteral writes a literal chunk and returns the number of bytes written.
|
||||
#
|
||||
# It assumes that:
|
||||
# dst is long enough to hold the encoded bytes
|
||||
# 1 <= len(lit) and len(lit) <= 65536
|
||||
func emitLiteral(dst: var openArray[byte], lit: openArray[byte]): int =
|
||||
var
|
||||
i = 0
|
||||
n = lit.len-1
|
||||
|
||||
if n < 60:
|
||||
dst[0] = (byte(n) shl 2) or tagLiteral
|
||||
i = 1
|
||||
elif n < (1 shl 8):
|
||||
dst[0] = (60 shl 2) or tagLiteral
|
||||
dst[1] = byte(n)
|
||||
i = 2
|
||||
else:
|
||||
dst[0] = (61 shl 2) or tagLiteral
|
||||
dst[1] = byte(n)
|
||||
dst[2] = byte(n shr 8)
|
||||
i = 3
|
||||
|
||||
copyMem(dst[i].addr, lit[0].unsafeAddr, lit.len)
|
||||
result = i + lit.len
|
||||
|
||||
|
||||
# emitCopy writes a copy chunk and returns the number of bytes written.
|
||||
#
|
||||
# It assumes that:
|
||||
# dst is long enough to hold the encoded bytes
|
||||
# 1 <= offset and offset <= 65535
|
||||
# 4 <= length and length <= 65535
|
||||
func emitCopy(dst: var openArray[byte], offset, length: int): int =
|
||||
var
|
||||
i = 0
|
||||
length = length
|
||||
# The maximum length for a single tagCopy1 or tagCopy2 op is 64 bytes. The
|
||||
# threshold for this loop is a little higher (at 68 = 64 + 4), and the
|
||||
# length emitted down below is is a little lower (at 60 = 64 - 4), because
|
||||
# it's shorter to encode a length 67 copy as a length 60 tagCopy2 followed
|
||||
# by a length 7 tagCopy1 (which encodes as 3+2 bytes) than to encode it as
|
||||
# a length 64 tagCopy2 followed by a length 3 tagCopy2 (which encodes as
|
||||
# 3+3 bytes). The magic 4 in the 64±4 is because the minimum length for a
|
||||
# tagCopy1 op is 4 bytes, which is why a length 3 copy has to be an
|
||||
# encodes-as-3-bytes tagCopy2 instead of an encodes-as-2-bytes tagCopy1.
|
||||
while length >= 68:
|
||||
# Emit a length 64 copy, encoded as 3 bytes.
|
||||
dst[i+0] = (63 shl 2) or tagCopy2
|
||||
dst[i+1] = byte(offset)
|
||||
dst[i+2] = byte(offset shr 8)
|
||||
inc(i, 3)
|
||||
dec(length, 64)
|
||||
|
||||
if length > 64:
|
||||
# Emit a length 60 copy, encoded as 3 bytes.
|
||||
dst[i+0] = (59 shl 2) or tagCopy2
|
||||
dst[i+1] = byte(offset)
|
||||
dst[i+2] = byte(offset shr 8)
|
||||
inc(i, 3)
|
||||
dec(length, 60)
|
||||
|
||||
if (length >= 12) or (offset >= 2048):
|
||||
# Emit the remaining copy, encoded as 3 bytes.
|
||||
dst[i+0] = (byte(length-1) shl 2) or tagCopy2
|
||||
dst[i+1] = byte(offset)
|
||||
dst[i+2] = byte(offset shr 8)
|
||||
return i + 3
|
||||
|
||||
# Emit the remaining copy, encoded as 2 bytes.
|
||||
dst[i+0] = (byte(offset shr 8) shl 5) or (byte(length-4) shl 2) or tagCopy1
|
||||
dst[i+1] = byte(offset)
|
||||
result = i + 2
|
||||
|
||||
when false:
|
||||
# extendMatch returns the largest k such that k <= len(src) and that
|
||||
# src[i:i+k-j] and src[j:k] have the same contents.
|
||||
#
|
||||
# It assumes that:
|
||||
# 0 <= i and i < j and j <= len(src)
|
||||
func extendMatch(src: openArray[byte], i, j: int): int =
|
||||
var
|
||||
i = i
|
||||
j = j
|
||||
while j < src.len and src[i] == src[j]:
|
||||
inc i
|
||||
inc j
|
||||
result = j
|
||||
|
||||
func hash(u, shift: uint32): uint32 =
|
||||
result = (u * 0x1e35a7bd) shr shift
|
||||
|
||||
# encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It
|
||||
# assumes that the varint-encoded length of the decompressed bytes has already
|
||||
# been written.
|
||||
#
|
||||
# It also assumes that:
|
||||
# len(dst) >= MaxEncodedLen(len(src)) and
|
||||
# minNonLiteralBlockSize <= len(src) and len(src) <= maxBlockSize
|
||||
func encodeBlock(dst, src: var openArray[byte]): int =
|
||||
# Initialize the hash table. Its size ranges from 1shl8 to 1shl14 inclusive.
|
||||
# The table element type is uint16, as s < sLimit and sLimit < len(src)
|
||||
# and len(src) <= maxBlockSize and maxBlockSize == 65536.
|
||||
const
|
||||
maxTableSize = 1 shl 14
|
||||
# tableMask is redundant, but helps the compiler eliminate bounds
|
||||
# checks.
|
||||
tableMask = maxTableSize - 1
|
||||
|
||||
var
|
||||
shift = 32 - 8
|
||||
tableSize = 1 shl 8
|
||||
|
||||
while tableSize < maxTableSize and tableSize < src.len:
|
||||
tableSize = tableSize * 2
|
||||
dec shift
|
||||
|
||||
# In Nim, all array elements are zero-initialized, so there is no advantage
|
||||
# to a smaller tableSize per se. However, it matches the C++ algorithm,
|
||||
# and in the asm versions of this code, we can get away with zeroing only
|
||||
# the first tableSize elements.
|
||||
var table: array[maxTableSize, uint16]
|
||||
|
||||
# sLimit is when to stop looking for offset/length copies. The inputMargin
|
||||
# lets us use a fast path for emitLiteral in the main loop, while we are
|
||||
# looking for copies.
|
||||
var sLimit = src.len - inputMargin
|
||||
# nextEmit is where in src the next emitLiteral should start from.
|
||||
var nextEmit = 0
|
||||
|
||||
# The encoded form must start with a literal, as there are no previous
|
||||
# bytes to copy, so we start looking for hash matches at s == 1.
|
||||
var s = 1
|
||||
var nextHash = hash(load32(src, s), shift.uint32)
|
||||
var d = 0
|
||||
|
||||
template emitRemainder(): untyped =
|
||||
if nextEmit < src.len:
|
||||
let litLen = emitLiteral(dst[d..^1], src[nextEmit..^1])
|
||||
inc(d, litLen)
|
||||
return d
|
||||
|
||||
while true:
|
||||
# Copied from the C++ snappy implementation:
|
||||
#
|
||||
# Heuristic match skipping: If 32 bytes are scanned with no matches
|
||||
# found, start looking only at every other byte. If 32 more bytes are
|
||||
# scanned (or skipped), look at every third byte, etc.. When a match
|
||||
# is found, immediately go back to looking at every byte. This is a
|
||||
# small loss (~5% performance, ~0.1% density) for compressible data
|
||||
# due to more bookkeeping, but for non-compressible data (such as
|
||||
# JPEG) it's a huge win since the compressor quickly "realizes" the
|
||||
# data is incompressible and doesn't bother looking for matches
|
||||
# everywhere.
|
||||
#
|
||||
# The "skip" variable keeps track of how many bytes there are since
|
||||
# the last match; dividing it by 32 (ie. right-shifting by five) gives
|
||||
# the number of bytes to move ahead for each iteration.
|
||||
var skip = 32
|
||||
|
||||
var nextS = s
|
||||
var candidate = 0
|
||||
while true:
|
||||
s = nextS
|
||||
let bytesBetweenHashLookups = skip shr 5
|
||||
nextS = s + bytesBetweenHashLookups
|
||||
inc(skip, bytesBetweenHashLookups)
|
||||
if nextS > sLimit:
|
||||
emitRemainder()
|
||||
|
||||
candidate = int(table[nextHash and tableMask])
|
||||
table[nextHash and tableMask] = uint16(s)
|
||||
nextHash = hash(load32(src, nextS), shift.uint32)
|
||||
if load32(src, s) == load32(src, candidate):
|
||||
break
|
||||
|
||||
# A 4-byte match has been found. We'll later see if more than 4 bytes
|
||||
# match. But, prior to the match, src[nextEmit:s] are unmatched. Emit
|
||||
# them as literal bytes.
|
||||
var litLen = emitLiteral(dst[d..^1], src[nextEmit..<s])
|
||||
inc(d, litLen)
|
||||
|
||||
# Call emitCopy, and then see if another emitCopy could be our next
|
||||
# move. Repeat until we find no match for the input immediately after
|
||||
# what was consumed by the last emitCopy call.
|
||||
#
|
||||
# If we exit this loop normally then we need to call emitLiteral next,
|
||||
# though we don't yet know how big the literal will be. We handle that
|
||||
# by proceeding to the next iteration of the main loop. We also can
|
||||
# exit this loop via goto if we get close to exhausting the input.
|
||||
while true:
|
||||
# Invariant: we have a 4-byte match at s, and no need to emit any
|
||||
# literal bytes prior to s.
|
||||
var base = s
|
||||
|
||||
# Extend the 4-byte match as long as possible.
|
||||
#
|
||||
# This is an inlined version of:
|
||||
# s = extendMatch(src, candidate+4, s+4)
|
||||
inc(s, 4)
|
||||
var i = candidate + 4
|
||||
while s < src.len and src[i] == src[s]:
|
||||
inc i
|
||||
inc s
|
||||
|
||||
litLen = emitCopy(dst[d..^1], base-candidate, s-base)
|
||||
inc(d, litLen)
|
||||
nextEmit = s
|
||||
if s >= sLimit:
|
||||
emitRemainder()
|
||||
|
||||
# We could immediately start working at s now, but to improve
|
||||
# compression we first update the hash table at s-1 and at s. If
|
||||
# another emitCopy is not our next move, also calculate nextHash
|
||||
# at s+1. At least on ARCH=amd64, these three hash calculations
|
||||
# are faster as one load64 call (with some shifts) instead of
|
||||
# three load32 calls.
|
||||
var x = load64(src, s-1)
|
||||
var prevHash = hash(uint32(x shr 0), shift.uint32)
|
||||
table[prevHash and tableMask] = uint16(s - 1)
|
||||
var currHash = hash(uint32(x shr 8), shift.uint32)
|
||||
candidate = int(table[currHash and tableMask])
|
||||
table[currHash and tableMask] = uint16(s)
|
||||
if uint32(x shr 8) != load32(src, candidate):
|
||||
nextHash = hash(uint32(x shr 16), shift.uint32)
|
||||
inc s
|
||||
break
|
||||
result = d
|
||||
|
||||
const
|
||||
decodeErrCodeCorrupt = 1
|
||||
decodeErrCodeUnsupportedLiteralLength = 2
|
||||
|
||||
func decode(dst, src: var openArray[byte]): int =
|
||||
var
|
||||
d = 0
|
||||
s = 0
|
||||
offset = 0
|
||||
length = 0
|
||||
|
||||
while s < src.len:
|
||||
let tag = src[s] and 0x03
|
||||
case tag
|
||||
of tagLiteral:
|
||||
var x = int(src[s]) shr 2
|
||||
if x < 60:
|
||||
inc s
|
||||
elif x == 60:
|
||||
inc(s, 2)
|
||||
if s > src.len:
|
||||
return decodeErrCodeCorrupt
|
||||
x = int(src[s-1])
|
||||
elif x == 61:
|
||||
inc(s, 3)
|
||||
if s > src.len:
|
||||
return decodeErrCodeCorrupt
|
||||
x = int(src[s-2]) or (int(src[s-1]) shl 8)
|
||||
elif x == 62:
|
||||
inc(s, 4)
|
||||
if s > src.len:
|
||||
return decodeErrCodeCorrupt
|
||||
x = int(src[s-3]) or (int(src[s-2]) shl 8) or (int(src[s-1]) shl 16)
|
||||
elif x == 63:
|
||||
inc(s, 5)
|
||||
if s > src.len:
|
||||
return decodeErrCodeCorrupt
|
||||
x = int(src[s-4]) or (int(src[s-3]) shl 8) or (int(src[s-2]) shl 16) or (int(src[s-1]) shl 24)
|
||||
length = x + 1
|
||||
if length <= 0:
|
||||
return decodeErrCodeUnsupportedLiteralLength
|
||||
|
||||
if (length > (dst.len-d)) or (length > (src.len-s)):
|
||||
return decodeErrCodeCorrupt
|
||||
|
||||
copyMem(dst[d].addr, src[s].addr, length)
|
||||
inc(d, length)
|
||||
inc(s, length)
|
||||
continue
|
||||
|
||||
of tagCopy1:
|
||||
inc(s, 2)
|
||||
if s > src.len:
|
||||
return decodeErrCodeCorrupt
|
||||
length = 4 + ((int(src[s-2]) shr 2) and 0x07)
|
||||
offset = ((int(src[s-2]) and 0xe0) shl 3) or int(src[s-1])
|
||||
|
||||
of tagCopy2:
|
||||
s += 3
|
||||
if s > src.len:
|
||||
return decodeErrCodeCorrupt
|
||||
length = 1 + (int(src[s-3]) shr 2)
|
||||
offset = int(src[s-2]) or (int(src[s-1]) shl 8)
|
||||
|
||||
of tagCopy4:
|
||||
s += 5
|
||||
if s > src.len:
|
||||
return decodeErrCodeCorrupt
|
||||
length = 1 + (int(src[s-5]) shr 2)
|
||||
offset = int(src[s-4]) or (int(src[s-3]) shl 8) or (int(src[s-2]) shl 16) or (int(src[s-1]) shl 24)
|
||||
|
||||
else: discard
|
||||
|
||||
if offset <= 0 or d < offset or (length > (dst.len-d)):
|
||||
return decodeErrCodeCorrupt
|
||||
|
||||
# Copy from an earlier sub-slice of dst to a later sub-slice. Unlike
|
||||
# the built-in copy function, this byte-by-byte copy always runs
|
||||
# forwards, even if the slices overlap. Conceptually, this is:
|
||||
#
|
||||
# d += forwardCopy(dst[d:d+length], dst[d-offset:])
|
||||
var stop = d + length
|
||||
while d != stop:
|
||||
dst[d] = dst[d-offset]
|
||||
inc d
|
||||
|
||||
if d != dst.len:
|
||||
return decodeErrCodeCorrupt
|
||||
return 0
|
||||
|
||||
# MaxEncodedLen returns the maximum length of a snappy block, given its
|
||||
# uncompressed length.
|
||||
#
|
||||
# It will return a zero value if srcLen is too large to encode.
|
||||
func maxEncodedLen(srcLen: int): int =
|
||||
var n = uint64(srcLen)
|
||||
if n > 0xffffffff'u64:
|
||||
return 0
|
||||
|
||||
# Compressed data can be defined as:
|
||||
# compressed := item* literal*
|
||||
# item := literal* copy
|
||||
#
|
||||
# The trailing literal sequence has a space blowup of at most 62/60
|
||||
# since a literal of length 60 needs one tag byte + one extra byte
|
||||
# for length information.
|
||||
#
|
||||
# Item blowup is trickier to measure. Suppose the "copy" op copies
|
||||
# 4 bytes of data. Because of a special check in the encoding code,
|
||||
# we produce a 4-byte copy only if the offset is < 65536. Therefore
|
||||
# the copy op takes 3 bytes to encode, and this type of item leads
|
||||
# to at most the 62/60 blowup for representing literals.
|
||||
#
|
||||
# Suppose the "copy" op copies 5 bytes of data. If the offset is big
|
||||
# enough, it will take 5 bytes to encode the copy op. Therefore the
|
||||
# worst case here is a one-byte literal followed by a five-byte copy.
|
||||
# That is, 6 bytes of input turn into 7 bytes of "compressed" data.
|
||||
#
|
||||
# This last factor dominates the blowup, so the final estimate is:
|
||||
n = 32'u64 + n + n div 6'u64
|
||||
if n > 0xffffffff'u64:
|
||||
return 0
|
||||
|
||||
result = int(n)
|
||||
|
||||
const
|
||||
maxBlockSize = 65536
|
||||
|
||||
# minNonLiteralBlockSize is the minimum size of the input to encodeBlock that
|
||||
# could be encoded with a copy tag. This is the minimum with respect to the
|
||||
# algorithm used by encodeBlock, not a minimum enforced by the file format.
|
||||
#
|
||||
# The encoded output must start with at least a 1 byte literal, as there are
|
||||
# no previous bytes to copy. A minimal (1 byte) copy after that, generated
|
||||
# from an emitCopy call in encodeBlock's main loop, would require at least
|
||||
# another inputMargin bytes, for the reason above: we want any emitLiteral
|
||||
# calls inside encodeBlock's main loop to use the fast path if possible, which
|
||||
# requires being able to overrun by inputMargin bytes. Thus,
|
||||
# minNonLiteralBlockSize equals 1 + 1 + inputMargin.
|
||||
#
|
||||
# The C++ code doesn't use this exact threshold, but it could, as discussed at
|
||||
# https:#groups.google.com/d/topic/snappy-compression/oGbhsdIJSJ8/discussion
|
||||
# The difference between Nim (2+inputMargin) and C++ (inputMargin) is purely an
|
||||
# optimization. It should not affect the encoded form. This is tested by
|
||||
# TestSameEncodingAsCppShortCopies.
|
||||
const
|
||||
minNonLiteralBlockSize = 1 + 1 + inputMargin
|
||||
|
||||
# Encode returns the encoded form of src. The returned slice may be a sub-
|
||||
# slice of dst if dst was large enough to hold the entire encoded block.
|
||||
# Otherwise, a newly allocated slice will be returned.
|
||||
#
|
||||
# The dst and src must not overlap. It is valid to pass a nil dst.
|
||||
proc encode*(src: openArray[byte]): seq[byte] =
|
||||
let n = maxEncodedLen(src.len)
|
||||
if n == 0: return
|
||||
var dst = newSeq[byte](n)
|
||||
|
||||
# The block starts with the varint-encoded length of the decompressed bytes.
|
||||
var
|
||||
p = 0
|
||||
d = putUVarInt(dst, uint64(src.len))
|
||||
len = src.len
|
||||
|
||||
while len > 0:
|
||||
var blockSize = len
|
||||
if blockSize > maxBlockSize:
|
||||
blockSize = maxBlockSize
|
||||
|
||||
if blockSize < minNonLiteralBlockSize:
|
||||
let litLen = emitLiteral(dst[d..^1], src[p..<p+blockSize])
|
||||
inc(d, litLen)
|
||||
else:
|
||||
let blockLen = encodeBlock(dst[d..^1], src[p..<p+blockSize])
|
||||
inc(d, blockLen)
|
||||
|
||||
inc(p, blockSize)
|
||||
dec(len, blockSize)
|
||||
|
||||
dst.setLen(d)
|
||||
shallowCopy(result, dst)
|
||||
|
||||
# decodedLen returns the length of the decoded block and the number of bytes
|
||||
# that the length header occupied.
|
||||
proc decode*(src: openArray[byte]): seq[byte] =
|
||||
let (len, bytesRead) = uvarint(src)
|
||||
if bytesRead <= 0 or len > 0xffffffff'u64:
|
||||
return
|
||||
|
||||
const wordSize = sizeof(uint) * 8
|
||||
if (wordSize == 32) and (len > 0x7fffffff'u64):
|
||||
return
|
||||
|
||||
if int(len) > 0:
|
||||
result = newSeq[byte](len)
|
||||
let errCode = decode(result, src[bytesRead..^1])
|
||||
if errCode != 0: result = @[]
|
|
@ -0,0 +1,12 @@
|
|||
packageName = "snappy"
|
||||
version = "0.1.0"
|
||||
author = "Andri Lim"
|
||||
description = "Nim implementation of snappy compression algorithm"
|
||||
license = "MIT"
|
||||
skipDirs = @["tests"]
|
||||
|
||||
requires: "nim >= 0.19.0"
|
||||
|
||||
task test, "Run all tests":
|
||||
exec "nim c tests/test"
|
||||
exec "nim c -d:release tests/test"
|
|
@ -0,0 +1 @@
|
|||
switch("path", "..")
|
|
@ -0,0 +1,23 @@
|
|||
Some of the benchmark data in in this directory is licensed thusly:
|
||||
|
||||
- fireworks.jpeg is Copyright 2013 Steinar H. Gunderson, and
|
||||
is licensed under the Creative Commons Attribution 3.0 license
|
||||
(CC-BY-3.0). See https://creativecommons.org/licenses/by/3.0/
|
||||
for more information.
|
||||
|
||||
- kppkn.gtb is taken from the Gaviota chess tablebase set, and
|
||||
is licensed under the MIT License. See
|
||||
https://sites.google.com/site/gaviotachessengine/Home/endgame-tablebases-1
|
||||
for more information.
|
||||
|
||||
- paper-100k.pdf is an excerpt (bytes 92160 to 194560) from the paper
|
||||
“Combinatorial Modeling of Chromatin Features Quantitatively Predicts DNA
|
||||
Replication Timing in _Drosophila_” by Federico Comoglio and Renato Paro,
|
||||
which is licensed under the CC-BY license. See
|
||||
http://www.ploscompbiol.org/static/license for more ifnormation.
|
||||
|
||||
- alice29.txt, asyoulik.txt, plrabn12.txt and lcet10.txt are from Project
|
||||
Gutenberg. The first three have expired copyrights and are in the public
|
||||
domain; the latter does not have expired copyright, but is still in the
|
||||
public domain according to the license information
|
||||
(http://www.gutenberg.org/ebooks/53).
|
|
@ -0,0 +1,396 @@
|
|||
Produced by David Widger. The previous edition was updated by Jose
|
||||
Menendez.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
THE ADVENTURES OF TOM SAWYER
|
||||
BY
|
||||
MARK TWAIN
|
||||
(Samuel Langhorne Clemens)
|
||||
|
||||
|
||||
|
||||
|
||||
P R E F A C E
|
||||
|
||||
MOST of the adventures recorded in this book really occurred; one or
|
||||
two were experiences of my own, the rest those of boys who were
|
||||
schoolmates of mine. Huck Finn is drawn from life; Tom Sawyer also, but
|
||||
not from an individual--he is a combination of the characteristics of
|
||||
three boys whom I knew, and therefore belongs to the composite order of
|
||||
architecture.
|
||||
|
||||
The odd superstitions touched upon were all prevalent among children
|
||||
and slaves in the West at the period of this story--that is to say,
|
||||
thirty or forty years ago.
|
||||
|
||||
Although my book is intended mainly for the entertainment of boys and
|
||||
girls, I hope it will not be shunned by men and women on that account,
|
||||
for part of my plan has been to try to pleasantly remind adults of what
|
||||
they once were themselves, and of how they felt and thought and talked,
|
||||
and what queer enterprises they sometimes engaged in.
|
||||
|
||||
THE AUTHOR.
|
||||
|
||||
HARTFORD, 1876.
|
||||
|
||||
|
||||
|
||||
T O M S A W Y E R
|
||||
|
||||
|
||||
|
||||
CHAPTER I
|
||||
|
||||
"TOM!"
|
||||
|
||||
No answer.
|
||||
|
||||
"TOM!"
|
||||
|
||||
No answer.
|
||||
|
||||
"What's gone with that boy, I wonder? You TOM!"
|
||||
|
||||
No answer.
|
||||
|
||||
The old lady pulled her spectacles down and looked over them about the
|
||||
room; then she put them up and looked out under them. She seldom or
|
||||
never looked THROUGH them for so small a thing as a boy; they were her
|
||||
state pair, the pride of her heart, and were built for "style," not
|
||||
service--she could have seen through a pair of stove-lids just as well.
|
||||
She looked perplexed for a moment, and then said, not fiercely, but
|
||||
still loud enough for the furniture to hear:
|
||||
|
||||
"Well, I lay if I get hold of you I'll--"
|
||||
|
||||
She did not finish, for by this time she was bending down and punching
|
||||
under the bed with the broom, and so she needed breath to punctuate the
|
||||
punches with. She resurrected nothing but the cat.
|
||||
|
||||
"I never did see the beat of that boy!"
|
||||
|
||||
She went to the open door and stood in it and looked out among the
|
||||
tomato vines and "jimpson" weeds that constituted the garden. No Tom.
|
||||
So she lifted up her voice at an angle calculated for distance and
|
||||
shouted:
|
||||
|
||||
"Y-o-u-u TOM!"
|
||||
|
||||
There was a slight noise behind her and she turned just in time to
|
||||
seize a small boy by the slack of his roundabout and arrest his flight.
|
||||
|
||||
"There! I might 'a' thought of that closet. What you been doing in
|
||||
there?"
|
||||
|
||||
"Nothing."
|
||||
|
||||
"Nothing! Look at your hands. And look at your mouth. What IS that
|
||||
truck?"
|
||||
|
||||
"I don't know, aunt."
|
||||
|
||||
"Well, I know. It's jam--that's what it is. Forty times I've said if
|
||||
you didn't let that jam alone I'd skin you. Hand me that switch."
|
||||
|
||||
The switch hovered in the air--the peril was desperate--
|
||||
|
||||
"My! Look behind you, aunt!"
|
||||
|
||||
The old lady whirled round, and snatched her skirts out of danger. The
|
||||
lad fled on the instant, scrambled up the high board-fence, and
|
||||
disappeared over it.
|
||||
|
||||
His aunt Polly stood surprised a moment, and then broke into a gentle
|
||||
laugh.
|
||||
|
||||
"Hang the boy, can't I never learn anything? Ain't he played me tricks
|
||||
enough like that for me to be looking out for him by this time? But old
|
||||
fools is the biggest fools there is. Can't learn an old dog new tricks,
|
||||
as the saying is. But my goodness, he never plays them alike, two days,
|
||||
and how is a body to know what's coming? He 'pears to know just how
|
||||
long he can torment me before I get my dander up, and he knows if he
|
||||
can make out to put me off for a minute or make me laugh, it's all down
|
||||
again and I can't hit him a lick. I ain't doing my duty by that boy,
|
||||
and that's the Lord's truth, goodness knows. Spare the rod and spile
|
||||
the child, as the Good Book says. I'm a laying up sin and suffering for
|
||||
us both, I know. He's full of the Old Scratch, but laws-a-me! he's my
|
||||
own dead sister's boy, poor thing, and I ain't got the heart to lash
|
||||
him, somehow. Every time I let him off, my conscience does hurt me so,
|
||||
and every time I hit him my old heart most breaks. Well-a-well, man
|
||||
that is born of woman is of few days and full of trouble, as the
|
||||
Scripture says, and I reckon it's so. He'll play hookey this evening, *
|
||||
and [* Southwestern for "afternoon"] I'll just be obleeged to make him
|
||||
work, to-morrow, to punish him. It's mighty hard to make him work
|
||||
Saturdays, when all the boys is having holiday, but he hates work more
|
||||
than he hates anything else, and I've GOT to do some of my duty by him,
|
||||
or I'll be the ruination of the child."
|
||||
|
||||
Tom did play hookey, and he had a very good time. He got back home
|
||||
barely in season to help Jim, the small colored boy, saw next-day's
|
||||
wood and split the kindlings before supper--at least he was there in
|
||||
time to tell his adventures to Jim while Jim did three-fourths of the
|
||||
work. Tom's younger brother (or rather half-brother) Sid was already
|
||||
through with his part of the work (picking up chips), for he was a
|
||||
quiet boy, and had no adventurous, troublesome ways.
|
||||
|
||||
While Tom was eating his supper, and stealing sugar as opportunity
|
||||
offered, Aunt Polly asked him questions that were full of guile, and
|
||||
very deep--for she wanted to trap him into damaging revealments. Like
|
||||
many other simple-hearted souls, it was her pet vanity to believe she
|
||||
was endowed with a talent for dark and mysterious diplomacy, and she
|
||||
loved to contemplate her most transparent devices as marvels of low
|
||||
cunning. Said she:
|
||||
|
||||
"Tom, it was middling warm in school, warn't it?"
|
||||
|
||||
"Yes'm."
|
||||
|
||||
"Powerful warm, warn't it?"
|
||||
|
||||
"Yes'm."
|
||||
|
||||
"Didn't you want to go in a-swimming, Tom?"
|
||||
|
||||
A bit of a scare shot through Tom--a touch of uncomfortable suspicion.
|
||||
He searched Aunt Polly's face, but it told him nothing. So he said:
|
||||
|
||||
"No'm--well, not very much."
|
||||
|
||||
The old lady reached out her hand and felt Tom's shirt, and said:
|
||||
|
||||
"But you ain't too warm now, though." And it flattered her to reflect
|
||||
that she had discovered that the shirt was dry without anybody knowing
|
||||
that that was what she had in her mind. But in spite of her, Tom knew
|
||||
where the wind lay, now. So he forestalled what might be the next move:
|
||||
|
||||
"Some of us pumped on our heads--mine's damp yet. See?"
|
||||
|
||||
Aunt Polly was vexed to think she had overlooked that bit of
|
||||
circumstantial evidence, and missed a trick. Then she had a new
|
||||
inspiration:
|
||||
|
||||
"Tom, you didn't have to undo your shirt collar where I sewed it, to
|
||||
pump on your head, did you? Unbutton your jacket!"
|
||||
|
||||
The trouble vanished out of Tom's face. He opened his jacket. His
|
||||
shirt collar was securely sewed.
|
||||
|
||||
"Bother! Well, go 'long with you. I'd made sure you'd played hookey
|
||||
and been a-swimming. But I forgive ye, Tom. I reckon you're a kind of a
|
||||
singed cat, as the saying is--better'n you look. THIS time."
|
||||
|
||||
She was half sorry her sagacity had miscarried, and half glad that Tom
|
||||
had stumbled into obedient conduct for once.
|
||||
|
||||
But Sidney said:
|
||||
|
||||
"Well, now, if I didn't think you sewed his collar with white thread,
|
||||
but it's black."
|
||||
|
||||
"Why, I did sew it with white! Tom!"
|
||||
|
||||
But Tom did not wait for the rest. As he went out at the door he said:
|
||||
|
||||
"Siddy, I'll lick you for that."
|
||||
|
||||
In a safe place Tom examined two large needles which were thrust into
|
||||
the lapels of his jacket, and had thread bound about them--one needle
|
||||
carried white thread and the other black. He said:
|
||||
|
||||
"She'd never noticed if it hadn't been for Sid. Confound it! sometimes
|
||||
she sews it with white, and sometimes she sews it with black. I wish to
|
||||
geeminy she'd stick to one or t'other--I can't keep the run of 'em. But
|
||||
I bet you I'll lam Sid for that. I'll learn him!"
|
||||
|
||||
He was not the Model Boy of the village. He knew the model boy very
|
||||
well though--and loathed him.
|
||||
|
||||
Within two minutes, or even less, he had forgotten all his troubles.
|
||||
Not because his troubles were one whit less heavy and bitter to him
|
||||
than a man's are to a man, but because a new and powerful interest bore
|
||||
them down and drove them out of his mind for the time--just as men's
|
||||
misfortunes are forgotten in the excitement of new enterprises. This
|
||||
new interest was a valued novelty in whistling, which he had just
|
||||
acquired from a negro, and he was suffering to practise it undisturbed.
|
||||
It consisted in a peculiar bird-like turn, a sort of liquid warble,
|
||||
produced by touching the tongue to the roof of the mouth at short
|
||||
intervals in the midst of the music--the reader probably remembers how
|
||||
to do it, if he has ever been a boy. Diligence and attention soon gave
|
||||
him the knack of it, and he strode down the street with his mouth full
|
||||
of harmony and his soul full of gratitude. He felt much as an
|
||||
astronomer feels who has discovered a new planet--no doubt, as far as
|
||||
strong, deep, unalloyed pleasure is concerned, the advantage was with
|
||||
the boy, not the astronomer.
|
||||
|
||||
The summer evenings were long. It was not dark, yet. Presently Tom
|
||||
checked his whistle. A stranger was before him--a boy a shade larger
|
||||
than himself. A new-comer of any age or either sex was an impressive
|
||||
curiosity in the poor little shabby village of St. Petersburg. This boy
|
||||
was well dressed, too--well dressed on a week-day. This was simply
|
||||
astounding. His cap was a dainty thing, his close-buttoned blue cloth
|
||||
roundabout was new and natty, and so were his pantaloons. He had shoes
|
||||
on--and it was only Friday. He even wore a necktie, a bright bit of
|
||||
ribbon. He had a citified air about him that ate into Tom's vitals. The
|
||||
more Tom stared at the splendid marvel, the higher he turned up his
|
||||
nose at his finery and the shabbier and shabbier his own outfit seemed
|
||||
to him to grow. Neither boy spoke. If one moved, the other moved--but
|
||||
only sidewise, in a circle; they kept face to face and eye to eye all
|
||||
the time. Finally Tom said:
|
||||
|
||||
"I can lick you!"
|
||||
|
||||
"I'd like to see you try it."
|
||||
|
||||
"Well, I can do it."
|
||||
|
||||
"No you can't, either."
|
||||
|
||||
"Yes I can."
|
||||
|
||||
"No you can't."
|
||||
|
||||
"I can."
|
||||
|
||||
"You can't."
|
||||
|
||||
"Can!"
|
||||
|
||||
"Can't!"
|
||||
|
||||
An uncomfortable pause. Then Tom said:
|
||||
|
||||
"What's your name?"
|
||||
|
||||
"'Tisn't any of your business, maybe."
|
||||
|
||||
"Well I 'low I'll MAKE it my business."
|
||||
|
||||
"Well why don't you?"
|
||||
|
||||
"If you say much, I will."
|
||||
|
||||
"Much--much--MUCH. There now."
|
||||
|
||||
"Oh, you think you're mighty smart, DON'T you? I could lick you with
|
||||
one hand tied behind me, if I wanted to."
|
||||
|
||||
"Well why don't you DO it? You SAY you can do it."
|
||||
|
||||
"Well I WILL, if you fool with me."
|
||||
|
||||
"Oh yes--I've seen whole families in the same fix."
|
||||
|
||||
"Smarty! You think you're SOME, now, DON'T you? Oh, what a hat!"
|
||||
|
||||
"You can lump that hat if you don't like it. I dare you to knock it
|
||||
off--and anybody that'll take a dare will suck eggs."
|
||||
|
||||
"You're a liar!"
|
||||
|
||||
"You're another."
|
||||
|
||||
"You're a fighting liar and dasn't take it up."
|
||||
|
||||
"Aw--take a walk!"
|
||||
|
||||
"Say--if you give me much more of your sass I'll take and bounce a
|
||||
rock off'n your head."
|
||||
|
||||
"Oh, of COURSE you will."
|
||||
|
||||
"Well I WILL."
|
||||
|
||||
"Well why don't you DO it then? What do you keep SAYING you will for?
|
||||
Why don't you DO it? It's because you're afraid."
|
||||
|
||||
"I AIN'T afraid."
|
||||
|
||||
"You are."
|
||||
|
||||
"I ain't."
|
||||
|
||||
"You are."
|
||||
|
||||
Another pause, and more eying and sidling around each other. Presently
|
||||
they were shoulder to shoulder. Tom said:
|
||||
|
||||
"Get away from here!"
|
||||
|
||||
"Go away yourself!"
|
||||
|
||||
"I won't."
|
||||
|
||||
"I won't either."
|
||||
|
||||
So they stood, each with a foot placed at an angle as a brace, and
|
||||
both shoving with might and main, and glowering at each other with
|
||||
hate. But neither could get an advantage. After struggling till both
|
||||
were hot and flushed, each relaxed his strain with watchful caution,
|
||||
and Tom said:
|
||||
|
||||
"You're a coward and a pup. I'll tell my big brother on you, and he
|
||||
can thrash you with his little finger, and I'll make him do it, too."
|
||||
|
||||
"What do I care for your big brother? I've got a brother that's bigger
|
||||
than he is--and what's more, he can throw him over that fence, too."
|
||||
[Both brothers were imaginary.]
|
||||
|
||||
"That's a lie."
|
||||
|
||||
"YOUR saying so don't make it so."
|
||||
|
||||
Tom drew a line in the dust with his big toe, and said:
|
||||
|
||||
"I dare you to step over that, and I'll lick you till you can't stand
|
||||
up. Anybody that'll take a dare will steal sheep."
|
||||
|
||||
The new boy stepped over promptly, and said:
|
||||
|
||||
"Now you said you'd do it, now let's see you do it."
|
||||
|
||||
"Don't you crowd me now; you better look out."
|
||||
|
||||
"Well, you SAID you'd do it--why don't you do it?"
|
||||
|
||||
"By jingo! for two cents I WILL do it."
|
||||
|
||||
The new boy took two broad coppers out of his pocket and held them out
|
||||
with derision. Tom struck them to the ground. In an instant both boys
|
||||
were rolling and tumbling in the dirt, gripped together like cats; and
|
||||
for the space of a minute they tugged and tore at each other's hair and
|
||||
clothes, punched and scratched each other's nose, and covered
|
||||
themselves with dust and glory. Presently the confusion took form, and
|
||||
through the fog of battle Tom appeared, seated astride the new boy, and
|
||||
pounding him with his fists. "Holler 'nuff!" said he.
|
||||
|
||||
The boy only struggled to free himself. He was crying--mainly from rage.
|
||||
|
||||
"Holler 'nuff!"--and the pounding went on.
|
||||
|
||||
At last the stranger got out a smothered "'Nuff!" and Tom let him up
|
||||
and said:
|
||||
|
||||
"Now that'll learn you. Better look out who you're fooling with next
|
||||
time."
|
||||
|
||||
The new boy went off brushing the dust from his clothes, sobbing,
|
||||
snuffling, and occasionally looking back and shaking his head and
|
||||
threatening what he would do to Tom the "next time he caught him out."
|
||||
To which Tom responded with jeers, and started off in high feather, and
|
||||
as soon as his back was turned the new boy snatched up a stone, threw
|
||||
it and hit him between the shoulders and then turned tail and ran like
|
||||
an antelope. Tom chased the traitor home, and thus found out where he
|
||||
lived. He then held a position at the gate for some time, daring the
|
||||
enemy to come outside, but the enemy only made faces at him through the
|
||||
window and declined. At last the enemy's mother appeared, and called
|
||||
Tom a bad, vicious, vulgar child, and ordered him away. So he went
|
||||
away; but he said he "'lowed" to "lay" for that boy.
|
||||
|
||||
He got home pretty late that night, and when he climbed cautiously in
|
||||
at the window, he uncovered an ambuscade, in the person of his aunt;
|
||||
and when she saw the state his clothes were in her resolution to turn
|
||||
his Saturday holiday into captivity at hard labor became adamantine in
|
||||
its firmness.
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 120 KiB |
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,598 @@
|
|||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=10 M=100 Y=50 K=0</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>10.000002</xmpG:cyan>
|
||||
<xmpG:magenta>100.000000</xmpG:magenta>
|
||||
<xmpG:yellow>50.000000</xmpG:yellow>
|
||||
<xmpG:black>0.000000</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=0 M=95 Y=20 K=0</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>0.000000</xmpG:cyan>
|
||||
<xmpG:magenta>94.999999</xmpG:magenta>
|
||||
<xmpG:yellow>19.999999</xmpG:yellow>
|
||||
<xmpG:black>0.000000</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=25 M=25 Y=40 K=0</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>25.000000</xmpG:cyan>
|
||||
<xmpG:magenta>25.000000</xmpG:magenta>
|
||||
<xmpG:yellow>39.999998</xmpG:yellow>
|
||||
<xmpG:black>0.000000</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=40 M=45 Y=50 K=5</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>39.999998</xmpG:cyan>
|
||||
<xmpG:magenta>44.999999</xmpG:magenta>
|
||||
<xmpG:yellow>50.000000</xmpG:yellow>
|
||||
<xmpG:black>5.000001</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=50 M=50 Y=60 K=25</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>50.000000</xmpG:cyan>
|
||||
<xmpG:magenta>50.000000</xmpG:magenta>
|
||||
<xmpG:yellow>60.000002</xmpG:yellow>
|
||||
<xmpG:black>25.000000</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=55 M=60 Y=65 K=40</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>55.000001</xmpG:cyan>
|
||||
<xmpG:magenta>60.000002</xmpG:magenta>
|
||||
<xmpG:yellow>64.999998</xmpG:yellow>
|
||||
<xmpG:black>39.999998</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=25 M=40 Y=65 K=0</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>25.000000</xmpG:cyan>
|
||||
<xmpG:magenta>39.999998</xmpG:magenta>
|
||||
<xmpG:yellow>64.999998</xmpG:yellow>
|
||||
<xmpG:black>0.000000</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=30 M=50 Y=75 K=10</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>30.000001</xmpG:cyan>
|
||||
<xmpG:magenta>50.000000</xmpG:magenta>
|
||||
<xmpG:yellow>75.000000</xmpG:yellow>
|
||||
<xmpG:black>10.000002</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=35 M=60 Y=80 K=25</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>35.000002</xmpG:cyan>
|
||||
<xmpG:magenta>60.000002</xmpG:magenta>
|
||||
<xmpG:yellow>80.000001</xmpG:yellow>
|
||||
<xmpG:black>25.000000</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=40 M=65 Y=90 K=35</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>39.999998</xmpG:cyan>
|
||||
<xmpG:magenta>64.999998</xmpG:magenta>
|
||||
<xmpG:yellow>90.000004</xmpG:yellow>
|
||||
<xmpG:black>35.000002</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=40 M=70 Y=100 K=50</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>39.999998</xmpG:cyan>
|
||||
<xmpG:magenta>69.999999</xmpG:magenta>
|
||||
<xmpG:yellow>100.000000</xmpG:yellow>
|
||||
<xmpG:black>50.000000</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=50 M=70 Y=80 K=70</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>50.000000</xmpG:cyan>
|
||||
<xmpG:magenta>69.999999</xmpG:magenta>
|
||||
<xmpG:yellow>80.000001</xmpG:yellow>
|
||||
<xmpG:black>69.999999</xmpG:black>
|
||||
</rdf:li>
|
||||
</rdf:Seq>
|
||||
</xmpG:Colorants>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:groupName>Grays</xmpG:groupName>
|
||||
<xmpG:groupType>1</xmpG:groupType>
|
||||
<xmpG:Colorants>
|
||||
<rdf:Seq>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=0 M=0 Y=0 K=100</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>0.000000</xmpG:cyan>
|
||||
<xmpG:magenta>0.000000</xmpG:magenta>
|
||||
<xmpG:yellow>0.000000</xmpG:yellow>
|
||||
<xmpG:black>100.000000</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=0 M=0 Y=0 K=90</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>0.000000</xmpG:cyan>
|
||||
<xmpG:magenta>0.000000</xmpG:magenta>
|
||||
<xmpG:yellow>0.000000</xmpG:yellow>
|
||||
<xmpG:black>89.999402</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=0 M=0 Y=0 K=80</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>0.000000</xmpG:cyan>
|
||||
<xmpG:magenta>0.000000</xmpG:magenta>
|
||||
<xmpG:yellow>0.000000</xmpG:yellow>
|
||||
<xmpG:black>79.998797</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=0 M=0 Y=0 K=70</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>0.000000</xmpG:cyan>
|
||||
<xmpG:magenta>0.000000</xmpG:magenta>
|
||||
<xmpG:yellow>0.000000</xmpG:yellow>
|
||||
<xmpG:black>69.999701</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=0 M=0 Y=0 K=60</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>0.000000</xmpG:cyan>
|
||||
<xmpG:magenta>0.000000</xmpG:magenta>
|
||||
<xmpG:yellow>0.000000</xmpG:yellow>
|
||||
<xmpG:black>59.999102</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=0 M=0 Y=0 K=50</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>0.000000</xmpG:cyan>
|
||||
<xmpG:magenta>0.000000</xmpG:magenta>
|
||||
<xmpG:yellow>0.000000</xmpG:yellow>
|
||||
<xmpG:black>50.000000</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=0 M=0 Y=0 K=40</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>0.000000</xmpG:cyan>
|
||||
<xmpG:magenta>0.000000</xmpG:magenta>
|
||||
<xmpG:yellow>0.000000</xmpG:yellow>
|
||||
<xmpG:black>39.999402</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=0 M=0 Y=0 K=30</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>0.000000</xmpG:cyan>
|
||||
<xmpG:magenta>0.000000</xmpG:magenta>
|
||||
<xmpG:yellow>0.000000</xmpG:yellow>
|
||||
<xmpG:black>29.998803</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=0 M=0 Y=0 K=20</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>0.000000</xmpG:cyan>
|
||||
<xmpG:magenta>0.000000</xmpG:magenta>
|
||||
<xmpG:yellow>0.000000</xmpG:yellow>
|
||||
<xmpG:black>19.999701</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=0 M=0 Y=0 K=10</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>0.000000</xmpG:cyan>
|
||||
<xmpG:magenta>0.000000</xmpG:magenta>
|
||||
<xmpG:yellow>0.000000</xmpG:yellow>
|
||||
<xmpG:black>9.999102</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=0 M=0 Y=0 K=5</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>0.000000</xmpG:cyan>
|
||||
<xmpG:magenta>0.000000</xmpG:magenta>
|
||||
<xmpG:yellow>0.000000</xmpG:yellow>
|
||||
<xmpG:black>4.998803</xmpG:black>
|
||||
</rdf:li>
|
||||
</rdf:Seq>
|
||||
</xmpG:Colorants>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:groupName>Brights</xmpG:groupName>
|
||||
<xmpG:groupType>1</xmpG:groupType>
|
||||
<xmpG:Colorants>
|
||||
<rdf:Seq>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=0 M=100 Y=100 K=0</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>0.000000</xmpG:cyan>
|
||||
<xmpG:magenta>100.000000</xmpG:magenta>
|
||||
<xmpG:yellow>100.000000</xmpG:yellow>
|
||||
<xmpG:black>0.000000</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=0 M=75 Y=100 K=0</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>0.000000</xmpG:cyan>
|
||||
<xmpG:magenta>75.000000</xmpG:magenta>
|
||||
<xmpG:yellow>100.000000</xmpG:yellow>
|
||||
<xmpG:black>0.000000</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=0 M=10 Y=95 K=0</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>0.000000</xmpG:cyan>
|
||||
<xmpG:magenta>10.000002</xmpG:magenta>
|
||||
<xmpG:yellow>94.999999</xmpG:yellow>
|
||||
<xmpG:black>0.000000</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=85 M=10 Y=100 K=0</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>84.999996</xmpG:cyan>
|
||||
<xmpG:magenta>10.000002</xmpG:magenta>
|
||||
<xmpG:yellow>100.000000</xmpG:yellow>
|
||||
<xmpG:black>0.000000</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=100 M=90 Y=0 K=0</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>100.000000</xmpG:cyan>
|
||||
<xmpG:magenta>90.000004</xmpG:magenta>
|
||||
<xmpG:yellow>0.000000</xmpG:yellow>
|
||||
<xmpG:black>0.000000</xmpG:black>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:swatchName>C=60 M=90 Y=0 K=0</xmpG:swatchName>
|
||||
<xmpG:mode>CMYK</xmpG:mode>
|
||||
<xmpG:type>PROCESS</xmpG:type>
|
||||
<xmpG:cyan>60.000002</xmpG:cyan>
|
||||
<xmpG:magenta>90.000004</xmpG:magenta>
|
||||
<xmpG:yellow>0.003099</xmpG:yellow>
|
||||
<xmpG:black>0.003099</xmpG:black>
|
||||
</rdf:li>
|
||||
</rdf:Seq>
|
||||
</xmpG:Colorants>
|
||||
</rdf:li>
|
||||
</rdf:Seq>
|
||||
</xmpTPg:SwatchGroups>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
|
||||
<pdf:Producer>Adobe PDF library 9.00</pdf:Producer>
|
||||
</rdf:Description>
|
||||
</rdf:RDF>
|
||||
</x:xmpmeta>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<?xpacket end="w"?>
|
||||
endstream
endobj
145 0 obj<</Metadata 144 0 R>>
endobj
1 0 obj<</Contents 3 0 R/Type/Page/Parent 102 0 R/Rotate 0/MediaBox[0 0 612.28302 790.866028]/CropBox[0 0 612.28302 790.866028]/Resources 2 0 R>>
endobj
2 0 obj<</ColorSpace<</Cs8 117 0 R>>/Font<</F2 122 0 R/F3 121 0 R/F6 118 0 R/F7 125 0 R/F8 56 0 R/F9 70 0 R/F10 71 0 R/F11 61 0 R/F12 65 0 R/F13 72 0 R>>/ProcSet[/PDF/Text]/ExtGState<</GS1 113 0 R>>>>
endobj
3 0 obj<</Length 8934/Filter/FlateDecode>>stream
|
||||
hÞ”[MsÜF’½ëWðn<>m |