/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
/* vi: set expandtab shiftwidth=4 tabstop=4: */
/**
* \file
* <PRE>
* MODP_B85 - High performance base85 encoder/decoder
* http://code.google.com/p/stringencoders/
*
* Copyright © 2006, 2007 Nick Galbreath -- nickg [at] modp [dot] com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of the modp.com nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This is the standard "new" BSD license:
* http://www.opensource.org/licenses/bsd-license.php
* </pre>
*/
/* exported public header */
#include "modp_b85.h"
#include "modp_stdint.h"
/* private header */
#include "modp_b85_data.h"
/*
* Might need changing depending on platform
* we need htonl, and ntohl
*/
#include <arpa/inet.h>
/**
* you can decode IN PLACE!
* no memory allocated
*/
size_t modp_b85_decode(char* out, const char* data, size_t len)
{
size_t i;
int j;
const size_t buckets = len / 5;
const uint8_t* d2 = (const uint8_t*) data;
if (len % 5 != 0) {
return (size_t)-1;
}
uint32_t* o2 = (uint32_t*)out;
for (i = 0; i < buckets; ++i) {
uint32_t tmp = 0;
for (j = 0; j < 5; ++j) {
uint32_t digit = gsCharToInt[(uint32_t) *d2++];
if (digit >= 85) {
return (size_t)-1;
}
tmp = tmp * 85 + digit;
}
*o2++ = htonl(tmp);
}
return 4 * buckets;
}
/**
* src != out
*/
size_t modp_b85_encode(char* out, const char* src, size_t len)
{
const uint32_t* sary = (const uint32_t*) src;
const size_t buckets = len / 4;
if (len % 4 != 0) {
return (size_t)-1;
}
size_t i;
for (i = 0; i < buckets; ++i) {
uint32_t tmp = *sary++;
tmp = htonl(tmp);
/* this crazy function */
#if 1
*out++ = (char)gsIntToChar[(tmp / 52200625)]; // don't need % 85 here, always < 85
*out++ = (char)gsIntToChar[(tmp / 614125) % 85];
*out++ = (char)gsIntToChar[(tmp / 7225) % 85];
*out++ = (char)gsIntToChar[(tmp / 85) % 85];
*out++ = (char)gsIntToChar[tmp % 85];
#else
/* is really this */
*(out+4) = gsIntToChar[tmp % 85]; tmp /= 85;
*(out+3) = gsIntToChar[tmp % 85]; tmp /= 85;
*(out+2) = gsIntToChar[tmp % 85]; tmp /= 85;
*(out+1) = gsIntToChar[tmp % 85]; tmp /= 85;
*out = gsIntToChar[tmp];
out += 5;
#endif
// NOTES
// Version 1 under -O3 is about 10-20 PERCENT faster than version 2
// BUT Version 1 is 10 TIMES SLOWER when used with -Os !!!
// Reason: gcc does a lot of tricks to remove the divisions
// op with multiplies and shift.
// In V1 with -O3 this works. Under -Os it reverts to very
// slow division.
// In V2 -O3 it does the same thing, but under Os, it's smart
// enough to know we want the quotient and remainder and only
// one div call per line.
}
*out = 0; // final null
return buckets * 5;
}