/*
 * Copyright 2006-2008 The FLWOR Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once
#ifndef ZORBA_QUERY_LOC_H
#define ZORBA_QUERY_LOC_H

#include <zorba/internal/ztd.h>
#include <zorba/internal/diagnostic.h>
#include "zorbatypes/zstring.h"

namespace zorba {

namespace serialization
{
  class Archiver;
}

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

/**
 * Class to save the query location of zorba elements that correspond to a code
 * snipped in the query.
 * This class is a replacement of yy::location which is generated by the bison 
 * parser generator. yy::location is used as few as possible in zorba to reduced
 * dependencies to the parser.
 */
class QueryLoc 
{
  typedef zorba::internal::ztd::explicit_bool explicit_bool;
public:
  typedef internal::diagnostic::location::line_type line_type;
  typedef internal::diagnostic::location::column_type column_type;

  static QueryLoc null;

  zstring     theFilename;
  line_type   theLineBegin;
  column_type theColumnBegin;
  line_type   theLineEnd;
  column_type theColumnEnd;

  QueryLoc();

  QueryLoc( zstring const &filename, line_type lineBegin, line_type lineEnd,
            column_type columnBegin = 0, column_type columnEnd = 0 );

  const zstring& getFilename() const { return theFilename; }
 
  void setFilename(const zstring& aFilename) { theFilename = aFilename; }

  void setFilename(const char* aFilename) { theFilename = aFilename; }

  line_type getLineBegin() const { return theLineBegin; }  
   
  void setLineBegin(line_type aLineBegin) { theLineBegin = aLineBegin; }

  line_type getLineEnd() const { return theLineEnd; }    

  void setLineEnd(line_type aLineEnd) { theLineEnd = aLineEnd; }

  column_type getColumnBegin() const { return theColumnBegin; }
   
  column_type getColumnEnd() const { return theColumnEnd; }     

  void setColumnBegin(column_type aColumnBegin) { theColumnBegin = aColumnBegin; }

  void setColumnEnd(column_type aColumnEnd) { theColumnEnd = aColumnEnd; }

  line_type getLineno() const { return getLineBegin(); }
 
  bool equals(const QueryLoc& loc) const;

  operator explicit_bool::type() const {
    return explicit_bool::value_of( !equals( null ) );
  }
};

inline bool operator==( QueryLoc const &q1, QueryLoc const &q2 ) {
  return q1.equals( q2 );
}

inline bool operator!=( QueryLoc const &q1, QueryLoc const &q2 ) {
  return !(q1 == q2);
}

inline bool operator<( QueryLoc const &q1, QueryLoc const &q2 ) {
  return q1.getLineBegin()  <  q2.getLineBegin()
      || (q1.getLineBegin() == q2.getLineBegin()
          && q1.getColumnBegin() < q2.getColumnBegin());
}

std::ostream& operator<< (std::ostream& aOstr, const QueryLoc& aQueryLoc);

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

} // namespace zorba

#endif /* ZORBA_QUERY_LOC_H */
/* vim:set et sw=2 ts=2: */
