Example #1
0
        /// <summary>
        /// Returns array of objects read from va_list with help of printf format string.
        /// </summary>
        /// <param name="msg"> printf format string. </param>
        /// <param name="args"> va_list of function parameters. </param>
        public static unsafe object[] GetObjectsByFormat(string format, va_list va_list)
        {
            string[] formatSpecifiers = Printf.GetFormatSpecifiers(format);
            if (formatSpecifiers == null || va_list == null || va_list.GetPointer() == IntPtr.Zero)
                return null;

            IntPtr args = va_list.GetPointer();
            List<object> objects = new List<object>(formatSpecifiers.Length);

            int offset = 0;
            foreach (string spec in formatSpecifiers)
            {
                var info = Printf.GetFormatSpecifierInfo(spec);
                if (info.type == '\0')
                    continue;

                // dynamic width and precision arguments
                // these are stored in stack before the actual value
                if (info.flags.HasFlag(Printf.FormatFlags.DynamicWidth))
                {
                    int widthArg = Marshal.ReadInt32(args, offset);
                    objects.Add(widthArg);
                    offset += Marshal.SizeOf(typeof(IntPtr));
                }
                if (info.flags.HasFlag(Printf.FormatFlags.DynamicPrecision))
                {
                    int precArg = Marshal.ReadInt32(args, offset);
                    objects.Add(precArg);
                    offset += Marshal.SizeOf(typeof(IntPtr));
                }

                int iSize = info.flags.HasFlag(Printf.FormatFlags.IsLongLong)
                    ? Marshal.SizeOf(typeof(Int64)) : Marshal.SizeOf(typeof(IntPtr));

                // marshal objects from pointer
                switch (info.type)
                {
                    // 8/16-bit integers
                    // char / wchar_t (promoted to int)
                    case 'c':
                        char c = (char)Marshal.ReadByte(args, offset);
                        objects.Add(c);
                        offset += Marshal.SizeOf(typeof(Int32));
                        break;

                    // signed integers
                    case 'd':
                    case 'i':
                        {
                            if (info.flags.HasFlag(Printf.FormatFlags.IsShort)) // h
                            {
                                short sh = (short)Marshal.ReadInt32(args, offset);
                                objects.Add(sh);
                                offset += Marshal.SizeOf(typeof(Int32));
                            }
                            else if (info.flags.HasFlag(Printf.FormatFlags.IsLongLong)) // ll
                            {
                                long l = Marshal.ReadInt64(args, offset);
                                objects.Add(l);
                                offset += iSize;
                            }
                            else // int and long types
                            {
                                int i = Marshal.ReadInt32(args, offset);
                                objects.Add(i);
                                offset += iSize;
                            }
                        }
                        break;

                    // unsigned integers
                    case 'u':
                    case 'o':
                    case 'x':
                    case 'X':
                        {
                            if (info.flags.HasFlag(Printf.FormatFlags.IsShort)) // h
                            {
                                ushort su = (ushort)Marshal.ReadInt32(args, offset);
                                objects.Add(su);
                                offset += Marshal.SizeOf(typeof(Int32));
                            }
                            else if (info.flags.HasFlag(Printf.FormatFlags.IsLongLong)) // ll
                            {
                                ulong lu = (ulong)(long)Marshal.ReadInt64(args, offset);
                                objects.Add(lu);
                                offset += iSize;
                            }
                            else // uint and ulong types
                            {
                                uint u = (uint)Marshal.ReadInt32(args, offset);
                                objects.Add(u);
                                offset += iSize;
                            }
                        }
                        break;

                    // floating-point types
                    case 'f':
                    case 'F':
                    case 'e':
                    case 'E':
                    case 'g':
                    case 'G':
                        {
                            if (info.flags.HasFlag(Printf.FormatFlags.IsLongDouble))  // L
                            {
                                // not really supported but read it as long
                                long lfi = Marshal.ReadInt64(args, offset);
                                double d = *(double*)(void*)&lfi;
                                objects.Add(d);
                                offset += Marshal.SizeOf(typeof(double));
                            }
                            else // double
                            {
                                long lfi = Marshal.ReadInt64(args, offset);
                                double d = *(double*)(void*)&lfi;
                                objects.Add(d);
                                offset += Marshal.SizeOf(typeof(double));
                            }
                        }
                        break;

                    // string
                    case 's':
                        {
                            string s = null;

                            if (info.flags.HasFlag(Printf.FormatFlags.IsLong))
                                s = Marshal.PtrToStringUni(Marshal.ReadIntPtr(args, offset));
                            else
                                s = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(args, offset));

                            objects.Add(s);
                            offset += Marshal.SizeOf(typeof(IntPtr));
                        }
                        break;

                    // pointer
                    case 'p':
                        IntPtr ptr = Marshal.ReadIntPtr(args, offset);
                        objects.Add(ptr);
                        offset += Marshal.SizeOf(typeof(IntPtr));
                        break;

                    // non-marshallable types, ignored
                    case ' ':
                    case '%':
                    case 'n':
                        break;

                    default:
                        throw new ApplicationException("printf specifier '%" + info.type + "' not supported");
                }
            }

            return objects.ToArray();
        }
Example #2
0
        /// <summary> Wraps, parses and formats the variable arguments of the real delegate. </summary>
        private static void LogHandlerWrapper(libobs.log_error_level lvl, string format, IntPtr args, IntPtr p)
        {
            using (va_list arglist = new va_list(args))
            {
                object[] objs = arglist.GetObjectsByFormat(format);
                string formattedMsg = Printf.sprintf(format, objs);

                realHandler((LogErrorLevel)lvl, formattedMsg, p);
            }
        }
