[libcxx] Implement parsing of root_name for paths on windows
Differential Revision: https://reviews.llvm.org/D91176
This commit is contained in:
		
							parent
							
								
									8ddfcec91b
								
							
						
					
					
						commit
						929f0bcc24
					
				| 
						 | 
					@ -64,6 +64,10 @@ bool isSeparator(path::value_type C) {
 | 
				
			||||||
  return false;
 | 
					  return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool isDriveLetter(path::value_type C) {
 | 
				
			||||||
 | 
					  return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace parser {
 | 
					namespace parser {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using string_view_t = path::__string_view;
 | 
					using string_view_t = path::__string_view;
 | 
				
			||||||
| 
						 | 
					@ -120,6 +124,12 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (State) {
 | 
					    switch (State) {
 | 
				
			||||||
    case PS_BeforeBegin: {
 | 
					    case PS_BeforeBegin: {
 | 
				
			||||||
 | 
					      PosPtr TkEnd = consumeRootName(Start, End);
 | 
				
			||||||
 | 
					      if (TkEnd)
 | 
				
			||||||
 | 
					        return makeState(PS_InRootName, Start, TkEnd);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					      _LIBCPP_FALLTHROUGH();
 | 
				
			||||||
 | 
					    case PS_InRootName: {
 | 
				
			||||||
      PosPtr TkEnd = consumeSeparator(Start, End);
 | 
					      PosPtr TkEnd = consumeSeparator(Start, End);
 | 
				
			||||||
      if (TkEnd)
 | 
					      if (TkEnd)
 | 
				
			||||||
        return makeState(PS_InRootDir, Start, TkEnd);
 | 
					        return makeState(PS_InRootDir, Start, TkEnd);
 | 
				
			||||||
| 
						 | 
					@ -142,7 +152,6 @@ public:
 | 
				
			||||||
    case PS_InTrailingSep:
 | 
					    case PS_InTrailingSep:
 | 
				
			||||||
      return makeState(PS_AtEnd);
 | 
					      return makeState(PS_AtEnd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case PS_InRootName:
 | 
					 | 
				
			||||||
    case PS_AtEnd:
 | 
					    case PS_AtEnd:
 | 
				
			||||||
      _LIBCPP_UNREACHABLE();
 | 
					      _LIBCPP_UNREACHABLE();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -160,9 +169,15 @@ public:
 | 
				
			||||||
      if (PosPtr SepEnd = consumeSeparator(RStart, REnd)) {
 | 
					      if (PosPtr SepEnd = consumeSeparator(RStart, REnd)) {
 | 
				
			||||||
        if (SepEnd == REnd)
 | 
					        if (SepEnd == REnd)
 | 
				
			||||||
          return makeState(PS_InRootDir, Path.data(), RStart + 1);
 | 
					          return makeState(PS_InRootDir, Path.data(), RStart + 1);
 | 
				
			||||||
 | 
					        PosPtr TkStart = consumeRootName(SepEnd, REnd);
 | 
				
			||||||
 | 
					        if (TkStart == REnd)
 | 
				
			||||||
 | 
					          return makeState(PS_InRootDir, RStart, RStart + 1);
 | 
				
			||||||
        return makeState(PS_InTrailingSep, SepEnd + 1, RStart + 1);
 | 
					        return makeState(PS_InTrailingSep, SepEnd + 1, RStart + 1);
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        PosPtr TkStart = consumeName(RStart, REnd);
 | 
					        PosPtr TkStart = consumeRootName(RStart, REnd);
 | 
				
			||||||
 | 
					        if (TkStart == REnd)
 | 
				
			||||||
 | 
					          return makeState(PS_InRootName, TkStart + 1, RStart + 1);
 | 
				
			||||||
 | 
					        TkStart = consumeName(RStart, REnd);
 | 
				
			||||||
        return makeState(PS_InFilenames, TkStart + 1, RStart + 1);
 | 
					        return makeState(PS_InFilenames, TkStart + 1, RStart + 1);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -173,11 +188,17 @@ public:
 | 
				
			||||||
      PosPtr SepEnd = consumeSeparator(RStart, REnd);
 | 
					      PosPtr SepEnd = consumeSeparator(RStart, REnd);
 | 
				
			||||||
      if (SepEnd == REnd)
 | 
					      if (SepEnd == REnd)
 | 
				
			||||||
        return makeState(PS_InRootDir, Path.data(), RStart + 1);
 | 
					        return makeState(PS_InRootDir, Path.data(), RStart + 1);
 | 
				
			||||||
      PosPtr TkEnd = consumeName(SepEnd, REnd);
 | 
					      PosPtr TkStart = consumeRootName(SepEnd ? SepEnd : RStart, REnd);
 | 
				
			||||||
      return makeState(PS_InFilenames, TkEnd + 1, SepEnd + 1);
 | 
					      if (TkStart == REnd) {
 | 
				
			||||||
 | 
					        if (SepEnd)
 | 
				
			||||||
 | 
					          return makeState(PS_InRootDir, SepEnd + 1, RStart + 1);
 | 
				
			||||||
 | 
					        return makeState(PS_InRootName, TkStart + 1, RStart + 1);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      TkStart = consumeName(SepEnd, REnd);
 | 
				
			||||||
 | 
					      return makeState(PS_InFilenames, TkStart + 1, SepEnd + 1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case PS_InRootDir:
 | 
					    case PS_InRootDir:
 | 
				
			||||||
      // return makeState(PS_InRootName, Path.data(), RStart + 1);
 | 
					      return makeState(PS_InRootName, Path.data(), RStart + 1);
 | 
				
			||||||
    case PS_InRootName:
 | 
					    case PS_InRootName:
 | 
				
			||||||
    case PS_BeforeBegin:
 | 
					    case PS_BeforeBegin:
 | 
				
			||||||
      _LIBCPP_UNREACHABLE();
 | 
					      _LIBCPP_UNREACHABLE();
 | 
				
			||||||
| 
						 | 
					@ -284,7 +305,7 @@ private:
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PosPtr consumeSeparator(PosPtr P, PosPtr End) const noexcept {
 | 
					  PosPtr consumeSeparator(PosPtr P, PosPtr End) const noexcept {
 | 
				
			||||||
    if (P == End || !isSeparator(*P))
 | 
					    if (P == nullptr || P == End || !isSeparator(*P))
 | 
				
			||||||
      return nullptr;
 | 
					      return nullptr;
 | 
				
			||||||
    const int Inc = P < End ? 1 : -1;
 | 
					    const int Inc = P < End ? 1 : -1;
 | 
				
			||||||
    P += Inc;
 | 
					    P += Inc;
 | 
				
			||||||
| 
						 | 
					@ -293,15 +314,72 @@ private:
 | 
				
			||||||
    return P;
 | 
					    return P;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Consume exactly N separators, or return nullptr.
 | 
				
			||||||
 | 
					  PosPtr consumeNSeparators(PosPtr P, PosPtr End, int N) const noexcept {
 | 
				
			||||||
 | 
					    PosPtr Ret = consumeSeparator(P, End);
 | 
				
			||||||
 | 
					    if (Ret == nullptr)
 | 
				
			||||||
 | 
					      return nullptr;
 | 
				
			||||||
 | 
					    if (P < End) {
 | 
				
			||||||
 | 
					      if (Ret == P + N)
 | 
				
			||||||
 | 
					        return Ret;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      if (Ret == P - N)
 | 
				
			||||||
 | 
					        return Ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return nullptr;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PosPtr consumeName(PosPtr P, PosPtr End) const noexcept {
 | 
					  PosPtr consumeName(PosPtr P, PosPtr End) const noexcept {
 | 
				
			||||||
    if (P == End || isSeparator(*P))
 | 
					    PosPtr Start = P;
 | 
				
			||||||
 | 
					    if (P == nullptr || P == End || isSeparator(*P))
 | 
				
			||||||
      return nullptr;
 | 
					      return nullptr;
 | 
				
			||||||
    const int Inc = P < End ? 1 : -1;
 | 
					    const int Inc = P < End ? 1 : -1;
 | 
				
			||||||
    P += Inc;
 | 
					    P += Inc;
 | 
				
			||||||
    while (P != End && !isSeparator(*P))
 | 
					    while (P != End && !isSeparator(*P))
 | 
				
			||||||
      P += Inc;
 | 
					      P += Inc;
 | 
				
			||||||
 | 
					    if (P == End && Inc < 0) {
 | 
				
			||||||
 | 
					      // Iterating backwards and consumed all the rest of the input.
 | 
				
			||||||
 | 
					      // Check if the start of the string would have been considered
 | 
				
			||||||
 | 
					      // a root name.
 | 
				
			||||||
 | 
					      PosPtr RootEnd = consumeRootName(End + 1, Start);
 | 
				
			||||||
 | 
					      if (RootEnd)
 | 
				
			||||||
 | 
					        return RootEnd - 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return P;
 | 
					    return P;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  PosPtr consumeDriveLetter(PosPtr P, PosPtr End) const noexcept {
 | 
				
			||||||
 | 
					    if (P == End)
 | 
				
			||||||
 | 
					      return nullptr;
 | 
				
			||||||
 | 
					    if (P < End) {
 | 
				
			||||||
 | 
					      if (P + 1 == End || !isDriveLetter(P[0]) || P[1] != ':')
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					      return P + 2;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      if (P - 1 == End || !isDriveLetter(P[-1]) || P[0] != ':')
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					      return P - 2;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  PosPtr consumeNetworkRoot(PosPtr P, PosPtr End) const noexcept {
 | 
				
			||||||
 | 
					    if (P == End)
 | 
				
			||||||
 | 
					      return nullptr;
 | 
				
			||||||
 | 
					    if (P < End)
 | 
				
			||||||
 | 
					      return consumeName(consumeNSeparators(P, End, 2), End);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      return consumeNSeparators(consumeName(P, End), End, 2);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  PosPtr consumeRootName(PosPtr P, PosPtr End) const noexcept {
 | 
				
			||||||
 | 
					#if defined(_LIBCPP_WIN32API)
 | 
				
			||||||
 | 
					    if (PosPtr Ret = consumeDriveLetter(P, End))
 | 
				
			||||||
 | 
					      return Ret;
 | 
				
			||||||
 | 
					    if (PosPtr Ret = consumeNetworkRoot(P, End))
 | 
				
			||||||
 | 
					      return Ret;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    return nullptr;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
string_view_pair separate_filename(string_view_t const& s) {
 | 
					string_view_pair separate_filename(string_view_t const& s) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue