1920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell/**************************************
2920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell * Compiler Options
3920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell **************************************/
4920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell#ifdef _MSC_VER    /* Visual Studio */
5920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell#  define _CRT_SECURE_NO_WARNINGS // for MSVC
6920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell#  define snprintf sprintf_s
7920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell#endif
8920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell#ifdef __GNUC__
9920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell#  pragma GCC diagnostic ignored "-Wmissing-braces"   /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
10920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell#endif
11920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell
12920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell
13920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell/**************************************
14920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell * Includes
15920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell **************************************/
16920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell#include <stdio.h>
17920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell#include <stdint.h>
18920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell#include <stdlib.h>
19920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell#include <string.h>
20920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell#include "lz4.h"
21920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell
22920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell
23920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell/* Returns non-zero on failure. */
24920bf21714f99cc20d3b8bcc28060136a390354aNick Terrellint test_compress(const char *input, int inSize, char *output, int outSize)
25920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell{
26920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    LZ4_stream_t lz4Stream_body = { 0 };
27920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    LZ4_stream_t* lz4Stream = &lz4Stream_body;
28920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell
29920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    int inOffset = 0;
30920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    int outOffset = 0;
31920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell
32920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    if (inSize & 3) return -1;
33920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell
34920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    while (inOffset < inSize) {
35920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        const int length = inSize >> 2;
36920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        if (inSize > 1024) return -2;
37920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        if (outSize - (outOffset + 8) < LZ4_compressBound(length)) return -3;
38920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        {
393580d9698098e8ad2ef757d1c3673aceca38c576Yann Collet            const int outBytes = LZ4_compress_fast_continue(
403580d9698098e8ad2ef757d1c3673aceca38c576Yann Collet                lz4Stream, input + inOffset, output + outOffset + 8, length, outSize-outOffset, 1);
41920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell            if(outBytes <= 0) return -4;
42920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell            memcpy(output + outOffset, &length, 4); /* input length */
43920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell            memcpy(output + outOffset + 4, &outBytes, 4); /* output length */
44920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell            inOffset += length;
45920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell            outOffset += outBytes + 8;
46920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        }
47920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    }
48920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    if (outOffset + 8 > outSize) return -5;
49920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    memset(output + outOffset, 0, 4);
50920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    memset(output + outOffset + 4, 0, 4);
51920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    return 0;
52920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell}
53920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell
54920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell/* Returns non-zero on failure. Not a safe function. */
55920bf21714f99cc20d3b8bcc28060136a390354aNick Terrellint test_decompress(const char *uncompressed, const char *compressed)
56920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell{
57920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    char outBufferA[1024];
58920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    char spacing; /* So prefixEnd != dest */
59920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    char outBufferB[1024];
60920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    char *output = outBufferA;
61920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    char *lastOutput = outBufferB;
62920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    LZ4_streamDecode_t lz4StreamDecode_body = { 0 };
63920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    LZ4_streamDecode_t* lz4StreamDecode = &lz4StreamDecode_body;
64920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    int offset = 0;
65920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    int unOffset = 0;
66920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    int lastBytes = 0;
67920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell
68920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    (void)spacing;
69920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell
70920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    for(;;) {
71920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        int32_t bytes;
72920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        int32_t unBytes;
73920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        /* Read uncompressed size and compressed size */
74920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        memcpy(&unBytes, compressed + offset, 4);
75920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        memcpy(&bytes, compressed + offset + 4, 4);
76920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        offset += 8;
77920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        /* Check if we reached end of stream or error */
78920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        if(bytes == 0 && unBytes == 0) return 0;
79920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        if(bytes <= 0 || unBytes <= 0 || unBytes > 1024) return 1;
80920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell
81920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        /* Put the last output in the dictionary */
82920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        LZ4_setStreamDecode(lz4StreamDecode, lastOutput, lastBytes);
83920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        /* Decompress */
84920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        bytes = LZ4_decompress_fast_continue(
85920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell            lz4StreamDecode, compressed + offset, output, unBytes);
86920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        if(bytes <= 0) return 2;
87920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        /* Check result */
883f6f57768752a5687c2715ad4a7cd4ebfa502bc2Yann Collet        {   int const r = memcmp(uncompressed + unOffset, output, unBytes);
89920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell            if (r) return 3;
90920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        }
913f6f57768752a5687c2715ad4a7cd4ebfa502bc2Yann Collet        { char* const tmp = output; output = lastOutput; lastOutput = tmp; }
92920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        offset += bytes;
93920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        unOffset += unBytes;
94920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        lastBytes = unBytes;
95920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    }
96920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell}
97920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell
98920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell
99920bf21714f99cc20d3b8bcc28060136a390354aNick Terrellint main(int argc, char **argv)
100920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell{
101920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    char input[] =
102920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        "Hello Hello Hello Hello Hello Hello Hello Hello!"
103920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        "Hello Hello Hello Hello Hello Hello Hello Hello!"
104920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        "Hello Hello Hello Hello Hello Hello Hello Hello!"
105920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        "Hello Hello Hello Hello Hello Hello Hello Hello!"
106920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        "Hello Hello Hello Hello Hello Hello Hello Hello!"
107920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        "Hello Hello Hello Hello Hello Hello Hello Hello!"
108920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        "Hello Hello Hello Hello Hello Hello Hello Hello!"
109920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        "Hello Hello Hello Hello Hello Hello Hello Hello!"
110920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        "Hello Hello Hello Hello Hello Hello Hello Hello!"
111920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        "Hello Hello Hello Hello Hello Hello Hello Hello!"
112920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        "Hello Hello Hello Hello Hello Hello Hello Hello!"
113920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        "Hello Hello Hello Hello Hello Hello Hello Hello!"
114920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        "Hello Hello Hello Hello Hello Hello Hello Hello!"
115920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        "Hello Hello Hello Hello Hello Hello Hello Hello!"
116920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        "Hello Hello Hello Hello Hello Hello Hello Hello!"
117920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        "Hello Hello Hello Hello Hello Hello Hello Hello";
118920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    char output[LZ4_COMPRESSBOUND(4096)];
119920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    int r;
120920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell
121920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    (void)argc;
122920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    (void)argv;
123920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell
124920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    if ((r = test_compress(input, sizeof(input), output, sizeof(output)))) {
125920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        return r;
126920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    }
127920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    if ((r = test_decompress(input, output))) {
128920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell        return r;
129920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    }
130920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell    return 0;
131920bf21714f99cc20d3b8bcc28060136a390354aNick Terrell}
132