Example #1
0
/**
 * Loads a ruleset's contents from a YAML file.
 * @param filename YAML filename.
 */
void Ruleset::load(const std::string &filename)
{
	std::string s = Options::getDataFolder() + "Ruleset/" + filename + ".rul";
	std::ifstream fin(s.c_str());
	if (!fin)
	{
		throw Exception("Failed to load ruleset");
	}
	YAML::Parser parser(fin);
	YAML::Node doc;

	parser.GetNextDocument(doc);
	for (YAML::Iterator i = doc.begin(); i != doc.end(); ++i)
	{
		std::string key;
		i.first() >> key;
		if (key == "countries")
		{
			for (YAML::Iterator j = i.second().begin(); j != i.second().end(); ++j)
			{
				std::string type;
				(*j)["type"] >> type;
				RuleCountry *rule;
				if (_countries.find(type) != _countries.end())
				{
					rule = _countries[type];
				}
				else
				{
					rule = new RuleCountry(type);
					_countries[type] = rule;
					_countriesIndex.push_back(type);
				}
				rule->load(*j);
			}
		}
		else if (key == "regions")
		{
			for (YAML::Iterator j = i.second().begin(); j != i.second().end(); ++j)
			{
				std::string type;
				(*j)["type"] >> type;
				RuleRegion *rule;
				if (_regions.find(type) != _regions.end())
				{
					rule = _regions[type];
				}
				else
				{
					rule = new RuleRegion(type);
					_regions[type] = rule;
					_regionsIndex.push_back(type);
				}
				rule->load(*j);
			}
		}
		else if (key == "facilities")
Example #2
0
Program::Program(const YAML::Node& fns) {
  for (YAML::Iterator it = fns.begin(); it != fns.end(); ++it) {
    std::string name;
    it.first() >> name;
    ReadFn(name, it.second());
  }
}
Example #3
0
void ExtraStrings::load(const YAML::Node &node)
{
	for (YAML::Iterator i = node.begin(); i != node.end(); ++i)
	{
		std::string key;
		i.first() >> key;
		if (key == "strings")
		{
			for (YAML::Iterator j = i.second().begin(); j != i.second().end(); ++j)
			{
				std::string index;
				j.first() >> index;
				std::string translation;
				j.second() >> translation;
				_strings[index] = translation;
			}
		}
	}
}
Example #4
0
 worker_types_t context::get_worker_types() const {
   worker_types_t worker_types;
   if( application_configuration_.count( "configuration-file" ) ) {
     std::fstream stream( application_configuration_["configuration-file"].as<string>().c_str() );
     YAML::Parser parser( stream );
     YAML::Node doc;
     parser.GetNextDocument( doc );
     YAML::Iterator it = doc.begin();
     it.second() >> worker_types;
   }
Example #5
0
void ExtraSprites::load(const YAML::Node &node)
{
	for (YAML::Iterator i = node.begin(); i != node.end(); ++i)
	{
		std::string key;
		i.first() >> key;
		if (key == "width")
		{
			i.second() >> _width;
		}
		else if (key == "height")
Example #6
0
/**
 * Add the weighted options from a YAML::Node to a WeightedOptions.
 * The weight option list is not replaced, only values in @a nd will be added /
 * changed.
 * @param nd The YAML node (containing a map) with the new values.
 * @param wo The list to change.
 */
void WeightedOptions::load(const YAML::Node &nd)
{
	for (YAML::Iterator val = nd.begin(); val != nd.end(); ++val)
	{
		std::string id;
		unsigned w;
		val.first() >> id;
		val.second() >> w;
		set(id, w);
	}
}
Example #7
0
/*
 * Loads the extra sound set from yaml.
 * @param node YAML node.
 * @param modIndex the internal index of the associated mod.
 */
void ExtraSounds::load(const YAML::Node &node, int modIndex)
{
	for (YAML::Iterator i = node.begin(); i != node.end(); ++i)
	{
		std::string key;
		i.first() >> key;
		if (key == "files")
		{
			for (YAML::Iterator j = i.second().begin(); j != i.second().end(); ++j)
			{
				int index;
				j.first() >> index;
				std::string filename;
				j.second() >> filename;
				_sounds[index] = filename;
			}
		}
	}
	_modIndex = modIndex;
}
Example #8
0
/**
 * Loads the inventory from a YAML file.
 * @param node YAML node.
 */
void RuleInventory::load(const YAML::Node &node)
{
	int a = 0;
	for (YAML::Iterator i = node.begin(); i != node.end(); ++i)
	{
		std::string key;
		i.first() >> key;
		if (key == "id")
		{
			i.second() >> _id;
		}
		else if (key == "x")
	/**
	 * Loads the article definition from a YAML file.
	 * @param node YAML node.
	 */
	void ArticleDefinition::load(const YAML::Node &node)
	{
		int a = 0;
		for (YAML::Iterator i = node.begin(); i != node.end(); ++i)
		{
			std::string key;
			i.first() >> key;
			if (key == "id")
			{
				i.second() >> id;
				i.second() >> title;
			}
			else if (key == "type_id")
Example #10
0
/**
 * Loads the unit from a YAML file.
 * @param node YAML node.
 */
void Unit::load(const YAML::Node &node)
{
	int a = 0;

	for (YAML::Iterator i = node.begin(); i != node.end(); ++i)
	{
		std::string key;
		i.first() >> key;
		if (key == "type")
		{
			i.second() >> _type;
		}
		else if (key == "race")
/*!
 * Parses the binding config YAML specification.
 *
 * \param[in] node The YAML node containing the binding config specification.
 * \param[out] b The object in which to store the binding configuration information.
 */
void parse_binding_config(YAML::Node const& node, controlit::BindingConfig& bc)
{
    // Parameters
    // for (YAML::Iterator it = node["parameters"].begin();
    //      it !=node["parameters"].end(); ++it)
    // {
    //     std::string paramName;
    //     *it >> paramName;
    //     bc.addParameter(paramName);
    // }

    std::string parameter;
    node["parameter"] >> parameter;
    bc.setParameter(parameter);

    // Direction
    std::string direction;
    node["direction"] >> direction;

    bc.setDirection(controlit::BindingConfig::Direction::Undefined);
    if (direction == "input") bc.setDirection(controlit::BindingConfig::Direction::Input);
    if (direction == "output") bc.setDirection(controlit::BindingConfig::Direction::Output);
    if (direction == "bidirectional") bc.setDirection(controlit::BindingConfig::Direction::Bidirectional);

    // Target
    YAML::Node const& targetNode = *(node.FindValue("target"));
    // targetNode["transportType"] >> bc.transportType;
    std::string transportType;
    std::string transportDataType;

    targetNode["type"] >> transportType;
    targetNode["dataType"] >> transportDataType;

    bc.setTransportType(transportType);
    bc.setTransportDataType(transportDataType);

    // Target properties
    YAML::Node const* propertiesNode = targetNode.FindValue("properties");
    if (propertiesNode != NULL)
    {
        for (YAML::Iterator it = propertiesNode->begin(); it != propertiesNode->end(); ++it)
        {
            std::string key, value;
            it.first() >> key;
            it.second() >> value;
            bc.addProperty(key, value);
        }
    }
}
void Property::loadChildren( const YAML::Node& yaml_node )
{
  if( yaml_node.Type() != YAML::NodeType::Map )
  {
    printf( "Property::loadChildren() TODO: error handling - unexpected YAML type.\n" );
    return;
  }

  // A special map entry named "Value" means the value of this property, not a child.
  if( const YAML::Node *value_node = yaml_node.FindValue( "Value" ))
  {
    loadValue( *value_node );
  }

  // Yaml-cpp's FindValue() and operator[] functions are order-N,
  // according to the docs, so we don't want to use those.  Instead we
  // make a hash table of the existing property children, then loop
  // over all the yaml key-value pairs, looking up their targets by
  // key (name) in the map.  This should keep this function down to
  // order-N or close, instead of order N squared.

  // First make the hash table of all child properties indexed by name.
  QHash<QString, Property*> child_map;
  int num_property_children = children_.size();
  for( int i = 0; i < num_property_children; i++ )
  {
    Property* child = children_.at( i );
    child_map[ child->getName() ] = child;
  }

  // Next loop over all yaml key/value pairs, calling load() on each
  // child whose name we find.
  for( YAML::Iterator it = yaml_node.begin(); it != yaml_node.end(); ++it )
  {
    QString key;
    it.first() >> key;
    QHash<QString, Property*>::const_iterator hash_iter = child_map.find( key );
    if( hash_iter != child_map.end() )
    {
      Property* child = hash_iter.value();
      child->load( it.second() );
    }
  }
}
Example #13
0
 static ConfigMap parseConfigMapFromYamlNode(const YAML::Node &n) {
   ConfigMap configMap;
   for(YAML::Iterator it = n.begin(); it != n.end(); ++it) {
     if(it.second().Type() == YAML::NodeType::Scalar) {
       configMap[it.first().to<std::string>()].push_back(parseConfigItemFromYamlNode(it.second()));
     } else if(it.second().Type() == YAML::NodeType::Sequence) {
       configMap[it.first().to<std::string>()] = parseConfigVectorFromYamlNode(it.second());
     } else if(it.second().Type() == YAML::NodeType::Map) {
       ConfigItem item;
       item.children = parseConfigMapFromYamlNode(it.second());
       configMap[it.first().to<std::string>()].push_back(item);
     } else if(it.second().Type() == YAML::NodeType::Null) {
       continue;
     } else {
       fprintf(stderr, "Unknown YAML::NodeType: %d\n", it.second().Type());
       continue;
     }
   }
   return configMap;
 }
Example #14
0
void Settings::ParseAppConfig(const YAML::Node* pNode, const char* appType, AppsConfig::AppMap& appMap) {
    const YAML::Node* pBaseNode = pNode->FindValue(appType);
    if (pBaseNode) {
        for (YAML::Iterator iter = pBaseNode->begin(); iter != pBaseNode->end(); ++iter) {
#define setString(a, b) {std::string c; b->GetScalar(c); a = c.c_str();}
            AppConfig config;
            const YAML::Node* pName = &iter.first();
            if (pName) setString(config.m_Name, pName);
            const YAML::Node& appNode = iter.second();
            const YAML::Node* pVer = appNode.FindValue(VERSION);
            if (pVer) setString(config.m_Version, pVer);
            const YAML::Node* pRunPath = appNode.FindValue(RUN_PATH);
            if (pRunPath) setString(config.m_RunPath, pRunPath);
            const YAML::Node* pInstallCmd = appNode.FindValue(INSTALL_CMD);
            if (pInstallCmd) setString(config.m_InstallCmd, pInstallCmd);
            const YAML::Node* pUninstallCmd = appNode.FindValue(UNINSTALL_CMD);
            if (pUninstallCmd) setString(config.m_UninstallCmd, pUninstallCmd);
            const YAML::Node* pInstallParams = appNode.FindValue(INSTALL_PARAMS);
            if (pInstallParams) setString(config.m_InstallParams, pInstallParams);
            const YAML::Node* pUninstallParams = appNode.FindValue(UNINSTALL_PARAMS);
            if (pUninstallParams) setString(config.m_UninstallParams, pUninstallParams);

            const YAML::Node* pInstalledFiles = appNode.FindValue(INSTALLED_FILES);
            if (pInstalledFiles) {
                for (YAML::Iterator iter = pInstalledFiles->begin();
                     iter != pInstalledFiles->end();
                     ++iter) {
                    std::string a;
                    *iter >> a;
                    config.m_InstalledFiles.push_back(a.c_str());
                }
            }

            appMap[config.m_Name][config.m_Version] = config;
        }
    }
}
Example #15
0
void YamlConfigReader::readYamlNode( Config& config, const YAML::Node& yaml_node )
{
  switch( yaml_node.Type() )
  {
  case YAML::NodeType::Map:
  {
    for( YAML::Iterator it = yaml_node.begin(); it != yaml_node.end(); ++it )
    {
      std::string key;
      it.first() >> key;
      Config child = config.mapMakeChild( QString::fromStdString( key ));
      readYamlNode( child, it.second() );
    }
    break;
  }
  case YAML::NodeType::Sequence:
  {
    for( YAML::Iterator it = yaml_node.begin(); it != yaml_node.end(); ++it )
    {
      Config child = config.listAppendNew();
      readYamlNode( child, *it );
    }
    break;
  }
  case YAML::NodeType::Scalar:
  {
    std::string s;
    yaml_node >> s;
    config.setValue( QString::fromStdString( s ));
    break;
  }
  case YAML::NodeType::Null:
  default:
    break;
  }
}
Example #16
0
/*
 * For converting param specs for Regions and LinkPolicies
 */
ValueMap toValueMap(const char* yamlstring,
                    Collection<ParameterSpec>& parameters,
                    const std::string & nodeType,
                    const std::string & regionName)
{

    ValueMap vm;

    // yaml-cpp bug: append a space if it is only one character
    // This is very inefficient, but should be ok since it is
    // just used at construction time for short strings
    std::string paddedstring(yamlstring);
    // TODO: strip white space to determine if empty
    bool empty = (paddedstring.size() == 0);

    if (paddedstring.size() < 2)
        paddedstring = paddedstring + " ";
    std::stringstream s(paddedstring);
    // IMemStream s(yamlstring, ::strlen(yamlstring));

    // TODO: utf-8 compatible?
    YAML::Node doc;
    if (!empty)
    {
        YAML::Parser parser(s);
        bool success = parser.GetNextDocument(doc);

        if (!success)
            NTA_THROW << "Unable to find document in YAML string";

        // A ValueMap is specified as a dictionary
        if (doc.Type() != YAML::NodeType::Map)
        {
            std::string ys(yamlstring);
            if (ys.size() > 30)
            {
                ys = ys.substr(0, 30) + "...";
            }
            NTA_THROW << "YAML string '" << ys
                      << "' does not not specify a dictionary of key-value pairs. "
                      << "Region and Link parameters must be specified at a dictionary";
        }
    }

    // Grab each value out of the YAML dictionary and put into the ValueMap
    // if it is allowed by the nodespec.
    YAML::Iterator i;
    for (i = doc.begin(); i != doc.end(); i++)
    {
        const std::string key = i.first().to<std::string>();
        if (!parameters.contains(key))
        {
            std::stringstream ss;
            for (UInt j = 0; j < parameters.getCount(); j++)
            {
                ss << "   " << parameters.getByIndex(j).first << "\n";
            }

            if (nodeType == std::string(""))
            {
                NTA_THROW << "Unknown parameter '" << key << "'\n"
                          << "Valid parameters are:\n" << ss.str();
            }
            else
            {
                NTA_CHECK(regionName != std::string(""));
                NTA_THROW << "Unknown parameter '" << key << "' for region '"
                          << regionName << "' of type '" << nodeType << "'\n"
                          << "Valid parameters are:\n" << ss.str();
            }
        }
        if (vm.contains(key))
            NTA_THROW << "Parameter '" << key << "' specified more than once in YAML document";
        ParameterSpec spec = parameters.getByName(key);
        try
        {
            Value v = toValue(i.second(), spec.dataType);
            if (v.isScalar() && spec.count != 1)
            {
                throw std::runtime_error("Expected array value but got scalar value");
            }
            if (!v.isScalar() && spec.count == 1)
            {
                throw std::runtime_error("Expected scalar value but got array value");
            }
            vm.add(key, v);
        } catch (std::runtime_error& e) {
            NTA_THROW << "Unable to set parameter '" << key << "'. " << e.what();
        }
    }

    // Populate ValueMap with default values if they were not specified in the YAML dictionary.
    for (size_t i = 0; i < parameters.getCount(); i++)
    {
        std::pair<std::string, ParameterSpec>& item = parameters.getByIndex(i);
        if (!vm.contains(item.first))
        {
            ParameterSpec & ps = item.second;
            if (ps.defaultValue != "")
            {
                // TODO: This check should be uncommented after dropping NuPIC 1.x nodes (which don't comply)
                // if (ps.accessMode != ParameterSpec::CreateAccess)
                // {
                //   NTA_THROW << "Default value for non-create parameter: " << item.first;
                // }

                try {
#ifdef YAMLDEBUG
                    NTA_DEBUG << "Adding default value '" << ps.defaultValue
                              << "' to parameter " << item.first
                              << " of type " << BasicType::getName(ps.dataType)
                              << " count " << ps.count;
#endif
                    Value v = toValue(ps.defaultValue, ps.dataType);
                    vm.add(item.first, v);
                } catch (...) {
                    NTA_THROW << "Unable to set default value for item '"
                              << item.first << "' of datatype "
                              << BasicType::getName(ps.dataType)
                              <<" with value '" << ps.defaultValue << "'";
                }
            }
        }
    }

    return vm;
}
Example #17
0
void
YamlConfiguration::read_config_doc(const YAML::Node &doc, YamlConfigurationNode *&node)
{
  if (! node) {
    node = new YamlConfigurationNode("root");
  }

  if (doc.Type() == YAML::NodeType::Map) {
#ifdef HAVE_YAMLCPP_0_5
    for (YAML::const_iterator it = doc.begin(); it != doc.end(); ++it) {
      std::string key = it->first.as<std::string>();
#else
    for (YAML::Iterator it = doc.begin(); it != doc.end(); ++it) {
      std::string key;
      it.first() >> key;
#endif
      YamlConfigurationNode *in = node;
      if (key.find("/") != std::string::npos) {
	// we need to split and find the proper insertion node
	std::vector<std::string> pel = str_split(key);
	for (size_t i = 0; i < pel.size() - 1; ++i) {
	  YamlConfigurationNode *n = (*in)[pel[i]];
	  if (! n) {
	    n = new YamlConfigurationNode(pel[i]);
	    in->add_child(pel[i], n);
	  }
	  in = n;
	}

	key = pel.back();
      }

      YamlConfigurationNode *tmp = (*in)[key];
      if (tmp) {
#ifdef HAVE_YAMLCPP_0_5
	if (tmp->is_scalar() && it->second.Type() != YAML::NodeType::Scalar)
#else
	if (tmp->is_scalar() && it.second().Type() != YAML::NodeType::Scalar)
#endif
	{
	  throw Exception("YamlConfig: scalar %s cannot be overwritten by non-scalar",
			  tmp->name().c_str());
	}
#ifdef HAVE_YAMLCPP_0_5
	tmp->set_scalar(it->second.Scalar());
#else
	std::string s;
	if (it.second().GetScalar(s)) {
	  tmp->set_scalar(s);
	}
#endif
      } else {
#ifdef HAVE_YAMLCPP_0_5
	YamlConfigurationNode *tmp = new YamlConfigurationNode(key, it->second);
	in->add_child(key, tmp);
	read_config_doc(it->second, tmp);
#else
	YamlConfigurationNode *tmp = new YamlConfigurationNode(key, it.second());
	in->add_child(key, tmp);
	read_config_doc(it.second(), tmp);
#endif
      }
    }

  } else if (doc.Type() == YAML::NodeType::Scalar) {
    if (doc.Tag() == "tag:fawkesrobotics.org,cfg/tcp-port" ||
	doc.Tag() == "tag:fawkesrobotics.org,cfg/udp-port")
    {
      unsigned int p = 0;
      try {
	p = node->get_uint();
      } catch (Exception &e) {
	e.prepend("YamlConfig: Invalid TCP/UDP port number (not an unsigned int)");
	throw;
      }
      if (p <= 0 || p >= 65535) {
	throw Exception("YamlConfig: Invalid TCP/UDP port number "
			"(%u out of allowed range)", p);
      }
    } else if (doc.Tag() == "tag:fawkesrobotics.org,cfg/url") {
#ifdef HAVE_YAMLCPP_0_5
      std::string scalar = doc.Scalar();
#else
      std::string scalar;
      doc.GetScalar(scalar);
#endif
#ifdef USE_REGEX_CPP
      if (regex_search(scalar, __url_regex)) {
#  if 0
	// just for emacs auto-indentation
      }
#  endif
#else
      if (regexec(&__url_regex, scalar.c_str(), 0, NULL, 0) == REG_NOMATCH) {
	throw Exception("YamlConfig: %s is not a valid URL", scalar.c_str());
      }
#endif
    } else if (doc.Tag() == "tag:fawkesrobotics.org,cfg/frame") {
#ifdef HAVE_YAMLCPP_0_5
      std::string scalar = doc.Scalar();
#else
      std::string scalar;
      doc.GetScalar(scalar);
#endif
#ifdef USE_REGEX_CPP
      if (regex_search(scalar, __frame_regex)) {
#  if 0
	// just for emacs auto-indentation
      }
#  endif
#else
      if (regexec(&__frame_regex, scalar.c_str(), 0, NULL, 0) == REG_NOMATCH) {
	throw Exception("YamlConfig: %s is not a valid frame ID", scalar.c_str());
      }
#endif
    }

  }
}
Example #18
0
static void yaml_traverse(struct VMGlobals* g, const YAML::Node & node, PyrObject *parent, PyrSlot *slot) {
	YAML::NodeType::value type = node.Type();
	string out;
	PyrObject *result = NULL;

	switch (type)
	{
		case YAML::NodeType::Scalar:
			node >> out;
			result = (PyrObject*)newPyrString(g->gc, out.c_str(), 0, true);
			SetObject(slot, result);
			if(parent) g->gc->GCWriteNew(parent, result); // we know result is white so we can use GCWriteNew
			break;

		case YAML::NodeType::Sequence:
			result = newPyrArray(g->gc, node.size(), 0, true);
			SetObject(slot, result);
			if(parent) g->gc->GCWriteNew(parent, result); // we know result is white so we can use GCWriteNew
			for (unsigned int i = 0; i < node.size(); i++) {
				const YAML::Node & subnode = node[i];
				result->size++;
				yaml_traverse(g, subnode, result, result->slots+i);
			}
			break;

		case YAML::NodeType::Map:
		{
			result = instantiateObject( g->gc, s_dictionary->u.classobj, 0, false, true );
			SetObject(slot, result);
			if(parent) g->gc->GCWriteNew(parent, result); // we know result is white so we can use GCWriteNew

			PyrObject *array = newPyrArray(g->gc, node.size()*2, 0, true);
			result->size = 2;
			SetObject(result->slots, array);      // array
			SetInt(result->slots+1, node.size()); // size
			g->gc->GCWriteNew(result, array); // we know array is white so we can use GCWriteNew

			int j = 0;
			for (YAML::Iterator i = node.begin(); i != node.end(); ++i) {
				const YAML::Node & key   = i.first();
				const YAML::Node & value = i.second();
				key >> out;
				PyrObject *pkey = (PyrObject*)newPyrString(g->gc, out.c_str(), 0, true);
				SetObject(array->slots+j, pkey);
				array->size++;
				g->gc->GCWriteNew(array, pkey); // we know pkey is white so we can use GCWriteNew

				array->size++;
				yaml_traverse(g, value, array, array->slots+j+1);

				j += 2;
			}
			break;
		}

		case YAML::NodeType::Null:
			SetNil(slot);
			break;

		default:
			postfl("WARNING: yaml_traverse(): unknown/unsupported node type\n");
			SetNil(slot);
	}
}
Example #19
0
    void Robots::loadYaml(string filename)
    {
        cout << endl << "Loading yaml configuration " << filename << endl;

        try
        {
            ifstream cfgfile(filename.c_str());
            if(!cfgfile)
                throw string("Failed to open file " + filename);

            YAML::Parser parser(cfgfile);
            YAML::Node doc;

            bool result = parser.GetNextDocument(doc);
            if(!result)
                throw string("Parser failed to load document");

            if(!doc.FindValue("robots"))
            {
                throw string("Config error : no robots entry in yaml doc");
            }
            else
            {
                YAML::Iterator it;
                int i;

                string name, host, environment, move;
                int port;
                vector<string> loadedMoves;

                for(it=doc["robots"].begin();it!=doc["robots"].end();++it)
                {
                    loadedMoves.clear();

                    // Name
                    it.first() >> name;
                    robots[name] = new Robot(new CommandsStore, name);

                    // Host & port
                    if(it.second().FindValue("host"))
                    {
                        if(it.second().FindValue("host"))
                            it.second()["host"] >> host;
                        else
                            host = "localhost";

                        if(it.second().FindValue("port")) {
                            it.second()["port"] >> port;
                        } else {
                            port = 7777;
                        }

                        robots[name]->connect(host.c_str(), port);
                    }

                    // Environment
                    if(it.second().FindValue("environment"))
                    {
                        it.second()["environment"] >> environment;
                        robots[name]->loadEnvironment(environment);
                    }
Example #20
0
	Result process()
	{
		if (const YAML::Node *n = m_entry.FindValue(kSkip))
			return kSkipped;

		if (const YAML::Node *n = m_entry.FindValue(kPath))
		{
			n->GetScalar(m_path);
		}
		else
		{
			logerr("no path specified, line %d", n->GetMark().line);
			return kManifestError;
		}

		if (const YAML::Node *n = m_entry.FindValue(kMD5Sum))
		{
			std::string md5 = md5sum(m_path);
			std::string expectedMD5;
			n->GetScalar(expectedMD5);
			if (md5 != expectedMD5)
			{
				logerr("md5 checksum differs from expected value");
				return kFailure;
			}
		}

		AFfilehandle file = afOpenFile(m_path.c_str(), "r", NULL);

		if (const YAML::Node *n = m_entry.FindValue(kInvalid))
		{
			if (!file)
				return kSuccess;
			logerr("opening invalid file did not fail as expected");
			return kFailure;
		}

		if (!file)
		{
			logerr("could not open file");
			return kFailure;
		}

		for (YAML::Iterator i = m_entry.begin(); i != m_entry.end(); ++i)
		{
			std::string key = i.first().to<std::string>();
			std::string value = i.second().to<std::string>();

			if (key == kFileFormat)
			{
				const char *fileFormat =
					(const char *) afQueryPointer(AF_QUERYTYPE_FILEFMT,
						AF_QUERY_LABEL, afGetFileFormat(file, NULL), 0, 0);
				assert(fileFormat);
				expect(key, std::string(fileFormat), value);
			}
			else if (key == kChannels)
			{
				int expectedChannels = atoi(value.c_str());
				expect(key, expectedChannels,
					afGetChannels(file, AF_DEFAULT_TRACK));
			}
			else if (key == kByteOrder)
			{
				int expectedByteOrder;
				if (value == kByteOrder_Big)
					expectedByteOrder = AF_BYTEORDER_BIGENDIAN;
				else if (value == kByteOrder_Little)
					expectedByteOrder = AF_BYTEORDER_LITTLEENDIAN;
				else
				{
					logerr("bad value for byte order: %s, line %d",
						value.c_str(),
						i.second().GetMark().line);
					return kManifestError;
				}

				expect(key, expectedByteOrder,
					afGetByteOrder(file, AF_DEFAULT_TRACK));
			}
			else if (key == kSampleRate)
			{
				double expectedSampleRate = atof(value.c_str());

				expect(key, expectedSampleRate,
					afGetRate(file, AF_DEFAULT_TRACK));
			}
			else if (key == kSampleFormat)
			{
				std::string width = value.substr(1, value.length() - 1);
				char format = value[0];

				int expectedSampleWidth = atoi(width.c_str());
				bool isValidSampleWidth =
					(expectedSampleWidth >= 1 && expectedSampleWidth <= 32) ||
					expectedSampleWidth == 64;
				if (!isValidSampleWidth)
				{
					logerr("bad value for sample format: %s, line %d",
						value.c_str(), i.second().GetMark().line);
					return kManifestError;
				}

				int expectedSampleFormat = -1;
				switch (format)
				{
					case 's':
						expectedSampleFormat = AF_SAMPFMT_TWOSCOMP; break;
					case 'u':
						expectedSampleFormat = AF_SAMPFMT_UNSIGNED; break;
					case 'f':
						if (expectedSampleWidth == 32)
							expectedSampleFormat = AF_SAMPFMT_FLOAT;
						else if (expectedSampleWidth == 64)
							expectedSampleFormat = AF_SAMPFMT_DOUBLE;
						break;
					default:
						logerr("bad value for sample format: %s, line %d",
							value.c_str(), i.second().GetMark().line);
						return kManifestError;
				}

				int sampleFormat, sampleWidth;
				afGetSampleFormat(file, AF_DEFAULT_TRACK, &sampleFormat, &sampleWidth);
				expect(key, expectedSampleFormat, sampleFormat);
				expect(key, expectedSampleWidth, sampleWidth);
			}
			else if (key == kCompression)
			{
				int expectedCompression;
				if (value == kCompression_None)
					expectedCompression = AF_COMPRESSION_NONE;
				else if (value == kCompression_IMA_ADPCM)
					expectedCompression = AF_COMPRESSION_IMA;
				else if (value == kCompression_MS_ADPCM)
					expectedCompression = AF_COMPRESSION_MS_ADPCM;
				else if (value == kCompression_ulaw)
					expectedCompression = AF_COMPRESSION_G711_ULAW;
				else if (value == kCompression_alaw)
					expectedCompression = AF_COMPRESSION_G711_ALAW;
				else if (value == kCompression_FLAC)
					expectedCompression = AF_COMPRESSION_FLAC;
				else if (value == kCompression_ALAC)
					expectedCompression = AF_COMPRESSION_ALAC;
				else
				{
					logerr("bad value for compression: %s, line %d",
						value.c_str(), i.second().GetMark().line);
					return kManifestError;
				}

				expect(key, expectedCompression,
					afGetCompression(file, AF_DEFAULT_TRACK));
			}
			else if (key == kFrames)
			{
				AFframecount expectedFrameCount = atoll(value.c_str());
				expect(key, expectedFrameCount,
					afGetFrameCount(file, AF_DEFAULT_TRACK));

				int bufferFrameCount = 1024;
				int channels = afGetChannels(file, AF_DEFAULT_TRACK);
				int maxBytesPerFrame = 8;
				char *buffer = new char[channels * bufferFrameCount * maxBytesPerFrame];
				AFframecount framesRead = 0;
				while (framesRead < expectedFrameCount)
				{
					AFframecount framesToRead = std::min<AFframecount>(bufferFrameCount,
						expectedFrameCount - framesRead);
					AFframecount result = afReadFrames(file, AF_DEFAULT_TRACK,
						buffer, framesToRead);
					if (result != framesToRead)
					{
						m_failures++;
						break;
					}
					framesRead += result;
				}
				delete [] buffer;
			}
			else if (key == kBytes)
			{
				AFfileoffset expectedTrackBytes = atoll(value.c_str());
				expect(key, expectedTrackBytes,
					afGetTrackBytes(file, AF_DEFAULT_TRACK));
			}
		}

		afCloseFile(file);

		return m_failures == 0 ? kSuccess : kFailure;
	}