diff options
Diffstat (limited to 'Build/source/utils/asymptote/LspCpp/LibLsp/lsp/utils.cpp')
-rw-r--r-- | Build/source/utils/asymptote/LspCpp/LibLsp/lsp/utils.cpp | 602 |
1 files changed, 0 insertions, 602 deletions
diff --git a/Build/source/utils/asymptote/LspCpp/LibLsp/lsp/utils.cpp b/Build/source/utils/asymptote/LspCpp/LibLsp/lsp/utils.cpp deleted file mode 100644 index 532f4bf6d70..00000000000 --- a/Build/source/utils/asymptote/LspCpp/LibLsp/lsp/utils.cpp +++ /dev/null @@ -1,602 +0,0 @@ -#include "utils.h" - -#include <algorithm> -#include <cassert> -#include <cctype> -#include <cstring> -#include <fstream> -#include <functional> - -#include <queue> -#include <sstream> -#include <string> -#include <unordered_map> -#include <sys/stat.h> - -#include "lsPosition.h" -#include "utf8.h" -#ifdef _WIN32 -#include <Windows.h> -#endif - - -// DEFAULT_RESOURCE_DIRECTORY is passed with quotes for non-MSVC compilers, ie, -// foo vs "foo". -#if defined(_MSC_VER) -#define _STRINGIFY(x) #x -#define ENSURE_STRING_MACRO_ARGUMENT(x) _STRINGIFY(x) -#else -#define ENSURE_STRING_MACRO_ARGUMENT(x) x -#endif -#include <boost/filesystem/path.hpp> -#include <boost/filesystem/operations.hpp> -#include <boost/algorithm/string.hpp> -namespace lsp -{ - - -// See http://stackoverflow.com/a/2072890 -bool EndsWith(std::string value, std::string ending) { - if (ending.size() > value.size()) - return false; - return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); -} - -bool StartsWith(std::string value, std::string start) { - if (start.size() > value.size()) - return false; - return std::equal(start.begin(), start.end(), value.begin()); -} - -bool AnyStartsWith(const std::vector<std::string>& values, - const std::string& start) { - return std::any_of( - std::begin(values), std::end(values), - [&start](const std::string& value) { return StartsWith(value, start); }); -} - -bool StartsWithAny(const std::string& value, - const std::vector<std::string>& startings) { - return std::any_of(std::begin(startings), std::end(startings), - [&value](const std::string& starting) { - return StartsWith(value, starting); - }); -} - -bool EndsWithAny(const std::string& value, - const std::vector<std::string>& endings) { - return std::any_of( - std::begin(endings), std::end(endings), - [&value](const std::string& ending) { return EndsWith(value, ending); }); -} - -bool FindAnyPartial(const std::string& value, - const std::vector<std::string>& values) { - return std::any_of(std::begin(values), std::end(values), - [&value](const std::string& v) { - return value.find(v) != std::string::npos; - }); -} - -std::string GetDirName(std::string path) { - - ReplaceAll(path, "\\", "/"); - if (path.size() && path.back() == '/') - path.pop_back(); - size_t last_slash = path.find_last_of('/'); - if (last_slash == std::string::npos) - return "./"; - return path.substr(0, last_slash + 1); -} - -std::string GetBaseName(const std::string& path) { - size_t last_slash = path.find_last_of('/'); - if (last_slash != std::string::npos && (last_slash + 1) < path.size()) - return path.substr(last_slash + 1); - return path; -} - -std::string StripFileType(const std::string& path) { - size_t last_period = path.find_last_of('.'); - if (last_period != std::string::npos) - return path.substr(0, last_period); - return path; -} - -// See http://stackoverflow.com/a/29752943 -std::string ReplaceAll(const std::string& source, - const std::string& from, - const std::string& to) { - std::string result; - result.reserve(source.length()); // avoids a few memory allocations - - std::string::size_type last_pos = 0; - std::string::size_type find_pos; - - while (std::string::npos != (find_pos = source.find(from, last_pos))) { - result.append(source, last_pos, find_pos - last_pos); - result += to; - last_pos = find_pos + from.length(); - } - - // Care for the rest after last occurrence - result += source.substr(last_pos); - - return result; -} - -std::vector<std::string> SplitString(const std::string& str, - const std::string& delimiter) { - // http://stackoverflow.com/a/13172514 - std::vector<std::string> strings; - - std::string::size_type pos = 0; - std::string::size_type prev = 0; - while ((pos = str.find(delimiter, prev)) != std::string::npos) { - strings.emplace_back(str.substr(prev, pos - prev)); - prev = pos + 1; - } - - // To get the last substring (or only, if delimiter is not found) - strings.emplace_back(str.substr(prev)); - - return strings; -} - -void EnsureEndsInSlash(std::string& path) { - if (path.empty() || path[path.size() - 1] != '/') - path += '/'; -} - -std::string EscapeFileName(std::string path) { - if (path.size() && path.back() == '/') - path.pop_back(); - std::replace(path.begin(), path.end(), '\\', '@'); - std::replace(path.begin(), path.end(), '/', '@'); - std::replace(path.begin(), path.end(), ':', '@'); - return path; -} - -// http://stackoverflow.com/a/6089413 -std::istream& SafeGetline(std::istream& is, std::string& t) { - t.clear(); - - // The characters in the stream are read one-by-one using a std::streambuf. - // That is faster than reading them one-by-one using the std::istream. Code - // that uses streambuf this way must be guarded by a sentry object. The sentry - // object performs various tasks, such as thread synchronization and updating - // the stream state. - - std::istream::sentry se(is, true); - std::streambuf* sb = is.rdbuf(); - - for (;;) { - int c = sb->sbumpc(); - if (c == EOF) { - // Also handle the case when the last line has no line ending - if (t.empty()) - is.setstate(std::ios::eofbit); - return is; - } - - t += (char)c; - - if (c == '\n') - return is; - } -} - -bool FileExists(const std::string& filename) { - std::ifstream cache(filename); - return cache.is_open(); -} - -boost::optional<std::string> ReadContent(const AbsolutePath& filename) { - - std::ifstream cache; - cache.open(filename.path); - - try { - return std::string(std::istreambuf_iterator<char>(cache), - std::istreambuf_iterator<char>()); - } catch (std::ios_base::failure&) { - return {}; - } -} - -std::vector<std::string> ReadLinesWithEnding(const AbsolutePath& filename) { - std::vector<std::string> result; - - std::ifstream input(filename.path); - for (std::string line; SafeGetline(input, line);) - result.emplace_back(line); - - return result; -} - -bool WriteToFile(const std::string& filename, const std::string& content) { - std::ofstream file(filename, - std::ios::out | std::ios::trunc | std::ios::binary); - if (!file.good()) { - - return false; - } - - file << content; - return true; -} - - -std::string FormatMicroseconds(long long microseconds) { - long long milliseconds = microseconds / 1000; - long long remaining = microseconds - milliseconds; - - // Only show two digits after the dot. - while (remaining >= 100) - remaining /= 10; - - return std::to_string(milliseconds) + "." + std::to_string(remaining) + "ms"; -} - - - -std::string UpdateToRnNewlines(std::string output) { - size_t idx = 0; - while (true) { - idx = output.find('\n', idx); - - // No more matches. - if (idx == std::string::npos) - break; - - // Skip an existing "\r\n" match. - if (idx > 0 && output[idx - 1] == '\r') { - ++idx; - continue; - } - - // Replace "\n" with "\r|n". - output.replace(output.begin() + idx, output.begin() + idx + 1, "\r\n"); - } - - return output; -} - - - -bool IsAbsolutePath(const std::string& path) { - return IsUnixAbsolutePath(path) || IsWindowsAbsolutePath(path); -} - -bool IsUnixAbsolutePath(const std::string& path) { - return !path.empty() && path[0] == '/'; -} - -bool IsWindowsAbsolutePath(const std::string& path) { - auto is_drive_letter = [](char c) { - return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); - }; - - return path.size() > 3 && path[1] == ':' && - (path[2] == '/' || path[2] == '\\') && is_drive_letter(path[0]); -} - -bool IsDirectory(const std::string& path) { - struct stat path_stat; - - if (stat(path.c_str(), &path_stat) != 0) { - perror("cannot access path"); - return false; - } - - return path_stat.st_mode & S_IFDIR; -} - - -std::string ws2s(std::wstring const& wstr) { - - std::string narrow; - utf8::utf32to8(wstr.begin(), wstr.end(), std::back_inserter(narrow)); - return narrow; -} -std::wstring s2ws(const std::string& str) { - std::wstring wide; - utf8::utf8to32(str.begin(), str.end(), std::back_inserter(wide)); - return wide; -} - - -#ifdef _WIN32 - -#else -// Returns the canonicalized absolute pathname, without expanding symbolic -// links. This is a variant of realpath(2), C++ rewrite of -// https://github.com/freebsd/freebsd/blob/master/lib/libc/stdlib/realpath.c -AbsolutePath RealPathNotExpandSymlink(std::string path, - bool ensure_exists) { - if (path.empty()) { - errno = EINVAL; - return {}; - } - if (path[0] == '\0') { - errno = ENOENT; - return {}; - } - - // Do not use PATH_MAX because it is tricky on Linux. - // See https://eklitzke.org/path-max-is-tricky - char tmp[1024]; - std::string resolved; - size_t i = 0; - struct stat sb; - if (path[0] == '/') { - resolved = "/"; - i = 1; - } - else { - if (!getcwd(tmp, sizeof tmp) && ensure_exists) - return {}; - resolved = tmp; - } - - while (i < path.size()) { - auto j = path.find('/', i); - if (j == std::string::npos) - j = path.size(); - auto next_token = path.substr(i, j - i); - i = j + 1; - if (resolved.back() != '/') - resolved += '/'; - if (next_token.empty() || next_token == ".") { - // Handle consequential slashes and "." - continue; - } - else if (next_token == "..") { - // Strip the last path component except when it is single "/" - if (resolved.size() > 1) - resolved.resize(resolved.rfind('/', resolved.size() - 2) + 1); - continue; - } - // Append the next path component. - // Here we differ from realpath(3), we use stat(2) instead of - // lstat(2) because we do not want to resolve symlinks. - resolved += next_token; - if (stat(resolved.c_str(), &sb) != 0 && ensure_exists) - return {}; - if (!S_ISDIR(sb.st_mode) && j < path.size() && ensure_exists) { - errno = ENOTDIR; - return {}; - } - } - - // Remove trailing slash except when a single "/". - if (resolved.size() > 1 && resolved.back() == '/') - resolved.pop_back(); - return AbsolutePath(resolved, true /*validate*/); -} -#endif - - -AbsolutePath NormalizePath(const std::string& path0, - bool ensure_exists , - bool force_lower_on_windows) { -#ifdef _WIN32 - - std::wstring path = lsp::s2ws(path0); - - wchar_t buffer[MAX_PATH] = (L""); - - // Normalize the path name, ie, resolve `..`. - unsigned long len = GetFullPathNameW(path.c_str(), MAX_PATH, buffer, nullptr); - if (!len) - return {}; - path = std::wstring(buffer, len); - - // Get the actual casing of the path, ie, if the file on disk is `C:\FooBar` - // and this function is called with `c:\fooBar` this will return `c:\FooBar`. - // (drive casing is lowercase). - if (ensure_exists) { - len = GetLongPathNameW(path.c_str(), buffer, MAX_PATH); - if (!len) - return {}; - path = std::wstring(buffer, len); - } - - // Empty paths have no meaning. - if (path.empty()) - return {}; - - // We may need to normalize the drive name to upper-case; at the moment - // vscode sends lower-case path names. - /* - path[0] = toupper(path[0]); - */ - // Make the path all lower-case, since windows is case-insensitive. - if (force_lower_on_windows) { - for (size_t i = 0; i < path.size(); ++i) - path[i] = (wchar_t)tolower(path[i]); - } - - // cquery assumes forward-slashes. - std::replace(path.begin(), path.end(), '\\', '/'); - - - return AbsolutePath(lsp::ws2s(path), false /*validate*/); -#else - - return RealPathNotExpandSymlink(path0, ensure_exists); - -#endif - - -} - -// VSCode (UTF-16) disagrees with Emacs lsp-mode (UTF-8) on how to represent -// text documents. -// We use a UTF-8 iterator to approximate UTF-16 in the specification (weird). -// This is good enough and fails only for UTF-16 surrogate pairs. -int GetOffsetForPosition(lsPosition position, const std::string& content) { - size_t i = 0; - // Iterate lines until we have found the correct line. - while (position.line > 0 && i < content.size()) { - if (content[i] == '\n') - position.line--; - i++; - } - // Iterate characters on the target line. - while (position.character > 0 && i < content.size()) { - if (uint8_t(content[i++]) >= 128) { - // Skip 0b10xxxxxx - while (i < content.size() && uint8_t(content[i]) >= 128 && - uint8_t(content[i]) < 192) - i++; - } - position.character--; - } - return int(i); -} - - -lsPosition GetPositionForOffset(size_t offset,const std::string& content) { - lsPosition result; - for (size_t i = 0; i < offset && i < content.length(); ++i) { - if (content[i] == '\n') { - result.line++; - result.character = 0; - } - else { - result.character++; - } - } - return result; -} - -lsPosition CharPos(const std::string& search, - char character, - int character_offset) { - lsPosition result; - size_t index = 0; - while (index < search.size()) { - char c = search[index]; - if (c == character) - break; - if (c == '\n') { - result.line += 1; - result.character = 0; - } - else { - result.character += 1; - } - ++index; - } - assert(index < search.size()); - result.character += character_offset; - return result; -} - -void scanDirsUseRecursive(const std::wstring& rootPath, std::vector<std::wstring>& ret) -{ - namespace fs = boost::filesystem; - fs::path fullpath(rootPath); - if (!fs::exists(fullpath)) { return; } - fs::recursive_directory_iterator end_iter; - for (fs::recursive_directory_iterator iter(fullpath); iter != end_iter; iter++) { - try { - if (fs::is_directory(*iter)) { - ret.push_back(iter->path().wstring()); - } - } - catch (const std::exception& ex) { - continue; - } - } -} - -void scanDirsNoRecursive(const std::wstring& rootPath, std::vector<std::wstring>& ret) -{ - namespace fs = boost::filesystem; - boost::filesystem::path myPath(rootPath); - if (!fs::exists(rootPath)) { return; } - boost::filesystem::directory_iterator endIter; - for (boost::filesystem::directory_iterator iter(myPath); iter != endIter; iter++) { - if (boost::filesystem::is_directory(*iter)) { - ret.push_back(iter->path().wstring()); - } - } -} - -void scanFilesUseRecursive( - const std::wstring& rootPath, - std::vector<std::wstring>& ret, - std::wstring suf) { - namespace fs = boost::filesystem; - boost::to_lower(suf); - - fs::path fullpath(rootPath); - if (!fs::exists(fullpath)) { return; } - fs::recursive_directory_iterator end_iter; - for (fs::recursive_directory_iterator iter(fullpath); iter != end_iter; iter++) { - try { - if (!fs::is_directory(*iter) && fs::is_regular_file(*iter)) { - auto temp_path = iter->path().wstring(); - auto size = suf.size(); - if (!size) - { - ret.push_back(std::move(temp_path)); - } - else - { - - if (temp_path.size() < size) continue; - auto suf_temp = temp_path.substr(temp_path.size() - size); - boost::to_lower(suf_temp); - if (suf_temp == suf) - { - ret.push_back(std::move(temp_path)); - } - } - } - } - catch (const std::exception&) { - continue; - } - } -} - -void scanFileNamesUseRecursive(const std::wstring& rootPath, std::vector<std::wstring>& ret, - std::wstring strSuf) -{ - scanFilesUseRecursive(rootPath, ret, strSuf); - std::vector<std::wstring> names; - for (auto& it : ret) - { - if (it.size() >= rootPath.size()) - { - names.push_back(it.substr(rootPath.size())); - } - } - ret.swap(names); -} - -void scanFileNamesUseRecursive(const std::string& rootPath, std::vector<std::string>& ret, std::string strSuf) -{ - std::vector<std::wstring> out; - scanFileNamesUseRecursive(s2ws(rootPath), out, s2ws(strSuf)); - for (auto& it : out) - { - ret.push_back(ws2s(it)); - } -} - -void scanFilesUseRecursive(const std::string& rootPath, std::vector<std::string>& ret, std::string strSuf) -{ - std::vector<std::wstring> out; - scanFilesUseRecursive(s2ws(rootPath), out, s2ws(strSuf)); - for (auto& it : out) - { - ret.push_back(ws2s(it)); - } -} - - -} |