// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.

#ifndef tools_value
#define tools_value

#include "array"
#include "typedefs"
#include "num2s"
#include "b2s"

namespace tools {

class value {
  static const std::string& s_class() {
    static const std::string s_v("tools::value");
    return s_v;
  }
public:
  enum e_type {
    NONE = 0,
    UNSIGNED_SHORT = 12,
    SHORT = 13,
    UNSIGNED_INT = 14,
    INT = 15,
    UNSIGNED_INT64 = 16,
    INT64 = 17,
    // reals :
    FLOAT = 30,
    DOUBLE = 31,
    // else :
    BOOL = 50,
    STRING = 51,
    // pointers :
    VOID_STAR = 100,
    DOUBLE_STAR = 101,
    FLOAT_STAR = 102,
    INT_STAR = 103,

    // multidimensional vectors (1000+base type) :
    ARRAY_UNSIGNED_SHORT = 1012,
    ARRAY_SHORT = 1013,
    ARRAY_UNSIGNED_INT = 1014,
    ARRAY_INT = 1015,
    ARRAY_UNSIGNED_INT64 = 1016,
    ARRAY_INT64 = 1017,
    ARRAY_FLOAT = 1030,
    ARRAY_DOUBLE = 1031,
    ARRAY_BOOL = 1050,
    ARRAY_STRING = 1051
  };

public:
  value():m_label(0) {
    m_type = NONE;
    u.m_unsigned_int64 = 0;
  }

  value(bool a_value):m_label(0) {
    m_type = BOOL;
    u.m_bool = a_value;
  }
  value(short a_value):m_label(0) {
    m_type = SHORT;
    u.m_short = a_value;
  }
  value(int a_value):m_label(0) {
    m_type = INT;
    u.m_int = a_value;
  }
  value(int64 a_value):m_label(0) {
    m_type = INT64;
    u.m_int64 = a_value;
  }
  value(uint64 a_value):m_label(0) {
    m_type = UNSIGNED_INT64;
    u.m_unsigned_int64 = a_value;
  }
  value(float a_value):m_label(0) {
    m_type = FLOAT;
    u.m_float = a_value;
  }
  value(double a_value):m_label(0) {
    m_type = DOUBLE;
    u.m_double = a_value;
  }

  value(unsigned short a_value):m_label(0) {
    m_type = UNSIGNED_SHORT;
    u.m_unsigned_short = a_value;
  }
  value(unsigned int a_value):m_label(0) {
    m_type = UNSIGNED_INT;
    u.m_unsigned_int = a_value;
  }
  value(void* a_value):m_label(0) {
    m_type = VOID_STAR;
    u.m_void_star = a_value;
  }
  value(double* a_value):m_label(0) {
    m_type = DOUBLE_STAR;
    u.m_double_star = a_value;
  }
  value(float* a_value):m_label(0) {
    m_type = FLOAT_STAR;
    u.m_float_star = a_value;
  }
  value(int* a_value):m_label(0) {
    m_type = INT_STAR;
    u.m_int_star = a_value;
  }

  value(const char* a_value):m_label(0) {
    m_type = STRING;
    u.m_string = new std::string(a_value?a_value:"");
  }
  value(const std::string& a_value):m_label(0) {
    m_type = STRING;
    u.m_string = new std::string(a_value);
  }

#define TOOLS_VALUE_CSTOR(a_what,a_m_what,a_type) \
  value(const std::vector<a_what>& a_v):m_label(0){\
    m_type = a_type;\
    std::vector<unsigned int> is(1);\
    is[0] = (unsigned int)a_v.size();\
    u.a_m_what = new array<a_what>(is);\
    u.a_m_what->fill(a_v);\
  }

