#include <typedefs.h>
#include <tokenizerlocal.h>

long int tokenizerlocal::countermax=10000000;

tokenizerlocal::tokenizerlocal(tokenizer& ref_)
  : ref(ref_), parent(0)
{
  i1=ref.current;
  i2=ref.seq.end();
  iend=ref.seq.end();
}

tokenizerlocal::tokenizerlocal
(
  tokenizerlocal& tl
)
  : ref(tl.ref), parent(&tl)
{
  reset(tl);
}

stringc & tokenizerlocal::operator() () const 
{ 
  return *ref.current; 
}

void tokenizerlocal::operator ++ () 
{ 
  if (ref.current!=i2) 
    ++ref; 
}

boolc tokenizerlocal::atomize_next
(
  stringc & atom1, 
  stringc& atom2
)
{
  if (ref.atomize_next(atom1)==false)
    return false;
  i1=ref.current;

  if (ref.atomize_next(atom2)==false)
    return false;
  i2=ref.current;

  return true;
}

boolc tokenizerlocal::scope(stringc& tag1)
{ 
  //bool res = ref.atomize_next_tag(i1,i2,tag1); 
  bool res = ref.atomize_next_tag(i1,i2,tag1,iend); 



//cout << "scope(stringc&) " << res << endl;
//cout << "  " << SHOW(*i1) << " " << SHOW(*i2) << SHOW(ref.current) << endl;
  return res;
}

boolc tokenizerlocal::scope
(
  stringc& tag1, 
  stringc& tag2
)
{
  if (scope(tag1)==false)
    return false;

//cout << "found " << SHOW(tag1) << endl;
  return scope(tag2);
}

boolc tokenizerlocal::scope
(
  stringc& tag1, 
  stringc& tag2, 
  stringc& tag3
)
{
  if (scope(tag1,tag2)==false)
    return false;

  return scope(tag3);
}

boolc tokenizerlocal::scope
(
  stringc& tag1, 
  stringc& tag2, 
  stringc& tag3,
  stringc& tag4
)
{
  if (scope(tag1,tag2,tag3)==false)
    return false;

  return scope(tag4);
}

boolc tokenizerlocal::scope
(
  stringc& tag1, 
  stringc& tag2, 
  stringc& tag3,
  stringc& tag4,
  stringc& tag5
)
{
  if (scope(tag1,tag2,tag3,tag4)==false)
    return false;

  return scope(tag5);
}

boolc tokenizerlocal::scope
(
  stringc& tag1, 
  stringc& tag2, 
  stringc& tag3,
  stringc& tag4,
  stringc& tag5,
  stringc& tag6
)
{
  if (scope(tag1,tag2,tag3,tag4,tag5)==false)
    return false;

  return scope(tag6);
}

boolc tokenizerlocal::operator ! () const 
{ 
  if (ref.current==i2) 
    return false; 
  assertreturnfalse(ref.current!=iend); 
  return true; 
}

void tokenizerlocal::reset()
{
  // Global scope. No parent so reset the tokenizer.
  if (parent==0)
  {
    ref.reset();
    i1 = ref.current;

    return;
  }

  // parent != 0
  // Assume valid pointer.
  i1=parent->i1;
  i2=parent->i2;
  iend=parent->i2;
  ref.current=parent->i1;
}

void tokenizerlocal::reset(tokenizerlocal& tl)
{
  i1=tl.i1;
  i2=tl.i2;
  iend=tl.i2;
  ref.current=i1;
}

void tokenizerlocal::endpointcontract()
{
  iend=i2;
}

void tokenizerlocal::endpointexpand()
{
  i2=iend;
}

void tokenizerlocal::endpointreset()
{
  iend=ref.seq.end();
  i2=iend;
}

boolc tokenizerlocal::scopesearch(stringc& tag)
{
  // Using the current as a starting point.
  string tag1=("<"+tag+">");

  for ( ; !ref; )
  {
    if (*ref==tag1)
      break;

    if (ref.current!=iend)
      ++ref;
  }
  if (ref.current==iend)
    return false;

  i1 = ref.current;
  ++ref;

  string tag2=("</"+tag+">");
  for ( ; !ref; )
  {
    if (*ref==tag2)
      break;
    if (ref.current!=iend)
      ++ref;
  }
  if (ref.current==iend)
    return false;

  i2 = ref.current;

  ref.current=i1;

  assert(*i1==tag1);
  assert(*i2==tag2);

  return true;
}

