//========================================================================
//
// JArithmeticDecoder.cc
//
// Copyright 2002-2004 Glyph & Cog, LLC
//
//========================================================================

#include <config.h>

#include "Object.h"
#include "Stream.h"
#include "JArithmeticDecoder.h"

//------------------------------------------------------------------------
// JArithmeticDecoderStates
//------------------------------------------------------------------------

JArithmeticDecoderStats::JArithmeticDecoderStats(int contextSizeA) {
  contextSize = contextSizeA;
  cxTab = (unsigned char *)gmallocn(contextSize, sizeof(unsigned char));
  reset();
}

JArithmeticDecoderStats::~JArithmeticDecoderStats() {
  gfree(cxTab);
}

JArithmeticDecoderStats *JArithmeticDecoderStats::copy() {
  JArithmeticDecoderStats *stats;

  stats = new JArithmeticDecoderStats(contextSize);
  memcpy(stats->cxTab, cxTab, contextSize);
  return stats;
}

void JArithmeticDecoderStats::reset() {
  memset(cxTab, 0, contextSize);
}

void JArithmeticDecoderStats::copyFrom(JArithmeticDecoderStats *stats) {
  memcpy(cxTab, stats->cxTab, contextSize);
}

void JArithmeticDecoderStats::setEntry(unsigned int cx, int i, int mps) {
  cxTab[cx] = (i << 1) + mps;
}

//------------------------------------------------------------------------
// JArithmeticDecoder
//------------------------------------------------------------------------

unsigned int JArithmeticDecoder::qeTab[47] = {
  0x56010000, 0x34010000, 0x18010000, 0x0AC10000,
  0x05210000, 0x02210000, 0x56010000, 0x54010000,
  0x48010000, 0x38010000, 0x30010000, 0x24010000,
  0x1C010000, 0x16010000, 0x56010000, 0x54010000,
  0x51010000, 0x48010000, 0x38010000, 0x34010000,
  0x30010000, 0x28010000, 0x24010000, 0x22010000,
  0x1C010000, 0x18010000, 0x16010000, 0x14010000,
  0x12010000, 0x11010000, 0x0AC10000, 0x09C10000,
  0x08A10000, 0x05210000, 0x04410000, 0x02A10000,
  0x02210000, 0x01410000, 0x01110000, 0x00850000,
  0x00490000, 0x00250000, 0x00150000, 0x00090000,
  0x00050000, 0x00010000, 0x56010000
};

int JArithmeticDecoder::nmpsTab[47] = {
   1,  2,  3,  4,  5, 38,  7,  8,  9, 10, 11, 12, 13, 29, 15, 16,
  17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
  33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 45, 46
};

int JArithmeticDecoder::nlpsTab[47] = {
   1,  6,  9, 12, 29, 33,  6, 14, 14, 14, 17, 18, 20, 21, 14, 14,
  15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
  30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 46
};

int JArithmeticDecoder::switchTab[47] = {
  1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

JArithmeticDecoder::JArithmeticDecoder() {
  str = nullptr;
  dataLen = 0;
  limitStream = false;
  nBytesRead = 0;
}

inline unsigned int JArithmeticDecoder::readByte() {
  if (limitStream) {
    --dataLen;
    if (dataLen < 0) {
      return 0xff;
    }
  }
  ++nBytesRead;
  return (unsigned int)str->getChar() & 0xff;
}

JArithmeticDecoder::~JArithmeticDecoder() {
  cleanup();
}

void JArithmeticDecoder::start() {
  buf0 = readByte();
  buf1 = readByte();

  // INITDEC
  c = (buf0 ^ 0xff) << 16;
  byteIn();
  c <<= 7;
  ct -= 7;
  a = 0x80000000;
}

void JArithmeticDecoder::restart(int dataLenA) {
  unsigned int cAdd;
  bool prevFF;
  int k, nBits;

  if (dataLen >= 0) {
    dataLen = dataLenA;
  } else if (dataLen == -1) {
    dataLen = dataLenA;
    buf1 = readByte();
  } else {
    k = (-dataLen - 1) * 8 - ct;
    dataLen = dataLenA;
    cAdd = 0;
    prevFF = false;
    while (k > 0) {
      buf0 = readByte();
      if (prevFF) {
	cAdd += 0xfe00 - (buf0 << 9);
	nBits = 7;
      } else {
	cAdd += 0xff00 - (buf0 << 8);
	nBits = 8;
      }
      prevFF = buf0 == 0xff;
      if (k > nBits) {
	cAdd <<= nBits;
	k -= nBits;
      } else {
	cAdd <<= k;
	ct = nBits - k;
	k = 0;
      }
    }
    c += cAdd;
    buf1 = readByte();
  }
}

void JArithmeticDecoder::cleanup() {
  if (limitStream) {
    while (dataLen > 0) {
      buf0 = buf1;
      buf1 = readByte();
    }
  }
}

int JArithmeticDecoder::decodeBit(unsigned int context,
				  JArithmeticDecoderStats *stats) {
  int bit;
  unsigned int qe;
  int iCX, mpsCX;

  iCX = stats->cxTab[context] >> 1;
  mpsCX = stats->cxTab[context] & 1;
  qe = qeTab[iCX];
  a -= qe;
  if (c < a) {
    if (a & 0x80000000) {
      bit = mpsCX;
    } else {
      // MPS_EXCHANGE
      if (a < qe) {
	bit = 1 - mpsCX;
	if (switchTab[iCX]) {
	  stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX);
	} else {
	  stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX;
	}
      } else {
	bit = mpsCX;
	stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX;
      }
      // RENORMD
      do {
	if (ct == 0) {
	  byteIn();
	}
	a <<= 1;
	c <<= 1;
	--ct;
      } while (!(a & 0x80000000));
    }
  } else {
    c -= a;
    // LPS_EXCHANGE
    if (a < qe) {
      bit = mpsCX;
      stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX;
    } else {
      bit = 1 - mpsCX;
      if (switchTab[iCX]) {
	stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX);
      } else {
	stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX;
      }
    }
    a = qe;
    // RENORMD
    do {
      if (ct == 0) {
	byteIn();
      }
      a <<= 1;
      c <<= 1;
      --ct;
    } while (!(a & 0x80000000));
  }
  return bit;
}

