예제 #1
0
        public DotNetCommandData Clone()
        {
            var copy = new DotNetCommandData()
            {
                IsFromSpec = this.IsFromSpec,
                OriginalName = this.OriginalName,
                NativeName = this.NativeName,
                DotNetName = this.DotNetName,
                NativeReturnType = this.NativeReturnType,
                VersionMajor = this.VersionMajor,
                VersionMinor = this.VersionMinor,
                IsUnsafe = this.IsUnsafe,
                ShouldUseGenerics = this.ShouldUseGenerics,
                Description = this.Description
            };

            foreach (var param in this.Params)
                copy.Params.Add(param.Clone());

            return copy;
        }
예제 #2
0
        private void ParseDocs(DotNetCommandData command, Options options)
        {
            string docFileName = this.GetDocsFileName(command, options);

            if (!File.Exists(docFileName))
                return;

            string docText = File.ReadAllText(docFileName);
            docText = ScrubDocs(docText);

            var document = XDocument.Parse(docText);

            var ns = document.Root.GetDefaultNamespace();
                
            command.Description = ScrubDescription(document.Root.Descendants(ns + "refpurpose").First().Value);

            if (!command.Params.Any())
                return;

            var paramsNode = document.Root.Descendants(ns + "refsect1").First();

            if (paramsNode != null)
            {
                foreach (var paramNode in paramsNode.Descendants(ns + "varlistentry"))
                {
                    string paramName = paramNode.Element(ns + "term").Element(ns + "parameter").Value;
                    var param = command.Params.SingleOrDefault(x => x.OriginalName == paramName);

                    if (param != null)
                    {
                        string description = ScrubDescription(paramNode.Element(ns + "listitem").Element(ns + "para").Value);
                        param.Description = description;
                    }
                }
            }
        }
예제 #3
0
        private string GetDocsFileName(DotNetCommandData command, Options options)
        {
            string docCommandName = "gl" + command.NativeName;
            string docFileName = Path.Combine(options.DocsFolder, docCommandName + ".xml");

            while (!File.Exists(docFileName) && docCommandName.Length > 0)
            {
                docCommandName = docCommandName.Substring(0, docCommandName.Length - 1);
                docFileName = Path.Combine(options.DocsFolder, docCommandName + ".xml");
            }

            return docFileName;
        }
예제 #4
0
        private DotNetCommandData ChangeFunctionParamsToEnums(DotNetCommandData function, IEnumerable<XmlCommandParamData> @params)
        {
            var copy = function.Clone();
            copy.IsFromSpec = false;

            foreach (var param in @params)
            {
                var dotNetParam = copy.Params.Single(x => x.OriginalName == param.Name);

                dotNetParam.DotNetType = param.TypeGroup;
                dotNetParam.IsEnum = true;
            }

            return copy;
        }
예제 #5
0
        private DotNetCommandData ChangeFunctionParamsToRefOrOut(DotNetCommandData function, IEnumerable<string> @params)
        {
            var copy = function.Clone();
            copy.IsFromSpec = false;

            foreach (var param in copy.Params.Where(x => @params.Contains(x.OriginalName)))
            {
                param.DotNetType = param.DotNetType.Replace("[]", "");

                if (param.IsOutput)
                {
                    param.ShouldUseOut = true;
                }
                else
                {
                    param.ShouldUseRef = true;
                }

				param.ShouldUseAddressOfOperator = true;
            }

            return copy;
        }
예제 #6
0
        private DotNetCommandData ChangeFunctionParamsToIntPtr(DotNetCommandData function, IEnumerable<string> @params)
        {
            var copy = function.Clone();
            copy.IsFromSpec = false;

            foreach (var param in copy.Params.Where(x => @params.Contains(x.OriginalName)))
            {
                param.DotNetType = "IntPtr";
                param.ShouldUseGenerics = false;
                param.ShouldUseFixed = false;
            }

            if (!copy.Params.Any(x => x.IsPointer))
                copy.IsUnsafe = false;

            if (!copy.Params.Any(x => x.ShouldUseGenerics))
                copy.ShouldUseGenerics = false;

            return copy;
        }
