/// 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;
}
예제 #2
0
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};
}
예제 #3
0
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();
}
예제 #4
0
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_);
}
예제 #5
0
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;
}
예제 #6
0
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;
    }
}
예제 #7
0
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);
			}
		}
	}
}
예제 #8
0
// -----------------------------------------------------------------------------
// 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());
}
예제 #9
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);
}
예제 #10
0
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);
}
예제 #11
0
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;
}
예제 #13
0
    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());
        }
    }
예제 #14
0
// -----------------------------------------------------------------------------
// 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);
}
예제 #15
0
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;
}
예제 #16
0
		skip(string_view const Str, string_view const Test) :
			m_Tail(starts_with(Str, Test) ? Str.substr(Test.size()) : string_view{})
		{
		}