00001 using System;
00002 using System.IO;
00003 using System.Runtime.InteropServices;
00004
00005 namespace SQLiteCSLib.Inner
00006 {
00010 public class OSQLiteCollation : IDisposable
00011 {
00015 protected GCHandle m_callbackpoint ;
00016
00020 protected OSQLiteDBWrap m_db;
00021
00025 protected ICollationFunction m_callinterface;
00026
00030 unsafe protected delegate int CallCollationDelegate(void* NotUsed,int nKey1, IntPtr pKey1,int nKey2, IntPtr pKey2);
00031
00032 #if MOBILEPC
00033
00037 protected IntPtr m_disposeevent = IntPtr.Zero;
00038
00042 protected IntPtr m_clrevent;
00043
00047 protected IntPtr m_nativepoint ;
00048 #endif
00049
00053 public OSQLiteCollation( OSQLiteDBWrap db, ICollationFunction iCallinterface )
00054 {
00055 m_db = db;
00056 m_callinterface = iCallinterface;
00057
00058 unsafe
00059 {
00060 m_callbackpoint = GCHandle.Alloc( new CallCollationDelegate( CallCollation ) );
00061 }
00062
00063 #if MOBILEPC
00064 m_disposeevent = CreateEvent( IntPtr.Zero , true, false, IntPtr.Zero );
00065 #endif
00066
00067 }
00068
00072 ‾OSQLiteCollation()
00073 {
00074 Dispose();
00075 }
00076
00080 public void Dispose()
00081 {
00082 #if MOBILEPC
00083 EventModify( m_disposeevent, 3 );
00084 CloseHandle( m_disposeevent );
00085 CloseHandle( m_clrevent );
00086 #endif
00087
00088 if( m_db != null )
00089 {
00090 m_callbackpoint.Free();
00091 m_db = null;
00092 m_callinterface = null;
00093 }
00094 }
00095
00101 public ResultEnum CreateFunction( string funcname )
00102 {
00103 #if MOBILEPC
00104 m_clrevent = CreateEvent( IntPtr.Zero , false, false, IntPtr.Zero );
00105
00106
00107 System.Threading.Thread thread = new System.Threading.Thread( new System.Threading.ThreadStart(OnCallBackThread) );
00108 thread.Start();
00109
00110 return (ResultEnum)osqlite3_createcollation( m_db.internaldb(), funcname, (int)CAPI3REF.UTF16,
00111 m_clrevent, ref m_nativepoint );
00112 #else
00113 unsafe
00114 {
00115 return (ResultEnum)osqlite3_createcollation( m_db.internaldb(), funcname, (int)CAPI3REF.UTF16,
00116 m_callbackpoint.Target as CallCollationDelegate );
00117 }
00118 #endif
00119 }
00120
00121 #if MOBILEPC
00122
00126 protected void OnCallBackThread()
00127 {
00128
00129 IntPtr[] handles = new IntPtr[2]{m_disposeevent,m_clrevent};
00130
00131 while( true )
00132 {
00133 int multiWaitRes = WaitForMultipleObjects( 2, handles, false, 3600000 );
00134 if( multiWaitRes == 0 )
00135 break;
00136 if( multiWaitRes == 1 )
00137 {
00138 int nKey1 = 0;
00139 int nKey2 = 0;
00140 IntPtr pKey1 = IntPtr.Zero;
00141 IntPtr pKey2 = IntPtr.Zero;
00142
00143 unsafe
00144 {
00145
00146 void* NotUsed = null;
00147
00148
00149 osqlite3collation_GetCallBackParam( m_nativepoint, ref NotUsed, ref nKey1, ref pKey1, ref nKey2, ref pKey2 );
00150
00151
00152 int iRes = CallCollation( NotUsed, nKey1, pKey1, nKey2, pKey2 );
00153
00154
00155 osqlite3collation_FinishCallBackParam( m_nativepoint, iRes );
00156 }
00157 }
00158 }
00159 }
00160 #endif
00161
00171 unsafe protected virtual int CallCollation( void* NotUsed,int nKey1, IntPtr pKey1,int nKey2, IntPtr pKey2 )
00172 {
00173
00174 byte[] bKey1 = new byte[nKey1+2];
00175 byte[] bKey2 = new byte[nKey2+2];
00176
00177 Marshal.Copy( pKey1, bKey1, 0, nKey1 );
00178 Marshal.Copy( pKey2, bKey2, 0, nKey2 );
00179
00180 System.Text.Decoder dec = System.Text.Encoding.Unicode.GetDecoder();
00181 int iLen1 = dec.GetCharCount( bKey1,0,nKey1 );
00182 char[] cKey1 = new char[iLen1];
00183 dec.GetChars(bKey1,0,nKey1, cKey1, 0 );
00184 string sKey1 = new string(cKey1);
00185
00186 int iLen2 = dec.GetCharCount( bKey2,0,nKey2 );
00187 char[] cKey2 = new char[iLen2];
00188 dec.GetChars(bKey2,0,nKey2, cKey2, 0 );
00189 string sKey2 = new string(cKey2);
00190
00191 return m_callinterface.Compare( sKey1, sKey2 );
00192 }
00193
00194 #region アンマネージ定義
00195
00196 #if MOBILEPC
00197 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00198 protected extern static int osqlite3_createcollation( IntPtr instance, string funcname,
00199 int eTextRep, IntPtr clrevent, ref IntPtr nativepoint );
00200
00201 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00202 unsafe protected extern static void osqlite3collation_GetCallBackParam( IntPtr instance, ref void* pNotUsed, ref int pnKey1, ref IntPtr ppKey1,ref int pnKey2, ref IntPtr ppKey2 );
00203
00204 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00205 protected extern static void osqlite3collation_FinishCallBackParam( IntPtr instance, int result );
00206
00207 [DllImport("coredll.dll", SetLastError=true)]
00208 static extern IntPtr CreateEvent(IntPtr lpsa, bool fManualReset, bool fInitialState, IntPtr lpszEventName );
00209
00210 [DllImport("coredll.dll", SetLastError=true)]
00211 static extern bool CloseHandle(IntPtr handle );
00212
00213 [DllImport("coredll.dll", SetLastError=true)]
00214 static extern bool EventModify(IntPtr handle, int dEvent );
00215
00216 [DllImport("coredll.dll", SetLastError=true)]
00217 static extern int WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);
00218
00219 [DllImport("coredll.dll", SetLastError=true)]
00220 static extern int WaitForMultipleObjects( int nCount, IntPtr[] hHandles, bool fWaitAll, int dwMilliseconds);
00221 #else
00222 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00223 protected extern static int osqlite3_createcollation( IntPtr instance, string funcname,
00224 int eTextRep, CallCollationDelegate xCompare );
00225 #endif
00226 #endregion
00227
00228 }
00229 }