예제 #7
0
		private void TranslateCommands(XmlSpecData spec, DotNetApiData api, Options options)
		{			
			foreach (var specCommand in spec.Commands.Where(x => options.CommandFilter(x)))
			{
				var specFeature = spec.Features.Where(x => x.AddedCommands.Contains(specCommand.Name)).FirstOrDefault();

				var commandData = new DotNetCommandData()
				{
                    IsFromSpec = true,
					OriginalName = specCommand.Name,
					NativeName = this.InflectFunctionNativeName(specCommand.Name, options),
					DotNetName = this.InflectFunctionDotNetName(specCommand.Name, options),
					NativeReturnType = this.InflectNativeReturnType(specCommand)
				};

                if (specFeature != null)
                {
                    commandData.VersionMajor = specFeature.VersionMajor;
					commandData.VersionMinor = specFeature.VersionMinor;
                }

				if (commandData.NativeReturnType == "string")
					commandData.IsUnsafe = true;

				foreach (var specCommandParam in specCommand.Params)
				{
					var functionParamData = new DotNetCommandParamData()
					{
						OriginalName = specCommandParam.Name,
						Name = this.InflectFunctionParamName(specCommandParam.Name),
						OriginalType = specCommandParam.Type,
						NativeType = this.InflectFunctionParamNativeType(specCommandParam),
						DotNetType = this.InflectFunctionParamDotNetType(specCommandParam),
						IsPointer = this.IsTypePointer(specCommandParam.Type),
						IsOutput = this.IsTypeOutput(specCommandParam.Type),
						ShouldUseGenerics = this.ShouldUseGenericsForType(specCommandParam.Type),
                        ShouldUseFixed = this.ShouldUseFixedForParam(specCommandParam),
						ShouldUseAddressOfOperator = this.ShouldUseAddressOfOperatorForParam(specCommandParam)
					};

					if (functionParamData.IsPointer)
						commandData.IsUnsafe = true;

					if (functionParamData.ShouldUseGenerics)
						commandData.ShouldUseGenerics = true;

                    if (functionParamData.IsOutput && functionParamData.DotNetType == "IntPtr")
                    {
                        functionParamData.ShouldUseOut = true;
                    }

					commandData.Params.Add(functionParamData);
				}

				api.Commands.Add(commandData);

                if (options.DocsFolder != null)
                {
                    this.ParseDocs(commandData, options);
                }

                // Create overload which accepts the Enum variant.
                if (specCommand.Params.Any(x => this.IsTypeEnum(x, api)))
                {
                    api.Commands.Add(this.ChangeFunctionParamsToEnums(commandData, specCommand.Params.Where(x => this.IsTypeEnum(x, api))));
                }                
			}

            foreach (var commandData in api.Commands.ToArray())
            {
                var specCommand = spec.Commands.Single(x => x.Name == commandData.OriginalName);

                // Commands which take a pointer and it could be a single element.
                if (specCommand.Params.Any(x => this.ShouldChangeFunctionParamToRefOrOut(x)))
                {
                    api.Commands.Add(this.ChangeFunctionParamsToRefOrOut(commandData, specCommand.Params.Where(x => this.ShouldChangeFunctionParamToRefOrOut(x)).Select(x => x.Name)));
                }

                // Commands which take a pointer and it could be a single element.
                if (specCommand.Params.Any(x => this.ShouldChangeFunctionParamToIntPtr(x)))
                {
                    api.Commands.Add(this.ChangeFunctionParamsToIntPtr(commandData, specCommand.Params.Where(x => this.ShouldChangeFunctionParamToIntPtr(x)).Select(x => x.Name)));
                }
            }

            api.Commands.Sort((x, y) => x.OriginalName != null && y.OriginalName != null ? x.OriginalName.CompareTo(y.OriginalName) : 0);
		}
예제 #8
0
		private string GetDotNetDeclaration(string padding, DotNetCommandData command, Options options)
		{
            string output = string.Empty;

            output += padding + "/// <summary>" + Environment.NewLine;
            output += padding + $"/// ({command.OriginalName}) {command.Description}" + Environment.NewLine;
            output += padding + "/// Since version: " + command.VersionMajor + "." + command.VersionMinor + Environment.NewLine;
            output += padding + "/// </summary>" + Environment.NewLine;

            foreach (var param in command.Params)
                output += padding + $"/// <param name=\"{param.Name.TrimStart('@')}\">{param.Description}</param>" + Environment.NewLine;

            output += padding + GetSignature("public ", command, true);

			output += Environment.NewLine + padding + "{" + Environment.NewLine;

			string bodyPadding = padding + "\t";

			if (command.NativeReturnType != "void")
				output += bodyPadding + command.NativeReturnType + " result;" + Environment.NewLine + Environment.NewLine;

            if (command.Params.Any(x => x.ShouldUseOut && !x.ShouldUseFixed))
            {
                foreach (var param in command.Params.Where(x => x.ShouldUseOut && !x.ShouldUseFixed))
                {
                    output += bodyPadding + param.Name + " = default(" + param.DotNetType + ");" + Environment.NewLine;
                }

                output += Environment.NewLine;
            }

			bool wrapInTryFinally = command.ShouldUseGenerics;

			if (command.IsUnsafe)
			{
				output += bodyPadding + "unsafe" + Environment.NewLine;
				output += bodyPadding + "{" + Environment.NewLine;
				bodyPadding += "\t";

				if (command.IsAtLeastOneParamNonVoidPointer)
				{
					foreach (var param in command.Params)
					{
						if (param.ShouldUseFixed)
						{
							output += bodyPadding + "fixed (" + param.NativeType + " " + param.Name + "Ptr = ";

							if (param.ShouldUseAddressOfOperator)
								output += "&";

							output += param.Name + ")" + Environment.NewLine;
						}
					}

					output += bodyPadding + "{" + Environment.NewLine;
					bodyPadding += "\t";
				}
			}

			if (wrapInTryFinally)
			{
				foreach (var param in command.Params)
				{
					if (param.ShouldUseGenerics)
						output += bodyPadding + "GCHandle " + param.Name + "Ptr = GCHandle.Alloc(" + param.Name + ", GCHandleType.Pinned);" + Environment.NewLine;
				}

				output += bodyPadding + "try" + Environment.NewLine;
				output += bodyPadding + "{" + Environment.NewLine;
				bodyPadding += "\t";
			}
						
			output += bodyPadding;

			if (command.NativeReturnType != "void")
				output += "result = ";

			if (command.NativeReturnType == "string")
				output += "new string ((sbyte*)";

			output += "this._" + command.NativeName + "(" + this.GetMethodCallParamsList(command);

			if (command.NativeReturnType == "string")
				output += ")";

			output += ");" + Environment.NewLine;

			if (wrapInTryFinally)
			{
				bodyPadding = bodyPadding.Substring(0, bodyPadding.Length - 1);
				output += bodyPadding + "}" + Environment.NewLine;
				output += bodyPadding + "finally" + Environment.NewLine;
				output += bodyPadding + "{" + Environment.NewLine;

				if (command.ShouldUseGenerics)
				{
					foreach (var param in command.Params)
					{
						if (param.ShouldUseGenerics)
							output += bodyPadding + "\t" + param.Name + "Ptr.Free();" + Environment.NewLine;
					}
				}

				output += bodyPadding + "}" + Environment.NewLine;
			}

			if (command.IsUnsafe)
			{
				if (command.IsAtLeastOneParamNonVoidPointer)
				{
					bodyPadding = bodyPadding.Substring(0, bodyPadding.Length - 1);
					output += bodyPadding + "}" + Environment.NewLine;
				}

				bodyPadding = bodyPadding.Substring(0, bodyPadding.Length - 1);
				output += bodyPadding + "}" + Environment.NewLine;
			}

			if (command.NativeReturnType != "void")
				output += Environment.NewLine + bodyPadding + "return result;" + Environment.NewLine;

			output += padding + "}";

			return output;
		}
