Opened 11 years ago

Last modified 11 years ago

#5588 new Bugs

property_tree INFO include directive

Reported by: sarum9in@… Owned by: Sebastian Redl
Milestone: To Be Determined Component: property_tree
Version: Boost 1.46.1 Severity: Problem
Keywords: Cc:

Description

When you use #include in C/C++ programs, preprocessor uses path relative to file, where you used '#include'. But in read_info realization '#include' finds file using path, relative to current work directory. So, when you create some complex config structure, you have to you absolute pathes or change current work directory to config file.

Attachments (1)

path_resolver.patch (9.5 KB ) - added by Filippov Aleksey <sarum9in@…> 11 years ago.
path_resolver patch

Download all attachments as: .zip

Change History (5)

comment:1 by Sebastian Redl, 11 years ago

Good point, but I can't fix this without introducing a dependency on Filesystem, which requires building. Not sure if I want to do that.

in reply to:  1 comment:2 by sarum9in@…, 11 years ago

Replying to cornedbee:

Good point, but I can't fix this without introducing a dependency on Filesystem, which requires building. Not sure if I want to do that.

Nevertheless it is possible to reimplement read_info function in the following way: we can introduce template argument (some functor), that will perform path resolving. Also we can provide default path-resolver that will behave as current implementation. Path-resolver that depends on boost::filesystem can be placed into separate header. Only and only if user wants to use this path-resolver the boost::filesystem dependency will be introduced.

If this idea seems good for you, I can try to create a patch.

comment:3 by Sebastian Redl, 11 years ago

Sounds good to me.

by Filippov Aleksey <sarum9in@…>, 11 years ago

Attachment: path_resolver.patch added

path_resolver patch

comment:4 by Filippov Aleksey <sarum9in@…>, 11 years ago

While I was changing current implementation I went to the following architecture:

We can implement event-like class that will receive the following events: enter(std::string) and exit(), also this class will provide a query method: resolve(std::string) -> std::string.

We can use this in the following way: let's introduce new template argument to every read_info function named PathResolver. Such functions will accept PathResolver instances as their last argument:

template<class Ptree, class Ch, class PathResolver>
void read_info(std::basic_istream<Ch> &stream, Ptree &pt,
               PathResolver &path_resolver)
{
    //...
}

We should also provide overloads with old interface for every such read_info function:

template<class Ptree, class Ch>
void read_info(std::basic_istream<Ch> &stream, Ptree &pt)
{
	default_path_resolver pr;
	read_info(stream, pt, pr);
}

Let's reimplement read_info_internal in the following way:

template<class Ptree, class Ch, class PathResolver>
void read_info_internal(std::basic_istream<Ch> &stream,
                        Ptree &pt,
                        const std::string &filename,
                        PathResolver &path_resolver,
                        int include_depth)
{
    //...
    std::basic_ifstream<Ch> inc_stream(
        path_resolver.resolve(inc_name.c_str()));
    //...
    path_resolver.enter(inc_name);
    read_info_internal(/*...*/);
    path_resolver.exit();
    //...
}

There is a case when we do not know the real file name, for example if user passes std::istream-like object. In that case PathResolver has to implement enter() method (without arguments).

As you has noticed, I used non-const references in code. In my opinion it should be done in that way because PathResolver can have inner state. It is much simplier and efficientlier to pass object by reference rather than implementing inner share-state for (PathResolver path_resolver) signature or (const PathResolver &path_resolver) one. Please note, that my changes will not break any legacy code. I have provided old-style overloads with default_path_resolver.

I do not think this changes are completed. I tried to show you only idea. My code is still unchecked and probably have bugs.

One question I have: how user should access standard path resolvers? Should we export them like read_info functions to boost::property_tree namespace? Or should we do something else?

P.S. In my opinion publishing code that is being at developing stage only to bugtracker is not a good idea. I have created public git repository to share my code, if you can't watch it through git, I have created a patch.

git repository is located at http://cs.istu.ru/gitweb/?p=boost.git;a=summary.

Note: See TracTickets for help on using tickets.