#ifndef __JGIZMO__JROOTOBJECTID__ #define __JGIZMO__JROOTOBJECTID__ #include #include #include #include #include "TString.h" #include "JLang/JException.hh" /** * \author mdejong */ namespace JGIZMO {} namespace JPP { using namespace JGIZMO; } namespace JGIZMO { using JLANG::JParseError; /** * Auxiliary class to handle file name, ROOT directory and object name. * * The general syntax is as follows:\n *
   *   \:[\]\
   * 
   * where
   * \ is optional and 
   * \ may be a regular expression (TRegexp).
   */
  class JRootObjectID
  {
  public:
    
    static const char LABEL_L_BRACKET     =  '[';     //!< left  bracket for label
    static const char LABEL_R_BRACKET     =  ']';     //!< right bracket for label
    static const char FILENAME_SEPARATOR  =  ':';     //!< file name separator
    static const char PATHNAME_SEPARATOR  =  '/';     //!< path name separator


    /**
     * Default constructor.
     */
    JRootObjectID()
    {}


    /**
     * Constructor.
     *
     * \param  file_name    file name
     * \param  name         object name
     */
    JRootObjectID(const std::string& file_name,
		  const std::string& name) :
      file_name(file_name),
      directory(""),
      name     (name)
    {}


    /**
     * Constructor.
     *
     * \param  file_name    file name
     * \param  dir          directory name
     * \param  name         object name
     */
    JRootObjectID(const std::string& file_name,
		  const std::string& dir,
		  const std::string& name) :
      file_name(file_name),
      directory(dir),
      name     (name)
    {}


    /**
     * Constructor.
     *
     * \param  full_name    full object name
     */
    JRootObjectID(const std::string& full_name)
    {
      std::istringstream(full_name) >> *this;
    }
  
  
    /**
     * Get file name.
     *
     * \return              file name
     */
    const std::string& getFilename() const
    {
      return file_name;
    }
  
    
    /**
     * Get directory.
     *
     * \return              directory
     */
    TString getDirectory() const
    {
      return TString(directory.c_str());
    }
  
    
    /**
     * Get object name.
     *
     * \return              object name
     */
    TString getObjectName() const
    {
      return TString(name.c_str());
    }
  
    
    /**
     * Get full file name, including path.
     *
     * \return              file name
     */
    TString getFullFilename() const
    {
      if (getDirectory() == "")
	return getFilename();
      else
	return getFilename() + PATHNAME_SEPARATOR + getDirectory();
    }
  
    
    /**
     * Get full object name, including path.
     *
     * \return              object name
     */
    TString getFullObjectName() const
    {
      if (getDirectory() == "")
	return getObjectName();
      else
	return getDirectory() + PATHNAME_SEPARATOR + getObjectName();
    }


    /**
     * Check validity.
     *
     * \return              true if valid ROOT object identifier; else false
     */
    bool is_valid() const
    {
      return (file_name != "" &&
	      name      != "");
    }

    /**
     * Clear.
     */
    void clear()
    {
      file_name.clear();
      directory.clear();
      name     .clear();
    }


    /**
     * Equal operator for object identifiers.
     *
     * \param  first        first  object identifier
     * \param  second       second object identifier
     * \return              true if first and second object identifier are equal; else false
     */
    friend inline bool operator==(const JRootObjectID& first, const JRootObjectID& second)
    {
      return (first.getFilename()   == second.getFilename()  &&
	      first.getDirectory()  == second.getDirectory() &&
	      first.getObjectName() == second.getObjectName());
    }
    

    /**
     * Read object identifier from input.
     *
     * \param  in           input stream
     * \param  object       object identifier
     * \return              input stream
     */
    friend inline std::istream& operator>>(std::istream& in, JRootObjectID& object)
    {
      using namespace std;

      object.clear();

      string buffer;

      for (int bracket = 0; in.peek() != EOF; ) {

	const char c = (char) in.get();

	if        (c == LABEL_L_BRACKET) {

	  ++bracket;

	} else if (c == LABEL_R_BRACKET) {

	  --bracket;

	} else if (isspace(c)) {

	  if (bracket <= 0) {
	    break;
	  }
	}

	buffer.push_back(c);
      }

      size_t pos = buffer.find(FILENAME_SEPARATOR);

      if (pos != string::npos) {

	object.file_name = buffer.substr(0, pos);
	object.name      = buffer.substr(pos + 1);

	pos = object.name.rfind(PATHNAME_SEPARATOR);

	if (pos != string::npos) {
	  
	  object.directory = object.name.substr(0, pos);
	  object.name      = object.name.substr(pos + 1);
	}

      } else if (!buffer.empty()) {

	throw JParseError("JRootObjectID error parsing " + buffer);
      }

      return in;
    }


    /**
     * Write object identifier to output.
     *
     * \param  out          output stream
     * \param  object       object identifier
     * \return              output stream
     */
    friend inline std::ostream& operator<<(std::ostream& out, const JRootObjectID& object)
    {
      return out << object.getFilename() << FILENAME_SEPARATOR << object.getFullObjectName();
    }

  protected:
    std::string file_name;
    std::string directory;
    std::string name;
  };
}

#endif