private Regex /*!*/ TransformPattern(RubyEncoding encoding, RubyRegexOptions kc) { // We can reuse cached CLR regex if it was created for the same k-coding: if (_cachedRegex != null && kc == _cachedKCode) { return(_cachedRegex); } string pattern; if (kc != 0 || encoding == RubyEncoding.Binary) { pattern = _pattern.ToString(encoding.Encoding); } else { pattern = _pattern.ConvertToString(); } Regex result; try { result = new Regex(RegexpTransformer.Transform(pattern, _options, out _hasGAnchor), ToClrOptions(_options)); } catch (Exception e) { throw new RegexpError(e.Message); } _cachedKCode = kc; _cachedRegex = result; return(result); }
internal static Process /*!*/ CreateProcess(RubyContext /*!*/ context, MutableString /*!*/ command, bool redirectInput, bool redirectOutput, bool redirectErrorOutput) { string fileName, arguments; RubyProcess.GetExecutable(context.DomainManager.Platform, command.ToString(), out fileName, out arguments); Utils.Log(String.Format("Starting: '{0}' with args: '{1}'", fileName, arguments), "PROCESS"); var p = new Process(); p.StartInfo.FileName = fileName; p.StartInfo.Arguments = arguments; p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardInput = redirectInput; p.StartInfo.RedirectStandardOutput = redirectOutput; p.StartInfo.RedirectStandardError = redirectErrorOutput; try { p.Start(); } catch (Exception e) { throw RubyExceptions.CreateENOENT(fileName, e); } context.ChildProcessExitStatus = new RubyProcess.Status(p); return(p); }
private Regex /*!*/ Transform(ref RubyEncoding encoding, MutableString /*!*/ input, int start, out string strInput) { ContractUtils.RequiresNotNull(input, "input"); // K-coding of the current operation (the current KCODE gets preference over the KCODE regex option): RubyRegexOptions kc = _options & RubyRegexOptions.EncodingMask; if (kc != 0) { encoding = _pattern.Encoding; } else { kc = RubyEncoding.ToRegexOption(encoding); } // Convert input to a string. Force k-coding if necessary. if (kc != 0) { // Handling multi-byte K-coded characters is not entirely correct here. // Three cases to be considered: // 1) Multi-byte character is explicitly contained in the pattern: /�*/ // 2) Subsequent escapes form a complete character: /\342\202\254*/ or /\xe2\x82\xac*/ // 3) Subsequent escapes form an incomplete character: /[\x7f-\xff]{1,3}/ // // In the first two cases we want to "group" the byte triplet so that regex operators like *, +, ? and {n,m} operate on // the entire character, not just the last byte. We could unescape the bytes and replace them with complete Unicode characters. // Then we could encode the input using the same K-coding and we would get a match. // However, case 3) requires the opposite: to match the bytes we need to encode the input using binary encoding. // Using this encoding makes *+? operators operate on the last byte (encoded as UTF16 character). // // The right solution would require the regex engine to handle multi-byte escaped characters, which it doesn't. // // TODO: // A correct workaround would be to wrap the byte sequence that forms a character into a non-capturing group, // for example transform /\342\202\254*/ to /(?:\342\202\254)*/ and use binary encoding on both input and pattern. // For now, we just detect if there are any non-ascii character escapes. If so we use a binary encoding accomodating case 3), // but breaking cases 1 and 2. Otherwise we encode using k-coding to make case 1 match. if (HasEscapedNonAsciiBytes(_pattern)) { encoding = RubyEncoding.Binary; kc = 0; } strInput = ForceEncoding(input, encoding.Encoding, start); } else if (input.Encoding.IsKCoding) { strInput = input.ToString(BinaryEncoding.Instance); } else { _pattern.RequireCompatibleEncoding(input); input.PrepareForCharacterRead(); strInput = input.ConvertToString(); } return(TransformPattern(encoding, kc)); }
public static int SysOpen(RubyClass /*!*/ self, [NotNull] MutableString path, [Optional] MutableString mode, [Optional] int perm) { if (RubyFileOps.DirectoryExists(self.Context, path)) { // TODO: What file descriptor should be returned for a directory? return(-1); } RubyIO io = new RubyFile(self.Context, path.ToString(), IOModeEnum.Parse(mode)); int fileDesc = io.GetFileDescriptor(); io.Close(); return(fileDesc); }
// declared private instance methods: // initialize // declared protected instance methods: // declared public instance methods: private static Exception MakeKeyTypeException(RubyContext /*!*/ context, object key) { if (key == null) { return(RubyExceptions.CreateTypeError("nil is not a symbol")); } else { MutableString repr = Protocols.ConvertToString(context, key); string message = String.Format("{0} is not a symbol", repr.ToString()); return(RubyExceptions.CreateArgumentError(message)); } }
public static IOInfo Parse(RubyContext /*!*/ context, MutableString /*!*/ modeAndEncoding) { if (!modeAndEncoding.IsAscii()) { throw IOModeEnum.IllegalMode(modeAndEncoding.ToAsciiString()); } string[] parts = modeAndEncoding.ToString().Split(':'); return(new IOInfo( IOModeEnum.Parse(parts[0]), (parts.Length > 1) ? TryParseEncoding(context, parts[1]) : null, (parts.Length > 2) ? TryParseEncoding(context, parts[2]) : null )); }
public static int Rename(RubyContext /*!*/ context, RubyClass /*!*/ self, [DefaultProtocol, NotNull] MutableString /*!*/ oldPath, [DefaultProtocol, NotNull] MutableString /*!*/ newPath) { string strOldPath = oldPath.ConvertToString(); if (!FileExists(context, strOldPath) && !DirectoryExists(context, strOldPath)) { throw new Errno.NoEntryError(String.Format("No such file or directory - {0}", oldPath)); } // TODO: Change to raise a SystemCallError instead of a native CLR error File.Move(strOldPath, newPath.ToString()); return(0); }
public static void RaiseException(Thread /*!*/ self, [NotNull] MutableString /*!*/ message) { if (self == Thread.CurrentThread) { KernelOps.RaiseException(self, message); return; } #if SILVERLIGHT throw new NotImplementedError("Thread#raise is not implemented on Silverlight"); #else Exception e = RubyExceptionData.InitializeException(new RuntimeError(message.ToString()), message); RaiseAsyncException(self, e); #endif }
private static string /*!*/ ForceEncoding(MutableString /*!*/ input, Encoding /*!*/ encoding, int start) { int byteCount = input.GetByteCount(); if (start < 0) { start += byteCount; } if (start < 0) { return(null); } return((start <= byteCount) ? input.ToString(encoding, start, byteCount - start) : null); }
public static void RaiseException(Thread /*!*/ self, [NotNull] MutableString /*!*/ message) { if (self == Thread.CurrentThread) { KernelOps.RaiseException(self, message); return; } #if FEATURE_EXCEPTION_STATE Exception e = RubyExceptionData.InitializeException(new RuntimeError(message.ToString()), message); RaiseAsyncException(self, e); #else throw new NotImplementedError("Thread#raise not supported on this platform"); #endif }
internal static Process /*!*/ CreateProcess(RubyContext /*!*/ context, MutableString /*!*/ command, MutableString[] /*!*/ args) { var psi = new ProcessStartInfo(command.ToString(), JoinArguments(args).ToString()); psi.UseShellExecute = false; psi.RedirectStandardError = true; try { Utils.Log(String.Format("Starting: '{0}' with args: '{1}'", psi.FileName, psi.Arguments), "PROCESS"); Process p = Process.Start(psi); p.WaitForExit(); context.ChildProcessExitStatus = new RubyProcess.Status(p); return(p); } catch (Exception e) { throw RubyExceptions.CreateENOENT(psi.FileName, e); } }
public static string GetSubstring(RubyScope /*!*/ scope, string /*!*/ self, [NotNull] RubyRegex /*!*/ regex, [DefaultProtocol] int occurrance) { if (regex.IsEmpty) { return(String.Empty); } MatchData match = RegexpOps.Match(scope, regex, MutableString.Create(self, RubyEncoding.UTF8)); if (match == null || !RegexpOps.NormalizeGroupIndex(ref occurrance, match.GroupCount)) { return(null); } MutableString result = match.GetGroupValue(occurrance); return(result != null?result.ToString() : null); }
public IOInfo AddEncoding(RubyContext /*!*/ context, MutableString /*!*/ encoding) { if (!encoding.IsAscii()) { context.ReportWarning(String.Format("Unsupported encoding {0} ignored", encoding.ToAsciiString())); return(this); } if (HasEncoding) { throw RubyExceptions.CreateArgumentError("encoding specified twice"); } string[] parts = encoding.ToString().Split(':'); return(new IOInfo( _mode, TryParseEncoding(context, parts[0]), (parts.Length > 1) ? TryParseEncoding(context, parts[1]) : null )); }
private string ReadSymbol(int typeFlag) { string result = null; if (typeFlag == ';') { int position = ReadInt32(); if (!_symbols.TryGetValue(position, out result)) { throw RubyExceptions.CreateArgumentError("bad symbol"); } } else { // Ruby appears to assume that it's a ':' in this context MutableString symbolName = ReadString(); result = symbolName.ToString(); int position = _symbols.Count; _symbols[position] = result; } return(result); }
public static string /*!*/ Concatenate(string /*!*/ self, [DefaultProtocol, NotNull] MutableString /*!*/ other) { return(self + other.ToString()); }
public override string /*!*/ ToString() { return(_string.ToString()); }
public static string /*!*/ Create(RubyClass /*!*/ self, [DefaultProtocol] MutableString /*!*/ str) { return(str.ToString()); }
public static MutableString /*!*/ FormatTime(DateTime self, [DefaultProtocol, NotNull] MutableString /*!*/ format) { bool inEscape = false; StringBuilder builder = new StringBuilder(); foreach (char c in format.ToString()) { if (c == '%' && !inEscape) { inEscape = true; continue; } if (inEscape) { string thisFormat = null; DateTime firstDay; int week; switch (c) { case 'a': thisFormat = "ddd"; break; case 'A': thisFormat = "dddd"; break; case 'b': thisFormat = "MMM"; break; case 'B': thisFormat = "MMMM"; break; case 'c': thisFormat = "g"; break; case 'd': thisFormat = "dd"; break; case 'H': thisFormat = "HH"; break; case 'I': thisFormat = "hh"; break; case 'j': builder.AppendFormat("{0:000}", self.DayOfYear); break; case 'm': thisFormat = "MM"; break; case 'M': thisFormat = "mm"; break; case 'p': thisFormat = "tt"; break; case 'S': thisFormat = "ss"; break; case 'U': firstDay = self.AddDays(1 - self.DayOfYear); DateTime firstSunday = firstDay.AddDays((7 - (int)firstDay.DayOfWeek) % 7); week = 1 + (int)Math.Floor((self - firstSunday).Days / 7.0); builder.AppendFormat("{0:00}", week); break; case 'W': firstDay = self.AddDays(1 - self.DayOfYear); DateTime firstMonday = firstDay.AddDays((8 - (int)firstDay.DayOfWeek) % 7); week = 1 + (int)Math.Floor((self - firstMonday).Days / 7.0); builder.AppendFormat("{0:00}", week); break; case 'w': builder.Append((int)self.DayOfWeek); break; case 'x': thisFormat = "d"; break; case 'X': thisFormat = "t"; break; case 'y': thisFormat = "yy"; break; case 'Y': thisFormat = "yyyy"; break; case 'Z': thisFormat = "%K"; break; default: builder.Append(c); break; } if (thisFormat != null) { builder.Append(self.ToString(thisFormat)); } inEscape = false; } else { builder.Append(c); } } return(MutableString.Create(builder.ToString())); }
public static IOMode Parse(MutableString mode, IOMode defaultMode) { return((mode != null) ? IOModeEnum.Parse(mode.ToString()) : defaultMode); }
public static MutableString /*!*/ Basename(RubyClass /*!*/ self, [DefaultProtocol, NotNull] MutableString /*!*/ path, [DefaultProtocol, NotNull, Optional] MutableString suffix) { if (path.IsEmpty) { return(path); } string strPath = path.ConvertToString(); string[] parts = strPath.Split(new[] { DirectorySeparatorChar, AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length == 0) { return(MutableString.CreateMutable(path.Encoding).Append((char)path.GetLastChar()).TaintBy(path)); } if (Environment.OSVersion.Platform != PlatformID.Unix && Environment.OSVersion.Platform != PlatformID.MacOSX) { string first = parts[0]; if (strPath.Length >= 2 && IsDirectorySeparator(strPath[0]) && IsDirectorySeparator(strPath[1])) { // UNC: skip 2 parts if (parts.Length <= 2) { return(MutableString.CreateMutable(path.Encoding).Append(DirectorySeparatorChar).TaintBy(path)); } } else if (first.Length == 2 && Tokenizer.IsLetter(first[0]) && first[1] == ':') { // skip drive letter "X:" if (parts.Length <= 1) { var result = MutableString.CreateMutable(path.Encoding).TaintBy(path); if (strPath.Length > 2) { result.Append(strPath[2]); } return(result); } } } string last = parts[parts.Length - 1]; if (MutableString.IsNullOrEmpty(suffix)) { return(MutableString.CreateMutable(last, path.Encoding)); } StringComparison comparison = Environment.OSVersion.Platform == PlatformID.Unix ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase; int matchLength = last.Length; if (suffix != null) { string strSuffix = suffix.ToString(); if (strSuffix.LastCharacter() == '*' && strSuffix.Length > 1) { int suffixIdx = last.LastIndexOf( strSuffix.Substring(0, strSuffix.Length - 1), comparison ); if (suffixIdx >= 0 && suffixIdx + strSuffix.Length <= last.Length) { matchLength = suffixIdx; } } else if (last.EndsWith(strSuffix, comparison)) { matchLength = last.Length - strSuffix.Length; } } return(MutableString.CreateMutable(path.Encoding).Append(last, 0, matchLength).TaintBy(path)); }
public static RubyEncoding /*!*/ GetEncoding(RubyClass /*!*/ self, [NotNull] MutableString /*!*/ name) { return(RubyEncoding.GetRubyEncoding(name.ToString())); }