/*
 * Copyright © 2018 Adobe Inc.
 *
 *  This is part of HarfBuzz, a text shaping library.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Adobe Author(s): Michiharu Ariza
 */
#ifndef HB_CFF_INTERP_DICT_COMMON_HH
#define HB_CFF_INTERP_DICT_COMMON_HH

#include "hb-cff-interp-common.hh"
#include <math.h>
#include <float.h>

namespace CFF {

using namespace OT;

/* an opstr and the parsed out dict value(s) */
struct DictVal : OpStr
{
  void init () { single_val.set_int (0); }
  void fini () {}

  Number	      single_val;
};

typedef DictVal NumDictVal;

template <typename VAL> struct DictValues : ParsedValues<VAL> {};

template <typename OPSTR=OpStr>
struct TopDictValues : DictValues<OPSTR>
{
  void init ()
  {
    DictValues<OPSTR>::init ();
    charStringsOffset = 0;
    FDArrayOffset = 0;
  }
  void fini () { DictValues<OPSTR>::fini (); }

  unsigned int calculate_serialized_op_size (const OPSTR& opstr) const
  {
    switch (opstr.op)
    {
      case OpCode_CharStrings:
      case OpCode_FDArray:
	return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);

      default:
	return opstr.str.len;
    }
  }

  unsigned int  charStringsOffset;
  unsigned int  FDArrayOffset;
};

struct DictOpSet : OpSet<Number>
{
  static void process_op (OpCode op, InterpEnv<Number>& env)
  {
    switch (op) {
      case OpCode_longintdict:  /* 5-byte integer */
	env.argStack.push_longint_from_substr (env.substr);
	break;

      case OpCode_BCD:  /* real number */
	env.argStack.push_real (parse_bcd (env.substr));
	break;

      default:
	OpSet<Number>::process_op (op, env);
	break;
    }
  }

  static double parse_bcd (SubByteStr& substr)
  {
    bool    neg = false;
    double  int_part = 0;
    uint64_t frac_part = 0;
    uint32_t  frac_count = 0;
    bool    exp_neg = false;
    uint32_t  exp_part = 0;
    bool    exp_overflow = false;
    enum Part { INT_PART=0, FRAC_PART, EXP_PART } part = INT_PART;
    enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END };
    const uint64_t MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 1^52-1 */
    const uint32_t MAX_EXP = 0x7FFu; /* 1^11-1 */

    double  value = 0.0;
    unsigned char byte = 0;
    for (uint32_t i = 0;; i++)
    {
      char d;
      if ((i & 1) == 0)
      {
	if (!substr.avail ())
	{
	  substr.set_error ();
	  return 0.0;
	}
	byte = substr[0];
	substr.inc ();
	d = byte >> 4;
      }
      else
	d = byte & 0x0F;

      switch (d)
      {
	case RESERVED:
	  substr.set_error ();
	  return value;

	case END:
	  value = (double)(neg? -int_part: int_part);
	  if (frac_count > 0)
	  {
	    double frac = (frac_part / pow (10.0, (double)frac_count));
	    if (neg) frac = -frac;
	    value += frac;
	  }
	  if (unlikely (exp_overflow))
	  {
	    if (value == 0.0)
	      return value;
	    if (exp_neg)
	      return neg? -DBL_MIN: DBL_MIN;
	    else
	      return neg? -DBL_MAX: DBL_MAX;
	  }
	  if (exp_part != 0)
	  {
	    if (exp_neg)
	      value /= pow (10.0, (double)exp_part);
	    else
	      value *= pow (10.0, (double)exp_part);
	  }
	  return value;

	case NEG:
	  if (i != 0)
	  {
	    substr.set_error ();
	    return 0.0;
	  }
	  neg = true;
	  break;

	case DECIMAL:
	  if (part != INT_PART)
	  {
	    substr.set_error ();
	    return value;
	  }
	  part = FRAC_PART;
	  break;

	case EXP_NEG:
	  exp_neg = true;
	  HB_FALLTHROUGH;

	case EXP_POS:
	  if (part == EXP_PART)
	  {
	    substr.set_error ();
	    return value;
	  }
	  part = EXP_PART;
	  break;

	default:
	  switch (part) {
	    default:
	    case INT_PART:
	      int_part = (int_part * 10) + d;
	      break;

	    case FRAC_PART:
	      if (likely (frac_part <= MAX_FRACT / 10))
	      {
		frac_part = (frac_part * 10) + (unsigned)d;
		frac_count++;
	      }
	      break;

	    case EXP_PART:
	      if (likely (exp_part * 10 + d <= MAX_EXP))
	      {
	      	exp_part = (exp_part * 10) + d;
	      }
	      else
	      	exp_overflow = true;
	      break;
	  }
      }
    }

    return value;
  }

  static bool is_hint_op (OpCode op)
  {
    switch (op)
    {
      case OpCode_BlueValues:
      case OpCode_OtherBlues:
      case OpCode_FamilyBlues:
      case OpCode_FamilyOtherBlues:
      case OpCode_StemSnapH:
      case OpCode_StemSnapV:
      case OpCode_StdHW:
      case OpCode_StdVW:
      case OpCode_BlueScale:
      case OpCode_BlueShift:
      case OpCode_BlueFuzz:
      case OpCode_ForceBold:
      case OpCode_LanguageGroup:
      case OpCode_ExpansionFactor:
	return true;
      default:
	return false;
    }
  }
};

template <typename VAL=OpStr>
struct TopDictOpSet : DictOpSet
{
  static void process_op (OpCode op, InterpEnv<Number>& env, TopDictValues<VAL> & dictval)
  {
    switch (op) {
      case OpCode_CharStrings:
	dictval.charStringsOffset = env.argStack.pop_uint ();
	env.clear_args ();
	break;
      case OpCode_FDArray:
	dictval.FDArrayOffset = env.argStack.pop_uint ();
	env.clear_args ();
	break;
      case OpCode_FontMatrix:
	env.clear_args ();
	break;
      default:
	DictOpSet::process_op (op, env);
	break;
    }
  }
};

template <typename OPSET, typename PARAM, typename ENV=NumInterpEnv>
struct DictInterpreter : Interpreter<ENV>
{
  bool interpret (PARAM& param)
  {
    param.init ();
    while (SUPER::env.substr.avail ())
    {
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
      if (unlikely (SUPER::env.in_error ()))
	return false;
    }

    return true;
  }

  private:
  typedef Interpreter<ENV> SUPER;
};

} /* namespace CFF */

#endif /* HB_CFF_INTERP_DICT_COMMON_HH */
