private void TranslateFunctions(XmlSpecData spec, DotNetApiData api, Options options)
        {
            foreach (var specCommand in spec.Commands.Where(x => options.CommandFilter(x)))
            {
                var specFeature = spec.Features.Where(x => x.Commands.Contains(specCommand.Name)).FirstOrDefault();

                var functionData = new DotNetFunctionData()
                {
                    IsNative = true,
                    OriginalName = specCommand.Name,
                    NativeName = this.InflectFunctionNativeName(specCommand.Name, options),
                    DotNetName = this.InflectFunctionDotNetName(specCommand.Name, options),
                    OriginalReturnType = specCommand.ReturnType,
                    NativeReturnType = this.InflectNativeReturnType(specCommand),
                    DotNetReturnType = this.InflectDotNetReturnType(specCommand)
                };

                if (specFeature != null)
                {
                    functionData.VersionMajor = specFeature.VersionMajor;
                    functionData.VersionMinor = specFeature.VersionMinor;
                    functionData.CanPInvoke = specFeature.VersionMajor == 1 && specFeature.VersionMinor <= 1;
                }

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

                foreach (var specCommandParam in specCommand.Params)
                {
                    var functionParamData = new DotNetFunctionParamData()
                    {
                        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)
                        functionData.IsUnsafe = true;

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

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

                    functionData.Params.Add(functionParamData);
                }

                api.Functions.Add(functionData);

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

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

                // Commands which take a pointer and it could be a single element.
                if (specCommand.Params.Any(x => this.ShouldChangeFunctionParamToRefOrOut(x)))
                {
                    api.Functions.Add(this.ChangeFunctionParamsToRefOrOut(functionData, 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.Functions.Add(this.ChangeFunctionParamsToIntPtr(functionData, specCommand.Params.Where(x => this.ShouldChangeFunctionParamToIntPtr(x)).Select(x => x.Name)));
                }
            }

            api.Functions.Sort((x, y) => x.OriginalName != null && y.OriginalName != null ? x.OriginalName.CompareTo(y.OriginalName) : 0);
        }
        public DotNetFunctionParamData Clone()
        {
            var copy = new DotNetFunctionParamData()
            {
                OriginalName = this.OriginalName,
                Name = this.Name,
                OriginalType = this.OriginalType,
                NativeType = this.NativeType,
                DotNetType = this.DotNetType,
                IsEnum = this.IsEnum,
                IsPointer = this.IsPointer,
                IsOutput = this.IsOutput,
                ShouldUseGenerics = this.ShouldUseGenerics,
                ShouldUseRef = this.ShouldUseRef,
                ShouldUseFixed = this.ShouldUseFixed,
                ShouldUseAddressOfOperator = this.ShouldUseAddressOfOperator
            };

            return copy;
        }