Index: gtest/gtest.xcodeproj/project.pbxproj =================================================================== --- gtest/gtest.xcodeproj/project.pbxproj +++ gtest/gtest.xcodeproj/project.pbxproj @@ -10,6 +10,8 @@ 236ED33319D49076008CA7D7 /* ThreadStateCoordinatorTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadStateCoordinatorTest.cpp; sourceTree = ""; }; 236ED33419D49081008CA7D7 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; 236ED33619D490B0008CA7D7 /* Makefile.rules */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Makefile.rules; sourceTree = ""; }; + 33064C981A5C7A1A0033D415 /* UriParserTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UriParserTest.cpp; path = Utility/UriParserTest.cpp; sourceTree = ""; }; + 33064C9D1A5C7AC90033D415 /* do-gtest.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = "do-gtest.py"; sourceTree = ""; }; 338C47F41A1E67B900B46077 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = Utility/Makefile; sourceTree = ""; }; 338C47F51A1E67B900B46077 /* StringExtractorTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringExtractorTest.cpp; path = Utility/StringExtractorTest.cpp; sourceTree = ""; }; /* End PBXFileReference section */ @@ -60,6 +62,7 @@ 23CDD8EE19D4790700461DDC = { isa = PBXGroup; children = ( + 33064C9D1A5C7AC90033D415 /* do-gtest.py */, 236ED33519D49098008CA7D7 /* make */, 236ED32F19D4901D008CA7D7 /* unittest */, ); @@ -68,6 +71,7 @@ 338C47F31A1E677900B46077 /* Utility */ = { isa = PBXGroup; children = ( + 33064C981A5C7A1A0033D415 /* UriParserTest.cpp */, 338C47F41A1E67B900B46077 /* Makefile */, 338C47F51A1E67B900B46077 /* StringExtractorTest.cpp */, ); Index: gtest/unittest/Utility/Makefile =================================================================== --- gtest/unittest/Utility/Makefile +++ gtest/unittest/Utility/Makefile @@ -5,7 +5,8 @@ CFLAGS_EXTRAS := -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS ENABLE_THREADS := YES CXX_SOURCES := $(wildcard *.cpp) \ - $(realpath $(LEVEL)/../../source/Utility/StringExtractor.cpp) + $(realpath $(LEVEL)/../../source/Utility/StringExtractor.cpp) \ + $(realpath $(LEVEL)/../../source/Utility/UriParser.cpp) MAKE_DSYM := NO OS := $(shell uname -s) Index: gtest/unittest/Utility/UriParserTest.cpp =================================================================== --- gtest/unittest/Utility/UriParserTest.cpp +++ gtest/unittest/Utility/UriParserTest.cpp @@ -0,0 +1,129 @@ +#include "gtest/gtest.h" +#include "Utility/UriParser.h" + +namespace +{ + class UriParserTest: public ::testing::Test + { + }; +} + +// result strings (scheme/hostname/port/path) passed into UriParser::Parse +// are initialized to kAsdf so we can verify that they are unmodified if the +// URI is invalid +static const char* kAsdf = "asdf"; + +class UriTestCase +{ +public: + UriTestCase(const char* uri, const char* scheme, const char* hostname, int port, const char* path) : + m_uri(uri), + m_result(true), + m_scheme(scheme), + m_hostname(hostname), + m_port(port), + m_path(path) + { + } + + UriTestCase(const char* uri) : + m_uri(uri), + m_result(false), + m_scheme(kAsdf), + m_hostname(kAsdf), + m_port(1138), + m_path(kAsdf) + { + } + + const char* m_uri; + bool m_result; + const char* m_scheme; + const char* m_hostname; + int m_port; + const char* m_path; +}; + +#define VALIDATE \ + std::string scheme(kAsdf); \ + std::string hostname(kAsdf); \ + int port(1138); \ + std::string path(kAsdf); \ + EXPECT_EQ (testCase.m_result, UriParser::Parse(testCase.m_uri, scheme, hostname, port, path)); \ + EXPECT_STREQ (testCase.m_scheme, scheme.c_str()); \ + EXPECT_STREQ (testCase.m_hostname, hostname.c_str()); \ + EXPECT_EQ (testCase.m_port, port); \ + EXPECT_STREQ (testCase.m_path, path.c_str()); + +TEST_F (UriParserTest, Minimal) +{ + const UriTestCase testCase("x://y", "x", "y", 0, "/"); + VALIDATE +} + +TEST_F (UriParserTest, MinimalPort) +{ + const UriTestCase testCase("x://y:1", "x", "y", 1, "/"); + VALIDATE +} + +TEST_F (UriParserTest, MinimalPath) +{ + const UriTestCase testCase("x://y/", "x", "y", 0, "/"); + VALIDATE +} + +TEST_F (UriParserTest, MinimalPortPath) +{ + const UriTestCase testCase("x://y:1/", "x", "y", 1, "/"); + VALIDATE +} + +TEST_F (UriParserTest, TypicalPortPath) +{ + const UriTestCase testCase("connect://192.168.100.132:5432/", "connect", "192.168.100.132", 5432, "/"); + VALIDATE +} + +TEST_F (UriParserTest, SchemeHostSeparator) +{ + const UriTestCase testCase("x:/y"); + VALIDATE +} + +TEST_F (UriParserTest, SchemeHostSeparator2) +{ + const UriTestCase testCase("x:y"); + VALIDATE +} + +TEST_F (UriParserTest, SchemeHostSeparator3) +{ + const UriTestCase testCase("x//y"); + VALIDATE +} + +TEST_F (UriParserTest, SchemeHostSeparator4) +{ + const UriTestCase testCase("x/y"); + VALIDATE +} + +TEST_F (UriParserTest, BadPort) +{ + const UriTestCase testCase("x://y:a/"); + VALIDATE +} + +TEST_F (UriParserTest, BadPort2) +{ + const UriTestCase testCase("x://y:5432a/"); + VALIDATE +} + +TEST_F (UriParserTest, Empty) +{ + const UriTestCase testCase(""); + VALIDATE +} + Index: lldb.xcodeproj/project.pbxproj =================================================================== --- lldb.xcodeproj/project.pbxproj +++ lldb.xcodeproj/project.pbxproj @@ -581,6 +581,8 @@ 26FFC19C14FC072100087D58 /* DYLDRendezvous.h in Headers */ = {isa = PBXBuildFile; fileRef = 26FFC19614FC072100087D58 /* DYLDRendezvous.h */; }; 26FFC19D14FC072100087D58 /* DynamicLoaderPOSIXDYLD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26FFC19714FC072100087D58 /* DynamicLoaderPOSIXDYLD.cpp */; }; 26FFC19E14FC072100087D58 /* DynamicLoaderPOSIXDYLD.h in Headers */ = {isa = PBXBuildFile; fileRef = 26FFC19814FC072100087D58 /* DynamicLoaderPOSIXDYLD.h */; }; + 33064C9A1A5C7A330033D415 /* UriParser.cpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 33064C991A5C7A330033D415 /* UriParser.cpp */; }; + 33064C9C1A5C7A490033D415 /* UriParser.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 33064C9B1A5C7A490033D415 /* UriParser.h */; }; 3FDFDDBD199C3A06009756A7 /* FileAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFDDBC199C3A06009756A7 /* FileAction.cpp */; }; 3FDFDDBF199D345E009756A7 /* FileCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFDDBE199D345E009756A7 /* FileCache.cpp */; }; 3FDFDDC6199D37ED009756A7 /* FileSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFDDC5199D37ED009756A7 /* FileSystem.cpp */; }; @@ -932,6 +934,8 @@ dstSubfolderSpec = 0; files = ( AF90106515AB7D3600FF120D /* lldb.1 in CopyFiles */, + 33064C9C1A5C7A490033D415 /* UriParser.h in CopyFiles */, + 33064C9A1A5C7A330033D415 /* UriParser.cpp in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; @@ -1794,6 +1798,8 @@ 26FFC19614FC072100087D58 /* DYLDRendezvous.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DYLDRendezvous.h; sourceTree = ""; }; 26FFC19714FC072100087D58 /* DynamicLoaderPOSIXDYLD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLoaderPOSIXDYLD.cpp; sourceTree = ""; }; 26FFC19814FC072100087D58 /* DynamicLoaderPOSIXDYLD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderPOSIXDYLD.h; sourceTree = ""; }; + 33064C991A5C7A330033D415 /* UriParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UriParser.cpp; path = source/Utility/UriParser.cpp; sourceTree = ""; }; + 33064C9B1A5C7A490033D415 /* UriParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UriParser.h; path = source/Utility/UriParser.h; sourceTree = ""; }; 3F5E8AF31A40D4A500A73232 /* PipeBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PipeBase.h; path = include/lldb/Host/PipeBase.h; sourceTree = ""; }; 3FDFD6C3199C396E009756A7 /* FileAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileAction.h; path = include/lldb/Target/FileAction.h; sourceTree = ""; }; 3FDFDDBC199C3A06009756A7 /* FileAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FileAction.cpp; path = source/Target/FileAction.cpp; sourceTree = ""; }; @@ -3031,6 +3037,8 @@ 2682F168115ED9C800CCFF99 /* Utility */ = { isa = PBXGroup; children = ( + 33064C9B1A5C7A490033D415 /* UriParser.h */, + 33064C991A5C7A330033D415 /* UriParser.cpp */, AF9107E91685709A00DBCD3C /* ARM64_GCC_Registers.h */, 26CF992414428766001E4138 /* AnsiTerminal.h */, 26F996A7119B79C300412154 /* ARM_DWARF_Registers.h */, Index: source/Utility/CMakeLists.txt =================================================================== --- source/Utility/CMakeLists.txt +++ source/Utility/CMakeLists.txt @@ -11,4 +11,5 @@ StringExtractorGDBRemote.cpp StringLexer.cpp TimeSpecTimeout.cpp + UriParser.cpp ) Index: source/Utility/UriParser.h =================================================================== --- source/Utility/UriParser.h +++ source/Utility/UriParser.h @@ -0,0 +1,31 @@ +//===-- UriParser.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_UriParser_h_ +#define utility_UriParser_h_ + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +// Project includes + +class UriParser +{ +public: + static bool Parse(const char* uri, + std::string& scheme, + std::string& hostname, + int& port, + std::string& path + ); +}; + +#endif // utility_UriParser_h_ Index: source/Utility/UriParser.cpp =================================================================== --- source/Utility/UriParser.cpp +++ source/Utility/UriParser.cpp @@ -0,0 +1,58 @@ +//===-- UriParser.cpp -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Utility/UriParser.h" + +// C Includes +#include + +// C++ Includes +// Other libraries and framework includes +// Project includes + +//---------------------------------------------------------------------- +// UriParser::Parse +//---------------------------------------------------------------------- +bool +UriParser::Parse(const char* uri, + std::string& scheme, + std::string& hostname, + int& port, + std::string& path + ) +{ + char scheme_buf[100] = {0}; + char hostname_buf[256] = {0}; + char port_buf[11] = {0}; // 10==strlen(2^32) + char path_buf[2049] = {'/', 0}; + + bool ok = false; + if (4==sscanf(uri, "%99[^:/]://%255[^/:]:%[^/]/%2047s", scheme_buf, hostname_buf, port_buf, path_buf+1)) { ok = true; } + else if (3==sscanf(uri, "%99[^:/]://%255[^/:]:%[^/]", scheme_buf, hostname_buf, port_buf)) { ok = true; } + else if (3==sscanf(uri, "%99[^:/]://%255[^/]/%2047s", scheme_buf, hostname_buf, path_buf+1)) { ok = true; } + else if (2==sscanf(uri, "%99[^:/]://%255[^/]", scheme_buf, hostname_buf)) { ok = true; } + + char* end = port_buf; + int port_tmp = strtoul(port_buf, &end, 10); + if (*end != 0) + { + // there are invalid characters in port_buf + return false; + } + + if (ok) + { + scheme.assign(scheme_buf); + hostname.assign(hostname_buf); + port = port_tmp; + path.assign(path_buf); + } + return ok; +} +