mirror of
				https://github.com/PaddlePaddle/FastDeploy.git
				synced 2025-10-31 11:56:44 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			202 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			202 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # Introduction #
 | |
| 
 | |
| A typical example, loading a configuration file, might look like this:
 | |
| 
 | |
| ```cpp
 | |
| YAML::Node config = YAML::LoadFile("config.yaml");
 | |
| 
 | |
| if (config["lastLogin"]) {
 | |
|   std::cout << "Last logged in: " << config["lastLogin"].as<DateTime>() << "\n";
 | |
| }
 | |
| 
 | |
| const std::string username = config["username"].as<std::string>();
 | |
| const std::string password = config["password"].as<std::string>();
 | |
| login(username, password);
 | |
| config["lastLogin"] = getCurrentDateTime();
 | |
| 
 | |
| std::ofstream fout("config.yaml");
 | |
| fout << config;
 | |
| ```
 | |
| 
 | |
| # Basic Parsing and Node Editing #
 | |
| 
 | |
| All nodes in a YAML document (including the root) are represented by `YAML::Node`. You can check what kind it is:
 | |
| 
 | |
| ```cpp
 | |
| YAML::Node node = YAML::Load("[1, 2, 3]");
 | |
| assert(node.Type() == YAML::NodeType::Sequence);
 | |
| assert(node.IsSequence());  // a shortcut!
 | |
| ```
 | |
| 
 | |
| Collection nodes (sequences and maps) act somewhat like STL vectors and maps:
 | |
| 
 | |
| ```cpp
 | |
| YAML::Node primes = YAML::Load("[2, 3, 5, 7, 11]");
 | |
| for (std::size_t i=0;i<primes.size();i++) {
 | |
|   std::cout << primes[i].as<int>() << "\n";
 | |
| }
 | |
| // or:
 | |
| for (YAML::const_iterator it=primes.begin();it!=primes.end();++it) {
 | |
|   std::cout << it->as<int>() << "\n";
 | |
| }
 | |
| 
 | |
| primes.push_back(13);
 | |
| assert(primes.size() == 6);
 | |
| ```
 | |
| 
 | |
| and
 | |
| 
 | |
| ```cpp
 | |
| YAML::Node lineup = YAML::Load("{1B: Prince Fielder, 2B: Rickie Weeks, LF: Ryan Braun}");
 | |
| for(YAML::const_iterator it=lineup.begin();it!=lineup.end();++it) {
 | |
|   std::cout << "Playing at " << it->first.as<std::string>() << " is " << it->second.as<std::string>() << "\n";
 | |
| }
 | |
| 
 | |
| lineup["RF"] = "Corey Hart";
 | |
| lineup["C"] = "Jonathan Lucroy";
 | |
| assert(lineup.size() == 5);
 | |
| ```
 | |
| 
 | |
| Querying for keys does **not** create them automatically (this makes handling optional map entries very easy)
 | |
| 
 | |
| ```cpp
 | |
| YAML::Node node = YAML::Load("{name: Brewers, city: Milwaukee}");
 | |
| if (node["name"]) {
 | |
|   std::cout << node["name"].as<std::string>() << "\n";
 | |
| }
 | |
| if (node["mascot"]) {
 | |
|   std::cout << node["mascot"].as<std::string>() << "\n";
 | |
| }
 | |
| assert(node.size() == 2); // the previous call didn't create a node
 | |
| ```
 | |
| 
 | |
| If you're not sure what kind of data you're getting, you can query the type of a node:
 | |
| 
 | |
| ```cpp
 | |
| switch (node.Type()) {
 | |
|   case Null: // ...
 | |
|   case Scalar: // ...
 | |
|   case Sequence: // ...
 | |
|   case Map: // ...
 | |
|   case Undefined: // ...
 | |
| }
 | |
| ```
 | |
| 
 | |
| or ask directly whether it's a particular type, e.g.:
 | |
| 
 | |
| ```cpp
 | |
| if (node.IsSequence()) {
 | |
|   // ...
 | |
| }
 | |
| ```
 | |
| 
 | |
| # Building Nodes #
 | |
| 
 | |
| You can build `YAML::Node` from scratch:
 | |
| 
 | |
