1 /* 2 Operating system dependent functionality. 3 4 Copyright (C) 2013 AMPL Optimization Inc 5 6 Permission to use, copy, modify, and distribute this software and its 7 documentation for any purpose and without fee is hereby granted, 8 provided that the above copyright notice appear in all copies and that 9 both that the copyright notice and this permission notice and warranty 10 disclaimer appear in supporting documentation. 11 12 The author and AMPL Optimization Inc disclaim all warranties with 13 regard to this software, including all implied warranties of 14 merchantability and fitness. In no event shall the author be liable 15 for any special, indirect or consequential damages or any damages 16 whatsoever resulting from loss of use, data or profits, whether in an 17 action of contract, negligence or other tortious action, arising out 18 of or in connection with the use or performance of this software. 19 20 Author: Victor Zverovich 21 */ 22 23 #ifndef MP_OS_H_ 24 #define MP_OS_H_ 25 26 #include "mp/error.h" 27 #include "mp/posix.h" 28 29 namespace mp { 30 31 // This class provides a subset of boost filesystem's path API. 32 class path { 33 private: 34 std::string str_; 35 36 37 inline std::size_t FindLastSep() const { 38 #ifdef _WIN32 39 const char *sep = "/\\"; 40 #else 41 const char sep = '/'; 42 #endif 43 return str_.find_last_of(sep); 44 } 45 46 public: 47 #ifdef _WIN32 48 static const char preferred_separator = '\\'; 49 #else 50 static const char preferred_separator = '/'; 51 #endif 52 53 path() {} 54 explicit path(const std::string &s): str_(s) {} 55 path(const char *begin, const char *end) : str_(begin, end) {} 56 57 const std::string &string() const { return str_; } 58 59 60 path filename() const { 61 size_t last_sep = FindLastSep(); 62 return last_sep == std::string::npos ? 63 *this : path(str_.substr(last_sep + 1)); 64 } 65 66 path &remove_filename() { 67 size_t last_sep = FindLastSep(); 68 if (last_sep == 0) 69 ++last_sep; 70 str_.resize(last_sep != std::string::npos ? last_sep : 0); 71 return *this; 72 } 73 74 // Returns a path to the system-specific temporary directory. 75 static path temp_directory_path(); 76 }; 77 78 // Returns the path to the currently running executable file. 79 // Throws Error on error. 80 path GetExecutablePath(); 81 82 namespace internal { 83 class MemoryMappedFileBase { 84 private: 85 char *start_; 86 std::size_t size_; 87 88 FMT_DISALLOW_COPY_AND_ASSIGN(MemoryMappedFileBase); 89 90 protected: 91 MemoryMappedFileBase() : start_(), size_(0) {} 92 ~MemoryMappedFileBase() { 93 if (start_) 94 unmap(); 95 } 96 97 void map(int fd, std::size_t size); 98 void unmap(); 99 100 public: 101 const char *start() const { return start_; } 102 std::size_t size() const { return size_; } 103 }; 104 105 // Converts file size to mmap size. 106 inline std::size_t ConvertFileToMmapSize(fmt::LongLong file_size, 107 fmt::CStringRef filename) { 108 MP_ASSERT(file_size >= 0, "negative file size"); 109 fmt::ULongLong unsigned_file_size = file_size; 110 // Check if file size fits in size_t. 111 std::size_t size = static_cast<std::size_t>(unsigned_file_size); 112 if (size != unsigned_file_size) 113 throw Error("file {} is too big", filename); 114 return size; 115 } 116 } // namespace internal 117 118 template <typename File = fmt::File> 119 class MemoryMappedFile : public internal::MemoryMappedFileBase { 120 public: 121 MemoryMappedFile() {} 122 MemoryMappedFile(const File &file, std::size_t size) { 123 internal::MemoryMappedFileBase::map(file.descriptor(), size); 124 } 125 126 void map(const File &file, std::size_t size) { 127 if (start()) 128 unmap(); 129 internal::MemoryMappedFileBase::map(file.descriptor(), size); 130 } 131 132 void map(const File &file, fmt::CStringRef filename) { 133 map(file, internal::ConvertFileToMmapSize(file.size(), filename)); 134 } 135 }; 136 137 // The default buffer size. 138 enum { BUFFER_SIZE = 500 }; 139 } // namespace mp 140 141 #endif // MP_OS_H_ 142