  TOOLS_VALUE_CSTOR(unsigned short,m_array_unsigned_short,ARRAY_UNSIGNED_SHORT)
  TOOLS_VALUE_CSTOR(short,m_array_short,ARRAY_SHORT)
  TOOLS_VALUE_CSTOR(unsigned int,m_array_unsigned_int,ARRAY_UNSIGNED_INT)
  TOOLS_VALUE_CSTOR(int,m_array_int,ARRAY_INT)
  TOOLS_VALUE_CSTOR(uint64,m_array_unsigned_int64,ARRAY_UNSIGNED_INT64)
  TOOLS_VALUE_CSTOR(int64,m_array_int64,ARRAY_INT64)
  TOOLS_VALUE_CSTOR(float,m_array_float,ARRAY_FLOAT)
  TOOLS_VALUE_CSTOR(double,m_array_double,ARRAY_DOUBLE)
  TOOLS_VALUE_CSTOR(bool,m_array_bool,ARRAY_BOOL)
  TOOLS_VALUE_CSTOR(std::string,m_array_string,ARRAY_STRING)

#undef TOOLS_VALUE_CSTOR

#define TOOLS_VALUE_CSTORA(a_what,a_m_what,a_type) \
  value(const array<a_what>& a_a):m_label(0){\
    m_type = a_type;\
    u.a_m_what = new array<a_what>(a_a);\
  }

  TOOLS_VALUE_CSTORA(unsigned short,m_array_unsigned_short,ARRAY_UNSIGNED_SHORT)
  TOOLS_VALUE_CSTORA(short,m_array_short,ARRAY_SHORT)
  TOOLS_VALUE_CSTORA(unsigned int,m_array_unsigned_int,ARRAY_UNSIGNED_INT)
  TOOLS_VALUE_CSTORA(int,m_array_int,ARRAY_INT)
  TOOLS_VALUE_CSTORA(uint64,m_array_unsigned_int64,ARRAY_UNSIGNED_INT64)
  TOOLS_VALUE_CSTORA(int64,m_array_int64,ARRAY_INT64)
  TOOLS_VALUE_CSTORA(float,m_array_float,ARRAY_FLOAT)
  TOOLS_VALUE_CSTORA(double,m_array_double,ARRAY_DOUBLE)
  TOOLS_VALUE_CSTORA(bool,m_array_bool,ARRAY_BOOL)
  TOOLS_VALUE_CSTORA(std::string,m_array_string,ARRAY_STRING)

#undef TOOLS_VALUE_CSTORA

  virtual ~value() {
    delete m_label;
    reset();
  }
public:
  value(const value& a_from):m_label(0){
    if(a_from.m_label) m_label = new std::string(*a_from.m_label);
    m_type = a_from.m_type;

    if(a_from.m_type==STRING) {
      u.m_string = new std::string(*a_from.u.m_string);

    } else if(a_from.m_type==ARRAY_UNSIGNED_SHORT) {
      u.m_array_unsigned_short =
        new array<unsigned short>(*a_from.u.m_array_unsigned_short);

    } else if(a_from.m_type==ARRAY_SHORT) {
      u.m_array_short = new array<short>(*a_from.u.m_array_short);

    } else if(a_from.m_type==ARRAY_UNSIGNED_INT) {
      u.m_array_unsigned_int = new array<unsigned int>(*a_from.u.m_array_unsigned_int);

    } else if(a_from.m_type==ARRAY_INT) {
      u.m_array_int = new array<int>(*a_from.u.m_array_int);

    } else if(a_from.m_type==ARRAY_UNSIGNED_INT64) {
      u.m_array_unsigned_int64 = new array<uint64>(*a_from.u.m_array_unsigned_int64);

    } else if(a_from.m_type==ARRAY_INT64) {
      u.m_array_int64 = new array<int64>(*a_from.u.m_array_int64);

    } else if(a_from.m_type==ARRAY_FLOAT) {
      u.m_array_float = new array<float>(*a_from.u.m_array_float);

    } else if(a_from.m_type==ARRAY_DOUBLE) {
      u.m_array_double = new array<double>(*a_from.u.m_array_double);

    } else if(a_from.m_type==ARRAY_BOOL) {
      u.m_array_bool = new array<bool>(*a_from.u.m_array_bool);

    } else if(a_from.m_type==ARRAY_STRING) {
      u.m_array_string = new array<std::string>(*a_from.u.m_array_string);

    } else {
      u = a_from.u;
    }
  }