boolc tokenizerlocal::erasetag(stringc& tag)
{
  ref.current=i1;
  assertreturnfalse( ref()==("<"+tag+">"));
  assertreturnfalse( *i2==("</"+tag+">") );
  ++i2;
  ref.seq.erase(i1,i2);

  return true;
}

boolc tokenizerlocal::writetag(stringc& val, stringc& tag)
{
  //ref.current=i1;

  assertreturnfalse( scopesearch(tag) );

  assert( *i1==("<"+tag+">"));
  ++ref;  
  assert( *i2==("</"+tag+">") );
/*
  assertreturnfalse( ref()==("<"+tag+">"));
  ++ref;  
  assertreturnfalse( *i2==("</"+tag+">") );
*/
  
  ref.seq.erase(ref.current,i2);

  // Insert the new element in.
  liststringi k=i1;
  ++k;
  ref.seq.insert(k,val);
  
  return true;
}

boolc tokenizerlocal::readtag(string& val, stringc& tag)
{
  val="";
  assertreturnfalse( ref()==("<"+tag+">"));
  ++ref;

  static long int counter;
  counter=0;

  stringc tagend("</"+tag+">");
  val.empty();
  for ( ; ref()!=tagend; ++ref )
  {
    val += ref();

    // Exit counter logic if not end token found.
    ++counter;
    if(counter>countermax)
      return false;
  }

  return true;
}

boolc tokenizerlocal::read(string& str, stringc& tag1)
{
  if( scope(tag1)==false)
    return false;

  return readtag(str,tag1);
}

boolc tokenizerlocal::read(string& str, stringc& tag1, stringc& tag2)
{
  if( scope(tag1,tag2)==false)
    return false;

  return readtag(str,tag2);
}

boolc tokenizerlocal::read(string& str, stringc& tag1, stringc& tag2, stringc& tag3)
{
  if( scope(tag1,tag2,tag3)==false)
    return false;

  return readtag(str,tag3);
}

boolc tokenizerlocal::read(string& str, stringc& tag1, stringc& tag2, stringc& tag3, stringc& tag4)
{
  if( scope(tag1,tag2,tag3,tag4)==false)
    return false;

  return readtag(str,tag4);
}

boolc tokenizerlocal::read(string& str, stringc& tag1, stringc& tag2, stringc& tag3, stringc& tag4, stringc& tag5)
{
  if( scope(tag1,tag2,tag3,tag4,tag5)==false)
    return false;

  return readtag(str,tag5);
}

boolc tokenizerlocal::read(string& str, stringc& tag1, stringc& tag2, stringc& tag3, stringc& tag4, stringc& tag5, stringc& tag6)
{
  if( scope(tag1,tag2,tag3,tag4,tag5,tag6)==false)
    return false;

  return readtag(str,tag6);
}

boolc tokenizerlocal::boundscope(stringc& tag1)
{
  if (scope(tag1)==false)
    return false;

  iend=i2;
  return true;
}

/*
tokenizerscope::tokenizerscope
(
  tokenizerlocal& tl_,
  stringc & scopetag_
)
  : tokenizerlocal(tl_), tl(tl_),
  scopetag(scopetag_)
{
  reset();
}

void tokenizerscope::reset()
{
  tokenizerlocal::reset(tl);
}

boolc tokenizerscope::operator ! ()
{
  return scope(scopetag);
}

tokenizerscope::tokenizerscope
(
  tokenizer& tk,
  stringc & scopetag_
)
  : tokenizerlocal(tk), tl(*this), scopetag(scopetag_)
{
}

*/

stringc tokenizerlocal::debug01() const
{
  string s0;
  s0 += ("i1=" + *i1);
  s0 += (" i2=" + *i2);
  s0 += (" iend=" + *iend);
  return s0;
}

tokenizerlocalvar::tokenizerlocalvar
(
  tokenizerlocal& tkl, 
  stringc& objtag_
)
  : tokenizerlocal(tkl), objtag(objtag_)
{
}

boolc tokenizerlocalvar::operator ! ()
{
  return scope(objtag);
}


