1 // ValueArray.cs - ValueArray wrapper implementation 2 // 3 // Authors: Mike Kestner <mkestner@ximian.com> 4 // 5 // Copyright (c) 2003 Novell, Inc. 6 // 7 // This program is free software; you can redistribute it and/or 8 // modify it under the terms of version 2 of the Lesser GNU General 9 // Public License as published by the Free Software Foundation. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 // Lesser General Public License for more details. 15 // 16 // You should have received a copy of the GNU Lesser General Public 17 // License along with this program; if not, write to the 18 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 // Boston, MA 02111-1307, USA. 20 21 22 namespace GLib { 23 24 using System; 25 using System.Collections; 26 using System.Collections.Generic; 27 using System.Runtime.InteropServices; 28 29 public class ValueArray : IDisposable, ICollection, ICloneable, IWrapper { 30 31 private IntPtr handle = IntPtr.Zero; 32 33 static private IList<IntPtr> PendingFrees = new List<IntPtr> (); 34 static private bool idle_queued = false; 35 36 [DllImport (Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)] g_value_array_new(uint n_preallocs)37 static extern IntPtr g_value_array_new (uint n_preallocs); 38 ValueArray(uint n_preallocs)39 public ValueArray (uint n_preallocs) 40 { 41 handle = g_value_array_new (n_preallocs); 42 } 43 ValueArray(IntPtr raw)44 public ValueArray (IntPtr raw) 45 { 46 handle = raw; 47 } 48 ~ValueArray()49 ~ValueArray () 50 { 51 Dispose (false); 52 } 53 54 // IDisposable Dispose()55 public void Dispose () 56 { 57 Dispose (true); 58 GC.SuppressFinalize (this); 59 } 60 61 [DllImport (Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)] g_value_array_free(IntPtr raw)62 static extern void g_value_array_free (IntPtr raw); 63 Dispose(bool disposing)64 void Dispose (bool disposing) 65 { 66 if (Handle == IntPtr.Zero) 67 return; 68 69 lock (PendingFrees) { 70 PendingFrees.Add (handle); 71 72 if (! idle_queued) { 73 Timeout.Add (50, new TimeoutHandler (PerformFrees)); 74 idle_queued = true; 75 } 76 } 77 78 handle = IntPtr.Zero; 79 } 80 PerformFrees()81 static bool PerformFrees () 82 { 83 IntPtr[] handles; 84 85 lock (PendingFrees) { 86 idle_queued = false; 87 88 handles = new IntPtr [PendingFrees.Count]; 89 PendingFrees.CopyTo (handles, 0); 90 PendingFrees.Clear (); 91 } 92 93 foreach (IntPtr h in handles) 94 g_value_array_free (h); 95 96 return false; 97 } 98 99 public IntPtr Handle { 100 get { 101 return handle; 102 } 103 } 104 105 struct NativeStruct { 106 public uint n_values; 107 public IntPtr values; 108 public uint n_prealloced; 109 } 110 111 NativeStruct Native { 112 get { return (NativeStruct) Marshal.PtrToStructure (Handle, typeof(NativeStruct)); } 113 } 114 115 public IntPtr ArrayPtr { 116 get { return Native.values; } 117 } 118 119 [DllImport (Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)] g_value_array_append(IntPtr raw, ref GLib.Value val)120 static extern void g_value_array_append (IntPtr raw, ref GLib.Value val); 121 Append(GLib.Value val)122 public void Append (GLib.Value val) 123 { 124 g_value_array_append (Handle, ref val); 125 } 126 127 [DllImport (Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)] g_value_array_insert(IntPtr raw, uint idx, ref GLib.Value val)128 static extern void g_value_array_insert (IntPtr raw, uint idx, ref GLib.Value val); 129 Insert(uint idx, GLib.Value val)130 public void Insert (uint idx, GLib.Value val) 131 { 132 g_value_array_insert (Handle, idx, ref val); 133 } 134 135 [DllImport (Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)] g_value_array_prepend(IntPtr raw, ref GLib.Value val)136 static extern void g_value_array_prepend (IntPtr raw, ref GLib.Value val); 137 Prepend(GLib.Value val)138 public void Prepend (GLib.Value val) 139 { 140 g_value_array_prepend (Handle, ref val); 141 } 142 143 [DllImport (Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)] g_value_array_remove(IntPtr raw, uint idx)144 static extern void g_value_array_remove (IntPtr raw, uint idx); 145 Remove(uint idx)146 public void Remove (uint idx) 147 { 148 g_value_array_remove (Handle, idx); 149 } 150 151 // ICollection 152 public int Count { 153 get { return (int) Native.n_values; } 154 } 155 156 [DllImport (Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)] g_value_array_get_nth(IntPtr raw, uint idx)157 static extern IntPtr g_value_array_get_nth (IntPtr raw, uint idx); 158 159 public object this [int index] { 160 get { 161 IntPtr raw_val = g_value_array_get_nth (Handle, (uint) index); 162 return Marshal.PtrToStructure (raw_val, typeof (GLib.Value)); 163 } 164 } 165 166 // Synchronization could be tricky here. Hmm. 167 public bool IsSynchronized { 168 get { return false; } 169 } 170 171 public object SyncRoot { 172 get { return null; } 173 } 174 CopyTo(Array array, int index)175 public void CopyTo (Array array, int index) 176 { 177 if (array == null) 178 throw new ArgumentNullException ("Array can't be null."); 179 180 if (index < 0) 181 throw new ArgumentOutOfRangeException ("Index must be greater than 0."); 182 183 if (index + Count < array.Length) 184 throw new ArgumentException ("Array not large enough to copy into starting at index."); 185 186 for (int i = 0; i < Count; i++) 187 ((IList) array) [index + i] = this [i]; 188 } 189 190 private class ListEnumerator : IEnumerator 191 { 192 private int current = -1; 193 private ValueArray vals; 194 ListEnumerator(ValueArray vals)195 public ListEnumerator (ValueArray vals) 196 { 197 this.vals = vals; 198 } 199 200 public object Current { 201 get { 202 if (current == -1) 203 return null; 204 return vals [current]; 205 } 206 } 207 MoveNext()208 public bool MoveNext () 209 { 210 if (++current >= vals.Count) { 211 current = -1; 212 return false; 213 } 214 215 return true; 216 } 217 Reset()218 public void Reset () 219 { 220 current = -1; 221 } 222 } 223 224 // IEnumerable GetEnumerator()225 public IEnumerator GetEnumerator () 226 { 227 return new ListEnumerator (this); 228 } 229 230 [DllImport (Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)] g_value_array_copy(IntPtr raw)231 static extern IntPtr g_value_array_copy (IntPtr raw); 232 233 // ICloneable Clone()234 public object Clone () 235 { 236 return new ValueArray (g_value_array_copy (Handle)); 237 } 238 239 [DllImport (Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)] g_value_array_get_type()240 static extern IntPtr g_value_array_get_type (); 241 242 public static GLib.GType GType { 243 get { 244 return new GLib.GType (g_value_array_get_type ()); 245 } 246 } 247 } 248 } 249