  value& operator=(const value& a_from) {
    if(&a_from==this) return *this;

    delete m_label;m_label = 0;
    if(a_from.m_label) m_label = new std::string(*a_from.m_label);

    reset();

    m_type = a_from.m_type;

    if(a_from.m_type==STRING) {
      u.m_string = new std::string(*a_from.u.m_string);

    } else if(a_from.m_type==ARRAY_UNSIGNED_SHORT) {
      u.m_array_unsigned_short = new array<unsigned short>(*a_from.u.m_array_unsigned_short);

    } else if(a_from.m_type==ARRAY_SHORT) {
      u.m_array_short = new array<short>(*a_from.u.m_array_short);

    } else if(a_from.m_type==ARRAY_UNSIGNED_INT) {
      u.m_array_unsigned_int = new array<unsigned int>(*a_from.u.m_array_unsigned_int);

    } else if(a_from.m_type==ARRAY_INT) {
      u.m_array_int = new array<int>(*a_from.u.m_array_int);

    } else if(a_from.m_type==ARRAY_UNSIGNED_INT64) {
      u.m_array_unsigned_int64 = new array<uint64>(*a_from.u.m_array_unsigned_int64);

    } else if(a_from.m_type==ARRAY_INT64) {
      u.m_array_int64 = new array<int64>(*a_from.u.m_array_int64);

    } else if(a_from.m_type==ARRAY_FLOAT) {
      u.m_array_float = new array<float>(*a_from.u.m_array_float);

    } else if(a_from.m_type==ARRAY_DOUBLE) {
      u.m_array_double = new array<double>(*a_from.u.m_array_double);

    } else if(a_from.m_type==ARRAY_BOOL) {
      u.m_array_bool = new array<bool>(*a_from.u.m_array_bool);

    } else if(a_from.m_type==ARRAY_STRING) {
      u.m_array_string = new array<std::string>(*a_from.u.m_array_string);

    } else {
      u = a_from.u;
    }

    return *this;
  }

private:
  static const std::string& s_empty() {
    static const std::string s_v("");
    return s_v;
  }
public:
  void set_label(const std::string& a_s) {
    delete m_label;
    m_label = new std::string(a_s);
  }
  const std::string& label() const {return m_label?(*m_label):s_empty();}

  e_type type() const {return m_type;}
  void set_type(e_type a_type) {
    reset();
    m_type = a_type;
    switch(a_type) {
    case NONE:      u.m_unsigned_int64 = 0;break;
    case UNSIGNED_SHORT:   u.m_unsigned_short = 0;break;
    case SHORT:     u.m_short = 0;break;
    case UNSIGNED_INT:     u.m_unsigned_int = 0;break;
    case INT:       u.m_int = 0;break;
    case UNSIGNED_INT64:   u.m_unsigned_int64 =0;break;
    case INT64:     u.m_int64 = 0;break;
    case FLOAT:     u.m_float = 0;break;
    case DOUBLE:    u.m_double = 0;break;
    case BOOL:      u.m_bool = false;break;
    case VOID_STAR:        u.m_void_star = 0;break;
    case DOUBLE_STAR:      u.m_double_star = 0;break;
    case FLOAT_STAR:       u.m_float_star = 0;break;
    case INT_STAR:         u.m_int_star = 0;break;
    case STRING:       u.m_string = new std::string("");break;

    case ARRAY_UNSIGNED_SHORT:
      u.m_array_unsigned_short = new array<unsigned short>();break;
    case ARRAY_SHORT:u.m_array_short = new array<short>();break;

    case ARRAY_UNSIGNED_INT:
      u.m_array_unsigned_int = new array<unsigned int>();break;
    case ARRAY_INT:u.m_array_int = new array<int>();break;
    case ARRAY_UNSIGNED_INT64:
      u.m_array_unsigned_int64 = new array<uint64>();break;
    case ARRAY_INT64:u.m_array_int64 = new array<int64>();break;

    case ARRAY_FLOAT:u.m_array_float = new array<float>();break;
    case ARRAY_DOUBLE:u.m_array_double = new array<double>();break;
    case ARRAY_BOOL:u.m_array_bool = new array<bool>();break;
    case ARRAY_STRING:u.m_array_string = new array<std::string>();break;
    }
  }

  void set_none() {
    reset();
    m_type = NONE;
    u.m_unsigned_int64 = 0;
  }

  void set(short a_value) {
    reset();
    m_type = SHORT;
    u.m_short = a_value;
  }
  void set(unsigned short a_value) {
    reset();
    m_type = UNSIGNED_SHORT;
    u.m_unsigned_short  = a_value;
  }
  void set(int a_value) {
    reset();
    m_type = INT;
    u.m_int = a_value;
  }
  void set(unsigned int a_value) {
    reset();
    m_type = UNSIGNED_INT;
    u.m_unsigned_int  = a_value;
  }
  void set(int64 a_value) {
    reset();
    m_type = INT64;
    u.m_int64 = a_value;
  }
  void set(uint64 a_value) {
    reset();
    m_type = UNSIGNED_INT64;
    u.m_unsigned_int64 = a_value;
  }
  void set(float a_value) {
    reset();
    m_type = FLOAT;
    u.m_float = a_value;
  }
  void set(double a_value) {
    reset();
    m_type = DOUBLE;
    u.m_double = a_value;
  }
  void set(bool a_value) {
    reset();
    m_type = BOOL;
    u.m_bool = a_value;
  }

