// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: resourceFile.iC,v 1.9 2002/02/27 12:18:42 sturm Exp $

BALL_INLINE 
void ResourceEntry::set(const ResourceEntry& entry, bool deep)
{
	// remove old contents (including children!)
	clear();
	
	// set the new values
  key_ = entry.key_;
  value_ = entry.value_;

	// in the case of deep copying, clone the children, too
  if (deep == true)
  {
    ResourceEntry* cloned = (ResourceEntry *)entry.create();

    mergeChildrenOf(*cloned, true);

    delete cloned;
  }
}

BALL_INLINE 
const ResourceEntry& ResourceEntry::operator = (const ResourceEntry &entry)
{
  set(entry);
  
  return *this;
}
  
BALL_INLINE 
void ResourceEntry::get(ResourceEntry& entry, bool deep) const
{
  entry.set(*this, deep);
}

BALL_INLINE 
const ResourceEntry& ResourceEntry::getRoot() const
{
  return ((ResourceEntry *)this)->getRoot();
}

BALL_INLINE 
ResourceEntry* ResourceEntry::getParent()
{
  return parent_;
}

BALL_INLINE 
const ResourceEntry* ResourceEntry::getParent() const
{
  return parent_;
}

BALL_INLINE 
ResourceEntry* ResourceEntry::getChild(Position index)
{
  if (index < (Position)number_children_) 
	{
    return child_[index];
  } 
	else 
	{
    return 0;
  }
}

BALL_INLINE 
const ResourceEntry* ResourceEntry::getChild(Position index) const
{
  return const_cast<ResourceEntry*>(this)->getChild(index);
}

BALL_INLINE 
const ResourceEntry* ResourceEntry::getEntry(const String& key_path) const
{
  return const_cast<ResourceEntry*>(this)->getEntry(key_path);
}

BALL_INLINE 
const String& ResourceEntry::getKey() const
{
  return key_;
}

BALL_INLINE 
void ResourceEntry::setValue(const String& value)
{
  value_ = value;
}

BALL_INLINE 
String& ResourceEntry::getValue()
{
  return value_;
}

BALL_INLINE 
const String& ResourceEntry::getValue() const
{
  return value_;
}

BALL_INLINE 
Size ResourceEntry::countChildren() const
{
  return number_children_;
}

BALL_INLINE 
Size ResourceEntry::getSize() const
{
  return (countDescendants() + 1);
}

BALL_INLINE 
ResourceEntry* ResourceEntry::insertSibling
	(const String& key, const String& value, bool replace_value)
{
  if (parent_ != 0) {
    return parent_->insertChild(key, value, replace_value);
  }
	else 
	{
    return 0;
  }
}

BALL_INLINE 
void ResourceEntry::destroy()
{
  clear();
}

BALL_INLINE 
ResourceEntry* ResourceEntry::findChild(const String& key)
{
  Index found = 0;
  
  if (number_children_ == 0 || findGreaterOrEqual_(key, found) == false) 
	{
    return 0;
  }
	else 
	{
    return child_[found];
  }
}

BALL_INLINE 
const ResourceEntry* ResourceEntry::findChild(const String& key) const
{
  return ((ResourceEntry *)this)->findChild(key);
}

BALL_INLINE 
const ResourceEntry* ResourceEntry::findDescendant(const String& key) const
{
  return ((ResourceEntry *)this)->findDescendant(key);
}

BALL_INLINE 
ResourceEntry* ResourceEntry::findEntry(const String& key)
{
  if (key_ == key) 
	{
    return this;
  } 
	else 
	{
    return findDescendant(key);
  }
}

BALL_INLINE 
const ResourceEntry* 
ResourceEntry::findEntry(const String& key) const
{
  return ((ResourceEntry *)this)->findEntry(key);
}

BALL_INLINE 
void ResourceEntry::host(Visitor<ResourceEntry>& visitor)
{
  visitor.visit(*this);
}

BALL_INLINE 
bool ResourceEntry::hasChild(const String& key) const
{
  return (findChild(key) != 0);
}

BALL_INLINE 
bool ResourceEntry::isEmpty() const
{
  return (number_children_ == 0);
}

BALL_INLINE 
bool ResourceEntry::isParentOf(const ResourceEntry& entry) const
{
  return (entry.parent_ == this);
}

BALL_INLINE 
bool ResourceEntry::isChildOf(const ResourceEntry& entry) const
{
  return entry.isParentOf(*this);
}
  
BALL_INLINE 
bool ResourceEntry::isDescendantOf(const ResourceEntry& entry) const
{
  return entry.isAncestorOf(*this);
}

