// Copyright (c) 2010-2014 SharpDX - Alexandre Mutel // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; using System.Collections.Generic; using System.Globalization; using System.Text.RegularExpressions; using SharpGen.Config; using SharpGen.CppModel; namespace SharpGen.Model { public static class CppElementExtensions { /// /// Finds the specified elements by regex. /// /// /// The regex. /// The C++ element finder instance to use. /// The selection mode for selecting matched elements. /// public static IEnumerable Find( this CppElementFinder finder, string regex, CppElementFinder.SelectionMode mode = CppElementFinder.SelectionMode.MatchedElement) where T : CppElement => finder.Find(BuildFullRegex(regex), mode); /// /// Strips the regex. Removes ^ and $ at the end of the string /// /// The regex. /// private static Regex BuildFullRegex(string regex) { string friendlyRegex = regex; // Remove ^ and $ if (friendlyRegex.StartsWith("^")) friendlyRegex = friendlyRegex.Substring(1); if (friendlyRegex.EndsWith("$")) friendlyRegex = friendlyRegex.Substring(0, friendlyRegex.Length - 1); return new Regex($"^{friendlyRegex}$"); } public static bool ExecuteRule(this CppElementFinder finder, string regex, MappingRule rule) where T : CppElement { var mode = CppElementFinder.SelectionMode.MatchedElement; var matchedAny = false; if (regex.StartsWith("#")) { mode = CppElementFinder.SelectionMode.Parent; regex = regex.Substring(1); } var fullRegex = BuildFullRegex(regex); foreach (var item in finder.Find(fullRegex, mode)) { matchedAny = true; ProcessRule(item, rule, fullRegex); } return matchedAny; } private static string RegexRename(Regex regex, string fromName, string replaceName) { return replaceName.Contains("$") ? regex.Replace(fromName, replaceName) : replaceName; } /// /// Fully rename a type and all references /// /// /// private static void ProcessRule(CppElement element, MappingRule newRule, Regex patchRegex) { var tag = element.Rule; if (newRule.Assembly != null) tag.Assembly = newRule.Assembly; if (newRule.Namespace != null) tag.Namespace = newRule.Namespace; if (newRule.DefaultValue != null) tag.DefaultValue = newRule.DefaultValue; if (newRule.MethodCheckReturnType.HasValue) tag.MethodCheckReturnType = newRule.MethodCheckReturnType; if (newRule.AlwaysReturnHResult.HasValue) tag.AlwaysReturnHResult = newRule.AlwaysReturnHResult; if (newRule.RawPtr.HasValue) tag.RawPtr = newRule.RawPtr; if (newRule.Visibility.HasValue) tag.Visibility = newRule.Visibility; if (newRule.NativeCallbackVisibility.HasValue) tag.NativeCallbackVisibility = newRule.NativeCallbackVisibility; if (newRule.ShadowVisibility.HasValue) tag.ShadowVisibility = newRule.ShadowVisibility; if (newRule.VtblVisibility.HasValue) tag.VtblVisibility = newRule.VtblVisibility; if (newRule.NativeCallbackName != null) tag.NativeCallbackName = RegexRename(patchRegex, element.FullName, newRule.NativeCallbackName); if (newRule.Property.HasValue) tag.Property = newRule.Property; if (newRule.CustomVtbl.HasValue) tag.CustomVtbl = newRule.CustomVtbl; if (newRule.Persist.HasValue) tag.Persist = newRule.Persist; if (newRule.MappingName != null) tag.MappingName = RegexRename(patchRegex, element.FullName, newRule.MappingName); if (newRule.NamingFlags.HasValue) tag.NamingFlags = newRule.NamingFlags.Value; if (newRule.IsFinalMappingName != null) tag.IsFinalMappingName = newRule.IsFinalMappingName; if (newRule.StructPack != null) tag.StructPack = newRule.StructPack; if (newRule.StructHasNativeValueType != null) tag.StructHasNativeValueType = newRule.StructHasNativeValueType; if (newRule.StructToClass != null) tag.StructToClass = newRule.StructToClass; if (newRule.StructCustomMarshal != null) tag.StructCustomMarshal = newRule.StructCustomMarshal; if (newRule.StructCustomNew != null) tag.StructCustomNew = newRule.StructCustomNew; if (newRule.IsStaticMarshal != null) tag.IsStaticMarshal = newRule.IsStaticMarshal; if (newRule.MappingType != null) tag.MappingType = RegexRename(patchRegex, element.FullName, newRule.MappingType); if (newRule.OverrideNativeType != null) tag.OverrideNativeType = newRule.OverrideNativeType; if (newRule.Pointer is { } pointer) tag.Pointer = pointer; if (newRule.TypeArrayDimension is { } arrayDimension) tag.TypeArrayDimension = arrayDimension; if (newRule.EnumHasFlags != null) tag.EnumHasFlags = newRule.EnumHasFlags; if (newRule.EnumHasNone != null) tag.EnumHasNone = newRule.EnumHasNone; if (newRule.IsCallbackInterface != null) tag.IsCallbackInterface = newRule.IsCallbackInterface; if (newRule.IsDualCallbackInterface != null) tag.IsDualCallbackInterface = newRule.IsDualCallbackInterface; if (newRule.AutoGenerateShadow != null) tag.AutoGenerateShadow = newRule.AutoGenerateShadow; if (newRule.AutoGenerateVtbl != null) tag.AutoGenerateVtbl = newRule.AutoGenerateVtbl; if (newRule.StaticShadowVtbl != null) tag.StaticShadowVtbl = newRule.StaticShadowVtbl; if (newRule.ShadowName != null) tag.ShadowName = RegexRename(patchRegex, element.FullName, newRule.ShadowName); if (newRule.VtblName != null) tag.VtblName = RegexRename(patchRegex, element.FullName, newRule.VtblName); if (newRule.IsKeepImplementPublic != null) tag.IsKeepImplementPublic = newRule.IsKeepImplementPublic; if (newRule.FunctionDllName != null) tag.FunctionDllName = RegexRename(patchRegex, element.FullName, newRule.FunctionDllName); if (newRule.Group != null) tag.Group = newRule.Group; if (newRule.ParameterAttribute is { } paramAttributeValue) tag.ParameterAttribute = paramAttributeValue; if (newRule.ParameterUsedAsReturnType != null) tag.ParameterUsedAsReturnType = newRule.ParameterUsedAsReturnType; if (newRule.Relation != null) tag.Relation = newRule.Relation; if (newRule.Hidden != null) tag.Hidden = newRule.Hidden; if (newRule.KeepPointers != null) tag.KeepPointers = newRule.KeepPointers; } } }