Example #1
0
File * File::get_by_path(const string path)
{
    File * file = FileCache::instance().get_by_path(path);
    if (file != File::NOT_FOUND) {
        return file;
    }
    
    if (path == "/") {
        return Folder::get_by_id("folder:root");
    }
    
    StrArray path_secs = Utils::str_split(path, "/");
    
    if (path_secs.back() == "") { // path ended by '/'
        path_secs.pop_back();
    }
    
    if (path_secs.size() <= 1) {
        throw runtime_error("Invalid path: " + path);
    }
    
    string filename = path_secs.back();
    filename = Utils::filter_extension(filename);
    
    path_secs.pop_back();
    list<File *> files = get_by_title(filename);
    list<File *> files_cands = files;
    
    // filter files iterately by parent
    int depth = 1;
    do {
        list<File *> files_cands_new;
        string parent_name = path_secs.back();
        for (list<File *>::iterator i = files_cands.begin(); i != files_cands.end(); i++) {
            File * file_cand = *i;
            // TODO memory leak optmize root
            Folder * parent = file_cand->get_parent();
            for (int i = 1; i < depth; i++) {
                parent = parent->get_parent();
            }
            if (parent->title == parent_name) {
                files_cands_new.push_back(file_cand);
            }
        }
        path_secs.pop_back();
        files_cands = files_cands_new;
        depth++;
    } while (files_cands.size() > 1 && path_secs.size() >= 1);
    
    file = NULL;
    // target file found
    if (files_cands.size() == 1) {
        file = files_cands.front();
    }
    
    // cache all other files
    for (list<File *>::iterator i = files.begin(); i != files.end(); i++) {
        File * file_cand = *i;
        if (file_cand != file) { // except for the target file
            FileCache::instance().save(file_cand);
        }
    }
    
    FileCache::instance().save(file, path);
    
    return file;
}