private XElement?GetSubNodeElement(string nodeNameOrPath, bool createIfNotFound) { Conditions.RequireString(nodeNameOrPath, nameof(nodeNameOrPath)); XElement?result = null; XElement currentElement = this.element; // Use backslash as the path separator because that's what RegistryKey.OpenSubKey uses, // and callers need to be able to switch between the ISettingsStore types without breaking. // FWIW, RegistryKey ignores the forward slash character, so we can't split on it. string[] nodeNames = nodeNameOrPath.Split('\\'); foreach (string nodeName in nodeNames) { result = GetSubNodeElements(currentElement).SingleOrDefault(e => GetNodeName(e) == nodeName); if (result == null) { if (!createIfNotFound) { break; } result = CreateNodeElement(nodeName); currentElement.Add(result); } currentElement = result; } return(result); }
internal static XElement CreateNodeElement(string nodeName) { Conditions.RequireString(nodeName, nameof(nodeName)); XElement result = new("Settings", new XAttribute("Name", nodeName)); return(result); }
/// <summary> /// Replaces a substring within the given text using the given comparison type. /// </summary> /// <param name="text">The text to search.</param> /// <param name="oldValue">The substring to search for.</param> /// <param name="newValue">The string that should replace the substring.</param> /// <param name="comparisonType">The type of string comparison to perform.</param> /// <returns>The string with the substring instances replaced.</returns> /// <exception cref="ArgumentNullException">If <paramref name="text"/> or <paramref name="oldValue"/> /// are null or empty.</exception> public static string Replace(string text, string oldValue, string?newValue, StringComparison comparisonType) { // Note: It's ok if newValue is null or empty. Conditions.RequireString(text, nameof(text)); Conditions.RequireString(oldValue, nameof(oldValue)); string result = text; int currentIndex = text.IndexOf(oldValue, comparisonType); if (currentIndex >= 0) { int textLength = text.Length; int oldValueLength = oldValue.Length; int previousIndex = 0; StringBuilder sb = new(text.Length); while (currentIndex >= 0) { if (currentIndex > previousIndex) { sb.Append(text.Substring(previousIndex, currentIndex - previousIndex)); } sb.Append(newValue); currentIndex += oldValueLength; previousIndex = currentIndex; if ((currentIndex + 1) < textLength) { currentIndex = text.IndexOf(oldValue, currentIndex + 1, comparisonType); } else { break; } } if (previousIndex < text.Length) { sb.Append(text.Substring(previousIndex)); } result = sb.ToString(); } return(result); }
/// <summary> /// Strips the opening and closing quotes off of a string if they exist. /// </summary> /// <param name="text">The text to search.</param> /// <param name="openQuote">The opening quote string.</param> /// <param name="closeQuote">The closing quote string.</param> /// <returns>The text with the quotes removed.</returns> public static string StripQuotes(string text, string openQuote, string closeQuote) { Conditions.RequireReference(text, nameof(text)); // An empty string is ok. Conditions.RequireString(openQuote, nameof(openQuote)); Conditions.RequireString(closeQuote, nameof(closeQuote)); int startIndex = 0; int length = text.Length; if (text.StartsWith(openQuote)) { int quoteLength = openQuote.Length; startIndex += quoteLength; length -= quoteLength; } if (text.EndsWith(closeQuote)) { length -= closeQuote.Length; } return(text.Substring(startIndex, length)); }
/// <summary> /// Ensures that the given text has the specified quotes at the start and end. /// </summary> /// <param name="text">The text to quote if necessary.</param> /// <param name="openQuote">The opening quote mark to use.</param> /// <param name="closeQuote">The closing quote mark to use.</param> /// <returns>The text enclosed in quotes.</returns> public static string EnsureQuotes(string text, string openQuote, string closeQuote) { Conditions.RequireReference(text, nameof(text)); // An empty string is ok. Conditions.RequireString(openQuote, nameof(openQuote)); Conditions.RequireString(closeQuote, nameof(closeQuote)); bool needsOpenQuote = !text.StartsWith(openQuote); bool needsCloseQuote = !text.EndsWith(closeQuote); if (needsOpenQuote && needsCloseQuote) { text = string.Concat(openQuote, text, closeQuote); } else if (needsOpenQuote) { text = openQuote + text; } else if (needsCloseQuote) { text += closeQuote; } return(text); }
internal static string?GetShellFileTypeAndIcon(string fileName, bool useExistingFile, IconOptions iconOptions, Action <IntPtr>?useIconHandle) { Conditions.RequireString(fileName, nameof(fileName)); Conditions.RequireArgument( (iconOptions == IconOptions.None && useIconHandle == null) || (iconOptions != IconOptions.None && useIconHandle != null), "The iconOptions and useIconHandle arguments must be compatible."); SHFILEINFO info = default; int cbFileInfo = Marshal.SizeOf(info); SHGFI flags = SHGFI.TypeName; int fileAttributes = 0; if (!useExistingFile) { flags |= SHGFI.UseFileAttributes; const int FILE_ATTRIBUTE_NORMAL = 128; const int FILE_ATTRIBUTE_DIRECTORY = 16; // http://stackoverflow.com/questions/1599235/how-do-i-fetch-the-folder-icon-on-windows-7-using-shell32-shgetfileinfo fileAttributes = iconOptions.HasFlag(IconOptions.Folder) ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL; } bool useIcon = iconOptions != IconOptions.None; if (useIcon) { flags |= SHGFI.Icon; // The Small and Large options are mutually exclusive. If they specify neither or both, then we'll default to small. if (iconOptions.HasFlag(IconOptions.Small) || !iconOptions.HasFlag(IconOptions.Large)) { flags |= SHGFI.SmallIcon; } else { flags |= SHGFI.LargeIcon; } if (iconOptions.HasFlag(IconOptions.ShellSize)) { flags |= SHGFI.ShellIconSize; } if (iconOptions.HasFlag(IconOptions.Open)) { flags |= SHGFI.OpenIcon; } if (iconOptions.HasFlag(IconOptions.Shortcut)) { flags |= SHGFI.LinkOverlay; } if (iconOptions.HasFlag(IconOptions.Selected)) { flags |= SHGFI.Selected; } } string?result = null; if (SHGetFileInfo(fileName, fileAttributes, out info, (uint)cbFileInfo, flags) != IntPtr.Zero) { result = info.szTypeName; if (useIcon && useIconHandle != null) { // The caller has to make a copy (e.g., Icon.FromHandle(hIcon).Clone()). useIconHandle(info.hIcon); DestroyIcon(info.hIcon); } } return(result); }