Exemplo n.º 1
0
            public static string WrapWithThrow(bool isVoid, string name, IEnumerable <string> args)
            {
                var argList = string.Join("", args.Select(a => $"{a}, "));
                var cs      = new IndentedCodeBuilder();

                cs.StartBlock("{");
                cs.AppendLine($"{(isVoid ? "" : "var result = ")}{name}({argList}out char_ptr_ptr errptr);");
                cs.AppendLine($"if (errptr != IntPtr.Zero)");
                cs.AppendIndentedLine("throw new RocksDbException(errptr);");
                if (!isVoid)
                {
                    cs.AppendLine($"return result;");
                }
                cs.EndBlock("}");
                return(cs.ToString());
            }
Exemplo n.º 2
0
        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.Error.WriteLine("Usage: <exe> <version>");
                Console.Error.WriteLine("  Where <exe> is this executable and <version> is something like v5.18.3");
                return;
            }

            var version = args[0];

            // Download the original by commit id
            var urlOfCHeader = $"https://raw.githubusercontent.com/facebook/rocksdb/{version}/include/rocksdb/c.h";
            var original     = Download(urlOfCHeader);

            Console.Error.WriteLine($"Using: {urlOfCHeader}");

            // Transform from CRLF to LF
            var modified = original.Replace("\r\n", "\n");

            var regions = ParseRocksHeaderFileRegion(modified).ToList();

            var managedFunctions = regions.ToDictionary(r => r.Title, r => GetManagedFunctions(r).ToArray());

            var nativeRawCs = new IndentedCodeBuilder();

            nativeRawCs.AppendLine($"/* WARNING: This file was autogenerated from version {version} of rocksdb/c.h at");
            nativeRawCs.AppendLine($"   {urlOfCHeader}");
            nativeRawCs.AppendLine($" */");

            nativeRawCs.AppendLine(GetCsharpHeader());

            nativeRawCs.AppendLine("namespace RocksDbSharp");
            nativeRawCs.StartBlock("{");

            nativeRawCs.AppendLine("#region Type aliases");
            // Get every type in use as an argument type or a return type
            var typeVariations = managedFunctions
                                 .SelectMany(rmf => rmf.Value)
                                 .SelectMany(mf =>
                                             mf.ReturnType.Once()
                                             .Concat(mf.Args
                                                     .SelectMany(mfa => mfa.Variations.Where(mfav => mfav.TypeStrategy != "delegate"))
                                                     .Select(mfav => mfav.Type)
                                                     )
                                             )
                                 .Select(v => Regex.Replace(v, @"\[\]$", ""))
                                 .ToHashSet();

            foreach (var typeAlias in GetTypeAliases(regions))
            {
                // Find all the variations that are actually in use and include those
                foreach (var typeVariation in typeVariations.Where(tv => tv.Contains(typeAlias.Name)))
                {
                    nativeRawCs.AppendLine(typeAlias.Variation(typeVariation));
                }
            }
            nativeRawCs.AppendLine("#endregion");

            nativeRawCs.AppendLine("#region Delegates");
            var delegateSignatures = managedFunctions
                                     .SelectMany(rmf => rmf.Value)
                                     .SelectMany(mf => mf.Args.Select(mfa => (FuncName: mf.Name.RegexReplace(@"^rocksdb_|_create$", ""), Arg: mfa)))
                                     .SelectMany(mfa => mfa.Arg.Variations
                                                 .Where(mfav => mfav.TypeStrategy == "delegate")
                                                 .Select(mfav => (mfa.FuncName, mfav.Type, ArgName: mfav.Name))
                                                 )
                                     .ToList();
            var delegatesByName = delegateSignatures.GroupBy(ds => ds.ArgName);

            foreach (var nameGroup in delegatesByName)
            {
                var unique = nameGroup.Select(ng => ng.Type).Distinct();
                if (unique.Count() == 1)
                {
                    var definition         = nameGroup.First();
                    var parsed             = Regex.Match(definition.Type, @"^\((.*?)\) -> (.+)$");
                    var delegateReturnType = parsed.Groups[2].Value;
                    var delegateSignature  = parsed.Groups[1].Value;
                    var delegateName       = nameGroup.Key;
                    var name = $"{SnakeCaseToPascalCase(delegateName)}Delegate";
                    nativeRawCs.AppendLine($"public delegate {delegateReturnType} {name}({delegateSignature});");
                }
                else
                {
                    nativeRawCs.AppendLine("// If you get the below error, then that means the c.h file in the rocksdb project");
                    nativeRawCs.AppendLine("// now contains delegate arguments which share a name, but have different signatures.");
                    nativeRawCs.AppendLine("// The code generator will need logic to try to generate different names for the");
                    nativeRawCs.AppendLine("// different arguments");
                    nativeRawCs.AppendLine(string.Join("", nameGroup.Select((ng, i) => $"  Arg {i + 1}: {ng.ArgName} in {ng.FuncName} with signature {ng.Type}\n")));
                    nativeRawCs.AppendLineWithoutIndent($"#error Unable to create single delegate because arguments named {nameGroup.Key} have different delegate signatures");
                }
            }
            nativeRawCs.AppendLine("#endregion");

            foreach (var region in regions.Where(r => (r.NativeEnums.Length + r.NativeFunctions.Length) > 0))
            {
                nativeRawCs.AppendLine($"#region {region.Title}");
                foreach (var managedEnum in GetManagedEnums(region))
                {
                    nativeRawCs.AppendLine(managedEnum);
                }

                nativeRawCs.AppendLine($"public partial class Native");
                nativeRawCs.StartBlock("{");
                foreach (var managedFunction in managedFunctions[region.Title])
                {
                    nativeRawCs.AppendLine(managedFunction.WithTypeLookup((name, type, strategy) => strategy == "delegate" ? $"{SnakeCaseToPascalCase(name)}Delegate" : type));
                }
                nativeRawCs.EndBlock($"}} // class Native");
                nativeRawCs.AppendLine($"#endregion // {region.Title}");
            }

            nativeRawCs.EndBlock("} // namespace RocksDbSharp");

            var output = nativeRawCs.ToString();

            Console.WriteLine(output);
            Console.Error.WriteLine($"Done");
        }