1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "flutter/fml/paths.h"
6
7 #include <windows.h>
8 #include <algorithm>
9
10 #include "flutter/fml/paths.h"
11
12 namespace fml {
13 namespace paths {
14
15 namespace {
16
17 constexpr char kFileURLPrefix[] = "file:///";
18 constexpr size_t kFileURLPrefixLength = sizeof(kFileURLPrefix) - 1;
19
RootLength(const std::string & path)20 size_t RootLength(const std::string& path) {
21 if (path.size() == 0)
22 return 0;
23 if (path[0] == '/')
24 return 1;
25 if (path[0] == '\\') {
26 if (path.size() < 2 || path[1] != '\\')
27 return 1;
28 // The path is a network share. Search for up to two '\'s, as they are
29 // the server and share - and part of the root part.
30 size_t index = path.find('\\', 2);
31 if (index > 0) {
32 index = path.find('\\', index + 1);
33 if (index > 0)
34 return index;
35 }
36 return path.size();
37 }
38 // If the path is of the form 'C:/' or 'C:\', with C being any letter, it's
39 // a root part.
40 if (path.length() >= 2 && path[1] == ':' &&
41 (path[2] == '/' || path[2] == '\\') &&
42 ((path[0] >= 'A' && path[0] <= 'Z') ||
43 (path[0] >= 'a' && path[0] <= 'z'))) {
44 return 3;
45 }
46 return 0;
47 }
48
LastSeparator(const std::string & path)49 size_t LastSeparator(const std::string& path) {
50 return path.find_last_of("/\\");
51 }
52
53 } // namespace
54
GetExecutableDirectoryPath()55 std::pair<bool, std::string> GetExecutableDirectoryPath() {
56 HMODULE module = GetModuleHandle(NULL);
57 if (module == NULL) {
58 return {false, ""};
59 }
60 char path[MAX_PATH];
61 DWORD read_size = GetModuleFileNameA(module, path, MAX_PATH);
62 if (read_size == 0 || read_size == MAX_PATH) {
63 return {false, ""};
64 }
65 return {true, GetDirectoryName(std::string{path, read_size})};
66 }
67
AbsolutePath(const std::string & path)68 std::string AbsolutePath(const std::string& path) {
69 char absPath[MAX_PATH];
70 _fullpath(absPath, path.c_str(), MAX_PATH);
71 return std::string(absPath);
72 }
73
GetDirectoryName(const std::string & path)74 std::string GetDirectoryName(const std::string& path) {
75 size_t rootLength = RootLength(path);
76 size_t separator = LastSeparator(path);
77 if (separator < rootLength)
78 separator = rootLength;
79 if (separator == std::string::npos)
80 return std::string();
81 return path.substr(0, separator);
82 }
83
FromURI(const std::string & uri)84 std::string FromURI(const std::string& uri) {
85 if (uri.substr(0, kFileURLPrefixLength) != kFileURLPrefix)
86 return uri;
87
88 std::string file_path = uri.substr(kFileURLPrefixLength);
89 std::replace(file_path.begin(), file_path.end(), '/', '\\');
90 return SanitizeURIEscapedCharacters(file_path);
91 }
92
GetCachesDirectory()93 fml::UniqueFD GetCachesDirectory() {
94 // Unsupported on this platform.
95 return {};
96 }
97
98 } // namespace paths
99 } // namespace fml
100