/*
* Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// -*- C++ -*-
// Small program for unpacking specially compressed Java packages.
// John R. Rose
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <stdint.h>
#include "defines.h"
#include "bytes.h"
#include "utils.h"
#include "coding.h"
#include "constants.h"
#include "unpack.h"
extern coding basic_codings[];
// CODING_PRIVATE causes a lot of them
#pragma GCC diagnostic ignored "-Wunused-variable"
#define CODING_PRIVATE(spec) \
int spec_ = spec; \
int B = CODING_B(spec_); \
int H = CODING_H(spec_); \
int L = 256 - H; \
int S = CODING_S(spec_); \
int D = CODING_D(spec_)
#define IS_NEG_CODE(S, codeVal) ((((int)(codeVal) + 1) & ((1 << S) - 1)) == 0)
#define DECODE_SIGN_S1(ux) (((uint32_t)(ux) >> 1) ^ -((int)(ux) & 1))
static int decode_sign(int S, uint32_t ux)
{ // == Coding.decodeSign32
assert(S > 0);
uint32_t sigbits = (ux >> S);
if (IS_NEG_CODE(S, ux))
return (int)(~sigbits);
else
return (int)(ux - sigbits);
// Note that (int)(ux-sigbits) can be negative, if ux is large enough.
}
coding *coding::init()
{
if (umax > 0)
return this; // already done
assert(spec != 0); // sanity
// fill in derived fields
CODING_PRIVATE(spec);
// Return nullptr if 'arb(BHSD)' parameter constraints are not met:
if (B < 1 || B > B_MAX)
return nullptr;
if (H < 1 || H > 256)
return nullptr;
if (S < 0 || S > 2)
return nullptr;
if (D < 0 || D > 1)
return nullptr;
if (B == 1 && H != 256)
return nullptr; // 1-byte coding must be fixed-size
if (B >= 5 && H == 256)
return nullptr; // no 5-byte fixed-size coding
// first compute the range of the coding, in 64 bits
int64_t range = 0;
{
int64_t H_i = 1;
for (int i = 0; i < B; i++)
{
range += H_i;
H_i *= H;
}
range *= L;
range += H_i;
}
assert(range > 0); // no useless codings, please
int this_umax;
// now, compute min and max
if (range >= ((int64_t)1 << 32))
{
this_umax = INT_MAX_VALUE;
this->umin = INT_MIN_VALUE;
this->max = INT_MAX_VALUE;
this->min = INT_MIN_VALUE;
}
else
{
this_umax = (range > INT_MAX_VALUE) ? INT_MAX_VALUE : (int)range - 1;
this->max = this_umax;
this->min = this->umin = 0;
if (S != 0 && range != 0)
{
int64_t maxPosCode = range - 1;
int64_t maxNegCode = range - 1;
while (IS_NEG_CODE(S, maxPosCode))
--maxPosCode;
while (!IS_NEG_CODE(S, maxNegCode))
--maxNegCode;
int maxPos = decode_sign(S, (uint32_t)maxPosCode);
if (maxPos < 0)
this->max = INT_MAX_VALUE; // 32-bit wraparound
else
this->max = maxPos;
if (maxNegCode < 0)
this->min = 0; // No negative codings at all.
else
this->min =