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

namespace CFF {

using namespace OT;

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

  number_t	      single_val;
};

typedef dict_val_t num_dict_val_t;

template <typename VAL> struct dict_values_t : parsed_values_t<VAL> {};

template <typename OPSTR=op_str_t>
struct top_dict_values_t : dict_values_t<OPSTR>
{
  void init ()
  {
    dict_values_t<OPSTR>::init ();
    charStringsOffset = 0;
    FDArrayOffset = 0;
  }
  void fini () { dict_values_t<OPSTR>::fini (); }

  unsigned int  charStringsOffset;
  unsigned int  FDArrayOffset;
};

struct dict_opset_t : opset_t<number_t>
{
  static void process_op (op_code_t op, interp_env_t<number_t>& env)
  {
    switch (op) {
      case OpCode_longintdict:  /* 5-byte integer */
	env.argStack.push_longint_from_substr (env.str_ref);
	break;

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

      default:
	opset_t<number_t>::process_op (op, env);
	break;
    }
  }

  /* Turns CFF's BCD format into strtod understandable string */
  static double parse_bcd (byte_str_ref_t& str_ref)
  {
    if (unlikely (str_ref.in_error ())) return .0;

    enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END };

    char buf[32];
    unsigned char byte = 0;
    for (unsigned i = 0, count = 0; count < ARRAY_LENGTH (buf); ++i, ++count)
    {
      unsigned nibble;
      if (!(i & 1))
      {
	if (unlikely (!str_ref.avail ())) break;

	byte = str_ref[0];
	str_ref.inc ();
	nibble = byte >> 4;
      }
      else
	nibble = byte & 0x0F;

      if (unlikely (nibble == RESERVED)) break;
      else if (nibble == END)
      {
	const char *p = buf;
	double pv;
	if (unlikely (!hb_parse_double (&p, p + count, &pv, true/* whole buffer */)))
	  break;
	return pv;
      }
      else
      {
	buf[count] = "0123456789.EE?-?"[nibble];
	if (nibble == EXP_NEG)
	{
	  ++count;
	  if (unlikely (count == ARRAY_LENGTH (buf))) break;
	  buf[count] = '-';
	}
      }
    }

    str_ref.set_error ();
    return .0;
  }

  static bool is_hint_op (op_code_t 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=op_str_t>
struct top_dict_opset_t : dict_opset_t
{
  static void process_op (op_code_t op, interp_env_t<number_t>& env, top_dict_values_t<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:
	dict_opset_t::process_op (op, env);
	break;
    }
  }
};

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

    return true;
  }

  private:
  typedef interpreter_t<ENV> SUPER;
};

} /* namespace CFF */

#endif /* HB_CFF_INTERP_DICT_COMMON_HH */