| ```cpp
 | |
| YAML::Node node;  // starts out as null
 | |
| node["key"] = "value";  // it now is a map node
 | |
| node["seq"].push_back("first element");  // node["seq"] automatically becomes a sequence
 | |
| node["seq"].push_back("second element");
 | |
| 
 | |
| node["mirror"] = node["seq"][0];  // this creates an alias
 | |
| node["seq"][0] = "1st element";  // this also changes node["mirror"]
 | |
| node["mirror"] = "element #1";  // and this changes node["seq"][0] - they're really the "same" node
 | |
| 
 | |
| node["self"] = node;  // you can even create self-aliases
 | |
| node[node["mirror"]] = node["seq"];  // and strange loops :)
 | |
| ```
 | |
| 
 | |
| The above node is now:
 | |
| 
 | |
| ```yaml
 | |
| &1
 | |
| key: value
 | |
| &2 seq: [&3 "element #1", second element]
 | |
| mirror: *3
 | |
| self: *1
 | |
| *3 : *2
 | |
| ```
 | |
| 
 | |
| # How Sequences Turn Into Maps #
 | |
| 
 | |
| Sequences can be turned into maps by asking for non-integer keys. For example,
 | |
| 
 | |
| ```cpp
 | |
| YAML::Node node  = YAML::Load("[1, 2, 3]");
 | |
| node[1] = 5;  // still a sequence, [1, 5, 3]
 | |
| node.push_back(-3) // still a sequence, [1, 5, 3, -3]
 | |
| node["key"] = "value"; // now it's a map! {0: 1, 1: 5, 2: 3, 3: -3, key: value}
 | |
| ```
 | |
| 
 | |
| Indexing a sequence node by an index that's not in its range will _usually_ turn it into a map, but if the index is one past the end of the sequence, then the sequence will grow by one to accommodate it. (That's the **only** exception to this rule.) For example,
 | |
| 
 | |
| ```cpp
 | |
| YAML::Node node = YAML::Load("[1, 2, 3]");
 | |
| node[3] = 4; // still a sequence, [1, 2, 3, 4]
 | |
| node[10] = 10;  // now it's a map! {0: 1, 1: 2, 2: 3, 3: 4, 10: 10}
 | |
| ```
 | |
| 
 | |
| # Converting To/From Native Data Types #
 | |
| 
 | |
| Yaml-cpp has built-in conversion to and from most built-in data types, as well as `std::vector`, `std::list`, and `std::map`. The following examples demonstrate when those conversions are used:
 | |
| 
 | |
| ```cpp
 | |
| YAML::Node node = YAML::Load("{pi: 3.14159, [0, 1]: integers}");
 | |
| 
 | |
| // this needs the conversion from Node to double
 | |
| double pi = node["pi"].as<double>();
 | |
| 
 | |
| // this needs the conversion from double to Node
 | |
| node["e"] = 2.71828;
 | |
| 
 | |
| // this needs the conversion from Node to std::vector<int> (*not* the other way around!)
 | |
| std::vector<int> v;
 | |
| v.push_back(0);
 | |
| v.push_back(1);
 | |
| std::string str = node[v].as<std::string>();
 | |
| ```
 | |
| 
 | |
| To use yaml-cpp with your own data types, you need to specialize the YAML::convert<> template class. For example, suppose you had a simple `Vec3` class:
 | |
| 
 | |
| ```cpp
 | |
| struct Vec3 { double x, y, z; /* etc - make sure you have overloaded operator== */ };
 | |
| ```
 | |
| 
 | |
| You could write
 | |
| 
 | |
| ```cpp
 | |
| namespace YAML {
 | |
| template<>
 | |
| struct convert<Vec3> {
 | |
|   static Node encode(const Vec3& rhs) {
 | |
|     Node node;
 | |
|     node.push_back(rhs.x);
 | |
|     node.push_back(rhs.y);
 | |
|     node.push_back(rhs.z);
 | |
|     return node;
 | |
|   }
 | |
| 
 | |
|   static bool decode(const Node& node, Vec3& rhs) {
 | |
|     if(!node.IsSequence() || node.size() != 3) {
 | |
|       return false;
 | |
|     }
 | |
| 
 | |
|     rhs.x = node[0].as<double>();
 | |
|     rhs.y = node[1].as<double>();
 | |
|     rhs.z = node[2].as<double>();
 | |
|     return true;
 | |
|   }
 | |
| };
 | |
| }
 | |
| ```
 | |
| 
 | |
| Then you could use `Vec3` wherever you could use any other type:
 | |
| 
 | |
| ```cpp
 | |
| YAML::Node node = YAML::Load("start: [1, 3, 0]");
 | |
| Vec3 v = node["start"].as<Vec3>();
 | |
| node["end"] = Vec3(2, -1, 0);
 | |
| ```
 | 
