Changeset 29

Show
Ignore:
Timestamp:
06/25/04 02:04:10 (4 years ago)
Author:
DenisG
Message:

[AprSharp] Makes AprArray? type-safe, IEnumerable and ICollection

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/AprSharp/dev/src/AprArgumentException.cs

    r1 r29  
    1212using System; 
    1313using System.Runtime.Serialization; 
    14 using Softec; 
    1514 
    1615namespace Softec.AprSharp 
  • trunk/AprSharp/dev/src/AprArgumentNullException.cs

    r24 r29  
    1212using System; 
    1313using System.Runtime.Serialization; 
    14 using Softec; 
    1514 
    1615namespace Softec.AprSharp 
  • trunk/AprSharp/dev/src/AprArgumentOutOfRangeException.cs

    r1 r29  
    1212using System; 
    1313using System.Runtime.Serialization; 
    14 using Softec; 
    1514 
    1615namespace Softec.AprSharp 
  • trunk/AprSharp/dev/src/AprArray.cs

    r22 r29  
    1111using System; 
    1212using System.Diagnostics; 
     13using System.Reflection; 
    1314using System.Runtime.InteropServices; 
    1415using System.Collections; 
     
    1617namespace Softec.AprSharp 
    1718{ 
    18     public unsafe struct AprArray 
     19    public unsafe struct AprArray : IEnumerable 
    1920    { 
    2021        private apr_array_header_t *mArray; 
     22        private Type mEltsType; 
    2123 
    2224        [StructLayout( LayoutKind.Sequential )] 
     
    2729            public int nelts; 
    2830            public int nalloc; 
    29             public byte *elts; 
     31            public IntPtr elts; 
    3032        } 
    3133 
     
    3436        { 
    3537            mArray = ptr; 
     38            mEltsType = null; 
    3639        } 
    3740 
     
    3942        { 
    4043            mArray = (apr_array_header_t *)ptr.ToPointer(); 
     44            mEltsType = null; 
     45        } 
     46 
     47        public AprArray(IntPtr ptr, Type eltsType) 
     48        { 
     49            mArray = (apr_array_header_t *)ptr.ToPointer(); 
     50            mEltsType = null; 
     51            if( eltsType != null ) 
     52                ElementType = eltsType; 
    4153        } 
    4254         
     
    5870        { 
    5971            mArray = null; 
     72            mEltsType = null; 
    6073        } 
    6174 
     
    7487            return("[apr_array_header_t:"+(new IntPtr(mArray)).ToInt32().ToString("X")+"]"); 
    7588        } 
     89         
     90        public Type ElementType 
     91        { 
     92            get 
     93            { 
     94                return(mEltsType); 
     95            } 
     96            set 
     97            { 
     98                if( (value.IsPrimitive && Marshal.SizeOf(value) != mArray->elt_size) 
     99                  ||(!value.IsPrimitive && Marshal.SizeOf(typeof(IntPtr)) != mArray->elt_size) ) 
     100                        throw new AprArgumentException("Type does not match element size."); 
     101                         
     102                if( value.IsPrimitive ) 
     103                    mEltsType = value; 
     104                else { 
     105                    if( value.GetConstructor(new Type[] {typeof(IntPtr)}) == null ) 
     106                        throw new AprInvalidOperationException("Type is not primitive and cannot be constructed from an IntPtr."); 
     107                    mEltsType = value; 
     108                } 
     109            } 
     110        } 
    76111        #endregion 
    77112         
    78113        #region Methods wrappers 
     114        public static AprArray Make(AprPool pool, int nElts, Type eltsType ) 
     115        { 
     116            if(eltsType.IsPrimitive) 
     117                return(new AprArray(Make(pool, nElts, Marshal.SizeOf(eltsType)),eltsType)); 
     118            else 
     119                return(new AprArray(Make(pool, nElts, Marshal.SizeOf(typeof(IntPtr))),eltsType)); 
     120        } 
     121 
    79122        public static AprArray Make(AprPool pool, int nElts, int eltSize ) 
    80123        { 
     
    101144            Debug.WriteLine(String.Format("Done({0:X})",((Int32)ptr))); 
    102145 
    103             return(ptr); 
     146            return(new AprArray(ptr,mEltsType)); 
    104147        } 
    105148 
     
    115158            Debug.WriteLine(String.Format("Done({0:X})",((Int32)ptr))); 
    116159 
    117             return(ptr); 
     160            return(new AprArray(ptr,mEltsType)); 
    118161        } 
    119162 
     
    121164        { 
    122165            IntPtr ptr; 
    123              
    124             CheckPtr(); 
     166            Type arrType; 
     167             
     168            CheckPtr(); 
     169            if (mEltsType != null && array.mEltsType != null && mEltsType != array.mEltsType) 
     170                throw new AprInvalidOperationException("Array type mismatch."); 
     171             
     172            if(mEltsType == null && array.mEltsType != null) 
     173                arrType = array.mEltsType; 
     174            arrType = mEltsType; 
     175                 
    125176            Debug.Write(String.Format("apr_array_append({0},{1},{2})...",pool,array,this)); 
    126177            ptr = Apr.apr_array_append(pool,(IntPtr)mArray,array); 
     
    129180            Debug.WriteLine(String.Format("Done({0:X})",((Int32)ptr))); 
    130181 
    131             return(ptr); 
     182            return(new AprArray(ptr,arrType)); 
    132183        } 
    133184 
    134185        public void Cat(AprArray array) 
    135186        { 
    136             CheckPtr(); 
     187            Type arrType; 
     188             
     189            CheckPtr(); 
     190            if (mEltsType != null && array.mEltsType != null && mEltsType != array.mEltsType) 
     191                throw new AprInvalidOperationException("Array type mismatch."); 
     192             
     193            if(mEltsType == null && array.mEltsType != null) 
     194                mEltsType = array.mEltsType; 
     195                 
    137196            Debug.WriteLine(String.Format("apr_array_cat({0},{1})",this,array)); 
    138197            Apr.apr_array_cat((IntPtr)mArray,array); 
     
    149208             
    150209            CheckPtr(); 
     210            if(mEltsType != null && mEltsType != typeof(AprString)) 
     211                throw new AprInvalidOperationException("Not an AprString array."); 
     212                 
    151213            Debug.Write(String.Format("apr_array_pstrcat({0},{1},{2})...",pool,this,sep)); 
    152214            ptr = Apr.apr_array_pstrcat(pool,new IntPtr(mArray),sep); 
     
    158220        }         
    159221 
     222        public void Push(byte o) 
     223        { 
     224            CheckPtr(); 
     225            Marshal.WriteByte(Push(),o); 
     226        } 
     227 
     228        public void Push(short o) 
     229        { 
     230            CheckPtr(); 
     231            Marshal.WriteInt16(Push(),o); 
     232        } 
     233         
     234        public void Push(int o) 
     235        { 
     236            CheckPtr(); 
     237            Marshal.WriteInt32(Push(),o); 
     238        } 
     239 
     240        public void Push(long o) 
     241        { 
     242            CheckPtr(); 
     243            Marshal.WriteInt64(Push(),o); 
     244        } 
     245         
     246        public void Push(IntPtr ptr) 
     247        { 
     248            CheckPtr(); 
     249            Marshal.WriteIntPtr(Push(),ptr); 
     250        } 
     251         
    160252        public IntPtr Push() 
    161253        { 
     
    170262 
    171263            return(ptr); 
    172         }         
     264        } 
     265         
     266        public object PopObject() 
     267        { 
     268            if(mEltsType == null)         
     269                throw new AprInvalidOperationException("Array not typed."); 
     270                 
     271            if(mEltsType.IsPrimitive) 
     272            { 
     273                object val; 
     274                switch(ElementSize) 
     275                { 
     276                    case 1: 
     277                        val = Marshal.ReadByte(Pop()); 
     278                        break; 
     279                    case 2: 
     280                        val = Marshal.ReadInt16(Pop()); 
     281                        break; 
     282                    case 4: 
     283                        val = Marshal.ReadInt32(Pop()); 
     284                        break; 
     285                    case 8: 
     286                        val = Marshal.ReadInt64(Pop()); 
     287                        break; 
     288                    default: 
     289                        throw new AprInvalidOperationException("Invalid element size."); 
     290                } 
     291                return(Convert.ChangeType(val,mEltsType)); 
     292            } 
     293             
     294            ConstructorInfo ctor = mEltsType.GetConstructor(new Type[] {typeof(IntPtr)}); 
     295            if( ctor == null ) 
     296                throw new AprInvalidOperationException("Type is not primitive and cannot be constructed from an IntPtr."); 
     297             
     298            IntPtr ptr = Marshal.ReadIntPtr(Pop()); 
     299            return(ctor.Invoke(new Object[] { ptr })); 
     300        }         
    173301         
    174302        public IntPtr Pop() 
     
    203331        }         
    204332 
     333        public int AllocatedCount 
     334        { 
     335            get { 
     336                return(mArray->nalloc); 
     337            } 
     338        } 
     339         
     340        public int ElementSize 
     341        { 
     342            get { 
     343                return(mArray->elt_size); 
     344            } 
     345        } 
     346         
     347        public IntPtr Data 
     348        { 
     349            get { 
     350                return(mArray->elts); 
     351            } 
     352        } 
     353        #endregion 
     354         
     355        #region ICollection 
     356        public void CopyTo(Array array, int arrayIndex) 
     357        { 
     358            if(null == array) 
     359                throw new AprArgumentNullException("array"); 
     360            if(arrayIndex < 0 || arrayIndex > array.Length) 
     361                throw new AprArgumentOutOfRangeException("arrayIndex"); 
     362            if(array.Rank > 1) 
     363                throw new AprArgumentException("array is multidimensional"); 
     364            if((array.Length - arrayIndex) < Count) 
     365                throw new AprArgumentException("Not enough room from arrayIndex to end of array for this AprArray"); 
     366             
     367            int i = arrayIndex; 
     368            IEnumerator it = GetEnumerator(); 
     369            while(it.MoveNext()) { 
     370                array.SetValue(it.Current, i++); 
     371            } 
     372        } 
     373         
     374        public bool IsSynchronized  
     375        { 
     376            get 
     377            { 
     378                return false; 
     379            } 
     380        } 
     381 
     382        public object SyncRoot  
     383        { 
     384            get 
     385            { 
     386                return this; 
     387            } 
     388        } 
     389 
    205390        public int Count 
    206391        { 
     
    209394            } 
    210395        } 
    211  
    212         public int AllocatedCount 
    213         { 
    214             get { 
    215                 return(mArray->nalloc); 
    216             } 
    217         } 
    218          
    219         public int ElementSize 
    220         { 
    221             get { 
    222                 return(mArray->elt_size); 
    223             } 
    224         } 
    225          
    226         public IntPtr Data 
    227         { 
    228             get { 
    229                 return(new IntPtr(mArray->elts)); 
    230             } 
    231         } 
    232  
    233         [CLSCompliant(false)] 
    234         public byte *NativeData 
    235         { 
    236             get { 
    237                 return(mArray->elts); 
    238             } 
     396        #endregion        
     397         
     398        #region IEnumerable 
     399        public IEnumerator GetEnumerator() 
     400        { 
     401            return (IEnumerator) new AprArrayEnumerator(this); 
    239402        } 
    240403        #endregion 
     404 
     405    } 
     406     
     407    public class AprArrayEnumerator : IEnumerator 
     408    { 
     409        AprArray mArray; 
     410        int mIndex; 
     411     
     412        public AprArrayEnumerator(AprArray array) 
     413        { 
     414            mArray = array; 
     415            mIndex = -1; 
     416        } 
     417         
     418        #region IEnumerator 
     419        public bool MoveNext() 
     420        { 
     421            if (++mIndex >= mArray.Count) { 
     422                mIndex = mArray.Count; 
     423                return(false); 
     424            } 
     425            return(true); 
     426        } 
     427         
     428        public void Reset() 
     429        { 
     430            mIndex = -1; 
     431        } 
     432                 
     433        public object Current 
     434        { 
     435            get 
     436            { 
     437                if (mIndex < 0 || mIndex >= mArray.Count) 
     438                    throw new AprInvalidOperationException("No current item."); 
     439                 
     440                if(mArray.ElementType == null) 
     441                    throw new AprInvalidOperationException("Array not typed."); 
     442                                 
     443                if(mArray.ElementType.IsPrimitive) 
     444                { 
     445                    object val; 
     446                    switch(mArray.ElementSize) 
     447                    { 
     448                        case 1: 
     449                            val = Marshal.ReadByte(mArray.Data,mIndex); 
     450                            break; 
     451                        case 2: 
     452                            val = Marshal.ReadInt16(mArray.Data,mIndex*2); 
     453                            break; 
     454                        case 4: 
     455                            val = Marshal.ReadInt32(mArray.Data,mIndex*4); 
     456                            break; 
     457                        case 8: 
     458                            val = Marshal.ReadInt64(mArray.Data,mIndex*8); 
     459                            break; 
     460                        default: 
     461                            throw new AprInvalidOperationException("Invalid element size."); 
     462                    } 
     463                    return(Convert.ChangeType(val,mArray.ElementType)); 
     464                } 
     465                 
     466                ConstructorInfo ctor = mArray.ElementType.GetConstructor(new Type[] {typeof(IntPtr)}); 
     467                if( ctor == null ) 
     468                    throw new AprInvalidOperationException("Type is not primitive and cannot be constructed from an IntPtr."); 
     469                 
     470                IntPtr ptr = Marshal.ReadIntPtr(mArray.Data,mIndex*mArray.ElementSize); 
     471                return(ctor.Invoke(new Object[] { ptr })); 
     472            } 
     473        } 
     474        #endregion 
     475 
    241476    } 
    242477} 
  • trunk/AprSharp/dev/src/AprNullReferenceException.cs

    r1 r29  
    1212using System; 
    1313using System.Runtime.Serialization; 
    14 using Softec; 
    1514 
    1615namespace Softec.AprSharp 
  • trunk/AprSharp/dev/src/AprSharp.prjx

    r6 r29  
    2020    <File name="./AprHashIndex.cs" subtype="Code" buildaction="Compile" dependson="" data="" /> 
    2121    <File name="./AprArray.cs" subtype="Code" buildaction="Compile" dependson="" data="" /> 
     22    <File name="./AprInvalidOperationException.cs" subtype="Code" buildaction="Compile" dependson="" data="" /> 
    2223  </Contents> 
    2324  <References /> 
  • trunk/AprSharp/test/src/AprArrayTest.cs

    r17 r29  
    9999         
    100100        [Test] 
     101        public void PushPopObject() 
     102        { 
     103            AprPool p = AprPool.Create(); 
     104            Assert.IsFalse(p.IsNull,"#B01"); 
     105         
     106            AprArray a = AprArray.Make(p,5,typeof(int)); 
     107            Assert.IsFalse(a.IsNull,"#B02"); 
     108             
     109            a.Push(1); 
     110            a.Push(2); 
     111            a.Push(3); 
     112            a.Push(4); 
     113            a.Push(5); 
     114             
     115            Assert.AreEqual(5,a.PopObject(),"#B05"); 
     116            Assert.AreEqual(4,a.PopObject(),"#BO6"); 
     117            Assert.AreEqual(3,a.PopObject(),"#BO7"); 
     118            Assert.AreEqual(2,a.PopObject(),"#BO8"); 
     119            Assert.AreEqual(1,a.PopObject(),"#BO9"); 
     120 
     121            a = AprArray.Make(p,5,typeof(AprString)); 
     122             
     123            a.Push(new AprString(p,"This")); 
     124            a.Push(new AprString(p,"is")); 
     125            a.Push(new AprString(p,"a")); 
     126            a.Push(new AprString(p,"test.")); 
     127 
     128            Assert.AreEqual("test.",a.PopObject().ToString(),"#B10"); 
     129            Assert.AreEqual("a",a.PopObject().ToString(),"#B11"); 
     130            Assert.AreEqual("is",a.PopObject().ToString(),"#B12"); 
     131            Assert.AreEqual("This",a.PopObject().ToString(),"#B13"); 
     132 
     133            p.Destroy(); 
     134            Assert.IsTrue(p.IsNull,"#B14"); 
     135        } 
     136         
     137        [Test] 
    101138        public void Copy() 
    102139        { 
     
    205242            p.Destroy(); 
    206243            Assert.IsTrue(p.IsNull,"#C04"); 
    207         }        
     244        } 
     245         
     246        [Test] 
     247        public void CopyTo() 
     248        { 
     249            AprPool p = AprPool.Create(); 
     250            Assert.IsFalse(p.IsNull,"#C01"); 
     251         
     252            AprArray a = AprArray.Make(p,5,typeof(AprString)); 
     253            Assert.IsFalse(a.IsNull,"#C02"); 
     254             
     255            Marshal.WriteIntPtr(a.Push(),new AprString(p,"1")); 
     256            Marshal.WriteIntPtr(a.Push(),new AprString(p,"2")); 
     257            Marshal.WriteIntPtr(a.Push(),new AprString(p,"3")); 
     258            Marshal.WriteIntPtr(a.Push(),new AprString(p,"4")); 
     259            Marshal.WriteIntPtr(a.Push(),new AprString(p,"5")); 
     260             
     261            AprString[] arr = new AprString[5];  
     262            a.CopyTo(arr,0); 
     263             
     264            Assert.AreEqual("1",arr[0].ToString(),"#C03"); 
     265            Assert.AreEqual("2",arr[1].ToString(),"#C04"); 
     266            Assert.AreEqual("3",arr[2].ToString(),"#C05"); 
     267            Assert.AreEqual("4",arr[3].ToString(),"#C06"); 
     268            Assert.AreEqual("5",arr[4].ToString(),"#C07"); 
     269             
     270            p.Destroy(); 
     271            Assert.IsTrue(p.IsNull,"#C08"); 
     272        } 
    208273    } 
    209274}