std::string URI::normalize()

in activemq-cpp/src/main/decaf/net/URI.cpp [594:694]


std::string URI::normalize(const std::string& path) const {

    if (path == "") {
        return path;
    }

    // count the number of '/'s, to determine number of segments
    std::size_t index = -1;
    std::size_t pathlen = path.length();
    unsigned int size = 0;

    if (pathlen > 0 && path.at(0) != '/') {
        size++;
    }

    while ((index = path.find('/', index + 1)) != string::npos) {
        if (index + 1 < pathlen && path.at(index + 1) != '/') {
            size++;
        }
    }

    std::vector<string> seglist(size);
    std::vector<bool> include(size);

    // break the path into segments and store in the list
    std::size_t current = 0;
    std::size_t index2 = 0;

    index = (pathlen > 0 && path.at(0) == '/') ? 1 : 0;
    while ((index2 = path.find('/', index + 1)) != string::npos) {
        seglist[current++] = path.substr(index, index2 - index);
        index = index2 + 1;
    }

    // if current==size, then the last character was a slash
    // and there are no more segments
    if (current < size) {
        seglist[current] = path.substr(index);
    }

    // determine which segments get included in the normalized path
    for (unsigned int i = 0; i < size; i++) {

        include[i] = true;

        if (seglist[i] == "..") {

            int remove = i - 1;

            // search back to find a segment to remove, if possible
            while (remove > -1 && !include[remove]) {
                remove--;
            }

            // if we find a segment to remove, remove it and the ".."
            // segment
            if (remove > -1 && !(seglist[remove] == "..")) {
                include[remove] = false;
                include[i] = false;
            }

        } else if (seglist[i] == ".") {
            include[i] = false;
        }
    }

    // put the path back together
    string newpath;
    if (path.at(0) == '/') {
        newpath.append("/");
    }

    for (unsigned int i = 0; i < seglist.size(); i++) {
        if (include[i]) {
            newpath.append(seglist[i]);
            newpath.append("/");
        }
    }

    // if we used at least one segment and the path previously ended with
    // a slash and the last segment is still used, then delete the extra
    // trailing '/'
    if (path.at(path.length() - 1) != '/' && seglist.size() > 0 && include[seglist.size() - 1]) {

        newpath.erase(newpath.length() - 1, 1);
    }

    string result = newpath;

    // check for a ':' in the first segment if one exists,
    // prepend "./" to normalize
    index = result.find(':');
    index2 = result.find('/');

    if (index != string::npos && (index < index2 || index2 == string::npos)) {
        newpath.insert(0, "./");
        result = newpath;
    }

    return result;
}