/* -*- c++ -*- */
#include "occurrence.h"
#include "traits.h"
#include "fixed.h"
#include <sstream>

using namespace aka2;

const int aka2::unbounded = -1;

bool occurrence::in_range(int count) const {
  assert(count >=0);
  if (maxOccurs_ == aka2::unbounded)
    return count >= minOccurs_;

  assert(minOccurs_ <= maxOccurs_);
  return (minOccurs_ <= count) && (count <= maxOccurs_);
}

bool occurrence::is_array() const {
  return minOccurs_ != 1 || maxOccurs_ != 1;
}



bool element_props::is_fixed_string(const std::string &val, 
				    const preconditions &pcd) const {
  const fixed_op *fop;
  if (get_schematype() == array_id) {
    const array_op &aop = static_cast<const array_op&>(*op_);
    assert(aop.get_item_op().get_schematype() == fixed_id);
    fop = &static_cast<const fixed_op&>(aop.get_item_op());
  }
  else if (get_schematype() == fixed_id) {
    fop = static_cast<const fixed_op*>(op_);
  }
  else {
    assert(!"Must not reach here.");
  }

  const simpletype_op &sop = fop->get_value_op();
  void *given = sop.create();
  std::istringstream istm(val);

  bool res = true;
  try {
    sop.read_text(given, istm, pcd);
  }
  catch ( ... /*!!!!!*/) {
    res = false;
  }
  if (res)
    res = sop.equals(given, default_->value());
  sop.destroy(given);
  return res;
} 

void element_props::write_fixed_string(std::ostream &ostm, const preconditions &pcd) const {
  const fixed_op *fop;
  if (get_schematype() == array_id) {
    const array_op &aop = static_cast<const array_op&>(*op_);
    assert(aop.get_item_op().get_schematype() == fixed_id);
    fop = &static_cast<const fixed_op&>(aop.get_item_op());
  }
  else if (get_schematype() == fixed_id) {
    fop = static_cast<const fixed_op*>(op_);
  }
  else {
    assert(!"Must not reach here.");
  }
  const simpletype_op &sop = fop->get_value_op();
  sop.write_text(default_->value(), ostm, pcd);
}

void element_props::set_default(void *e) const {
  assert(get_schematype() == simpletype_id);
  if (default_.get() == 0)
    return;
  if (default_->has_default())
    op_->copy(e, default_->value());
}

bool element_props::is_default(const void *e) const { 
  assert(is_default_specified());
  return op_->equals(e, default_->value());
}
