1#include <mbgl/storage/local_file_source.hpp>
2#include <mbgl/storage/file_source_request.hpp>
3#include <mbgl/storage/response.hpp>
4#include <mbgl/util/string.hpp>
5#include <mbgl/util/thread.hpp>
6#include <mbgl/util/url.hpp>
7#include <mbgl/util/util.hpp>
8#include <mbgl/util/io.hpp>
9
10#include <sys/types.h>
11#include <sys/stat.h>
12
13#if defined(_WINDOWS) && !defined(S_ISDIR)
14#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
15#endif
16
17namespace {
18
19const std::string fileProtocol = "file://";
20
21} // namespace
22
23namespace mbgl {
24
25class LocalFileSource::Impl {
26public:
27 Impl(ActorRef<Impl>) {}
28
29 void request(const std::string& url, ActorRef<FileSourceRequest> req) {
30 Response response;
31
32 if (!acceptsURL(url)) {
33 response.error = std::make_unique<Response::Error>(args: Response::Error::Reason::Other,
34 args: "Invalid file URL");
35 req.invoke(fn: &FileSourceRequest::setResponse, args&: response);
36 return;
37 }
38
39 // Cut off the protocol and prefix with path.
40 const auto path = mbgl::util::percentDecode(url.substr(pos: fileProtocol.size()));
41 struct stat buf;
42 int result = stat(file: path.c_str(), buf: &buf);
43
44 if (result == 0 && S_ISDIR(buf.st_mode)) {
45 response.error = std::make_unique<Response::Error>(args: Response::Error::Reason::NotFound);
46 } else if (result == -1 && errno == ENOENT) {
47 response.error = std::make_unique<Response::Error>(args: Response::Error::Reason::NotFound);
48 } else {
49 try {
50 response.data = std::make_shared<std::string>(args: util::read_file(filename: path));
51 } catch (...) {
52 response.error = std::make_unique<Response::Error>(
53 args: Response::Error::Reason::Other,
54 args: util::toString(error: std::current_exception()));
55 }
56 }
57
58 req.invoke(fn: &FileSourceRequest::setResponse, args&: response);
59 }
60
61};
62
63LocalFileSource::LocalFileSource()
64 : impl(std::make_unique<util::Thread<Impl>>(args: "LocalFileSource")) {
65}
66
67LocalFileSource::~LocalFileSource() = default;
68
69std::unique_ptr<AsyncRequest> LocalFileSource::request(const Resource& resource, Callback callback) {
70 auto req = std::make_unique<FileSourceRequest>(args: std::move(callback));
71
72 impl->actor().invoke(fn: &Impl::request, args: resource.url, args: req->actor());
73
74 return std::move(req);
75}
76
77bool LocalFileSource::acceptsURL(const std::string& url) {
78 return std::equal(first1: fileProtocol.begin(), last1: fileProtocol.end(), first2: url.begin());
79}
80
81} // namespace mbgl
82

source code of qtlocation/src/3rdparty/mapbox-gl-native/platform/default/local_file_source.cpp