1 // Copyright 2015 The Shaderc Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "libshaderc_util/file_finder.h" 16 #include "libshaderc_util/string_piece.h" 17 18 #include <cassert> 19 #include <fstream> 20 #include <ios> 21 22 namespace { 23 24 // Returns "" if path is empty or ends in '/'. Otherwise, returns "/". 25 std::string MaybeSlash(const shaderc_util::string_piece& path) { 26 return (path.empty() || path.back() == '/') ? "" : "/"; 27 } 28 29 } // anonymous namespace 30 31 namespace shaderc_util { 32 33 std::string FileFinder::FindReadableFilepath( 34 const std::string& filename) const { 35 assert(!filename.empty()); 36 static const auto for_reading = std::ios_base::in; 37 std::filebuf opener; 38 for (const auto& prefix : search_path_) { 39 const std::string prefixed_filename = 40 prefix + MaybeSlash(prefix) + filename; 41 if (opener.open(prefixed_filename, for_reading)) return prefixed_filename; 42 } 43 return ""; 44 } 45 46 std::string FileFinder::FindRelativeReadableFilepath( 47 const std::string& requesting_file, const std::string& filename) const { 48 assert(!filename.empty()); 49 50 string_piece dir_name(requesting_file); 51 52 size_t last_slash = requesting_file.find_last_of("/\\"); 53 if (last_slash != std::string::npos) { 54 dir_name = string_piece(requesting_file.c_str(), 55 requesting_file.c_str() + last_slash); 56 } 57 58 if (dir_name.size() == requesting_file.size()) { 59 dir_name.clear(); 60 } 61 62 static const auto for_reading = std::ios_base::in; 63 std::filebuf opener; 64 const std::string relative_filename = 65 dir_name.str() + MaybeSlash(dir_name) + filename; 66 if (opener.open(relative_filename, for_reading)) return relative_filename; 67 68 return FindReadableFilepath(filename); 69 } 70 71 } // namespace shaderc_util 72