Exemplo n.º 1
0
const Raul::Path
ClashAvoider::map_path(const Raul::Path& in)
{
    unsigned offset = 0;
    bool has_offset = false;
    const size_t pos = in.find_last_of('_');
    if (pos != string::npos && pos != (in.length()-1)) {
        const std::string trailing = in.substr(pos + 1);
        has_offset = (sscanf(trailing.c_str(), "%u", &offset) > 0);
    }

    // Path without _n suffix
    std::string base_path_str = in;
    if (has_offset) {
        base_path_str = base_path_str.substr(0, base_path_str.find_last_of('_'));
    }

    Raul::Path base_path(base_path_str);

    SymbolMap::iterator m = _symbol_map.find(in);
    if (m != _symbol_map.end()) {
        return m->second;
    } else {
        typedef std::pair<SymbolMap::iterator, bool> InsertRecord;

        // See if parent is mapped
        Raul::Path parent = in.parent();
        do {
            SymbolMap::iterator p = _symbol_map.find(parent);
            if (p != _symbol_map.end()) {
                const Raul::Path mapped = Raul::Path(
                                              p->second.base() + in.substr(parent.base().length()));
                InsertRecord i = _symbol_map.insert(make_pair(in, mapped));
                return i.first->second;
            }
            parent = parent.parent();
        } while (!parent.is_root());

        if (!exists(in) && _symbol_map.find(in) == _symbol_map.end()) {
            // No clash, use symbol unmodified
            InsertRecord i = _symbol_map.insert(make_pair(in, in));
            assert(i.second);
            return i.first->second;

        } else {
            // Append _2 _3 etc until an unused symbol is found
            while (true) {
                Offsets::iterator o = _offsets.find(base_path);
                if (o != _offsets.end()) {
                    offset = ++o->second;
                } else {
                    string parent_str = in.parent().base();
                    parent_str = parent_str.substr(0, parent_str.find_last_of("/"));
                    if (parent_str.empty())
                        parent_str = "/";
                }

                if (offset == 0)
                    offset = 2;

                std::stringstream ss;
                ss << base_path << "_" << offset;
                if (!exists(Raul::Path(ss.str()))) {
                    std::string name = base_path.symbol();
                    if (name == "")
                        name = "_";
                    Raul::Symbol sym(name);
                    string str = ss.str();
                    InsertRecord i = _symbol_map.insert(
                                         make_pair(in, Raul::Path(str)));
                    offset = _store.child_name_offset(in.parent(), sym, false);
                    _offsets.insert(make_pair(base_path, offset));
                    return i.first->second;
                } else {
                    if (o != _offsets.end())
                        offset = ++o->second;
                    else
                        ++offset;
                }
            }
        }
    }
}