// Expand directory path - these cases exist: // // 1. Empty string or nil means return current directory // 2. ~ with non-existent HOME directory throws exception // 3. ~, ~/ or ~\ which expands to HOME // 4. ~foo is left unexpanded // 5. Expand to full path if path is a relative path // // No attempt is made to determine whether the path is valid or not // Returned path is always canonicalized to forward slashes private static MutableString /*!*/ ExpandPath(RubyContext /*!*/ context, MutableString /*!*/ path) { PlatformAdaptationLayer pal = context.DomainManager.Platform; int length = path.Length; try { if (path == null || length == 0) { return(Glob.CanonicalizePath(MutableString.Create(Directory.GetCurrentDirectory()))); } if (length == 1 && path.GetChar(0) == '~') { return(Glob.CanonicalizePath(MutableString.Create(Path.GetFullPath(pal.GetEnvironmentVariable("HOME"))))); } if (path.GetChar(0) == '~' && (path.GetChar(1) == Path.DirectorySeparatorChar || path.GetChar(1) == Path.AltDirectorySeparatorChar)) { string homeDirectory = pal.GetEnvironmentVariable("HOME"); return(Glob.CanonicalizePath(length < 3 ? MutableString.Create(homeDirectory) : MutableString.Create(Path.Combine(homeDirectory, path.GetSlice(2).ConvertToString())))); } else { return(Glob.CanonicalizePath(MutableString.Create(Path.GetFullPath(path.ConvertToString())))); } } catch (Exception e) { // Re-throw exception as a reasonable Ruby exception throw new Errno.InvalidError(path.ConvertToString(), e); } }
internal static IEnumerable <char> /*!*/ ExpandRanges(MutableString /*!*/ str, int start, int end, bool infinite) { int rangeMax = -1; char c = '\0'; int i = start; char lookahead = str.GetChar(start); while (true) { if (c < rangeMax) { // next character of the current range: c++; } else if (i < end) { c = lookahead; i++; lookahead = (i < end) ? str.GetChar(i) : '\0'; if (lookahead == '-' && i + 1 < end) { // range: rangeMax = str.GetChar(i + 1); i += 2; lookahead = (i < end) ? str.GetChar(i) : '\0'; if (c > rangeMax) { continue; } } else { rangeMax = -1; } } else { break; } yield return(c); } if (infinite) { while (true) { yield return(c); } } }
private static MutableString /*!*/ TrimTrailingSlashes(MutableString /*!*/ path) { int offset = path.Length - 1; while (offset > 0) { if (path.GetChar(offset) != '/' && path.GetChar(offset) != '\\') { break; } --offset; } return(path.GetSlice(0, offset + 1)); }
private static void AppendDirectoryName(MutableString /*!*/ result, MutableString /*!*/ name) { int resultLength = result.GetCharCount(); int i; for (i = resultLength - 1; i >= 0; i--) { if (!IsDirectorySeparator(result.GetChar(i))) { break; } } if (i == resultLength - 1) { if (!IsDirectorySeparator(name.GetFirstChar())) { result.Append(DirectorySeparatorChar); } result.Append(name); } else if (IsDirectorySeparator(name.GetFirstChar())) { result.Replace(i + 1, resultLength - i - 1, name); } else { result.Append(name); } }
public static char Create(RubyClass /*!*/ self, [DefaultProtocol] MutableString /*!*/ str) { if (str.IsEmpty) { throw EmptyError("string"); } return(str.GetChar(0)); }
public static MutableString /*!*/ Basename(RubyClass /*!*/ self, [DefaultProtocol, NotNull] MutableString /*!*/ path, [DefaultProtocol, NotNull, Optional] MutableString extensionFilter) { if (path.IsEmpty) { return(path); } MutableString trimmedPath = TrimTrailingSlashes(path); // Special cases of drive letters C:\\ or C:/ if (trimmedPath.Length == 2) { if (Char.IsLetter(trimmedPath.GetChar(0)) && trimmedPath.GetChar(1) == ':') { var result = (path.Length > 2 ? MutableString.Create(path.GetChar(2).ToString()) : MutableString.CreateMutable()); return(result.TaintBy(path)); } } string trimmedPathAsString = trimmedPath.ConvertToString(); if (trimmedPathAsString == "/") { return(trimmedPath); } string filename = Path.GetFileName(trimmedPath.ConvertToString()); // Handle UNC host names correctly string root = Path.GetPathRoot(trimmedPath.ConvertToString()); if (MutableString.IsNullOrEmpty(extensionFilter)) { return(MutableString.Create(trimmedPathAsString == root ? root : filename)); } string fileExtension = Path.GetExtension(filename); string basename = Path.GetFileNameWithoutExtension(filename); string strResult = WildcardExtensionMatch(fileExtension, extensionFilter.ConvertToString()) ? basename : filename; return(Glob.CanonicalizePath(MutableString.Create(strResult)).TaintBy(path)); }
internal static MutableString /*!*/ AppendEscapeForwardSlash(MutableString /*!*/ result, MutableString /*!*/ pattern) { int first = 0; int i = SkipToUnescapedForwardSlash(pattern, 0); while (i >= 0) { Debug.Assert(i < pattern.Length); Debug.Assert(pattern.GetChar(i) == '/' && (i == 0 || pattern.GetChar(i - 1) != '\\')); result.Append(pattern, first, i - first); result.Append('\\'); first = i; // include forward slash in the next append i = SkipToUnescapedForwardSlash(pattern, i + 1); } result.Append(pattern, first, pattern.Length - first); return(result); }
public static MutableString /*!*/ CanonicalizePath(MutableString /*!*/ path) { for (int i = 0; i < path.Length; i++) { if (path.GetChar(i) == '\\') { path.SetChar(i, '/'); } } return(path); }
private static int SkipToUnescapedForwardSlash(MutableString /*!*/ pattern, int patternLength, int i) { while (i < patternLength) { i = pattern.IndexOf('/', i); if (i <= 0) { return(i); } if (pattern.GetChar(i - 1) != '\\') { return(i); } i++; } return(-1); }
public MutableString ReadLine(MutableString separator) { AssertOpenedForReading(); int c = ReadByteNormalizeEoln(); if (c == -1) { return(null); } int separatorOffset = 0; MutableString result = MutableString.CreateMutable(); do { result.Append((char)c); if (separator != null && c == separator.GetChar(separatorOffset)) { if (separatorOffset == separator.Length - 1) { break; } separatorOffset++; } else if (separatorOffset > 0) { separatorOffset = 0; } c = ReadByteNormalizeEoln(); } while (c != -1); return(result); }
internal static RubyRegexOptions StringToRegexEncoding(MutableString encoding) { if (MutableString.IsNullOrEmpty(encoding)) { return(RubyRegexOptions.NONE); } switch (encoding.GetChar(0)) { case 'N': case 'n': return(RubyRegexOptions.FIXED); case 'E': case 'e': return(RubyRegexOptions.EUC); case 'S': case 's': return(RubyRegexOptions.SJIS); case 'U': case 'u': return(RubyRegexOptions.UTF8); } return(RubyRegexOptions.NONE); }
public static CharacterMap /*!*/ Create(MutableString /*!*/ from, MutableString /*!*/ to) { Debug.Assert(!from.IsEmpty); int fromLength = from.GetCharCount(); bool complemental = from.StartsWith('^') && fromLength > 1; // TODO: kcodings // TODO: surrogates // TODO: max - min > threshold int min, max; if (from.DetectByteCharacters()) { min = 0; max = 255; } else { min = Int32.MaxValue; max = -1; for (int i = (complemental ? 1 : 0); i < fromLength; i++) { int c = from.GetChar(i); if (c < min) { min = c; } if (c > max) { max = c; } } } BitArray map; char[] image; if (complemental || to.IsEmpty) { image = null; map = MakeBitmap(from, fromLength, complemental, min, max); } else { map = null; image = new char[max - min + 1]; // no need to initialize the array: Debug.Assert(Unmapped == 0); bool needMap = false; var toEnum = ExpandRanges(to, 0, to.GetCharCount(), true).GetEnumerator(); foreach (var f in ExpandRanges(from, 0, fromLength, false)) { toEnum.MoveNext(); needMap |= (image[f - min] = toEnum.Current) == Unmapped; } if (needMap) { map = MakeBitmap(from, fromLength, false, min, max); } } return(new CharacterMap(map, image, complemental ? to.GetLastChar() : -1, complemental, min, max)); }
internal void DoGlob(string /*!*/ baseDirectory, int position, bool isPreviousDoubleStar) { if (!_pal.DirectoryExists(baseDirectory)) { return; } bool containsWildcard; int patternEnd = FindNextSeparator(position, true, out containsWildcard); bool isLastPathSegment = (patternEnd == _pattern.Length); string dirSegment = _pattern.Substring(position, patternEnd - position); if (!isLastPathSegment) { patternEnd++; } if (!containsWildcard) { string path = baseDirectory + "/" + dirSegment; TestPath(path, patternEnd, isLastPathSegment); return; } MutableString mPattern = MutableString.Create(dirSegment); bool doubleStar = dirSegment.Equals("**"); if (doubleStar && !isPreviousDoubleStar) { DoGlob(baseDirectory, patternEnd, true); } string[] files = Directory.GetFileSystemEntries(baseDirectory); foreach (string file in files) { string objectName = Path.GetFileName(file); if (FnMatch(mPattern, MutableString.Create(objectName), _flags)) { TestPath(file, patternEnd, isLastPathSegment); if (doubleStar) { DoGlob(file, position, true); } } } if (isLastPathSegment && (_flags & Constants.FNM_DOTMATCH) != 0 || mPattern.GetChar(0) == '.') { if (FnMatch(mPattern, MutableString.Create("."), _flags)) { string directory = baseDirectory + "/."; if (_dirOnly) { directory += '/'; } TestPath(directory, patternEnd, true); } if (FnMatch(mPattern, MutableString.Create(".."), _flags)) { string directory = baseDirectory + "/.."; if (_dirOnly) { directory += '/'; } TestPath(directory, patternEnd, true); } } }