00001 using System;
00002 using System.IO;
00003 using System.Runtime.InteropServices;
00004
00005
00006 namespace SQLiteCSLib.Inner
00007 {
00011 public class OSQLiteFunc : IDisposable
00012 {
00016 GCHandle m_funcpoint ;
00017 GCHandle m_steppoint ;
00018 GCHandle m_finalpoint ;
00019
00023 protected OSQLiteDBWrap m_db;
00024
00028 protected ICallUserFunction m_callinterface;
00029
00033 unsafe protected delegate void CallFuncDelegate( IntPtr context,int argc, void** inparams );
00034 unsafe protected delegate void CallStepDelegate( IntPtr context,int argc, void** inparams );
00035 unsafe protected delegate void CallFinalDelegate( IntPtr context );
00036
00037 #if MOBILEPC
00038
00042 protected IntPtr m_disposeevent = IntPtr.Zero;
00043
00047 protected IntPtr m_clrevent;
00048
00052 protected IntPtr m_nativepoint ;
00053 #endif
00054
00058 public OSQLiteFunc( OSQLiteDBWrap db, ICallUserFunction iCallinterface )
00059 {
00060 m_db = db;
00061 m_callinterface = iCallinterface;
00062
00063 unsafe
00064 {
00065 m_funcpoint = GCHandle.Alloc( new CallFuncDelegate( CallFunc ) );
00066 m_steppoint = GCHandle.Alloc( new CallStepDelegate( CallStep ) );
00067 m_finalpoint = GCHandle.Alloc( new CallFinalDelegate( CallFinal ) );
00068 }
00069
00070 #if MOBILEPC
00071 m_disposeevent = CreateEvent( IntPtr.Zero , true, false, IntPtr.Zero );
00072 #endif
00073 }
00074
00078 ‾OSQLiteFunc()
00079 {
00080 Dispose();
00081 }
00082
00086 public void Dispose()
00087 {
00088 #if MOBILEPC
00089 EventModify( m_disposeevent, 3 );
00090 CloseHandle( m_disposeevent );
00091 CloseHandle( m_clrevent );
00092 #endif
00093
00094 if( m_db != null )
00095 {
00096 m_funcpoint.Free();
00097 m_steppoint.Free();
00098 m_finalpoint.Free();
00099 m_db = null;
00100 m_callinterface = null;
00101 }
00102 }
00103
00104
00105
00106
00107 public ResultEnum CreateFunction( string funcname, int inArg )
00108 {
00109 #if MOBILEPC
00110 m_clrevent = CreateEvent( IntPtr.Zero , false, false, IntPtr.Zero );
00111
00112
00113 System.Threading.Thread thread = new System.Threading.Thread( new System.Threading.ThreadStart(OnCallBackThread) );
00114 thread.Start();
00115
00116 if( m_callinterface is IScalarCallUserFunction )
00117 {
00118
00119 return (ResultEnum)osqlite3_createfunction( m_db.internaldb(), funcname, inArg, (int)CAPI3REF.UTF16,
00120 m_clrevent, ref m_nativepoint, true, false, false );
00121 }
00122 else
00123 if( m_callinterface is IAggregateCallUserFunction )
00124 {
00125
00126 return (ResultEnum)osqlite3_createfunction( m_db.internaldb(), funcname, inArg, (int)CAPI3REF.UTF16,
00127 m_clrevent, ref m_nativepoint, false, true, true );
00128 }
00129
00130 return ResultEnum.ERROR;
00131 #else
00132 if( m_callinterface is IScalarCallUserFunction )
00133 {
00134
00135 unsafe
00136 {
00137 return (ResultEnum)osqlite3_createfunction( m_db.internaldb(), funcname, inArg, (int)CAPI3REF.UTF16,
00138 m_funcpoint.Target as CallFuncDelegate,
00139 null,null );
00140 }
00141 }
00142 else
00143 if( m_callinterface is IAggregateCallUserFunction )
00144 {
00145
00146 unsafe
00147 {
00148 return (ResultEnum)osqlite3_createfunction( m_db.internaldb(), funcname, inArg, (int)CAPI3REF.UTF16,
00149 null,
00150 m_steppoint.Target as CallStepDelegate,
00151 m_finalpoint.Target as CallFinalDelegate );
00152 }
00153 }
00154
00155 return ResultEnum.ERROR;
00156 #endif
00157 }
00158
00159 #if MOBILEPC
00160
00164 protected void OnCallBackThread()
00165 {
00166
00167 IntPtr[] handles = new IntPtr[2]{m_disposeevent,m_clrevent};
00168
00169 while( true )
00170 {
00171 int multiWaitRes = WaitForMultipleObjects( 2, handles, false, 3600000 );
00172 if( multiWaitRes == 0 )
00173 break;
00174 if( multiWaitRes == 1 )
00175 {
00176 IntPtr context = IntPtr.Zero;
00177 int argc = 0;
00178
00179 unsafe
00180 {
00181
00182 int iKind = osqlite3func_GetCallBackParam( m_nativepoint, ref argc );
00183
00184 switch( iKind )
00185 {
00186 case 1:
00187 {
00188
00189 CallFunc( context, argc, null );
00190 }
00191 break;
00192 case 2:
00193 {
00194
00195 CallStep( context, argc, null );
00196 }
00197 break;
00198 case 3:
00199
00200 CallFinal( context );
00201 break;
00202 }
00203
00204
00205 osqlite3func_FinishCallBackParam( m_nativepoint );
00206 }
00207 }
00208 }
00209 }
00210 #endif
00211
00218 unsafe protected virtual void CallFunc( IntPtr context,int argc, void** inparams )
00219 {
00220 IScalarCallUserFunction iScalar = m_callinterface as IScalarCallUserFunction;
00221 if( iScalar != null )
00222 {
00223 object returnval = iScalar.CallFunc( CreateParams(argc,inparams) );
00224 if( returnval != null )
00225 {
00226 SetResultValue( context, returnval );
00227 }
00228 }
00229 }
00230
00237 unsafe protected virtual void CallStep( IntPtr context,int argc, void** inparams )
00238 {
00239 IAggregateCallUserFunction iAggregate = m_callinterface as IAggregateCallUserFunction;
00240 if( iAggregate != null )
00241 {
00242 iAggregate.CallStep( CreateParams(argc,inparams) );
00243 }
00244 }
00245
00250 unsafe protected virtual void CallFinal( IntPtr context )
00251 {
00252 IAggregateCallUserFunction iAggregate = m_callinterface as IAggregateCallUserFunction;
00253 if( iAggregate != null )
00254 {
00255 object returnval = iAggregate.CallFinal();
00256 if( returnval != null )
00257 {
00258 SetResultValue( context, returnval );
00259 }
00260 }
00261 }
00262
00263 #if MOBILEPC
00270 unsafe protected object[] CreateParams( int argc , void** inparams )
00271 {
00272 object[] argslist = new object[argc];
00273
00274 for( int iIdx=0; iIdx<argc; iIdx++ )
00275 {
00276 DATATYPE iType = (DATATYPE)osqlite3func_GetParamType( m_nativepoint, iIdx );
00277 switch( iType )
00278 {
00279 case DATATYPE.INTEGER:
00280 argslist[ iIdx ] = osqlite3func_GetParamInt( m_nativepoint, iIdx );
00281 break;
00282 case DATATYPE.FLOAT:
00283 {
00284 double dVal = 0.0;
00285 osqlite3func_GetParamDouble( m_nativepoint, iIdx, ref dVal );
00286 argslist[ iIdx ] = dVal;
00287 }
00288 break;
00289 case DATATYPE.BLOB:
00290 {
00291 int valsize = 0;
00292 IntPtr pBin = osqlite3func_GetParamBlob( m_nativepoint, iIdx, ref valsize );
00293
00294 byte[] managememory = new byte[valsize];
00295 Marshal.Copy( pBin, managememory, 0, valsize );
00296
00297 argslist[ iIdx ] = managememory;
00298 }
00299 break;
00300 case DATATYPE.DBNULL:
00301 argslist[ iIdx ] = null;
00302 break;
00303 case DATATYPE.TEXT:
00304 argslist[ iIdx ] = StringFromC.String( osqlite3func_GetParamText( m_nativepoint, iIdx ) );
00305 break;
00306 }
00307 }
00308
00309 return argslist;
00310 }
00311 #else
00318 unsafe protected object[] CreateParams( int argc , void** inparams )
00319 {
00320 object[] argslist = new object[argc];
00321
00322 for( int iIdx=0; iIdx<argc; iIdx++ )
00323 {
00324 void* val = inparams[ iIdx ];
00325
00326 if( val != null )
00327 {
00328 IntPtr context = new IntPtr(val);
00329
00330 DATATYPE iType = (DATATYPE)__sqlite3_value_type( context );
00331
00332 switch( iType )
00333 {
00334 case DATATYPE.INTEGER:
00335 argslist[ iIdx ] = __sqlite3_value_int64( context );
00336 break;
00337 case DATATYPE.FLOAT:
00338 argslist[ iIdx ] = __sqlite3_value_double( context ) ;
00339 break;
00340 case DATATYPE.BLOB:
00341 {
00342 IntPtr pBin = __sqlite3_value_blob( context );
00343 int valsize = __sqlite3_value_bytes( context );
00344
00345 byte[] managememory = new byte[valsize];
00346 Marshal.Copy( pBin, managememory, 0, valsize );
00347
00348 argslist[ iIdx ] = managememory;
00349 }
00350
00351 break;
00352 case DATATYPE.DBNULL:
00353 argslist[ iIdx ] = null;
00354 break;
00355 case DATATYPE.TEXT:
00356 argslist[ iIdx ] = __sqlite3_value_text16( context );
00357 break;
00358 }
00359 }
00360 }
00361
00362 return argslist;
00363 }
00364 #endif
00365
00366 #if MOBILEPC
00367
00368
00369
00370 void SetResultValue( IntPtr context, object returnval )
00371 {
00372 if( returnval is Int32 )
00373 {
00374 osqlite3func_SetResultInt( m_nativepoint, (Int32)returnval );
00375 return;
00376 }
00377 else
00378 if( returnval is Int64 )
00379 {
00380 osqlite3func_SetResultInt( m_nativepoint, (Int32)returnval );
00381 return;
00382 }
00383 else
00384 if( returnval is double )
00385 {
00386 double val = (double)returnval;
00387 osqlite3func_SetResultDouble( m_nativepoint, ref val );
00388 return;
00389 }
00390 else
00391 if( returnval is string )
00392 {
00393 string sRetStr = (string)returnval;
00394
00395 System.Text.Encoder enc = System.Text.Encoding.Unicode.GetEncoder();
00396 int iLen = enc.GetByteCount( sRetStr.ToCharArray(), 0, sRetStr.Length, true );
00397 osqlite3func_SetResultText( m_nativepoint, sRetStr, iLen );
00398 return;
00399 }
00400 else
00401 if( returnval is byte[] )
00402 {
00403 byte[] bBin = returnval as byte[];
00404 int iValLen = (int)bBin.Length;
00405
00406
00407 IntPtr pBin = IntPtr.Zero;
00408 try
00409 {
00410
00411 pBin = AllocHGlobal( iValLen );
00412
00413
00414 Marshal.Copy( bBin, 0, pBin, iValLen );
00415
00416 osqlite3func_SetResultBlob( m_nativepoint, pBin, iValLen );
00417 }
00418 finally
00419 {
00420 if( pBin != IntPtr.Zero )
00421 {
00422 FreeHGlobal(pBin);
00423 }
00424 }
00425
00426 return;
00427 }
00428 }
00429 #else
00430
00431
00432
00433 void SetResultValue( IntPtr context, object returnval )
00434 {
00435 if( returnval is Int32 )
00436 {
00437 __sqlite3_result_int( context, (Int32)returnval );
00438 return;
00439 }
00440 else
00441 if( returnval is Int64 )
00442 {
00443 __sqlite3_result_int64( context, (Int64)returnval );
00444 return;
00445 }
00446 else
00447 if( returnval is double )
00448 {
00449 __sqlite3_result_double( context, (double)returnval );
00450 return;
00451 }
00452 else
00453 if( returnval is string )
00454 {
00455 string sRetStr = (string)returnval;
00456
00457 System.Text.Encoder enc = System.Text.Encoding.Unicode.GetEncoder();
00458 int iLen = enc.GetByteCount( sRetStr.ToCharArray(), 0, sRetStr.Length, true );
00459 __sqlite3_result_text16( context, sRetStr, iLen );
00460 return;
00461 }
00462 else
00463 if( returnval is byte[] )
00464 {
00465 byte[] bBin = returnval as byte[];
00466 int iValLen = (int)bBin.Length;
00467
00468
00469 IntPtr pBin = IntPtr.Zero;
00470 try
00471 {
00472
00473 pBin = Marshal.AllocHGlobal( iValLen );
00474
00475
00476 Marshal.Copy( bBin, 0, pBin, iValLen );
00477
00478 __sqlite3_result_blob( context, pBin, iValLen );
00479 }
00480 finally
00481 {
00482 if( pBin != IntPtr.Zero )
00483 {
00484 Marshal.FreeHGlobal(pBin);
00485 }
00486 }
00487
00488 return;
00489 }
00490 }
00491 #endif
00492
00493 #region アンマネージ定義
00494
00495 #if MOBILEPC
00496 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00497 protected extern static int osqlite3_createfunction( IntPtr instance, string funcname,
00498 int iarg, int eTextRep, IntPtr clrevent, ref IntPtr nativepoint, bool xFunc, bool xStep, bool xFinal );
00499
00500 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00501 protected extern static int osqlite3func_GetCallBackParam( IntPtr instance, ref int pargc );
00502
00503 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00504 protected extern static int osqlite3func_GetParamType( IntPtr instance, int iNo );
00505
00506 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00507 protected extern static int osqlite3func_GetParamInt( IntPtr instance, int iNo );
00508
00509 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00510 protected extern static void osqlite3func_GetParamDouble( IntPtr instance, int iNo, ref double pResult );
00511
00512 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00513 protected extern static IntPtr osqlite3func_GetParamText( IntPtr instance, int iNo );
00514
00515 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00516 protected extern static IntPtr osqlite3func_GetParamBlob( IntPtr instance, int iNo, ref int iLen );
00517
00518 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00519 protected extern static void osqlite3func_FinishCallBackParam( IntPtr instance );
00520
00521 [DllImport("coredll.dll", SetLastError=true)]
00522 static extern IntPtr CreateEvent(IntPtr lpsa, bool fManualReset, bool fInitialState, IntPtr lpszEventName );
00523
00524 [DllImport("coredll.dll", SetLastError=true)]
00525 static extern bool CloseHandle(IntPtr handle );
00526
00527 [DllImport("coredll.dll", SetLastError=true)]
00528 static extern bool EventModify(IntPtr handle, int dEvent );
00529
00530 [DllImport("coredll.dll", SetLastError=true)]
00531 static extern int WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);
00532
00533 [DllImport("coredll.dll", SetLastError=true)]
00534 static extern int WaitForMultipleObjects( int nCount, IntPtr[] hHandles, bool fWaitAll, int dwMilliseconds);
00535
00536
00537
00538
00539
00540
00541
00542
00543 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00544 protected extern static IntPtr AllocHGlobal( int isize );
00545
00546 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00547 protected extern static void FreeHGlobal( IntPtr pMem );
00548
00549 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00550 protected extern static void osqlite3func_SetResultInt(IntPtr instance, int val );
00551
00552 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00553 protected extern static void osqlite3func_SetResultDouble(IntPtr instance, ref double val );
00554
00555 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00556 protected extern static void osqlite3func_SetResultText(IntPtr instance, string val, int iLen );
00557
00558 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00559 protected extern static void osqlite3func_SetResultBlob(IntPtr instance, IntPtr val, int iLen );
00560
00561 #else
00562 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00563 protected extern static int osqlite3_createfunction( IntPtr instance, string funcname,
00564 int iarg, int eTextRep,
00565 CallFuncDelegate xFunc,
00566 CallStepDelegate xStep,
00567 CallFinalDelegate xFinal );
00568 #endif
00569 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00570 protected extern static int __sqlite3_value_type( IntPtr inparam );
00571
00572 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00573 protected extern static long __sqlite3_value_int64( IntPtr inparam );
00574
00575 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00576 protected extern static double __sqlite3_value_double( IntPtr inparam );
00577
00578 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00579 protected extern static int __sqlite3_value_bytes( IntPtr inparam );
00580
00581 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00582 protected extern static IntPtr __sqlite3_value_blob( IntPtr inparam );
00583
00584 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00585 protected extern static string __sqlite3_value_text16( IntPtr inparam );
00586
00587 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00588 protected extern static void __sqlite3_result_int( IntPtr inparam, int val );
00589
00590 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00591 protected extern static void __sqlite3_result_int64( IntPtr inparam, long val );
00592
00593 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00594 protected extern static void __sqlite3_result_double( IntPtr inparam, double val );
00595
00596 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00597 protected extern static void __sqlite3_result_text16( IntPtr inparam, string val, int ilen );
00598
00599 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00600 protected extern static void __sqlite3_result_blob( IntPtr inparam, IntPtr val, int ilen );
00601
00602 #endregion
00603 }
00604 }