예제 #9
0
		private string GetMethodCallParamsList(DotNetCommandData function)
		{
			string output = string.Empty;

			if (function.Params.Count > 0)
			{
				for (int i = 0; i < function.Params.Count; i++)
				{
					var param = function.Params[i];

					if (param.ShouldUseGenerics)
					{
						output += "(IntPtr)";
					}
                    else if (param.IsEnum)
                    {
                        output += "(uint)";
                    }

					output += param.Name;

					if (param.ShouldUseFixed || param.ShouldUseGenerics)
					{
						output += "Ptr";
					}
					
					if (param.ShouldUseGenerics)
					{
						output += ".AddrOfPinnedObject()";
					}
					
					if (i != function.Params.Count - 1)
						output += ", ";
				}
			}

			return output;
		}
예제 #10
0
		private string GetDelegateDeclaration(string padding, DotNetCommandData function)
		{
			string prefix = "public delegate ";

			if (function.IsUnsafe)
				prefix = "public unsafe delegate ";
												
			string signature = this.GetSignature(padding + prefix, function, false) + ";";

			return signature;
		}
예제 #11
0
		private string GetPInvokeDeclaration(string padding, DotNetCommandData command, bool asPublic)
		{
			string header = padding + "[System.Runtime.InteropServices.DllImport(Library, EntryPoint=\"" + command.OriginalName + "\", ExactSpelling=true)]" + Environment.NewLine;

			string prefix = string.Empty;

			if (asPublic)
				prefix = "public ";
			else
				prefix = "internal ";

			prefix += "static extern ";

			if (command.IsUnsafe)
				prefix += "unsafe ";
							
			string signature = this.GetSignature(padding + prefix, command, false) + ";";

			return header + signature;
		}
예제 #12
0
		private string GetSignature(string prefix, DotNetCommandData function, bool useDotNetStyle)
		{
			string signature = prefix;

			string returnType = function.NativeReturnType;

			if (returnType == "GLenum" || returnType == "GLbitfield")
				returnType = "uint";

			string functionName = (useDotNetStyle ? function.DotNetName : function.NativeName);

			signature += returnType + " " + functionName;

			if (useDotNetStyle && function.ShouldUseGenerics)
				signature += "<T>";

			signature += "(";

			int i = 0;
			foreach (var param in function.Params)
			{
                if (!useDotNetStyle)
                {
                    if (param.IsOutput)
                        signature += "[Out] ";
                }
                else
                {
                    if (param.ShouldUseRef)
                    {
                        signature += "ref ";
                    }
                    else if (param.ShouldUseOut)
                    {
                        signature += "out ";
                    }
                }
                
				signature += (useDotNetStyle ? param.DotNetType : param.NativeType) + " " + param.Name;

				if (i < function.Params.Count - 1)
					signature += ", ";

				i++;
			}

			signature += ")";

			if (useDotNetStyle && function.ShouldUseGenerics)
				signature += " where T : struct";

			return signature;
		}