  void set(const std::string& a_value) {
    reset();
    m_type = STRING;
    u.m_string = new std::string(a_value);
  }
  void set(const char* a_value) {
    // To avoid the bool, const std::string& and passing "text" problem.
    reset();
    m_type = STRING;
    u.m_string = new std::string(a_value);
  }

  void set(void* a_value) {
    reset();
    m_type = VOID_STAR;
    u.m_void_star = a_value;
  }

  void set(double* a_value) {
    reset();
    m_type = DOUBLE_STAR;
    u.m_double_star = a_value;
  }
  void set(float* a_value) {
    reset();
    m_type = FLOAT_STAR;
    u.m_float_star = a_value;
  }
  void set(int* a_value) {
    reset();
    m_type = INT_STAR;
    u.m_int_star = a_value;
  }

  unsigned int get_unsigned_int() const {return u.m_unsigned_int;}
  int get_int() const {return u.m_int;}

  int64 get_int64() const {return u.m_int64;}
  uint64 get_unsigned_int64() const {return u.m_unsigned_int64;}

  unsigned short get_unsigned_short() const{return u.m_unsigned_short;}
  short get_short() const {return u.m_short;}
  float get_float() const {return u.m_float;}
  double get_double() const {return u.m_double;}
  void* get_void_star() const {return u.m_void_star;}
  double* get_double_star() const {return u.m_double_star;}
  float* get_float_star() const {return u.m_float_star;}
  int* get_int_star() const {return u.m_int_star;}
  bool get_bool() const {return u.m_bool;}

  const std::string& get_string() const {return *u.m_string;}

#define TOOLS_VALUE_SET(a_what,a_m_what,a_type) \
  void set(const std::vector<unsigned int>& a_orders,const std::vector<a_what>& a_v){\
    reset();\
    m_type = a_type;\
    u.a_m_what = new array<a_what>(a_orders);\
    u.a_m_what->fill(a_v);\
  }

  TOOLS_VALUE_SET(unsigned short,m_array_unsigned_short,ARRAY_UNSIGNED_SHORT)
  TOOLS_VALUE_SET(short,m_array_short,ARRAY_SHORT)
  TOOLS_VALUE_SET(unsigned int,m_array_unsigned_int,ARRAY_UNSIGNED_INT)
  TOOLS_VALUE_SET(int,m_array_int,ARRAY_INT)
  TOOLS_VALUE_SET(uint64,m_array_unsigned_int64,ARRAY_UNSIGNED_INT64)
  TOOLS_VALUE_SET(int64,m_array_int64,ARRAY_INT64)
  TOOLS_VALUE_SET(float,m_array_float,ARRAY_FLOAT)
  TOOLS_VALUE_SET(double,m_array_double,ARRAY_DOUBLE)
  TOOLS_VALUE_SET(bool,m_array_bool,ARRAY_BOOL)
  TOOLS_VALUE_SET(std::string,m_array_string,ARRAY_STRING)

#undef TOOLS_VALUE_SET

#define TOOLS_VALUE_SET2(a_what,a_m_what,a_type) \
  void set(const std::vector<a_what>& a_v){\
    reset();\
    m_type = a_type;\
    std::vector<unsigned int> is(1);\
    is[0] = (unsigned int)a_v.size();\
    u.a_m_what = new array<a_what>(is);\
    u.a_m_what->fill(a_v);\
  }

