coreboot-v2/util/cbfstool/lzma/minilzma.cc
<<
>>
Prefs
   1/*
   2 * minimal lzma implementation
   3 *
   4 * Copyright (C) 2002 Eric Biederman
   5 * Copyright (C) 2005 Joel Yliluoma
   6 * Copyright (C) 2007 coresystems GmbH
   7 * (Adapted by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH)
   8 * Copyright (C) 2007 Patrick Georgi <patrick@georgi-clan.de>
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License as published by
  12 * the Free Software Foundation; either version 2 of the License, or
  13 * (at your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU General Public License for more details.
  19 *
  20 * You should have received a copy of the GNU General Public License
  21 * along with this program; if not, write to the Free Software
  22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
  23 */
  24
  25#include "C/Common/MyInitGuid.h"
  26#include "C/7zip/Compress/LZMA/LZMAEncoder.h"
  27
  28#include <sys/types.h>
  29#include <sys/stat.h>
  30#include <unistd.h>
  31#include <errno.h>
  32#include <cstring>
  33#include <cstdio>
  34#include <cstdlib>
  35#include <cctype>
  36
  37#include <vector>
  38#include <algorithm>
  39#include <stdint.h>
  40
  41const std::vector<unsigned char> LZMACompress
  42    (const std::vector<unsigned char>& buf);
  43
  44const std::vector<unsigned char> LZMADeCompress
  45    (const std::vector<unsigned char>& buf);
  46
  47static inline uint16_t R16(const void* p)
  48{
  49    const unsigned char* data = (const unsigned char*)p;
  50    return (data[0] << 0)  | (data[1] << 8);
  51}
  52static inline uint32_t R32(const void* p)
  53{
  54    const unsigned char* data = (const unsigned char*)p;
  55    return R16(data) | (R16(data+2) << 16);
  56}
  57
  58#define L (uint64_t)
  59
  60static inline uint64_t R64(const void* p)
  61{
  62    const unsigned char* data = (const unsigned char*)p;
  63    return (L R32(data)) | ((L R32(data+4)) << 32);
  64}
  65
  66#undef L
  67
  68static UInt32 SelectDictionarySizeFor(unsigned datasize)
  69{
  70   #if 1
  71    return datasize;
  72   #else
  73#ifdef __GNUC__
  74    /* gnu c can optimize this switch statement into a fast binary
  75     * search, but it cannot do so for the list of the if statements.
  76     */
  77    switch(datasize)
  78    {
  79        case 0 ... 512 : return 512;
  80        case 513 ... 1024: return 2048;
  81        case 1025 ... 4096: return 8192;
  82        case 4097 ... 16384: return 32768;
  83        case 16385 ... 65536: return 528288;
  84        case 65537 ... 528288: return 1048576*4;
  85        case 528289 ... 786432: return 1048576*16;
  86        default: return 1048576*32;
  87    }
  88#else
  89    if(datasize <= 512) return 512;
  90    if(datasize <= 1024) return 1024;
  91    if(datasize <= 4096) return 4096;
  92    if(datasize <= 16384) return 32768; 
  93    if(datasize <= 65536) return 528288;
  94    if(datasize <= 528288) return 1048576*4;
  95    if(datasize <= 786432) reutrn 1048576*16;
  96    return 32*1048576;
  97#endif
  98   #endif
  99}
 100
 101
 102class CInStreamRam: public ISequentialInStream, public CMyUnknownImp
 103{
 104    const std::vector<unsigned char>& input;
 105    size_t Pos;
 106public:
 107    MY_UNKNOWN_IMP
 108  
 109    CInStreamRam(const std::vector<unsigned char>& buf) : input(buf), Pos(0)
 110    {
 111    }
 112    virtual ~CInStreamRam() {}
 113  
 114    STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
 115};
 116
 117STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize)
 118{
 119    UInt32 remain = input.size() - Pos;
 120    if (size > remain) size = remain;
 121  
 122    std::memcpy(data, &input[Pos], size);
 123    Pos += size;
 124    
 125    if(processedSize != NULL) *processedSize = size;
 126    
 127    return S_OK;
 128}
 129
 130class COutStreamRam: public ISequentialOutStream, public CMyUnknownImp
 131{
 132    std::vector<Byte> result;
 133    size_t Pos;
 134public:
 135    MY_UNKNOWN_IMP
 136    
 137    COutStreamRam(): result(), Pos(0) { }
 138    virtual ~COutStreamRam() { }
 139    
 140    void Reserve(unsigned n) { result.reserve(n); }
 141    const std::vector<Byte>& Get() const { return result; }
 142  
 143    HRESULT WriteByte(Byte b)
 144    {
 145        if(Pos >= result.size()) result.resize(Pos+1);
 146        result[Pos++] = b;
 147        return S_OK;
 148    }
 149  
 150    STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
 151};
 152
 153STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize)
 154{
 155    if(Pos+size > result.size()) result.resize(Pos+size);
 156    
 157    std::memcpy(&result[Pos], data, size);
 158    if(processedSize != NULL) *processedSize = size;
 159    Pos += size;
 160    return S_OK;
 161}
 162
 163const std::vector<unsigned char> LZMACompress(const std::vector<unsigned char>& buf)
 164{
 165    if(buf.empty()) return buf;
 166    
 167    const UInt32 dictionarysize = SelectDictionarySizeFor(buf.size());
 168    
 169    NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder;
 170    CMyComPtr<ICompressCoder> encoder = encoderSpec;
 171    const PROPID propIDs[] = 
 172    {
 173        NCoderPropID::kAlgorithm,
 174        NCoderPropID::kDictionarySize,  
 175        NCoderPropID::kNumFastBytes,
 176    };
 177    const unsigned kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
 178    PROPVARIANT properties[kNumProps];
 179    properties[0].vt = VT_UI4; properties[0].ulVal = (UInt32)2;
 180    properties[1].vt = VT_UI4; properties[1].ulVal = (UInt32)dictionarysize;
 181    properties[2].vt = VT_UI4; properties[2].ulVal = (UInt32)64;
 182
 183    if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
 184    {
 185    Error:
 186        return std::vector<unsigned char> ();
 187    }
 188    
 189    COutStreamRam *const outStreamSpec = new COutStreamRam;
 190    CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
 191    CInStreamRam *const inStreamSpec = new CInStreamRam(buf);
 192    CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
 193    
 194    outStreamSpec->Reserve(buf.size());
 195
 196    if (encoderSpec->WriteCoderProperties(outStream) != S_OK) goto Error;
 197    
 198    for (unsigned i = 0; i < 8; i++)
 199    {
 200        UInt64 t = (UInt64)buf.size();
 201        outStreamSpec->WriteByte((Byte)((t) >> (8 * i)));
 202    }
 203
 204    HRESULT lzmaResult = encoder->Code(inStream, outStream, 0, 0, 0);
 205    if (lzmaResult != S_OK) goto Error;
 206    
 207    return outStreamSpec->Get();
 208}
 209
 210#undef RC_NORMALIZE
 211
 212#include "C/7zip/Decompress/LzmaDecode.h"
 213#include "C/7zip/Decompress/LzmaDecode.c"
 214
 215const std::vector<unsigned char> LZMADeCompress
 216    (const std::vector<unsigned char>& buf)
 217{
 218    if(buf.size() <= 5+8) return std::vector<unsigned char> ();
 219    
 220    uint_least64_t out_sizemax = R64(&buf[5]);
 221    
 222    std::vector<unsigned char> result(out_sizemax);
 223    
 224    CLzmaDecoderState state;
 225    LzmaDecodeProperties(&state.Properties, &buf[0], LZMA_PROPERTIES_SIZE);
 226    state.Probs = new CProb[LzmaGetNumProbs(&state.Properties)];
 227    
 228    SizeT in_done;
 229    SizeT out_done;
 230    LzmaDecode(&state, &buf[13], buf.size()-13, &in_done,
 231               &result[0], result.size(), &out_done);
 232    
 233    delete[] state.Probs;
 234    
 235    result.resize(out_done);
 236    return result;
 237}
 238
 239#ifndef COMPACT
 240int main(int argc, char *argv[])
 241{
 242        char  *s;
 243        FILE  *f, *infile, *outfile;
 244        int    c;
 245        
 246        if (argc != 4) {
 247                std::fprintf(stderr, "'lzma e file1 file2' encodes file1 into file2.\n"
 248                        "'lzma d file2 file1' decodes file2 into file1.\n");
 249
 250                return EXIT_FAILURE;
 251        }
 252        if (argc == 4) {
 253                if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL)
 254                        || (s = argv[2], (infile  = fopen(s, "rb")) == NULL)
 255                        || (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) {
 256                        std::fprintf(stderr, "??? %s\n", s);
 257                        return EXIT_FAILURE;
 258                }
 259        }
 260
 261        struct stat fs;
 262        int si;
 263        if (fstat(fileno(infile), &fs)) {
 264                std::perror(strerror(errno));
 265                return EXIT_FAILURE;
 266        }
 267        si=fs.st_size;
 268
 269        char *Buf=(char *)malloc(si);
 270        fread(Buf,si, 1, infile);
 271
 272        std::vector<unsigned char> result;
 273        if (toupper(*argv[1]) == 'E') 
 274                result = LZMACompress(std::vector<unsigned char>(Buf,Buf+si));
 275        else    
 276                result = LZMADeCompress(std::vector<unsigned char>(Buf,Buf+si));
 277
 278        fwrite(&result[0], result.size(), 1, outfile);
 279        fclose(infile);
 280        fclose(outfile);
 281        return EXIT_SUCCESS;
 282}
 283#else
 284extern "C" {
 285
 286/**
 287 * Compress a buffer with lzma
 288 * Don't copy the result back if it is too large.
 289 * @param in a pointer to the buffer
 290 * @param in_len the length in bytes
 291 * @param out a pointer to a buffer of at least size in_len
 292 * @param out_len a pointer to the compressed length of in 
 293 */
 294
 295void do_lzma_compress(char *in, int in_len, char *out, int *out_len) {
 296        std::vector<unsigned char> result;
 297        result = LZMACompress(std::vector<unsigned char>(in, in + in_len));
 298        *out_len = result.size();
 299        if (*out_len < in_len)
 300                std::memcpy(out, &result[0], *out_len);
 301}
 302
 303void do_lzma_uncompress(char *dst, int dst_len, char *src, int src_len) {
 304        std::vector<unsigned char> result;
 305        result = LZMADeCompress(std::vector<unsigned char>(src, src + src_len));
 306        if (result.size() <= (SizeT)dst_len)
 307                std::memcpy(dst, &result[0], result.size());
 308        else
 309        {
 310                fprintf(stderr, "Not copying %d bytes to %d-byte buffer!\n",
 311                        (unsigned int)result.size(), dst_len);
 312                exit(1);
 313        }
 314}
 315
 316}
 317#endif
 318
 319
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.