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