1
2
3
4
5
6 #include <soulng/util/MappedInputFile.hpp>
7 #include <soulng/util/FileLocking.hpp>
8 #include <boost/filesystem.hpp>
9 #include <boost/iostreams/device/mapped_file.hpp>
10 #include <stdexcept>
11
12 namespace soulng { namespace util {
13
14 class MappedInputFileImpl
15 {
16 public:
17 MappedInputFileImpl(const std::string& fileName);
18 const char* Data() const { return mappedFile.const_data(); }
19 boost::iostreams::mapped_file_source::size_type Size() const { return mappedFile.size(); }
20 private:
21 boost::iostreams::mapped_file mappedFile;
22 };
23
24 MappedInputFileImpl::MappedInputFileImpl(const std::string& fileName) : mappedFile()
25 {
26 try
27 {
28 LockFile(fileName, LockKind::read);
29 mappedFile.open(fileName, boost::iostreams::mapped_file::mapmode::readonly);
30 }
31 catch (std::exception& ex;)
32 {
33 throw std::runtime_error("error opening mapped file '" + fileName + "': " + ex.what());
34 }
35 catch (...)
36 {
37 throw std::runtime_error("error opening mapped file '" + fileName + "'");
38 }
39 }
40
41 MappedInputFile::MappedInputFile(const std::string& fileName_) : fileName(fileName_), impl(new MappedInputFileImpl(fileName))
42 {
43 }
44
45 MappedInputFile::~MappedInputFile()
46 {
47 delete impl;
48 UnlockFile(fileName, LockKind::read);
49 }
50
51 const char* MappedInputFile::Begin() const
52 {
53 const char* start = impl->Data();
54 if (impl->Size() >= 3)
55 {
56 if ((unsigned char)start[0] == (unsigned char)0xEF &&
57 (unsigned char)start[1] == (unsigned char)0xBB &&
58 (unsigned char)start[2] == (unsigned char)0xBF)
59 {
60 start += 3;
61 }
62 }
63 return start;
64 }
65
66 const char* MappedInputFile::End() const
67 {
68 return impl->Data() + impl->Size();
69 }
70
71 std::string ReadFile(const std::string& fileName)
72 {
73 if (!boost::filesystem::exists(fileName))
74 {
75 throw std::runtime_error("file '" + fileName + "' does not exist");
76 }
77 if (boost::filesystem::file_size(fileName) == 0)
78 {
79 return std::string();
80 }
81 MappedInputFile mappedFile(fileName);
82 return std::string(mappedFile.Begin(), mappedFile.End());
83 }
84
85 } }