RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
FileReader.cpp
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2009-2014 Klaus Post
5 Copyright (C) 2017 Roman Lebedev
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20*/
21
22#include "io/FileReader.h"
24#include "adt/Casts.h"
26#include "io/Buffer.h"
27#include "io/FileIOException.h"
28#include <cstdint>
29#include <cstdio>
30#include <limits>
31#include <memory>
32#include <utility>
33#include <vector>
34
35#if !(defined(__unix__) || defined(__APPLE__))
36#ifndef NOMINMAX
37#define NOMINMAX // do not want the min()/max() macros!
38#endif
39
40#include "io/FileIO.h"
41#include <Windows.h>
42#include <io.h>
43#include <tchar.h>
44#endif
45
46namespace rawspeed {
47
48std::pair<std::unique_ptr<std::vector<
49 uint8_t, DefaultInitAllocatorAdaptor<
50 uint8_t, AlignedAllocator<uint8_t, 16>>>>,
51 Buffer>
53 size_t fileSize = 0;
54
55#if defined(__unix__) || defined(__APPLE__)
56 auto fclose = [](std::FILE* fp) { std::fclose(fp); };
57 using file_ptr = std::unique_ptr<FILE, decltype(fclose)>;
58 file_ptr file(fopen(fileName, "rb"), fclose);
59
60 if (file == nullptr)
61 ThrowFIE("Could not open file \"%s\".", fileName);
62
63 if (fseek(file.get(), 0, SEEK_END) == -1)
64 ThrowFIE("Could not rewind to the end of the file");
65
66 const auto size = ftell(file.get());
67 if (size == -1)
68 ThrowFIE("Could not obtain the file size");
69
70 if (size <= 0)
71 ThrowFIE("File is 0 bytes.");
72
73 if (static_cast<int64_t>(size) >
74 std::numeric_limits<Buffer::size_type>::max())
75 ThrowFIE("File is too big (%zu bytes).", fileSize);
76
77 fileSize = size;
78
79 if (fseek(file.get(), 0, SEEK_SET) == -1)
80 ThrowFIE("Could not rewind to the beginning of the file");
81
82 auto dest = std::make_unique<std::vector<
83 uint8_t,
85 fileSize);
86
87 auto bytes_read = fread(dest->data(), 1, fileSize, file.get());
88 if (ferror(file.get()))
89 ThrowFIE("Could not read file, file reading error");
90 if (feof(file.get()))
91 ThrowFIE("Could not read file, reached end-of-file");
92 if (fileSize != bytes_read)
93 ThrowFIE("Could not read file, unknown problem");
94
95#else // __unix__
96
97 auto wFileName = widenFileName(fileName);
98
99 using file_ptr = std::unique_ptr<std::remove_pointer<HANDLE>::type,
100 decltype(&CloseHandle)>;
101 file_ptr file(CreateFileW(wFileName.data(), GENERIC_READ, FILE_SHARE_READ,
102 nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN,
103 nullptr),
104 &CloseHandle);
105
106 if (file.get() == INVALID_HANDLE_VALUE)
107 ThrowFIE("Could not open file \"%s\".", fileName);
108
109 LARGE_INTEGER size;
110 GetFileSizeEx(file.get(), &size);
111
112 static_assert(
113 std::numeric_limits<Buffer::size_type>::max() ==
114 std::numeric_limits<decltype(size.LowPart)>::max(),
115 "once Buffer migrates to 64-bit index, this needs to be updated.");
116
117 if (size.HighPart > 0)
118 ThrowFIE("File is too big.");
119 if (size.LowPart <= 0)
120 ThrowFIE("File is 0 bytes.");
121
122 auto dest = std::make_unique<std::vector<
123 uint8_t,
125 size.LowPart);
126
127 DWORD bytes_read;
128 if (!ReadFile(file.get(), dest->data(), size.LowPart, &bytes_read, nullptr))
129 ThrowFIE("Could not read file.");
130
131 if (size.LowPart != bytes_read)
132 ThrowFIE("Could not read file.");
133
134 fileSize = size.LowPart;
135
136#endif // __unix__
137
138 return {std::move(dest),
139 Buffer(dest->data(), implicit_cast<Buffer::size_type>(fileSize))};
140}
141
142} // namespace rawspeed
#define ThrowFIE(...)
std::pair< std::unique_ptr< std::vector< uint8_t, DefaultInitAllocatorAdaptor< uint8_t, AlignedAllocator< uint8_t, 16 > > > >, Buffer > readFile() const
const char * fileName
Definition FileReader.h:37
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
std::wstring widenFileName(const char *fileName)
Definition FileIO.h:35