/*******************************************************************************
* Copyright 2017-2018 Intel Corporation.
*
* This software and the related documents are Intel copyrighted  materials,  and
* your use of  them is  governed by the  express license  under which  they were
* provided to you (License).  Unless the License provides otherwise, you may not
* use, modify, copy, publish, distribute,  disclose or transmit this software or
* the related documents without Intel's prior written permission.
*
* This software and the related documents  are provided as  is,  with no express
* or implied  warranties,  other  than those  that are  expressly stated  in the
* License.
*******************************************************************************/

/*
 The example below shows how to use the functions:
        ippsEncodeLZOGetSize
        ippsEncodeLZO_8u
        ippsEncodeLZOInit_8u
        ippsDecodeLZO_8u
        ippsDecodeLZOSafe_8u
*/

#include <stdio.h>
#include <string.h>

#include <ippdc.h>      /* Data compression functions       */
#include <ipps.h>       /* Malloc/vector initialization function   */

/* Next two defines are created to simplify code reading and understanding          */
#define EXIT_MAIN       exitLine:                              /* Label for Exit    */
#define check_sts(st)   if((st) != ippStsNoErr) goto exitLine; /* Go to Exit if Intel(R) Integrated Primitives (Intel(R) IPP) function returned status different from ippStsNoErr */

#define TEST_SIZE (1024 * 4)
#define DECOMPR_MAX (TEST_SIZE + 64)

int main(void)
{
    Ipp8u           *srcBuf = NULL, *comprBuf = NULL, *decomprBuf = NULL;
    IppStatus       st;
    int             i;
    Ipp32u          stateSize;
    IppLZOState_8u  *lzoState = NULL;
    Ipp32u          comprLen, decomprLen;

    /* Allocate buffers */
    srcBuf      = ippsMalloc_8u(TEST_SIZE);
    decomprBuf  = ippsMalloc_8u(DECOMPR_MAX);    /* Extra 64 bytes may be required
                                                       for non-safe decompression       */
    comprBuf    = ippsMalloc_8u(TEST_SIZE + TEST_SIZE/10);
    /* Initialize source buffer */
    check_sts(  st = ippsVectorJaehne_8u(srcBuf, TEST_SIZE, IPP_MAX_8U)         )
    for(i = 0; i < TEST_SIZE; i++)
        srcBuf[i] >>= 6;                                /* Decrease source data entropy */
    /* Allocate and initialize LZO structure */
    check_sts(  st = ippsEncodeLZOGetSize(IppLZO1XST, TEST_SIZE, &stateSize)    )
    lzoState = (IppLZOState_8u*)ippsMalloc_8u(stateSize);
    check_sts(  st = ippsEncodeLZOInit_8u(IppLZO1XST, TEST_SIZE, lzoState)      )
    /* LZO compress, decompress and compare */
    comprLen = (TEST_SIZE + TEST_SIZE/10);
    check_sts(  st = ippsEncodeLZO_8u(srcBuf, TEST_SIZE, comprBuf, &comprLen, lzoState)   )
    printf("LZO compress: %d bytes compressed into %d bytes\n", TEST_SIZE, (int)comprLen);
    decomprLen = DECOMPR_MAX;
    check_sts(  st = ippsDecodeLZO_8u(comprBuf, comprLen, decomprBuf, &decomprLen)    )
    if(decomprLen != TEST_SIZE || memcmp(decomprBuf, srcBuf, TEST_SIZE) != 0)
    {
        printf("Non-safe decompress failed!\n");
        st = ippStsErr;
        goto exitLine;
    }
    else
        printf("Non-safe decompress verified.\n");
    /* Decompress using safe function */
    ippsZero_8u(decomprBuf, DECOMPR_MAX);
    decomprLen = TEST_SIZE;                         /* Can specify exact size */
    check_sts(  st = ippsDecodeLZOSafe_8u(comprBuf, comprLen, decomprBuf, &decomprLen)  )
    if(decomprLen != TEST_SIZE || memcmp(decomprBuf, srcBuf, TEST_SIZE) != 0)
    {
        printf("Safe decompress failed!\n");
        st = ippStsErr;
        goto exitLine;
    }
    else
        printf("Safe decompress verified.\n");

EXIT_MAIN
    ippsFree(srcBuf);
    ippsFree(decomprBuf);
    ippsFree(comprBuf);
    ippsFree(lzoState);
    return (int)st;
}