BALL_INLINE 
bool ResourceEntry::isRelatedWith(const ResourceEntry& entry) const
{
  return (&entry == this || entry.isAncestorOf(*this) || this->isAncestorOf(entry));
}
  
BALL_INLINE 
bool ResourceEntry::isRoot() const
{
  return (parent_ == 0);
}

BALL_INLINE 
ResourceEntry* ResourceEntry::newEntry
  (const String& key, const String& value, ResourceEntry* parent) const
{
  return new ResourceEntry(key, value, parent);
}

BALL_INLINE 
ResourceEntry** ResourceEntry::newEntryArray(Size size) const
{
  return (new ResourceEntry *[size]);
}

BALL_INLINE 
void ResourceEntry::deleteEntry(ResourceEntry* entry) const
{
	// if the entry is deletable, delete it
	// otherwise call clear()
	if ((entry != 0) && (!entry->isAutoDeletable()))
	{
		entry->clear();
	} 
	else 
	{
		delete entry;
	}
}
  
BALL_INLINE 
void ResourceEntry::deleteEntryArray(ResourceEntry** entry_array) const
{
  delete [] entry_array;
}
 
BALL_INLINE
bool ResourceEntry::operator == (const ResourceEntry& entry) const
{
	return (key_ == entry.key_ && value_ == entry.value_ && 
					number_children_ == entry.number_children_);
}

BALL_INLINE
bool ResourceEntry::operator != (const ResourceEntry& entry) const
{
	return !(*this == entry);
}


BALL_INLINE 
void ResourceFile::close()
{
  destroy();

  File::close();
}

BALL_INLINE 
void ResourceFile::saveAs(const String& name)
{
  saveAs(root_, name);
}

BALL_INLINE 
void ResourceFile::save(const Entry& entry)
{
  saveAs(entry, File::getName());
}

BALL_INLINE 
void ResourceFile::save()
{
  saveAs(root_ ,File::getName());
}

BALL_INLINE 
Size ResourceFile::getSize() const
{
  return root_.getSize();
}

BALL_INLINE 
ResourceFile::Entry& ResourceFile::getRoot()
{
  return root_;
}

BALL_INLINE 
const ResourceFile::Entry& ResourceFile::getRoot() const
{
  return root_;
}

BALL_INLINE 
ResourceFile::Entry* ResourceFile::getEntry(const String& key_path)
{
  return root_.getEntry(key_path);
}

BALL_INLINE 
const ResourceFile::Entry* ResourceFile::getEntry(const String& key_path) const
{
  return root_.getEntry(key_path);
}

BALL_INLINE 
String* ResourceFile::getValue(const String& key_path)
{
  Entry* entry = getEntry(key_path);
  
	if (entry == 0) {
		return 0;
	}
	else
	{
		return &(entry->getValue());
	}
}

BALL_INLINE 
ResourceFile::Entry* ResourceFile::insert(const String& key_path, const String& name)
{
  return root_.insert(key_path, name);
}

BALL_INLINE 
bool ResourceFile::removeKey(const String& key_path)
{
  return root_.removeKey(key_path);
}

BALL_INLINE 
const String* ResourceFile::getValue(const String& key_path) const
{
  return ((ResourceFile *)this)->getValue(key_path);
}

BALL_INLINE 
void ResourceFile::host(Visitor<ResourceFile>& visitor)
{
  visitor.visit(*this);
}

BALL_INLINE 
bool ResourceFile::hasKey(const String& key_path) const
{
  return (getEntry(key_path) != 0);
}

BALL_INLINE 
bool ResourceFile::isEmpty() const
{
  return root_.isEmpty();
}

BALL_INLINE 
bool ResourceFile::isValid() const
{
  return (File::isValid() && root_.isValid());
}

BALL_INLINE 
bool ResourceFile::apply(UnaryProcessor<Entry>& processor)
{
  return root_.apply(processor);
}

BALL_INLINE 
bool ResourceFile::applyChildren(Entry& entry, UnaryProcessor<Entry>& processor)
{
  return entry.applyChildren(processor);
}

BALL_INLINE
void ResourceFile::skipWhitespaces_()
{
	char c;
	get(c);

	while(good() && isspace(c))
	{
		get(c);
	}

	putback(c);
}

BALL_INLINE
bool ResourceFile::operator == (const ResourceFile& rf) const
{
	return (File::operator == (rf));
}

BALL_INLINE
bool ResourceFile::operator != (const ResourceFile& rf) const
{
	return !(*this == rf);
}