  TOOLS_VALUE_SET2(unsigned short,m_array_unsigned_short,ARRAY_UNSIGNED_SHORT)
  TOOLS_VALUE_SET2(short,m_array_short,ARRAY_SHORT)
  TOOLS_VALUE_SET2(unsigned int,m_array_unsigned_int,ARRAY_UNSIGNED_INT)
  TOOLS_VALUE_SET2(int,m_array_int,ARRAY_INT)
  TOOLS_VALUE_SET2(uint64,m_array_unsigned_int64,ARRAY_UNSIGNED_INT64)
  TOOLS_VALUE_SET2(int64,m_array_int64,ARRAY_INT64)
  TOOLS_VALUE_SET2(float,m_array_float,ARRAY_FLOAT)
  TOOLS_VALUE_SET2(double,m_array_double,ARRAY_DOUBLE)
  TOOLS_VALUE_SET2(bool,m_array_bool,ARRAY_BOOL)
  TOOLS_VALUE_SET2(std::string,m_array_string,ARRAY_STRING)

#undef TOOLS_VALUE_SET2

public:
  bool s_type(std::string& a_s) const {return s_type(m_type,a_s);}

  static bool s_type(value::e_type a_type,std::string& a_s){
    switch(a_type) {
    case NONE:a_s = "NONE";return true;
    case INT:a_s = "INT";return true;
    case INT64:a_s = "INT64";return true;
    case DOUBLE:a_s = "DOUBLE";return true;
    case STRING:a_s = "STRING";return true;
    case VOID_STAR:a_s = "VOID_STAR";return true;
    case DOUBLE_STAR:a_s = "DOUBLE_STAR";return true;
    case FLOAT_STAR:a_s = "FLOAT_STAR";return true;
    case INT_STAR:a_s = "INT_STAR";return true;
    case BOOL:a_s = "BOOL";return true;
    case SHORT:a_s = "SHORT";return true;
    case FLOAT:a_s = "FLOAT";return true;
    case UNSIGNED_SHORT:a_s = "UNSIGNED_SHORT";return true;
    case UNSIGNED_INT:a_s = "UNSIGNED_INT";return true;
    case UNSIGNED_INT64:a_s = "UNSIGNED_INT64";return true;
    case ARRAY_UNSIGNED_SHORT:a_s = "ARRAY_UNSIGNED_SHORT";return true;
    case ARRAY_SHORT:a_s = "ARRAY_SHORT";return true;
    case ARRAY_UNSIGNED_INT:a_s = "ARRAY_UNSIGNED_INT";return true;
    case ARRAY_INT:a_s = "ARRAY_INT";return true;
    case ARRAY_UNSIGNED_INT64:a_s = "ARRAY_UNSIGNED_INT64";return true;
    case ARRAY_INT64:a_s = "ARRAY_INT64";return true;
    case ARRAY_FLOAT:a_s = "ARRAY_FLOAT";return true;
    case ARRAY_DOUBLE:a_s = "ARRAY_DOUBLE";return true;
    case ARRAY_BOOL:a_s = "ARRAY_BOOL";return true;
    case ARRAY_STRING:a_s = "ARRAY_STRING";return true;
    default:a_s.clear();return false;
    }

  }
  bool tos(std::string& a_s) const {return tos(*this,a_s);}

