kastnermario / yaml-cpp

Automatically exported from code.google.com/p/yaml-cpp
MIT License
0 stars 0 forks source link

Default constructor for YAML::Parser #46

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
It would be nice if YAML::Parser provided a default constructor, so you
could assign it a stream later with parser.Load - this would be useful in
order to use the parser as a class member, when the stream-to-be-read can
not be constructed in the initializer list.

Original issue reported on code.google.com by stefan.walk on 30 Sep 2009 at 10:59

GoogleCodeExporter commented 8 years ago
The parser isn't really intended to be used as a class member - more of a 
one-off
type thing. One problem is that the stream must stick around as long as you're
parsing. So if you did the very plausible:

struct foo {
   YAML::Parser parser;
   // ...
};

foo::init() {
   std::ifstream fin("file.yaml");
   parser.Load(fin);
}

foo::dostuff() {
   YAML::Node doc;
   parser.GetNextDocument(doc);  // FAILS!!!
}

because when `GetNextDocument` is called, the stream is no longer valid. Why do 
you
want the parser as a class member?

Original comment by jbe...@gmail.com on 1 Oct 2009 at 2:18

GoogleCodeExporter commented 8 years ago
example code: (working now)

struct YAMLStreamer : BBStreamer {
    typedef std::vector<BoundingBox>::iterator iterator;
    boost::filesystem::ifstream file_in;
    boost::iostreams::filtering_stream<io::input> in;
    boost::scoped_ptr<YAML::Parser> parser;
    YAML::Node doc;
    GTImage img;
    YAMLStreamer(std::string const& filename) : file_in(filename) 
    {
        in.push(boost::iostreams::gzip_decompressor());
        in.push(file_in);
        parser.reset(new YAML::Parser(in));
    }
    bool advance() 
    {
        if (!*parser)
            return false;
        img = GTImage();
        parser->GetNextDocument(doc);
        doc >> img;
        return true;
    }
    iterator begin() 
    {
        return img.labels.begin();
    }
    iterator end() 
    {
        return img.labels.end();
    }
    std::string& get_filename()
    {
        return img.file;
    }
};

BBStreamer is just an abstract base class, there are streams for other file 
types
too. You basically give it a filename, it figures out if the file is compressed 
(code
for that is removed for clarity), applies decompression filters and passes the
filtered stream to the parser. The boost::scoped_ptr (deletes the parser when 
the ptr
goes out of scope) would be unneccessary if the parser could be used as a member
directly. So in this case, the stream is a member of the class too, but because 
i
must first prepare it before i can pass it to the parser i can't do so in the
initializer list ...

Original comment by stefan.walk on 1 Oct 2009 at 2:37

GoogleCodeExporter commented 8 years ago
OK, I implemented this in r277. You're right, it is useful to have a default
constructor; but I don't think I'm going to add this info to the wiki (yet) 
because I
want to encourage the single parameter construction. I'm not a huge fan of 
"zombie"
objects, but the operator bool() does take into account whether it's been 
initialized
yet.

Original comment by jbe...@gmail.com on 19 Oct 2009 at 10:44