Переглянути джерело

Add a snappytool command that uses the C++ library.

The pi.txt.rawsnappy file was generated by this tool, on an amd64
(little-endian) system.
Nigel Tao 9 роки тому
батько
коміт
343d0f4579
5 змінених файлів з 110 додано та 14 видалено
  1. 1 0
      .gitignore
  2. 74 0
      cmd/snappytool/main.cpp
  3. 35 14
      snappy_test.go
  4. 0 0
      testdata/pi.txt
  5. BIN
      testdata/pi.txt.rawsnappy

+ 1 - 0
.gitignore

@@ -1,3 +1,4 @@
+cmd/snappytool/snappytool
 testdata/bench
 
 # These explicitly listed benchmark data files are for an obsolete version of

+ 74 - 0
cmd/snappytool/main.cpp

@@ -0,0 +1,74 @@
+/*
+To build the snappytool binary:
+g++ main.cpp /usr/lib/libsnappy.a -o snappytool
+*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "snappy.h"
+
+#define N 1000000
+
+char dst[N];
+char src[N];
+
+int main(int argc, char** argv) {
+  // Parse args.
+  if (argc != 2) {
+    fprintf(stderr, "exactly one of -d or -e must be given\n");
+    return 1;
+  }
+  bool decode = strcmp(argv[1], "-d") == 0;
+  bool encode = strcmp(argv[1], "-e") == 0;
+  if (decode == encode) {
+    fprintf(stderr, "exactly one of -d or -e must be given\n");
+    return 1;
+  }
+
+  // Read all of stdin into src[:s].
+  size_t s = 0;
+  while (1) {
+    if (s == N) {
+      fprintf(stderr, "input too large\n");
+      return 1;
+    }
+    ssize_t n = read(0, src+s, N-s);
+    if (n == 0) {
+      break;
+    }
+    if (n < 0) {
+      fprintf(stderr, "read error: %s\n", strerror(errno));
+      // TODO: handle EAGAIN, EINTR?
+      return 1;
+    }
+    s += n;
+  }
+
+  // Encode or decode src[:s] to dst[:d], and write to stdout.
+  size_t d = 0;
+  if (encode) {
+    if (N < snappy::MaxCompressedLength(s)) {
+      fprintf(stderr, "input too large after encoding\n");
+      return 1;
+    }
+    snappy::RawCompress(src, s, dst, &d);
+  } else {
+    if (!snappy::GetUncompressedLength(src, s, &d)) {
+      fprintf(stderr, "could not get uncompressed length\n");
+      return 1;
+    }
+    if (N < d) {
+      fprintf(stderr, "input too large after decoding\n");
+      return 1;
+    }
+    if (!snappy::RawUncompress(src, s, dst)) {
+      fprintf(stderr, "input was not valid Snappy-compressed data\n");
+      return 1;
+    }
+  }
+  write(1, dst, d);
+  return 0;
+}

+ 35 - 14
snappy_test.go

@@ -29,13 +29,28 @@ func TestMaxEncodedLenOfMaxBlockSize(t *testing.T) {
 	}
 }
 
+func cmp(a, b []byte) error {
+	if bytes.Equal(a, b) {
+		return nil
+	}
+	if len(a) != len(b) {
+		return fmt.Errorf("got %d bytes, want %d", len(a), len(b))
+	}
+	for i := range a {
+		if a[i] != b[i] {
+			return fmt.Errorf("byte #%d: got 0x%02x, want 0x%02x", i, a[i], b[i])
+		}
+	}
+	return nil
+}
+
 func roundtrip(b, ebuf, dbuf []byte) error {
 	d, err := Decode(dbuf, Encode(ebuf, b))
 	if err != nil {
 		return fmt.Errorf("decoding error: %v", err)
 	}
-	if !bytes.Equal(b, d) {
-		return fmt.Errorf("roundtrip mismatch:\n\twant %v\n\tgot  %v", b, d)
+	if err := cmp(d, b); err != nil {
+		return fmt.Errorf("roundtrip mismatch: %v", err)
 	}
 	return nil
 }
@@ -327,6 +342,24 @@ func TestDecodeLengthOffset(t *testing.T) {
 	}
 }
 
+func TestDecodeGoldenInput(t *testing.T) {
+	src, err := ioutil.ReadFile("testdata/pi.txt.rawsnappy")
+	if err != nil {
+		t.Fatalf("ReadFile: %v", err)
+	}
+	got, err := Decode(nil, src)
+	if err != nil {
+		t.Fatalf("Decode: %v", err)
+	}
+	want, err := ioutil.ReadFile("testdata/pi.txt")
+	if err != nil {
+		t.Fatalf("ReadFile: %v", err)
+	}
+	if err := cmp(got, want); err != nil {
+		t.Fatal(err)
+	}
+}
+
 // TestEncodeNoiseThenRepeats encodes input for which the first half is very
 // incompressible and the second half is very compressible. The encoded form's
 // length should be closer to 50% of the original length than 100%.
@@ -348,18 +381,6 @@ func TestEncodeNoiseThenRepeats(t *testing.T) {
 	}
 }
 
-func cmp(a, b []byte) error {
-	if len(a) != len(b) {
-		return fmt.Errorf("got %d bytes, want %d", len(a), len(b))
-	}
-	for i := range a {
-		if a[i] != b[i] {
-			return fmt.Errorf("byte #%d: got 0x%02x, want 0x%02x", i, a[i], b[i])
-		}
-	}
-	return nil
-}
-
 func TestFramingFormat(t *testing.T) {
 	// src is comprised of alternating 1e5-sized sequences of random
 	// (incompressible) bytes and repeated (compressible) bytes. 1e5 was chosen

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
testdata/pi.txt


BIN
testdata/pi.txt.rawsnappy


Деякі файли не було показано, через те що забагато файлів було змінено