/******************************************************************************
 * Copyright (c) 2000-2023 Ericsson Telecom AB
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
 *
 * Contributors:
 *   Baranyi, Botond – initial implementation
 *
 ******************************************************************************/
#ifndef _PER_HH
#define _PER_HH

#include "Types.h"
#include "RInt.hh"
#include "Error.hh"
#include "Vector.hh"

class INTEGER;

enum PER_OPTIONS {
  PER_ALIGNED = 0x1,
  PER_CANONICAL = 0x2
};

#define PER_OCTET 256
#define PER_16K 16384
#define PER_64K 65536

extern const unsigned char FrontBitMask[9];
extern const unsigned char BackBitMask[9];
extern const unsigned char MiddleBitMask[8][9];

class PerConstraint {
public:
  virtual INTEGER get_nof_values() const;
  virtual INTEGER get_lower_bound() const;
  virtual INTEGER get_upper_bound() const;
  virtual boolean has_lower_bound() const;
  virtual boolean has_upper_bound() const;
  virtual boolean has_extension_marker() const;
  virtual boolean is_within_extension_root(const INTEGER&) const;
  virtual ~PerConstraint() { }
};

////////////////////////////////////////////////////////////////////////////////

class PerIntegerConstraint : public PerConstraint {
public:
  enum PerIntSetting {
    PER_INT_UNCONSTRAINED, // (MIN..MAX)
    PER_INT_SINGLE_VALUE, // (a)
    PER_INT_RANGE_FINITE, // (a..b)
    PER_INT_RANGE_MINUS_INFINITY, // (MIN..a)
    PER_INT_RANGE_PLUS_INFINITY   // (a..MAX)
  };

private:
  PerIntSetting setting;
  INTEGER* val_a;
  INTEGER* val_b;
  boolean extension_marker;

public:
  PerIntegerConstraint(boolean p_ext = FALSE);
  PerIntegerConstraint(PerIntSetting p_setting, INTEGER* p_a, boolean p_ext);
  PerIntegerConstraint(INTEGER* p_a, INTEGER* p_b, boolean p_ext);
  ~PerIntegerConstraint();

  INTEGER get_nof_values() const;
  INTEGER get_lower_bound() const;
  INTEGER get_upper_bound() const;
  boolean has_lower_bound() const;
  boolean has_upper_bound() const;
  boolean has_extension_marker() const { return extension_marker; }
  boolean is_within_extension_root(const INTEGER& x) const;
};

struct ASN_PERdescriptor_t {
  const PerConstraint* c;
};

extern const ASN_PERdescriptor_t INTEGER_per_;
extern const ASN_PERdescriptor_t FLOAT_per_;
extern const ASN_PERdescriptor_t BOOLEAN_per_;
extern const ASN_PERdescriptor_t BITSTRING_per_;
extern const ASN_PERdescriptor_t OCTETSTRING_per_;
extern const ASN_PERdescriptor_t GeneralString_per_;
extern const ASN_PERdescriptor_t NumericString_per_;
extern const ASN_PERdescriptor_t UTF8String_per_;
extern const ASN_PERdescriptor_t PrintableString_per_;
extern const ASN_PERdescriptor_t UniversalString_per_;
extern const ASN_PERdescriptor_t BMPString_per_;
extern const ASN_PERdescriptor_t GraphicString_per_;
extern const ASN_PERdescriptor_t IA5String_per_;
extern const ASN_PERdescriptor_t TeletexString_per_;
extern const ASN_PERdescriptor_t VideotexString_per_;
extern const ASN_PERdescriptor_t VisibleString_per_;
extern const ASN_PERdescriptor_t ASN_NULL_per_;
extern const ASN_PERdescriptor_t OBJID_per_;
extern const ASN_PERdescriptor_t ASN_ROID_per_;
extern const ASN_PERdescriptor_t ASN_ANY_per_;
extern const ASN_PERdescriptor_t ENUMERATED_per_;
extern const ASN_PERdescriptor_t EXTERNAL_per_;
extern const ASN_PERdescriptor_t EMBEDDED_PDV_per_;
extern const ASN_PERdescriptor_t CHARACTER_STRING_per_;
extern const ASN_PERdescriptor_t ObjectDescriptor_per_;
extern const ASN_PERdescriptor_t ASN_GeneralizedTime_per_;

#endif // _PER_HH