/*
 * 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>

namespace CFF {

using namespace OT;

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

  inline void fini (void)
  {
  }

  Number	      single_val;
};

typedef DictVal NumDictVal;

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

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

  inline void fini (void)
  {
    DictValues<OPSTR>::fini ();
  }

  inline 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 inline 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 inline float parse_bcd (SubByteStr& substr)
  {
    float v = 0.0f;

    bool    neg = false;
    double  int_part = 0;
    long    frac_part = 0;
    unsigned int  frac_count = 0;
    bool    exp_neg = false;
    unsigned int  exp_part = 0;
    enum Part { INT_PART=0, FRAC_PART, EXP_PART } part = INT_PART;
    enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END };

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

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

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

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

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

	case EXP_NEG:
	  exp_neg = true;
	  HB_FALLTHROUGH;

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

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

	    case FRAC_PART:
	      frac_part = (frac_part * 10) + d;
	      frac_count++;
	      break;

	    case EXP_PART:
	      exp_part = (exp_part * 10) + d;
	      break;
	  }
      }
    }

    return v;
  }

  static inline 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 inline 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>
{
  inline 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 */