Example #3
0
        /// <summary>
        /// Returns array of objects read from va_list with help of printf format string.
        /// </summary>
        /// <param name="msg"> printf format string. </param>
        /// <param name="args"> va_list of function parameters. </param>
        public static unsafe object[] GetObjectsByFormat(string format, va_list va_list)
        {
            string[] formatSpecifiers = Printf.GetFormatSpecifiers(format);
            if (formatSpecifiers == null || va_list == null || va_list.GetPointer() == IntPtr.Zero)
            {
                return(null);
            }

            IntPtr        args    = va_list.GetPointer();
            List <object> objects = new List <object>(formatSpecifiers.Length);

            int offset = 0;

            foreach (string spec in formatSpecifiers)
            {
                var info = Printf.GetFormatSpecifierInfo(spec);
                if (info.type == '\0')
                {
                    continue;
                }

                // dynamic width and precision arguments
                // these are stored in stack before the actual value
                if (info.flags.HasFlag(Printf.FormatFlags.DynamicWidth))
                {
                    int widthArg = Marshal.ReadInt32(args, offset);
                    objects.Add(widthArg);
                    offset += Marshal.SizeOf(typeof(IntPtr));
                }
                if (info.flags.HasFlag(Printf.FormatFlags.DynamicPrecision))
                {
                    int precArg = Marshal.ReadInt32(args, offset);
                    objects.Add(precArg);
                    offset += Marshal.SizeOf(typeof(IntPtr));
                }

                int iSize = info.flags.HasFlag(Printf.FormatFlags.IsLongLong)
                                        ? Marshal.SizeOf(typeof(Int64)) : Marshal.SizeOf(typeof(IntPtr));

                // marshal objects from pointer
                switch (info.type)
                {
                // 8/16-bit integers
                // char / wchar_t (promoted to int)
                case 'c':
                    char c = (char)Marshal.ReadByte(args, offset);
                    objects.Add(c);
                    offset += Marshal.SizeOf(typeof(Int32));
                    break;

                // signed integers
                case 'd':
                case 'i':
                {
                    if (info.flags.HasFlag(Printf.FormatFlags.IsShort))                                     // h
                    {
                        short sh = (short)Marshal.ReadInt32(args, offset);
                        objects.Add(sh);
                        offset += Marshal.SizeOf(typeof(Int32));
                    }
                    else if (info.flags.HasFlag(Printf.FormatFlags.IsLongLong))                                     // ll
                    {
                        long l = Marshal.ReadInt64(args, offset);
                        objects.Add(l);
                        offset += iSize;
                    }
                    else                                     // int and long types
                    {
                        int i = Marshal.ReadInt32(args, offset);
                        objects.Add(i);
                        offset += iSize;
                    }
                }
                break;

                // unsigned integers
                case 'u':
                case 'o':
                case 'x':
                case 'X':
                {
                    if (info.flags.HasFlag(Printf.FormatFlags.IsShort))                                     // h
                    {
                        ushort su = (ushort)Marshal.ReadInt32(args, offset);
                        objects.Add(su);
                        offset += Marshal.SizeOf(typeof(Int32));
                    }
                    else if (info.flags.HasFlag(Printf.FormatFlags.IsLongLong))                                     // ll
                    {
                        ulong lu = (ulong)(long)Marshal.ReadInt64(args, offset);
                        objects.Add(lu);
                        offset += iSize;
                    }
                    else                                     // uint and ulong types
                    {
                        uint u = (uint)Marshal.ReadInt32(args, offset);
                        objects.Add(u);
                        offset += iSize;
                    }
                }
                break;

                // floating-point types
                case 'f':
                case 'F':
                case 'e':
                case 'E':
                case 'g':
                case 'G':
                {
                    if (info.flags.HasFlag(Printf.FormatFlags.IsLongDouble))                                      // L
                    {
                        // not really supported but read it as long
                        long   lfi = Marshal.ReadInt64(args, offset);
                        double d   = *(double *)(void *)&lfi;
                        objects.Add(d);
                        offset += Marshal.SizeOf(typeof(double));
                    }
                    else                                     // double
                    {
                        long   lfi = Marshal.ReadInt64(args, offset);
                        double d   = *(double *)(void *)&lfi;
                        objects.Add(d);
                        offset += Marshal.SizeOf(typeof(double));
                    }
                }
                break;

                // string
                case 's':
                {
                    string s = null;

                    if (info.flags.HasFlag(Printf.FormatFlags.IsLong))
                    {
                        s = Marshal.PtrToStringUni(Marshal.ReadIntPtr(args, offset));
                    }
                    else
                    {
                        s = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(args, offset));
                    }

                    objects.Add(s);
                    offset += Marshal.SizeOf(typeof(IntPtr));
                }
                break;

                // pointer
                case 'p':
                    IntPtr ptr = Marshal.ReadIntPtr(args, offset);
                    objects.Add(ptr);
                    offset += Marshal.SizeOf(typeof(IntPtr));
                    break;

                // non-marshallable types, ignored
                case ' ':
                case '%':
                case 'n':
                    break;

                default:
                    throw new ApplicationException("printf specifier '%" + info.type + "' not supported");
                }
            }

            return(objects.ToArray());
        }