// try to replace volume GUID (if present) with drive letter // used by ConvertNameToReal() only static string TryConvertVolumeGuidToDrivePath(string_view const Path, const string_view AbsPath = {}) { string Result(Path); size_t DirectoryOffset; if (ParsePath(Path, &DirectoryOffset) == root_type::volume) { if (imports.GetVolumePathNamesForVolumeNameW) { string VolumePathNames; if (os::fs::GetVolumePathNamesForVolumeName(ExtractPathRoot(Path), VolumePathNames)) { for(const auto& i: enum_substrings(VolumePathNames.c_str())) { if (!AbsPath.empty() && starts_with_icase(AbsPath, i)) return string(i); if (IsRootPath(i)) { Result.replace(0, DirectoryOffset, i.data(), i.size()); break; } } } if (!AbsPath.empty()) Result.clear(); } else if (!AbsPath.empty()) Result.clear(); else { string strVolumeGuid; const os::fs::enum_drives Enumerator(os::fs::get_logical_drives()); const auto ItemIterator = std::find_if(ALL_CONST_RANGE(Enumerator), [&](const auto& i) { return os::fs::GetVolumeNameForVolumeMountPoint(os::fs::get_root_directory(i), strVolumeGuid) && starts_with(Path, string_view(strVolumeGuid).substr(0, DirectoryOffset)); }); if (ItemIterator != Enumerator.cend()) { Result.replace(0, DirectoryOffset, os::fs::get_drive(*ItemIterator)); } } } else if (!AbsPath.empty()) Result.clear(); return Result; }
bool ColorConfig::reset (string_view filename) { bool ok = true; delete m_impl; m_impl = new ColorConfig::Impl; #ifdef USE_OCIO OCIO::SetLoggingLevel (OCIO::LOGGING_LEVEL_NONE); try { if (filename.empty()) { getImpl()->config_ = OCIO::GetCurrentConfig(); } else { getImpl()->config_ = OCIO::Config::CreateFromFile (filename.c_str()); } } catch(OCIO::Exception &e) { getImpl()->error_ = e.what(); ok = false; } catch(...) { getImpl()->error_ = "An unknown error occurred in OpenColorIO creating the config"; ok = false; } #endif getImpl()->inventory (); // If we populated our own, remove any errors. if (getNumColorSpaces() && !getImpl()->error_.empty()) getImpl()->error_.clear(); return ok; }
bool OSLQuery::open (string_view shadername, string_view searchpath) { OSOReaderQuery oso (*this); std::string filename = shadername; // Add file extension if not already there if (Filesystem::extension (filename) != std::string(".oso")) filename += ".oso"; // Apply search paths if (! searchpath.empty ()) { std::vector<std::string> dirs; Filesystem::searchpath_split (searchpath, dirs); filename = Filesystem::searchpath_find (filename, dirs); } if (filename.empty()) { error ("File \"%s\" could not be found.", shadername); return false; } bool ok = oso.parse_file (filename); return ok; }
bool ImageBufAlgo::ociofiletransform (ImageBuf &dst, const ImageBuf &src, string_view name, bool inverse, bool unpremult, ColorConfig *colorconfig, ROI roi, int nthreads) { if (name.empty()) { dst.error ("Unknown filetransform name"); return false; } ColorProcessor *processor = NULL; { spin_lock lock (colorconfig_mutex); if (! colorconfig) colorconfig = default_colorconfig.get(); if (! colorconfig) default_colorconfig.reset (colorconfig = new ColorConfig); processor = colorconfig->createFileTransform (name, inverse); if (! processor) { if (colorconfig->error()) dst.error ("%s", colorconfig->geterror()); else dst.error ("Could not construct the color transform"); return false; } } bool ok = colorconvert (dst, src, processor, unpremult, roi, nthreads); if (ok) dst.specmod().attribute ("oiio:ColorSpace", name); { spin_lock lock (colorconfig_mutex); colorconfig->deleteColorProcessor (processor); } return ok; }
// ----------------------------------------------------------------------------- // This is the general, all-purpose 'save archive' function. // Takes into account whether the archive is contained within another, is // already on the disk, etc etc. // Does a 'save as' if [filename] is specified, unless the archive is contained // within another. // Returns false if saving was unsuccessful, true otherwise // ----------------------------------------------------------------------------- bool Archive::save(string_view filename) { bool success = false; // Check if the archive is read-only if (read_only_) { Global::error = "Archive is read-only"; return false; } // If the archive has a parent ArchiveEntry, just write it to that if (parent_) { success = write(parent_->data()); parent_->setState(ArchiveEntry::State::Modified); } else { // Otherwise, file stuff if (!filename.empty()) { // New filename is given (ie 'save as'), write to new file and change archive filename accordingly success = write(filename); if (success) filename_ = filename; // Update variables on_disk_ = true; } else if (!filename_.empty()) { // No filename is given, but the archive has a filename, so overwrite it (and make a backup) // Create backup if (backup_archives && wxFileName::FileExists(filename_) && save_backup) { // Copy current file contents to new backup file auto bakfile = filename_ + ".bak"; Log::info("Creating backup {}", bakfile); wxCopyFile(filename_, bakfile, true); } // Write it to the file success = write(filename_); // Update variables on_disk_ = true; } } // If saving was successful, update variables and announce save if (success) { setModified(false); announce("saved"); } return success; }
//=========================================================================== static void addRoot(string * out, string_view val) { if (val.empty()) return; out->append(val); if (out->back() != ':') out->push_back(':'); }
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()); } }
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(); }
static int tiff_compression_code (string_view name) { if (name.empty()) COMPRESSION_ADOBE_DEFLATE; // default for (int i = 0; tiff_compressions[i].name; ++i) if (Strutil::iequals (name, tiff_compressions[i].name)) return tiff_compressions[i].code; return COMPRESSION_ADOBE_DEFLATE; // default }
bool ImageBufAlgo::ociolook (ImageBuf &dst, const ImageBuf &src, string_view looks, string_view from, string_view to, bool inverse, bool unpremult, string_view key, string_view value, ColorConfig *colorconfig, ROI roi, int nthreads) { if (from.empty() || from == "current") { from = src.spec().get_string_attribute ("oiio:Colorspace", "Linear"); } if (to.empty() || to == "current") { to = src.spec().get_string_attribute ("oiio:Colorspace", "Linear"); } if (from.empty() || to.empty()) { dst.error ("Unknown color space name"); return false; } ColorProcessor *processor = NULL; { spin_lock lock (colorconfig_mutex); if (! colorconfig) colorconfig = default_colorconfig.get(); if (! colorconfig) default_colorconfig.reset (colorconfig = new ColorConfig); processor = colorconfig->createLookTransform (looks, from, to, inverse, key, value); if (! processor) { if (colorconfig->error()) dst.error ("%s", colorconfig->geterror()); else dst.error ("Could not construct the color transform"); return false; } } bool ok = colorconvert (dst, src, processor, unpremult, roi, nthreads); if (ok) dst.specmod().attribute ("oiio:ColorSpace", to); { spin_lock lock (colorconfig_mutex); colorconfig->deleteColorProcessor (processor); } return ok; }
size_t TypeDesc::fromstring(string_view typestring) { *this = TypeDesc::UNKNOWN; string_view orig = typestring; if (typestring.empty()) { return 0; } // The first "word" should be a type name. string_view type = Strutil::parse_identifier(typestring); // Check the scalar types in our table above TypeDesc t; for (int i = 0; i < LASTBASE; ++i) { if (type == basetype_name[i]) { t.basetype = i; break; } } // Some special case names for aggregates if (t.basetype != UNKNOWN) { // already solved } else if (type == "color") t = TypeColor; else if (type == "point") t = TypePoint; else if (type == "vector") t = TypeVector; else if (type == "normal") t = TypeNormal; else if (type == "matrix33") t = TypeMatrix33; else if (type == "matrix" || type == "matrix44") t = TypeMatrix44; else if (type == "timecode") t = TypeTimeCode; else if (type == "rational") t = TypeRational; else { return 0; // unknown } // Is there an array length following the type name? if (Strutil::parse_char(typestring, '[')) { int arraylen = -1; Strutil::parse_int(typestring, arraylen); if (!Strutil::parse_char(typestring, ']')) return 0; // malformed t.arraylen = arraylen; } *this = t; return orig.length() - typestring.length(); }
//=========================================================================== static void addExt(string * out, string_view ext) { if (ext.empty()) return; if (ext[0] != '.') out->push_back('.'); out->append(ext); while (!out->empty() && out->back() == '.') out->pop_back(); }
std::string normalize_path_segments(string_view path) { std::string result; if (!path.empty()) { std::vector<std::string> path_segments; network_boost::split(path_segments, path, [](char ch) { return ch == '/'; }); // remove single dot segments detail::remove_erase_if( path_segments, [](const std::string& s) { return (s == "."); }); // remove double dot segments std::vector<std::string> normalized_segments; for (auto& segment : path_segments) { if (segment == "..") { if (normalized_segments.size() <= 1) { throw uri_builder_error(); } normalized_segments.pop_back(); } else { normalized_segments.push_back(segment); } } // remove adjacent slashes optional<std::string> prev_segment; detail::remove_erase_if( normalized_segments, [&prev_segment](const std::string& segment) { bool has_adjacent_slash = ((prev_segment && prev_segment->empty()) && segment.empty()); if (!has_adjacent_slash) { prev_segment = segment; } return has_adjacent_slash; }); result = network_boost::join(normalized_segments, "/"); } if (result.empty()) { result = "/"; } return result; }
response<empty_body> do_head_request( SyncStream& stream, DynamicBuffer& buffer, string_view target, error_code& ec) { // Do some type checking to be a good citizen static_assert(is_sync_stream<SyncStream>::value, "SyncStream requirements not met"); static_assert(is_dynamic_buffer<DynamicBuffer>::value, "DynamicBuffer requirments not met"); // The interfaces we are using are low level and do not // perform any checking of arguments; so we do it here. if(target.empty()) throw std::invalid_argument("target may not be empty"); // Build the HEAD request for the target request<empty_body> req; req.version = 11; req.method(verb::head); req.target(target); req.set(field::user_agent, "test"); // A client MUST send a Host header field in all HTTP/1.1 request messages. // https://tools.ietf.org/html/rfc7230#section-5.4 req.set(field::host, "localhost"); // Now send it write(stream, req, ec); if(ec) return {}; // Create a parser to read the response. // Responses to HEAD requests MUST NOT include // a body, so we use the `empty_body` type and // only attempt to read the header. parser<false, empty_body> p; read_header(stream, buffer, p, ec); if(ec) return {}; // Transfer ownership of the response to the caller. return p.release(); }
static bool open_wd(gitdb & db, git_wd & wd, string_view path) { std::string apath = absolute_path(clean_path(path)); path = apath; while (!path.empty()) { std::string nonbare_path = join_paths(path, ".git"); if (file::is_directory(nonbare_path)) { db.open(nonbare_path); wd.open(db, path); return true; } path = path_head(path); } return false; }
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; }
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; }
static void parse_elements (string_view name, TypeDesc type, const char *type_code, string_view value, ImageIOParameter ¶m) { int num_items = type.numelements() * type.aggregate; T *data = (T*) param.data(); // Erase any leading whitespace value.remove_prefix (value.find_first_not_of (" \t")); for (int i = 0; i < num_items; ++i) { // Make a temporary copy so we for sure have a 0-terminated string. std::string temp = value; // Grab the first value from it sscanf (temp.c_str(), type_code, &data[i]); // Skip the value (eat until we find a delimiter -- space, comma, tab) value.remove_prefix (value.find_first_of (" ,\t")); // Skip the delimiter value.remove_prefix (value.find_first_not_of (" ,\t")); if (value.empty()) break; // done if nothing left to parse } }
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); } } } }
bool OSLCompilerImpl::compile_buffer (string_view sourcecode, std::string &osobuffer, const std::vector<std::string> &options, string_view stdoslpath) { string_view filename ("<buffer>"); #if OIIO_VERSION >= 10604 m_cwd = OIIO::Filesystem::current_path(); #else m_cwd = boost::filesystem::current_path().string(); #endif m_main_filename = filename; // Determine where the installed shader include directory is, and // look for ../shaders/stdosl.h and force it to include. if (stdoslpath.empty()) { // look in $OSLHOME/shaders const char *OSLHOME = getenv ("OSLHOME"); if (OSLHOME && OSLHOME[0]) { std::string path = std::string(OSLHOME) + "/shaders"; if (OIIO::Filesystem::exists (path)) { path = path + "/stdosl.h"; if (OIIO::Filesystem::exists (path)) stdoslpath = ustring(path); } } } if (stdoslpath.empty() || ! OIIO::Filesystem::exists(stdoslpath)) warning (ustring(filename), 0, "Unable to find \"stdosl.h\""); std::vector<std::string> defines; std::vector<std::string> includepaths; read_compile_options (options, defines, includepaths); std::string preprocess_result; if (! preprocess_buffer (sourcecode, filename, stdoslpath, defines, includepaths, preprocess_result)) { return false; } else if (m_preprocess_only) { std::cout << preprocess_result; } else { bool parseerr = osl_parse_buffer (preprocess_result); if (! parseerr) { if (shader()) shader()->typecheck (); else error (ustring(), 0, "No shader function defined"); } // Print the parse tree if there were no errors if (m_debug) { symtab().print (); if (shader()) shader()->print (std::cout); } if (! error_encountered()) { shader()->codegen (); track_variable_dependencies (); track_variable_lifetimes (); check_for_illegal_writes (); // if (m_optimizelevel >= 1) // coalesce_temporaries (); } if (! error_encountered()) { m_output_filename = "<buffer>"; std::ostringstream oso_output; ASSERT (m_osofile == NULL); m_osofile = &oso_output; write_oso_file (m_output_filename, OIIO::Strutil::join(options," ")); osobuffer = oso_output.str(); ASSERT (m_osofile == NULL); } oslcompiler = NULL; } return ! error_encountered(); }
bool Panel::MakeListFile(string& ListFileName, bool ShortNames, string_view const Modifers) { uintptr_t CodePage = CP_OEMCP; if (!Modifers.empty()) { if (contains(Modifers, L'A')) // ANSI { CodePage = CP_ACP; } else if (contains(Modifers, L'U')) // UTF8 { CodePage = CP_UTF8; } else if (contains(Modifers, L'W')) // UTF16LE { CodePage = CP_UNICODE; } } const auto& transform = [&](string& strFileName) { if (!Modifers.empty()) { if (contains(Modifers, L'F') && PointToName(strFileName).size() == strFileName.size()) // 'F' - использовать полный путь; //BUGBUG ? { strFileName = path::join(ShortNames ? ConvertNameToShort(m_CurDir) : m_CurDir, strFileName); //BUGBUG ? } if (contains(Modifers, L'Q')) // 'Q' - заключать имена с пробелами в кавычки; QuoteSpaceOnly(strFileName); if (contains(Modifers, L'S')) // 'S' - использовать '/' вместо '\' в путях файлов; { ReplaceBackslashToSlash(strFileName); } } }; try { ListFileName = MakeTemp(); if (const auto ListFile = os::fs::file(ListFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, CREATE_ALWAYS)) { os::fs::filebuf StreamBuffer(ListFile, std::ios::out); std::ostream Stream(&StreamBuffer); Stream.exceptions(Stream.badbit | Stream.failbit); encoding::writer Writer(Stream, CodePage); for (const auto& i: enum_selected()) { auto Name = ShortNames? i.AlternateFileName() : i.FileName; transform(Name); Writer.write(Name); Writer.write(L"\r\n"sv); } Stream.flush(); } else { throw MAKE_FAR_EXCEPTION(msg(lng::MCannotCreateListTemp)); } return true; } catch (const far_exception& e) { os::fs::delete_file(ListFileName); Message(MSG_WARNING, e.get_error_state(), msg(lng::MError), { msg(lng::MCannotCreateListFile), e.get_message() }, { lng::MOk }); return false; } }
std::unique_ptr<ImageInput> ImageInput::create(const std::string& filename, bool do_open, const ImageSpec* config, string_view plugin_searchpath) { // In case the 'filename' was really a REST-ful URI with query/config // details tacked on to the end, strip them off so we can correctly // extract the file extension. std::unique_ptr<ImageInput> in; std::map<std::string, std::string> args; std::string filename_stripped; if (!Strutil::get_rest_arguments(filename, filename_stripped, args)) { OIIO::pvt::errorf( "ImageInput::create() called with malformed filename"); return in; } if (filename_stripped.empty()) filename_stripped = filename; if (filename_stripped.empty()) { // Can't even guess if no filename given OIIO::pvt::errorf("ImageInput::create() called with no filename"); return in; } // Extract the file extension from the filename (without the leading dot) std::string format = Filesystem::extension(filename_stripped, false); if (format.empty()) { // If the file had no extension, maybe it was itself the format name format = filename; } ImageInput::Creator create_function = nullptr; { // scope the lock: recursive_lock_guard lock(imageio_mutex); // Ensure thread safety // See if it's already in the table. If not, scan all plugins we can // find to populate the table. Strutil::to_lower(format); InputPluginMap::const_iterator found = input_formats.find(format); if (found == input_formats.end()) { if (plugin_searchpath.empty()) plugin_searchpath = pvt::plugin_searchpath; catalog_all_plugins(plugin_searchpath); found = input_formats.find(format); } if (found != input_formats.end()) create_function = found->second; } // Remember which prototypes we've already tried, so we don't double dip. std::vector<ImageInput::Creator> formats_tried; std::string specific_error; if (create_function && filename != format) { // If given a full filename, double-check that our guess // based on the extension actually works. You never know // when somebody will have an incorrectly-named file, let's // deal with it robustly. formats_tried.push_back(create_function); in = std::unique_ptr<ImageInput>(create_function()); if (!do_open && in && in->valid_file(filename)) { // Special case: we don't need to return the file // already opened, and this ImageInput says that the // file is the right type. return in; } ImageSpec tmpspec; bool ok = false; if (in && config) ok = in->open(filename, tmpspec, *config); else if (in) ok = in->open(filename, tmpspec); if (ok) { // It worked if (!do_open) in->close(); return in; } else { // Oops, it failed. Apparently, this file can't be // opened with this II. Clear create_function to force // the code below to check every plugin we know. create_function = nullptr; if (in) specific_error = in->geterror(); } in.reset(); } if (!create_function) { // If a plugin can't be found that was explicitly designated for // this extension, then just try every one we find and see if // any will open the file. Add a configuration request that // includes a "nowait" option so that it returns immediately if // it's a plugin that might wait for an event, like a socket that // doesn't yet exist). ImageSpec myconfig; if (config) myconfig = *config; myconfig.attribute("nowait", (int)1); recursive_lock_guard lock(imageio_mutex); // Ensure thread safety for (auto&& plugin : input_formats) { // If we already tried this create function, don't do it again if (std::find(formats_tried.begin(), formats_tried.end(), plugin.second) != formats_tried.end()) continue; formats_tried.push_back(plugin.second); // remember ImageSpec tmpspec; try { ImageInput::Creator create_function = plugin.second; in = std::unique_ptr<ImageInput>(create_function()); } catch (...) { // Safety in case the ctr throws an exception } if (!in) continue; if (!do_open && !in->valid_file(filename)) { // Since we didn't need to open it, we just checked whether // it was a valid file, and it's not. Try the next one. in.reset(); continue; } // We either need to open it, or we already know it appears // to be a file of the right type. bool ok = in->open(filename, tmpspec, myconfig); if (ok) { if (!do_open) in->close(); return in; } in.reset(); } } if (!create_function) { recursive_lock_guard lock(imageio_mutex); // Ensure thread safety if (input_formats.empty()) { // This error is so fundamental, we echo it to stderr in // case the app is too dumb to do so. const char* msg = "ImageInput::create() could not find any ImageInput plugins!\n" " Perhaps you need to set OIIO_LIBRARY_PATH.\n"; fprintf(stderr, "%s", msg); OIIO::pvt::errorf("%s", msg); } else if (!specific_error.empty()) { // Pass along any specific error message we got from our // best guess of the format. OIIO::pvt::errorf("%s", specific_error); } else if (Filesystem::exists(filename)) pvt::errorf( "OpenImageIO could not find a format reader for \"%s\". " "Is it a file format that OpenImageIO doesn't know about?\n", filename); else OIIO::pvt::errorf( "Image \"%s\" does not exist. Also, it is not the name of an image format that OpenImageIO recognizes.\n", filename); DASSERT(!in); return in; } return std::unique_ptr<ImageInput>(create_function()); }
// ----------------------------------------------------------------------------- // Splits [text] into separate lines (split by newlines), also performs further // splitting to word wrap the text within the box // ----------------------------------------------------------------------------- void TextBox::split(string_view text) { // Clear current text lines lines_.clear(); // Do nothing for empty string if (text.empty()) return; // Split at newlines auto split = StrUtil::splitV(text, '\n'); for (auto& line : split) lines_.emplace_back(line); // Don't bother wrapping if width is really small if (width_ < 32) return; // Word wrap unsigned line = 0; while (line < lines_.size()) { // Ignore empty or single-character line if (lines_[line].length() < 2) { line++; continue; } // Get line width double width = Drawing::textExtents(lines_[line], font_).x; // Continue to next line if within box if (width < width_) { line++; continue; } // Halve length until it fits in the box unsigned c = lines_[line].length() - 1; while (width >= width_) { if (c <= 1) break; c *= 0.5; width = Drawing::textExtents(lines_[line].substr(0, c), font_).x; } // Increment length until it doesn't fit while (width < width_) { c++; width = Drawing::textExtents(lines_[line].substr(0, c), font_).x; } c--; // Find previous space int sc = c; while (sc >= 0) { if (lines_[line][sc] == ' ') break; sc--; } if (sc <= 0) sc = c; else sc++; // Split line auto nl = lines_[line].substr(sc); lines_[line] = lines_[line].substr(0, sc); lines_.insert(lines_.begin() + line + 1, nl); line++; } // Update height if (line_height_ < 0) height_ = Drawing::textExtents(lines_[0], font_).y * lines_.size(); else height_ = line_height_ * lines_.size(); }
#include <functional> #include <type_traits> #include <catch/catch.hpp> using namespace rttr; using namespace std; ///////////////////////////////////////////////////////////////////////////////////////// TEST_CASE("string_view - string_view()", "[string_view]") { string_view text; CHECK(text.empty() == true); } ///////////////////////////////////////////////////////////////////////////////////////// TEST_CASE("string_view - string_view(const string_view&)", "[string_view]") { string_view text1; string_view text2 = text1; string_view text3 = "Hello World"; string_view text4 = text3; CHECK(text1.empty() == true); CHECK(text2.empty() == true); CHECK(text3.empty() == false); CHECK(text4.empty() == false);
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); }
// ----------------------------------------------------------------------------- // Adds a [context] of the function // ----------------------------------------------------------------------------- void TLFunction::addContext( string_view context, string_view args, string_view return_type, string_view description, string_view deprecated_f) { contexts_.emplace_back(context, return_type, description); auto& ctx = contexts_.back(); // Parse args Tokenizer tz; tz.setSpecialCharacters("[],"); tz.openString(args); vector<string> arg_tokens; while (true) { while (!tz.check(",")) { arg_tokens.push_back(tz.current().text); if (tz.atEnd()) break; tz.adv(); } ctx.params.push_back({}); ctx.params.back().parse(arg_tokens); arg_tokens.clear(); if (tz.atEnd()) break; tz.adv(); } if (!deprecated_f.empty()) { // Parse deprecated string tz.openString(deprecated_f); for (unsigned t = 0; t < 2; t++) { while (tz.check(",")) tz.adv(); bool is_replacement = true; for (auto&& c : tz.current().text) { char chr = c; if (isdigit(chr) || chr == '.') { is_replacement = false; break; } } if (is_replacement) ctx.deprecated_f = tz.current().text; else ctx.deprecated_v = tz.current().text; if (tz.atEnd()) break; tz.adv(); } } }