/// <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); } }
public static object /*?*/ va_arg(va_list argp, Type t) { ArgIterator ai = argp; if (ai.GetRemainingCount() > 0) { TypedReference tr = ai.GetNextArg(); // TODO: coerce return value to type t... return((object)(__refvalue(tr, object))); } throw new FormatException(); }
static char[] buf = new char[etBUFSIZE]; /* Conversion buffer */ static void sqlite3VXPrintf( StrAccum pAccum, /* Accumulate results here */ int useExtended, /* Allow extended %-conversions */ string fmt, /* Format string */ va_list[] ap /* arguments */ ) { int c; /* Next character in the format string */ int bufpt; /* Pointer to the conversion buffer */ int precision; /* Precision of the current field */ int length; /* Length of the field */ int idx; /* A general purpose loop counter */ int width; /* Width of the current field */ etByte flag_leftjustify; /* True if "-" flag is present */ etByte flag_plussign; /* True if "+" flag is present */ etByte flag_blanksign; /* True if " " flag is present */ etByte flag_alternateform; /* True if "#" flag is present */ etByte flag_altform2; /* True if "!" flag is present */ etByte flag_zeropad; /* True if field width constant starts with zero */ etByte flag_long; /* True if "l" flag is present */ etByte flag_longlong; /* True if the "ll" flag is present */ etByte done; /* Loop termination flag */ i64 longvalue; LONGDOUBLE_TYPE realvalue; /* Value for real types */ et_info infop; /* Pointer to the appropriate info structure */ char[] buf = new char[etBUFSIZE]; /* Conversion buffer */ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ byte xtype = 0; /* Conversion paradigm */ // Not used in C# -- string zExtra; /* Extra memory used for etTCLESCAPE conversions */ #if !SQLITE_OMIT_FLOATING_POINT int exp, e2; /* exponent of real numbers */ double rounder; /* Used for rounding floating point values */ etByte flag_dp; /* True if decimal point should be shown */ etByte flag_rtz; /* True if trailing zeros should be removed */ etByte flag_exp; /* True to force display of the exponent */ int nsd; /* Number of significant digits returned */ #endif length = 0; bufpt = 0; int _fmt = 0; // Work around string pointer fmt += '\0'; for ( ; _fmt <= fmt.Length && ( c = fmt[_fmt] ) != 0; ++_fmt ) { if ( c != '%' ) { int amt; bufpt = _fmt; amt = 1; while ( _fmt < fmt.Length && ( c = ( fmt[++_fmt] ) ) != '%' && c != 0 ) amt++; sqlite3StrAccumAppend( pAccum, fmt.Substring( bufpt, amt ), amt ); if ( c == 0 ) break; } if ( _fmt < fmt.Length && ( c = ( fmt[++_fmt] ) ) == 0 ) { sqlite3StrAccumAppend( pAccum, "%", 1 ); break; } /* Find out what flags are present */ flag_leftjustify = flag_plussign = flag_blanksign = flag_alternateform = flag_altform2 = flag_zeropad = false; done = false; do { switch ( c ) { case '-': flag_leftjustify = true; break; case '+': flag_plussign = true; break; case ' ': flag_blanksign = true; break; case '#': flag_alternateform = true; break; case '!': flag_altform2 = true; break; case '0': flag_zeropad = true; break; default: done = true; break; } } while ( !done && _fmt < fmt.Length - 1 && ( c = ( fmt[++_fmt] ) ) != 0 ); /* Get the field width */ width = 0; if ( c == '*' ) { width = (int)va_arg( ap, "int" ); if ( width < 0 ) { flag_leftjustify = true; width = -width; } c = fmt[++_fmt]; } else { while ( c >= '0' && c <= '9' ) { width = width * 10 + c - '0'; c = fmt[++_fmt]; } } if ( width > etBUFSIZE - 10 ) { width = etBUFSIZE - 12; } /* Get the precision */ if ( c == '.' ) { precision = 0; c = fmt[++_fmt]; if ( c == '*' ) { precision = (int)va_arg( ap, "int" ); if ( precision < 0 ) precision = -precision; c = fmt[++_fmt]; } else { while ( c >= '0' && c <= '9' ) { precision = precision * 10 + c - '0'; c = fmt[++_fmt]; } } } else { precision = -1; } /* Get the conversion type modifier */ if ( c == 'l' ) { flag_long = true; c = fmt[++_fmt]; if ( c == 'l' ) { flag_longlong = true; c = fmt[++_fmt]; } else { flag_longlong = false; } } else { flag_long = flag_longlong = false; } /* Fetch the info entry for the field */ infop = fmtinfo[0]; xtype = etINVALID; for ( idx = 0; idx < ArraySize( fmtinfo ); idx++ ) { if ( c == fmtinfo[idx].fmttype ) { infop = fmtinfo[idx]; if ( useExtended != 0 || ( infop.flags & FLAG_INTERN ) == 0 ) { xtype = infop.type; } else { return; } break; } } //zExtra = null; /* Limit the precision to prevent overflowing buf[] during conversion */ if ( precision > etBUFSIZE - 40 && ( infop.flags & FLAG_STRING ) == 0 ) { precision = etBUFSIZE - 40; } /* ** At this point, variables are initialized as follows: ** ** flag_alternateform TRUE if a '#' is present. ** flag_altform2 TRUE if a '!' is present. ** flag_plussign TRUE if a '+' is present. ** flag_leftjustify TRUE if a '-' is present or if the ** field width was negative. ** flag_zeropad TRUE if the width began with 0. ** flag_long TRUE if the letter 'l' (ell) prefixed ** the conversion character. ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed ** the conversion character. ** flag_blanksign TRUE if a ' ' is present. ** width The specified field width. This is ** always non-negative. Zero is the default. ** precision The specified precision. The default ** is -1. ** xtype The class of the conversion. ** infop Pointer to the appropriate info struct. */ switch ( xtype ) { case etPOINTER: flag_longlong = true;// char*.Length == sizeof(i64); flag_long = false;// char*.Length == sizeof(long); /* Fall through into the next case */ goto case etRADIX; case etORDINAL: case etRADIX: if ( ( infop.flags & FLAG_SIGNED ) != 0 ) { i64 v; if ( flag_longlong ) { v = (long)va_arg( ap, "i64" ); } else if ( flag_long ) { v = (long)va_arg( ap, "long int" ); } else { v = (int)va_arg( ap, "int" ); } if ( v < 0 ) { longvalue = -v; prefix = '-'; } else { longvalue = v; if ( flag_plussign ) prefix = '+'; else if ( flag_blanksign ) prefix = ' '; else prefix = '\0'; } } else { if ( flag_longlong ) { longvalue = (i64)va_arg( ap, "longlong int" ); } else if ( flag_long ) { longvalue = (i64)va_arg( ap, "long int" ); } else { longvalue = (i64)va_arg( ap, "long" ); } prefix = '\0'; } if ( longvalue == 0 ) flag_alternateform = false; if ( flag_zeropad && precision < width - ( ( prefix != '\0' ) ? 1 : 0 ) ) { precision = width - ( ( prefix != '\0' ) ? 1 : 0 ); } bufpt = buf.Length;//[etBUFSIZE-1]; char[] _bufOrd = null; if ( xtype == etORDINAL ) { char[] zOrd = "thstndrd".ToCharArray(); int x = (int)( longvalue % 10 ); if ( x >= 4 || ( longvalue / 10 ) % 10 == 1 ) { x = 0; } _bufOrd = new char[2]; _bufOrd[0] = zOrd[x * 2]; _bufOrd[1] = zOrd[x * 2 + 1]; //bufpt -= 2; } { char[] _buf; switch ( infop._base ) { case 16: _buf = longvalue.ToString( "x" ).ToCharArray(); break; case 8: _buf = Convert.ToString( (long)longvalue, 8 ).ToCharArray(); break; default: { if ( flag_zeropad ) _buf = longvalue.ToString( new string( '0', width - ( ( prefix != '\0' ) ? 1 : 0 ) ) ).ToCharArray(); else _buf = longvalue.ToString().ToCharArray(); } break; } bufpt = buf.Length - _buf.Length - ( _bufOrd == null ? 0 : 2 ); Array.Copy( _buf, 0, buf, bufpt, _buf.Length ); if ( _bufOrd != null ) { buf[buf.Length - 1] = _bufOrd[1]; buf[buf.Length - 2] = _bufOrd[0]; } //char* cset; /* Use registers for speed */ //int _base; //cset = aDigits[infop.charset]; //_base = infop._base; //do //{ /* Convert to ascii */ // *(--bufpt) = cset[longvalue % (ulong)_base]; // longvalue = longvalue / (ulong)_base; //} while (longvalue > 0); } length = buf.Length - bufpt;//length = (int)(&buf[etBUFSIZE-1]-bufpt); for ( idx = precision - length; idx > 0; idx-- ) { buf[( --bufpt )] = '0'; /* Zero pad */ } if ( prefix != '\0' ) buf[--bufpt] = prefix; /* Add sign */ if ( flag_alternateform && infop.prefix != 0 ) { /* Add "0" or "0x" */ int pre; char x; pre = infop.prefix; for ( ; ( x = aPrefix[pre] ) != 0; pre++ ) buf[--bufpt] = x; } length = buf.Length - bufpt;//length = (int)(&buf[etBUFSIZE-1]-bufpt); break; case etFLOAT: case etEXP: case etGENERIC: realvalue = (double)va_arg( ap, "double" ); #if SQLITE_OMIT_FLOATING_POINT length = 0; #else if ( precision < 0 ) precision = 6; /* Set default precision */ if ( precision > etBUFSIZE / 2 - 10 ) precision = etBUFSIZE / 2 - 10; if ( realvalue < 0.0 ) { realvalue = -realvalue; prefix = '-'; } else { if ( flag_plussign ) prefix = '+'; else if ( flag_blanksign ) prefix = ' '; else prefix = '\0'; } if ( xtype == etGENERIC && precision > 0 ) precision--; #if FALSE /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */ for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1); #else /* It makes more sense to use 0.5 */ for ( idx = precision, rounder = 0.5; idx > 0; idx--, rounder *= 0.1 ) { } #endif if ( xtype == etFLOAT ) realvalue += rounder; /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ exp = 0; double d = 0; if ( Double.IsNaN( realvalue ) || !( Double.TryParse( Convert.ToString( realvalue ), out d ) ) )//if( sqlite3IsNaN((double)realvalue) ) { buf[0] = 'N'; buf[1] = 'a'; buf[2] = 'N';// "NaN" length = 3; break; } if ( realvalue > 0.0 ) { while ( realvalue >= 1e32 && exp <= 350 ) { realvalue *= 1e-32; exp += 32; } while ( realvalue >= 1e8 && exp <= 350 ) { realvalue *= 1e-8; exp += 8; } while ( realvalue >= 10.0 && exp <= 350 ) { realvalue *= 0.1; exp++; } while ( realvalue < 1e-8 ) { realvalue *= 1e8; exp -= 8; } while ( realvalue < 1.0 ) { realvalue *= 10.0; exp--; } if ( exp > 350 ) { if ( prefix == '-' ) { buf[0] = '-'; buf[1] = 'I'; buf[2] = 'n'; buf[3] = 'f';// "-Inf" bufpt = 4; } else if ( prefix == '+' ) { buf[0] = '+'; buf[1] = 'I'; buf[2] = 'n'; buf[3] = 'f';// "+Inf" bufpt = 4; } else { buf[0] = 'I'; buf[1] = 'n'; buf[2] = 'f';// "Inf" bufpt = 3; } length = sqlite3Strlen30( bufpt );// sqlite3Strlen30(bufpt); bufpt = 0; break; } } bufpt = 0; /* ** If the field type is etGENERIC, then convert to either etEXP ** or etFLOAT, as appropriate. */ flag_exp = xtype == etEXP; if ( xtype != etFLOAT ) { realvalue += rounder; if ( realvalue >= 10.0 ) { realvalue *= 0.1; exp++; } } if ( xtype == etGENERIC ) { flag_rtz = !flag_alternateform; if ( exp < -4 || exp > precision ) { xtype = etEXP; } else { precision = precision - exp; xtype = etFLOAT; } } else { flag_rtz = false; } if ( xtype == etEXP ) { e2 = 0; } else { e2 = exp; } nsd = 0; flag_dp = ( precision > 0 ? true : false ) | flag_alternateform | flag_altform2; /* The sign in front of the number */ if ( prefix != '\0' ) { buf[bufpt++] = prefix; } /* Digits prior to the decimal point */ if ( e2 < 0 ) { buf[bufpt++] = '0'; } else { for ( ; e2 >= 0; e2-- ) { buf[bufpt++] = (char)( et_getdigit( ref realvalue, ref nsd ) + '0' ); // *(bufpt++) = et_getdigit(ref realvalue, ref nsd); } } /* The decimal point */ if ( flag_dp ) { buf[bufpt++] = '.'; } /* "0" digits after the decimal point but before the first ** significant digit of the number */ for ( e2++; e2 < 0; precision--, e2++ ) { Debug.Assert( precision > 0 ); buf[bufpt++] = '0'; } /* Significant digits after the decimal point */ while ( ( precision-- ) > 0 ) { buf[bufpt++] = (char)( et_getdigit( ref realvalue, ref nsd ) + '0' ); // *(bufpt++) = et_getdigit(&realvalue, nsd); } /* Remove trailing zeros and the "." if no digits follow the "." */ if ( flag_rtz && flag_dp ) { while ( buf[bufpt - 1] == '0' ) buf[--bufpt] = '\0'; Debug.Assert( bufpt > 0 ); if ( buf[bufpt - 1] == '.' ) { if ( flag_altform2 ) { buf[( bufpt++ )] = '0'; } else { buf[( --bufpt )] = '0'; } } } /* Add the "eNNN" suffix */ if ( flag_exp || xtype == etEXP ) { buf[bufpt++] = aDigits[infop.charset]; if ( exp < 0 ) { buf[bufpt++] = '-'; exp = -exp; } else { buf[bufpt++] = '+'; } if ( exp >= 100 ) { buf[bufpt++] = (char)( exp / 100 + '0' ); /* 100's digit */ exp %= 100; } buf[bufpt++] = (char)( exp / 10 + '0' ); /* 10's digit */ buf[bufpt++] = (char)( exp % 10 + '0' ); /* 1's digit */ } //bufpt = 0; /* The converted number is in buf[] and zero terminated. Output it. ** Note that the number is in the usual order, not reversed as with ** integer conversions. */ length = bufpt;//length = (int)(bufpt-buf); bufpt = 0; /* Special case: Add leading zeros if the flag_zeropad flag is ** set and we are not left justified */ if ( flag_zeropad && !flag_leftjustify && length < width ) { int i; int nPad = width - length; for ( i = width; i >= nPad; i-- ) { buf[bufpt + i] = buf[bufpt + i - nPad]; } i = ( prefix != '\0' ? 1 : 0 ); while ( nPad-- != 0 ) buf[( bufpt++ ) + i] = '0'; length = width; bufpt = 0; } #endif //* !defined(SQLITE_OMIT_FLOATING_POINT) */ break; case etSIZE: ap[0] = pAccum.nChar; // *(va_arg(ap,int*)) = pAccum.nChar; length = width = 0; break; case etPERCENT: buf[0] = '%'; bufpt = 0; length = 1; break; case etCHARX: c = (char)va_arg( ap, "char" ); buf[0] = (char)c; if ( precision >= 0 ) { for ( idx = 1; idx < precision; idx++ ) buf[idx] = (char)c; length = precision; } else { length = 1; } bufpt = 0; break; case etSTRING: case etDYNSTRING: bufpt = 0;// string bufStr = (string)va_arg( ap, "string" ); if ( bufStr.Length > buf.Length ) buf = new char[bufStr.Length]; bufStr.ToCharArray().CopyTo( buf, 0 ); bufpt = bufStr.Length; if ( bufpt == 0 ) { buf[0] = '\0'; } else if ( xtype == etDYNSTRING ) { // zExtra = bufpt; } if ( precision >= 0 ) { for ( length = 0; length < precision && length < bufStr.Length && buf[length] != 0; length++ ) { } //length += precision; } else { length = sqlite3Strlen30( bufpt ); } bufpt = 0; break; case etSQLESCAPE: case etSQLESCAPE2: case etSQLESCAPE3: { int i; int j; int k; int n; bool isnull; bool needQuote; char ch; char q = ( ( xtype == etSQLESCAPE3 ) ? '"' : '\'' ); /* Quote character */ string escarg = (string)va_arg( ap, "char*" ) + '\0'; isnull = ( escarg == "" || escarg == "NULL\0" ); if ( isnull ) escarg = ( xtype == etSQLESCAPE2 ) ? "NULL\0" : "(NULL)\0"; k = precision; for ( i = n = 0; k != 0 && ( ch = escarg[i] ) != 0; i++, k-- ) { if ( ch == q ) n++; } needQuote = !isnull && ( xtype == etSQLESCAPE2 ); n += i + 1 + ( needQuote ? 2 : 0 ); if ( n > etBUFSIZE ) { buf = new char[n];//bufpt = zExtra = sqlite3Malloc(n); //if ( bufpt == 0 ) //{ // pAccum->mallocFailed = 1; // return; //} bufpt = 0; //Start of Buffer } else { //bufpt = buf; bufpt = 0; //Start of Buffer } j = 0; if ( needQuote ) buf[bufpt + j++] = q; k = i; for ( i = 0; i < k; i++ ) { buf[bufpt + j++] = ch = escarg[i]; if ( ch == q ) buf[bufpt + j++] = ch; } if ( needQuote ) buf[bufpt + j++] = q; buf[bufpt + j] = '\0'; length = j; /* The precision in %q and %Q means how many input characters to ** consume, not the length of the output... ** if( precision>=0 && precision<length ) length = precision; */ break; } case etTOKEN: { Token pToken = (Token)va_arg( ap, "Token" ); if ( pToken != null ) { sqlite3StrAccumAppend( pAccum, pToken.z.ToString(), (int)pToken.n ); } length = width = 0; break; } case etSRCLIST: { SrcList pSrc = (SrcList)va_arg( ap, "SrcList" ); int k = (int)va_arg( ap, "int" ); SrcList_item pItem = pSrc.a[k]; Debug.Assert( k >= 0 && k < pSrc.nSrc ); if ( pItem.zDatabase != null ) { sqlite3StrAccumAppend( pAccum, pItem.zDatabase, -1 ); sqlite3StrAccumAppend( pAccum, ".", 1 ); } sqlite3StrAccumAppend( pAccum, pItem.zName, -1 ); length = width = 0; break; } default: { Debug.Assert( xtype == etINVALID ); return; } }/* End switch over the format type */ /* ** The text of the conversion is pointed to by "bufpt" and is ** "length" characters long. The field width is "width". Do ** the output. */ if ( !flag_leftjustify ) { int nspace; nspace = width - length;// -2; if ( nspace > 0 ) { appendSpace( pAccum, nspace ); } } if ( length > 0 ) { sqlite3StrAccumAppend( pAccum, new string( buf, bufpt, length ), length ); } if ( flag_leftjustify ) { int nspace; nspace = width - length; if ( nspace > 0 ) { appendSpace( pAccum, nspace ); } } //if( zExtra ){ // sqlite3DbFree(db,ref zExtra); //} }/* End for loop over the format string */ } /* End of function */
public static extern int32_t va_list_test(va_list ap);
public static void va_end(va_list argp) { }
// First attempt public static void va_start(va_list argp, object dontcare) { }