// file      : examples/cxx/serializer/minimal/driver.cxx
// author    : Boris Kolpackov <boris@codesynthesis.com>
// copyright : not copyrighted - public domain

#include <stdio.h>

#include "people.hxx"
#include "people-sskel.hxx"

const char* gender_strings[] = {"male", "female"};

struct gender_simpl: gender_sskel, xml_schema::string_simpl
{
  virtual void
  pre (gender g)
  {
    string_simpl::pre (gender_strings[g]);
  }
};

struct person_simpl: person_sskel
{
  virtual void
  pre (const person& p)
  {
    person_ = &p;
  }

  virtual const char*
  first_name ()
  {
    return person_->first_name_;
  }

  virtual const char*
  last_name ()
  {
    return person_->last_name_;
  }

  virtual ::gender
  gender ()
  {
    return person_->gender_;
  }

  virtual unsigned short
  age ()
  {
    return person_->age_;
  }

private:
  const person* person_;
};

struct people_simpl: people_sskel
{
  virtual void
  pre (const people& p)
  {
    i_ = 0;
    people_ = &p;
  }

  virtual bool
  person_next ()
  {
    return i_ < people_->size_;
  }

  virtual const ::person&
  person ()
  {
    return people_->people_[i_++];
  }

private:
  size_t i_;
  const people* people_;
};

struct writer: xml_schema::writer
{
  virtual bool
  write (const char* s, size_t n)
  {
    return fwrite (s, n, 1, stdout) == 1;
  }

  virtual bool
  flush ()
  {
    return fflush (stdout) == 0;
  }
};

int
main ()
{
  // Create a sample person list.
  //
  people p;

  p.size_ = 2;
  p.people_ = new person[p.size_];

  if (p.people_ == 0)
  {
    fprintf (stderr, "error: no memory\n");
    return 1;
  }

  p.people_[0].first_name_ = "John";
  p.people_[0].last_name_ = "Doe";
  p.people_[0].gender_ = male;
  p.people_[0].age_ = 32;

  p.people_[1].first_name_ = "Jane";
  p.people_[1].last_name_ = "Doe";
  p.people_[1].gender_ = female;
  p.people_[1].age_ = 28;

  // Construct the serializer.
  //
  xml_schema::unsigned_short_simpl unsigned_short_s;
  xml_schema::string_simpl string_s;

  gender_simpl gender_s;
  person_simpl person_s;
  people_simpl people_s;

  person_s.serializers (string_s, string_s, gender_s, unsigned_short_s);
  people_s.serializers (person_s);

  // Serialize.
  //
  typedef xml_schema::serializer_error error;

  error e;
  writer w;

  do
  {
    xml_schema::document_simpl doc_s (people_s, "people");

    if (e = doc_s._error ())
      break;

    people_s.pre (p);

    if (e = people_s._error ())
      break;

    doc_s.serialize (w);

    if (e = doc_s._error ())
      break;

    people_s.post ();

    e = people_s._error ();

  } while (false);

  delete[] p.people_;

  // Handle errors.
  //
  if (e)
  {
    switch (e.type ())
    {
    case error::sys:
      {
        fprintf (stderr, "error: %s\n", e.sys_text ());
        break;
      }
    case error::xml:
      {
        fprintf (stderr, "error: %s\n", e.xml_text ());
        break;
      }
#ifdef XSDE_VALIDATION_SERIALIZER
    case error::schema:
      {
        fprintf (stderr, "error: %s\n", e.schema_text ());
        break;
      }
#endif
    case error::app:
      {
        fprintf (stderr, "application error: %d\n", e.app_code ());
        break;
      }
    default:
      break;
    }

    return 1;
  }

  return 0;
}
