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; }