  static bool tos(const value& a_v,std::string& a_s){
    switch(a_v.m_type) {
    case NONE:
      sprintf(a_s,5,"(nil)");
      return true;
    case BOOL:
      sprintf(a_s,5,"%s",a_v.u.m_bool?"true":"false");
      return true;
    case UNSIGNED_SHORT:
      sprintf(a_s,32,"%u",a_v.u.m_unsigned_short);
      return true;
    case SHORT:
      sprintf(a_s,32,"%d",a_v.u.m_short);
      return true;
    case UNSIGNED_INT:
      sprintf(a_s,32,"%u",a_v.u.m_unsigned_int);
      return true;
    case INT:
      sprintf(a_s,32,"%d",a_v.u.m_int);
      return true;
    case UNSIGNED_INT64:
      sprintf(a_s,32,int64_format(),a_v.u.m_unsigned_int64);
      return true;
    case INT64:
      sprintf(a_s,32,int64_format(),a_v.u.m_int64);
      return true;
    case FLOAT:
      sprintf(a_s,32,"%g",a_v.u.m_float);
      return true;
    case DOUBLE:
      sprintf(a_s,32,"%g",a_v.u.m_double);
      return true;
    case VOID_STAR:
      sprintf(a_s,32,upointer_format_x(),(upointer)a_v.u.m_void_star);
      return true;
    case DOUBLE_STAR:
      sprintf(a_s,32,upointer_format_x(),(upointer)a_v.u.m_double_star);
      return true;
    case FLOAT_STAR:
      sprintf(a_s,32,upointer_format_x(),(upointer)a_v.u.m_float_star);
      return true;
    case INT_STAR:
      sprintf(a_s,32,upointer_format_x(),(upointer)a_v.u.m_int_star);
      return true;
    case STRING:
      a_s = *a_v.u.m_string;
      return true;

    case ARRAY_UNSIGNED_SHORT:
      return nums2s<unsigned short>(a_v.u.m_array_unsigned_short->vector(),a_s);
    case ARRAY_SHORT:
      return nums2s<short>(a_v.u.m_array_short->vector(),a_s);

    case ARRAY_UNSIGNED_INT:
      return nums2s<unsigned int>(a_v.u.m_array_unsigned_int->vector(),a_s);
    case ARRAY_INT:
      return nums2s<int>(a_v.u.m_array_int->vector(),a_s);

    case ARRAY_UNSIGNED_INT64:
      return nums2s<uint64>(a_v.u.m_array_unsigned_int64->vector(),a_s);
    case ARRAY_INT64:
      return nums2s<int64>(a_v.u.m_array_int64->vector(),a_s);

    case ARRAY_FLOAT:
      return nums2s<float>(a_v.u.m_array_float->vector(),a_s);
    case ARRAY_DOUBLE:
      return nums2s<double>(a_v.u.m_array_double->vector(),a_s);
    case ARRAY_BOOL:
      b2s(a_v.u.m_array_bool->vector(),a_s);
      return true;
    case ARRAY_STRING:
      return nums2s<std::string>(a_v.u.m_array_string->vector(),a_s);
    default:
      a_s.clear();
      return false;
    }
  }

public: // for valop :

  std::string stype() const {
    std::string _s;
    if(!s_type(_s)) return "unknown";
    return _s;
  }

  static std::string stype(e_type a_type) {
    std::string _s;
    if(!s_type(a_type,_s)) return "unknown";
    return _s;
  }

  static std::string to_string(const value&);

protected:
  void reset() {
    if(m_type==STRING) {
      delete u.m_string;
      u.m_string = 0;
    } else if(m_type==ARRAY_UNSIGNED_SHORT) {
      delete u.m_array_unsigned_short;u.m_array_unsigned_short = 0;

    } else if(m_type==ARRAY_SHORT) {
      delete u.m_array_short;u.m_array_short = 0;

    } else if(m_type==ARRAY_UNSIGNED_INT) {
      delete u.m_array_unsigned_int;u.m_array_unsigned_int = 0;

    } else if(m_type==ARRAY_INT) {
      delete u.m_array_int;u.m_array_int = 0;

    } else if(m_type==ARRAY_UNSIGNED_INT64) {
      delete u.m_array_unsigned_int64;u.m_array_unsigned_int64 = 0;

    } else if(m_type==ARRAY_INT64) {
      delete u.m_array_int64;u.m_array_int64 = 0;

    } else if(m_type==ARRAY_FLOAT) {
      delete u.m_array_float;u.m_array_float = 0;

    } else if(m_type==ARRAY_DOUBLE) {
      delete u.m_array_double;u.m_array_double = 0;

    } else if(m_type==ARRAY_BOOL) {
      delete u.m_array_bool;u.m_array_bool = 0;

    } else if(m_type==ARRAY_STRING) {
      delete u.m_array_string;u.m_array_string = 0;

    } else {
      u.m_unsigned_int64 = 0;
    }
  }
protected:
  std::string* m_label;
protected:
  e_type m_type;
  union {
    bool m_bool;
    int m_int;
    short m_short;
    int64 m_int64;
    float m_float;
    double m_double;
    unsigned short m_unsigned_short;
    unsigned int m_unsigned_int;
    uint64 m_unsigned_int64;
    void* m_void_star;
    double* m_double_star;
    float* m_float_star;
    int* m_int_star;
    std::string* m_string;

    array<unsigned char>* m_array_unsigned_char;
    array<char>* m_array_char;
    array<unsigned short>* m_array_unsigned_short;
    array<short>* m_array_short;
    array<uint64>* m_array_unsigned_int64;
    array<int64>* m_array_int64;
    array<unsigned int>* m_array_unsigned_int;
    array<int>* m_array_int;
    array<float>* m_array_float;
    array<double>* m_array_double;
    array<bool>* m_array_bool;
    array<std::string>* m_array_string;
  } u;
};

}

#include "value.icc"

#endif
