void test_strview_basics(const string_view& sv, const char *p, size_t n) { ASSERT_EQ(p, sv.data()); ASSERT_EQ(n, sv.size()); ASSERT_EQ(n, sv.length()); ASSERT_EQ((n == 0), sv.empty()); ASSERT_EQ(p, sv.cbegin()); ASSERT_EQ(p, sv.begin()); ASSERT_EQ(p + n, sv.cend()); ASSERT_EQ(p + n, sv.end()); using reviter_t = std::reverse_iterator<string_view::const_iterator>; ASSERT_EQ(reviter_t(sv.end()), sv.rbegin()); ASSERT_EQ(reviter_t(sv.begin()), sv.rend()); ASSERT_EQ(reviter_t(sv.cend()), sv.crbegin()); ASSERT_EQ(reviter_t(sv.cbegin()), sv.crend()); for (size_t i = 0; i < n; ++i) { ASSERT_EQ(p[i], sv[i]); ASSERT_EQ(p[i], sv.at(i)); } ASSERT_THROW(sv.at(n), std::out_of_range); ASSERT_THROW(sv.at(string_view::npos), std::out_of_range); if (n > 0) { ASSERT_EQ(p, &(sv.front())); ASSERT_EQ(p + (n-1), &(sv.back())); ASSERT_EQ(p[0], sv.front()); ASSERT_EQ(p[n-1], sv.back()); } }
static string ProcessMetasymbols(string_view Str, subst_data& Data) { string Result; Result.reserve(Str.size()); while (!Str.empty()) { if (Str.front() == L'!') { Str = ProcessMetasymbol(Str, Data, Result); } else { Result.push_back(Str.front()); Str.remove_prefix(1); } } return Result; }
// Add the attribute -- figure out the type void parse_param(string_view paramname, string_view val, ImageSpec& spec) { TypeDesc type; // start out unknown // If the param string starts with a type name, that's what it is if (size_t typeportion = type.fromstring(paramname)) { paramname.remove_prefix(typeportion); Strutil::skip_whitespace(paramname); } // If the value string starts with a type name, that's what it is else if (size_t typeportion = type.fromstring(val)) { val.remove_prefix(typeportion); Strutil::skip_whitespace(val); } if (type.basetype == TypeDesc::UNKNOWN) { // If we didn't find a type name, try to guess if (val.size() >= 2 && val.front() == '\"' && val.back() == '\"') { // Surrounded by quotes? it's a string (strip off the quotes) val.remove_prefix(1); val.remove_suffix(1); type = TypeDesc::TypeString; } else if (Strutil::string_is<int>(val)) { // Looks like an int, is an int type = TypeDesc::TypeInt; } else if (Strutil::string_is<float>(val)) { // Looks like a float, is a float type = TypeDesc::TypeFloat; } else { // Everything else is assumed a string type = TypeDesc::TypeString; } } // Read the values and set the attribute int n = type.numelements() * type.aggregate; if (type.basetype == TypeDesc::INT) { std::vector<int> values(n); for (int i = 0; i < n; ++i) { Strutil::parse_int(val, values[i]); Strutil::parse_char(val, ','); // optional } if (n > 0) spec.attribute(paramname, type, &values[0]); } if (type.basetype == TypeDesc::FLOAT) { std::vector<float> values(n); for (int i = 0; i < n; ++i) { Strutil::parse_float(val, values[i]); Strutil::parse_char(val, ','); // optional } if (n > 0) spec.attribute(paramname, type, &values[0]); } else if (type.basetype == TypeDesc::STRING) { std::vector<ustring> values(n); for (int i = 0; i < n; ++i) { string_view v; Strutil::parse_string(val, v); Strutil::parse_char(val, ','); // optional values[i] = v; } if (n > 0) spec.attribute(paramname, type, &values[0]); } }
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); }