/// Deconstruct a "URI" string into the "fllename" part (returned) and turn /// the "query" part into a series of pairs of id and value. For example, /// deconstruct_uri("foo.tif?bar=1&blah=\"hello world\"", args) /// would be expected to return "foo.tif" and *args would contain two /// pairs: ("foo","1") and ("bar","\"hello world\""). static string_view deconstruct_uri (string_view uri, std::vector<std::pair<string_view,string_view> > *args=NULL) { if (args) args->clear (); size_t arg_start = uri.find ('?'); if (arg_start == string_view::npos) return uri; string_view argstring = uri.substr (arg_start+1); string_view filename = uri.substr (0, arg_start); if (! args) return filename; while (! argstring.empty()) { string_view id = Strutil::parse_until (argstring, "=&"); string_view value; if (! id.size()) break; if (! Strutil::parse_char (argstring, '=') || argstring.empty()) break; if (argstring[0] == '\"') Strutil::parse_string (argstring, value, true, Strutil::KeepQuotes); else value = Strutil::parse_until (argstring, "&\t\r\n"); args->push_back (std::make_pair(id, value)); Strutil::parse_char (argstring, '&'); } return filename; }
pair<string_view, string_view> splitPair(string_view s, char delim) noexcept { const auto pos = s.find_first_of(delim); string_view key, val; if (pos == string_view::npos) { key = s; } else { key = s.substr(0, pos); val = s.substr(pos + 1); } return {key, val}; }
void Request::add_line_to_multiline_header(const string_view& line, const string_view& header) { auto non_whitespace_pos = line.find_first_not_of("\t "); if (non_whitespace_pos != line.end()) if (!header.empty()) headers_[header.str()] += line.substr(non_whitespace_pos).str(); }
config_option::config_option(string_view category, string_view name, string_view description, const meta_state* meta, void* value) : meta_(meta), value_(value) { using std::copy; using std::accumulate; auto comma = name.find(','); auto long_name = name.substr(0, comma); auto short_names = comma == string_view::npos ? string_view{} : name.substr(comma + 1); auto total_size = [](std::initializer_list<string_view> xs) { return (xs.size() - 1) // one separator between all fields + accumulate(xs.begin(), xs.end(), size_t{0}, [](size_t x, string_view sv) { return x + sv.size(); }); }; auto ts = total_size({category, long_name, short_names, description}); CAF_ASSERT(ts <= std::numeric_limits<uint16_t>::max()); buf_size_ = static_cast<uint16_t>(ts); buf_.reset(new char[ts]); // fille the buffer with "<category>.<long-name>,<short-name>,<descriptions>" auto first = buf_.get(); auto i = first; auto pos = [&] { return static_cast<uint16_t>(std::distance(first, i)); }; // <category>. i = copy(category.begin(), category.end(), i); category_separator_ = pos(); *i++ = '.'; // <long-name>, i = copy(long_name.begin(), long_name.end(), i); long_name_separator_ = pos(); *i++ = ','; // <short-names>, i = copy(short_names.begin(), short_names.end(), i); short_names_separator_ = pos(); *i++ = ','; // <description> i = copy(description.begin(), description.end(), i); CAF_ASSERT(pos() == buf_size_); }
static lng_line_type parse_lng_line(const string_view str, bool ParseLabels, string_view& Label, string_view& Data) { Label = {}; Data = {}; //-- "Text" if (starts_with(str, L'"')) { Data = str.substr(1, str.size() - (ends_with(str, L'"')? 2 : 1)); return lng_line_type::text; } //-- //[Label] if (ParseLabels) { const auto Prefix = L"//["sv, Suffix = L"]"sv; if (starts_with(str, Prefix) && ends_with(str, Suffix)) { Label = str.substr(Prefix.size(), str.size() - Prefix.size() - Suffix.size()); return lng_line_type::label; } } //-- MLabel="Text" if (ParseLabels && !str.empty() && str.back() == L'"') { const auto eq_pos = str.find(L'='); if (eq_pos != str.npos && std::iswalpha(str[0])) { const auto Value = trim(str.substr(eq_pos + 1)); if (starts_with(Value, L'"')) { Label = trim(str.substr(0, eq_pos)); Data = Value.substr(1, Value.size() - 2); return lng_line_type::both; } } } return lng_line_type::none; }
path_match_result path_match(string_view input, string_view& match_contents) { if (input.length() < 2) return path_match_result::invalid; match_result result; token_kind kind; std::size_t length; switch (input.at(0)) { case '.': result = match_simple_string(input.data() + 1, input.data() + input.size(), kind, length); if (result == match_result::complete) { match_contents = input.substr(0, length + 1); return path_match_result::simple_object; } else { return path_match_result::invalid; } case '[': result = attempt_match(input.data() + 1, input.data() + input.length(), kind, length); if (result == match_result::complete) { if (input.length() == length + 1 || input.at(1 + length) != ']') return path_match_result::invalid; if (kind != token_kind::string && kind != token_kind::number) return path_match_result::invalid; match_contents = input.substr(0, length + 2); return path_match_result::brace; } else { return path_match_result::invalid; } default: return path_match_result::invalid; } }
static void parse_lng_line(const string_view str, string& label, string& data, bool& have_data) { have_data = false; //-- //[Label] if (starts_with(str, L"//["sv) && ends_with(str, L"]"sv)) { const auto LabelView = str.substr(3, str.size() - 3 - 1); //-- //[Label=0] assign(label, LabelView.substr(0, LabelView.find(L'='))); return; } //-- "Text" if (starts_with(str, L'"')) { have_data = true; assign(data, str.substr(1)); if (!data.empty() && data.back() == L'"') data.pop_back(); return; } //-- MLabel="Text" if (!str.empty() && str.back() == L'"') { const auto eq_pos = str.find(L'='); if (eq_pos != string::npos && InRange(L'A', upper(str[0]), L'Z')) { assign(data, trim(str.substr(eq_pos + 1))); if (data.size() > 1 && data[0] == L'"') { assign(label, trim(str.substr(0, eq_pos))); have_data = true; data.pop_back(); data.erase(0, 1); } } } }
// ----------------------------------------------------------------------------- // Returns the entry at the given path in the archive, or null if it doesn't // exist // ----------------------------------------------------------------------------- shared_ptr<ArchiveEntry> Archive::entryAtPathShared(string_view path) { // Get path as wxFileName for processing StrUtil::Path fn(StrUtil::startsWith(path, '/') ? path.substr(1) : path); // Get directory from path ArchiveTreeNode* dir; if (fn.path(false).empty()) dir = &dir_root_; else dir = this->dir(fn.path(true)); // If dir doesn't exist, return nullptr if (!dir) return nullptr; // Return entry return dir->sharedEntry(fn.fileName()); }
static void MixToFullPath(const string_view stPath, string& Dest, const string_view stCurrentDir) { string strDest; string_view pstCurrentDir; bool blIgnore = false; size_t PathDirOffset = 0; const auto PathType = ParsePath(stPath, &PathDirOffset); size_t PathOffset = PathDirOffset; switch (PathType) { case root_type::unknown: { if (HasPathPrefix(stPath)) // \\?\<ANY_UNKNOWN_FORMAT> { blIgnore = true; } else if (!stPath.empty() && IsSlash(stPath.front())) //"\" or "\abc" { ++PathOffset; if (!stCurrentDir.empty()) { size_t CurDirDirOffset = 0; if (ParsePath(stCurrentDir, &CurDirDirOffset) != root_type::unknown) { assign(strDest, stCurrentDir.substr(0, CurDirDirOffset)); } } } else //"abc" or whatever { pstCurrentDir = stCurrentDir; } } break; case root_type::drive_letter: //"C:" or "C:abc" { if(stPath.size() > 2 && IsSlash(stPath[2])) { PathOffset = 0; } else { const auto Drive = os::fs::get_drive(stPath[0]); const auto Value = os::env::get(L'=' + Drive); if (!Value.empty()) { strDest = Value; } else { if (upper(stPath[0])==upper(stCurrentDir[0])) { assign(strDest, stCurrentDir); } else { strDest = Drive; } } AddEndSlash(strDest); } } break; case root_type::remote: //"\\abc" { PathOffset = 0; } break; case root_type::unc_drive_letter: //"\\?\whatever" case root_type::unc_remote: case root_type::volume: case root_type::pipe: { blIgnore=true; PathOffset = 0; } break; } if (!pstCurrentDir.empty()) { append(strDest, pstCurrentDir); AddEndSlash(strDest); } append(strDest, stPath.substr(PathOffset)); if (!blIgnore && !HasPathPrefix(strDest)) MixToFullPath(strDest); Dest = std::move(strDest); }
bool ends_with_icase(const string_view Str, const string_view Suffix) { return Str.size() >= Suffix.size() && equal_icase(Str.substr(Str.size() - Suffix.size()), Suffix); }
bool starts_with_icase(const string_view Str, const string_view Prefix) { return Str.size() >= Prefix.size() && equal_icase(Str.substr(0, Prefix.size()), Prefix); }
void f2(const string_view str) { cout << str.substr(str.find("D"), 3) << endl; }
void testBuffer() { using namespace test; string_view const s = "Hello, world!"; // static_buffer_base { char buf[64]; static_buffer_base b{buf, sizeof(buf)}; ostream(b) << s; BEAST_EXPECT(buffers_to_string(b.data()) == s); b.consume(b.size()); BEAST_EXPECT(buffers_to_string(b.data()) == ""); } // static_buffer { static_buffer<64> b1; BEAST_EXPECT(b1.size() == 0); BEAST_EXPECT(b1.max_size() == 64); BEAST_EXPECT(b1.capacity() == 64); ostream(b1) << s; BEAST_EXPECT(buffers_to_string(b1.data()) == s); { static_buffer<64> b2{b1}; BEAST_EXPECT(buffers_to_string(b2.data()) == s); b2.consume(7); BEAST_EXPECT(buffers_to_string(b2.data()) == s.substr(7)); } { static_buffer<64> b2; b2 = b1; BEAST_EXPECT(buffers_to_string(b2.data()) == s); b2.consume(7); BEAST_EXPECT(buffers_to_string(b2.data()) == s.substr(7)); } } // cause memmove { static_buffer<10> b; write_buffer(b, "12345"); b.consume(3); write_buffer(b, "67890123"); BEAST_EXPECT(buffers_to_string(b.data()) == "4567890123"); try { b.prepare(1); fail("", __FILE__, __LINE__); } catch(std::length_error const&) { pass(); } } // read_size { static_buffer<10> b; BEAST_EXPECT(read_size(b, 512) == 10); b.prepare(4); b.commit(4); BEAST_EXPECT(read_size(b, 512) == 6); b.consume(2); BEAST_EXPECT(read_size(b, 512) == 8); b.prepare(8); b.commit(8); BEAST_EXPECT(read_size(b, 512) == 0); } // base { static_buffer<10> b; [&](static_buffer_base& base) { BEAST_EXPECT(base.max_size() == b.capacity()); } (b.base()); [&](static_buffer_base const& base) { BEAST_EXPECT(base.max_size() == b.capacity()); } (b.base()); } }
// ----------------------------------------------------------------------------- // Draws a texture box with name underneath for [texture] // ----------------------------------------------------------------------------- void LineInfoOverlay::drawTexture(float alpha, int x, int y, string_view texture, bool needed, string_view pos) const { bool required = (needed && texture == MapSide::TEX_NONE); int tex_box_size = 80 * scale_; int line_height = 16 * scale_; // Get colours ColRGBA col_fg = ColourConfiguration::colour("map_overlay_foreground"); col_fg.a = col_fg.a * alpha; // Get texture auto tex = MapEditor::textureManager() .texture(texture, Game::configuration().featureSupported(Game::Feature::MixTexFlats)) .gl_id; // Valid texture if (texture != MapSide::TEX_NONE && tex != OpenGL::Texture::missingTexture()) { // Draw background glEnable(GL_TEXTURE_2D); OpenGL::setColour(255, 255, 255, 255 * alpha, OpenGL::Blend::Normal); glPushMatrix(); glTranslated(x, y - tex_box_size - line_height, 0); Drawing::drawTextureTiled(OpenGL::Texture::backgroundTexture(), tex_box_size, tex_box_size); glPopMatrix(); // Draw texture OpenGL::setColour(255, 255, 255, 255 * alpha, OpenGL::Blend::Normal); Drawing::drawTextureWithin(tex, x, y - tex_box_size - line_height, x + tex_box_size, y - line_height, 0); glDisable(GL_TEXTURE_2D); // Draw outline OpenGL::setColour(col_fg.r, col_fg.g, col_fg.b, 255 * alpha, OpenGL::Blend::Normal); glDisable(GL_LINE_SMOOTH); Drawing::drawRect(x, y - tex_box_size - line_height, x + tex_box_size, y - line_height); } // Unknown texture else if (tex == OpenGL::Texture::missingTexture() && texture != MapSide::TEX_NONE) { // Draw unknown icon auto icon = MapEditor::textureManager().editorImage("thing/unknown").gl_id; glEnable(GL_TEXTURE_2D); OpenGL::setColour(180, 0, 0, 255 * alpha, OpenGL::Blend::Normal); Drawing::drawTextureWithin(icon, x, y - tex_box_size - line_height, x + tex_box_size, y - line_height, 0, 0.15); // Set colour to red (for text) col_fg = col_fg.ampf(1.0f, 0.0f, 0.0f, 1.0f); } // Missing texture else if (required) { // Draw missing icon auto icon = MapEditor::textureManager().editorImage("thing/minus").gl_id; glEnable(GL_TEXTURE_2D); OpenGL::setColour(180, 0, 0, 255 * alpha, OpenGL::Blend::Normal); Drawing::drawTextureWithin(icon, x, y - tex_box_size - line_height, x + tex_box_size, y - line_height, 0, 0.15); // Set colour to red (for text) col_fg = col_fg.ampf(1.0f, 0.0f, 0.0f, 1.0f); } // Draw texture name (even if texture is blank) string tex_str; if (required) tex_str = fmt::format("{}:MISSING", pos); else if (texture.size() > 8) tex_str = fmt::format("{}:{}...", pos, texture.substr(0, 8)); else tex_str = fmt::format("{}:{}", pos, texture); Drawing::drawText( tex_str, x + (tex_box_size * 0.5), y - line_height, col_fg, Drawing::Font::Condensed, Drawing::Align::Center); }
static string_view ProcessMetasymbol(string_view const CurStr, subst_data& SubstData, string& Out) { const auto append_with_escape = [EscapeAmpersands = SubstData.EscapeAmpersands](string& Destination, string_view const Str) { if (EscapeAmpersands && contains(Str, L"&"sv)) { string Escaped(Str); replace(Escaped, L"&"sv, L"&&"sv); append(Destination, Escaped); } else { append(Destination, Str); } }; if (const auto Tail = tokens::skip(CurStr, tokens::passive_panel)) { SubstData.PassivePanel = true; return Tail; } if (const auto Tail = tokens::skip(CurStr, tokens::active_panel)) { SubstData.PassivePanel = false; return Tail; } if (const auto Tail = tokens::skip(CurStr, tokens::exclamation)) { if (!starts_with(Tail, L'?')) { Out.push_back(L'!'); return Tail; } } if (const auto Tail = tokens::skip(CurStr, tokens::name_extension)) { if (!starts_with(Tail, L'?')) { append_with_escape(Out, SubstData.Default().Normal.Name); return Tail; } } if (const auto Tail = tokens::skip(CurStr, tokens::short_name)) { append_with_escape(Out, SubstData.Default().Short.NameOnly); return Tail; } const auto GetExtension = [](string_view const Name) { const auto Extension = PointToExt(Name); return Extension.empty()? Extension : Extension.substr(1); }; if (const auto Tail = tokens::skip(CurStr, tokens::short_extension)) { append_with_escape(Out, GetExtension(SubstData.Default().Short.Name)); return Tail; } if (const auto Tail = tokens::skip(CurStr, tokens::extension)) { append_with_escape(Out, GetExtension(SubstData.Default().Normal.Name)); return Tail; } const auto CollectNames = [&SubstData, &append_with_escape](string& Str, auto const Selector) { append_with_escape(Str, join(select(SubstData.Default().Panel->enum_selected(), Selector), L" "sv)); }; if (const auto Tail = tokens::skip(CurStr, tokens::short_list)) { if (!starts_with(Tail, L'?')) { CollectNames(Out, &os::fs::find_data::AlternateFileName); return Tail; } } if (const auto Tail = tokens::skip(CurStr, tokens::list)) { if (!starts_with(Tail, L'?')) { CollectNames(Out, [](const os::fs::find_data& Data) { return quote_space(Data.FileName); }); return Tail; } } const auto GetListName = [&Out, &append_with_escape](string_view const Tail, subst_data& Data, bool Short) { const auto ExclPos = Tail.find(L'!'); if (ExclPos == Tail.npos || starts_with(Tail.substr(ExclPos + 1), L'?')) return size_t{}; const auto Modifiers = Tail.substr(0, ExclPos); if (Data.ListNames) { string Str; if (Data.Default().Panel->MakeListFile(Str, Short, Modifiers)) { if (Short) Str = ConvertNameToShort(Str); append_with_escape(Out, Str); Data.ListNames->add(std::move(Str)); } } else { append(Out, L'!', Short? L'$' : L'@', Modifiers, L'!'); } return Modifiers.size() + 1; }; if (const auto Tail = tokens::skip(CurStr, tokens::list_file)) { if (const auto Offset = GetListName(Tail, SubstData, false)) return string_view(Tail).substr(Offset); } if (const auto Tail = tokens::skip(CurStr, tokens::short_list_file)) { if (const auto Offset = GetListName(Tail, SubstData, true)) return string_view(Tail).substr(Offset); } if (const auto Tail = tokens::skip(CurStr, tokens::short_name_extension)) { if (!starts_with(Tail, L'?')) { append_with_escape(Out, SubstData.Default().Short.Name); return Tail; } } if (const auto Tail = tokens::skip(CurStr, tokens::short_name_extension_safe)) { if (!starts_with(Tail, L'?')) { append_with_escape(Out, SubstData.Default().Short.Name); SubstData.PreserveLFN = true; return Tail; } } if (const auto Tail = tokens::skip(CurStr, tokens::current_drive)) { const auto CurDir = IsAbsolutePath(SubstData.This.Normal.Name)? SubstData.This.Normal.Name : SubstData.PassivePanel? SubstData.Another.Panel->GetCurDir() : SubstData.CmdDir; auto RootDir = GetPathRoot(CurDir); DeleteEndSlash(RootDir); append_with_escape(Out, RootDir); return Tail; } if (const auto Tail = tokens::skip(CurStr, tokens::description)) { Out += SubstData.Default().GetDescription(); return Tail; } const auto GetPath = [](string_view const Tail, const subst_data& Data, bool Short, bool Real) { // TODO: paths on plugin panels are ambiguous auto CurDir = Data.PassivePanel? Data.Another.Panel->GetCurDir() : Data.CmdDir; if (Real) CurDir = ConvertNameToReal(CurDir); if (Short) CurDir = ConvertNameToShort(CurDir); AddEndSlash(CurDir); return CurDir; }; if (const auto Tail = tokens::skip(CurStr, tokens::path)) { Out += GetPath(Tail, SubstData, false, false); return Tail; } if (const auto Tail = tokens::skip(CurStr, tokens::short_path)) { Out += GetPath(Tail, SubstData, true, false); return Tail; } if (const auto Tail = tokens::skip(CurStr, tokens::real_path)) { Out += GetPath(Tail, SubstData, false, true); return Tail; } if (const auto Tail = tokens::skip(CurStr, tokens::real_short_path)) { Out += GetPath(Tail, SubstData, true, true); return Tail; } // !?<title>?<init>! if (const auto Tail = tokens::skip(CurStr, tokens::input)) { auto SkipSize = SkipInputToken(CurStr); // if bad format string skip 1 char if (!SkipSize) SkipSize = 1; Out.append(CurStr.data(), SkipSize); return CurStr.substr(SkipSize); } if (const auto Tail = tokens::skip(CurStr, tokens::name)) { append(Out, PointToName(SubstData.Default().Normal.NameOnly)); return Tail; } return CurStr; }
skip(string_view const Str, string_view const Test) : m_Tail(starts_with(Str, Test) ? Str.substr(Test.size()) : string_view{}) { }