int JArithmeticDecoder::decodeByte(unsigned int context,
				   JArithmeticDecoderStats *stats) {
  int byte;
  int i;

  byte = 0;
  for (i = 0; i < 8; ++i) {
    byte = (byte << 1) | decodeBit(context, stats);
  }
  return byte;
}

bool JArithmeticDecoder::decodeInt(int *x, JArithmeticDecoderStats *stats) {
  int s;
  unsigned int v;
  int i;

  prev = 1;
  s = decodeIntBit(stats);
  if (decodeIntBit(stats)) {
    if (decodeIntBit(stats)) {
      if (decodeIntBit(stats)) {
	if (decodeIntBit(stats)) {
	  if (decodeIntBit(stats)) {
	    v = 0;
	    for (i = 0; i < 32; ++i) {
	      v = (v << 1) | decodeIntBit(stats);
	    }
	    v += 4436;
	  } else {
	    v = 0;
	    for (i = 0; i < 12; ++i) {
	      v = (v << 1) | decodeIntBit(stats);
	    }
	    v += 340;
	  }
	} else {
	  v = 0;
	  for (i = 0; i < 8; ++i) {
	    v = (v << 1) | decodeIntBit(stats);
	  }
	  v += 84;
	}
      } else {
	v = 0;
	for (i = 0; i < 6; ++i) {
	  v = (v << 1) | decodeIntBit(stats);
	}
	v += 20;
      }
    } else {
      v = decodeIntBit(stats);
      v = (v << 1) | decodeIntBit(stats);
      v = (v << 1) | decodeIntBit(stats);
      v = (v << 1) | decodeIntBit(stats);
      v += 4;
    }
  } else {
    v = decodeIntBit(stats);
    v = (v << 1) | decodeIntBit(stats);
  }

  if (s) {
    if (v == 0) {
      return false;
    }
    *x = -(int)v;
  } else {
    *x = (int)v;
  }
  return true;
}

int JArithmeticDecoder::decodeIntBit(JArithmeticDecoderStats *stats) {
  int bit;

  bit = decodeBit(prev, stats);
  if (prev < 0x100) {
    prev = (prev << 1) | bit;
  } else {
    prev = (((prev << 1) | bit) & 0x1ff) | 0x100;
  }
  return bit;
}

unsigned int JArithmeticDecoder::decodeIAID(unsigned int codeLen,
				     JArithmeticDecoderStats *stats) {
  unsigned int i;
  int bit;

  prev = 1;
  for (i = 0; i < codeLen; ++i) {
    bit = decodeBit(prev, stats);
    prev = (prev << 1) | bit;
  }
  return prev - (1 << codeLen);
}

void JArithmeticDecoder::byteIn() {
  if (buf0 == 0xff) {
    if (buf1 > 0x8f) {
      if (limitStream) {
	buf0 = buf1;
	buf1 = readByte();
	c = c + 0xff00 - (buf0 << 8);
      }
      ct = 8;
    } else {
      buf0 = buf1;
      buf1 = readByte();
      c = c + 0xfe00 - (buf0 << 9);
      ct = 7;
    }
  } else {
    buf0 = buf1;
    buf1 = readByte();
    c = c + 0xff00 - (buf0 << 8);
    ct = 8;
  }
}
