//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// // MemoryMapper1.cs 15-May-18//\\//\\//\\ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// // v4.4.5.53 Mapped in to Lock Out//\\//\\ // v4.4.5.53 Split from PrintForm2\\//\\// // v4.4.6.54 mm2 & mm3 transition //\\//\\ // Obsoletes mmf2 and mmf3 stuff. \\//\\// // (c) John P. Edwards 20-May-2018//\\//\\ // v4.5.6.54 name & path/no-path mech/\\// // Mapped in to Lock Out, extended//\\//\\ // v4.5.7.54neatobeto! All Dialed in!/\\// // v4.5.7.56nights Brings in Strings!\//\\ // v4.5.7.56nighttime perfects class//\\// // v4.5.7.56nightvision has Auto-Size!//\\ // v4.5.7.57 Auto-Size & args[6] Delete!// // v4.5.7.57 Perfects Int64 Handling. Fini // v4.5.7.58 Polished & Welltested. Jun-28 // v4.5.8.60 Revised For: Int64 lengths. // v4.5.9.63 Final Integrations. 15-Aug // v4.6.9.64 26-Aug-2018 Added omitted // locking on the rest of the methods.oop // 29-Aug-2018 Clarifies Resource Access: // v4.6.9.65 Replaced Lock w/ Mutex 4 IPC! // v4.6.9.67 08-Sep-2018 Mutex Properties. // v4.8.1.78 06-Oct-2018 LastAccess Time. // v4.9.3.87 15-Nov-2018 Favorites Mods. // v4.9.4.89 20-Nov-2018 Ironing & Polish. // v5.0.6.00 21-Feb-2019 Updated all: // List to Collection //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Threading; using MCR = MyCustomLibrary.Properties.Resources; namespace MyCustomLibrary { public static partial class MemoryMapper { private static readonly Mutex Mtx1 = new Mutex(false, MCR.M1); private static readonly Mutex Mtx2 = new Mutex(false, MCR.M2); private static readonly Mutex Mtx3 = new Mutex(false, MCR.M3); #region Doc // mmf = Memory Mapped File(s) Arguments // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // args[0] = Full Path to mmf. // args[1] = Size of file in bytes, // args[2] = Start @ Byte (offset) // args[3] = What to write? (OR Shred? T/F) // args[4] = true; Read? // args[5] = this mapping's name. // args[6] = true; Delete after Read? // args[7] = View Length from Offset. // (if Given) Not Required, either way.8 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #endregion #region MemoryMapper Class: Common Code. private static void Writer(string path) { using (new Mutex(false, "Writer")) { var time = DateTime.Now; File.SetLastWriteTime(path, time); File.SetLastAccessTime(path, time); } } private static void EndGame( bool del, string path) { using (new Mutex(false, "EndGame")) { if (del && File.Exists(path)) File.Delete(path); else if (File.Exists(path)) File.SetLastAccessTime( path, DateTime.Now); } } #endregion Common Code //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ #region Memory Mapped Files: Read & Write Bytes // Reads a List of Bytes from mmf. // v4.5.7.56 04-Jun-2018 for ReUseAbility. public static Collection ReadBytes(object[] args) { Mtx1.WaitOne(); const string t = "Read Bytes"; long size, offs, view = 0; if (args == null || args.Length < 7) throw new ArgumentException(t); bool read, dele, shred; string path, name; try // now unbox args. { path =args[0].ToString();//[0]); size = Convert.ToInt64(args[1]); offs = Convert.ToInt64(args[2]); try { shred = Convert.ToBoolean( args[3]);} catch(FormatException){shred=false;} catch(InvalidCastException){shred=false;} read=Convert.ToBoolean(args[4]); name=args[5].ToString(); //[5]); dele=Convert.ToBoolean(args[6]); if (args.Length > 7)// args[7]); { try { view = Convert.ToInt64(args[7]); } catch (FormatException) { view = 0; } catch(InvalidCastException){ view = 0;}} } catch (InvalidCastException) { throw new InvalidCastException(t); } catch (FormatException) { throw new FormatException(t); } var bites = ReadBytesKernal(path, name, size, read, offs, view, shred); EndGame(dele, path); Mtx1.ReleaseMutex(); return bites; } /******************************************** * Self Contained Instance-N ^v Methods: * * ThreadFileSafe Useable by any instance. * * so long as the file varies or such.-JpE- * ********************************************/ public static bool WriteBytes(object[] args) { Mtx1.WaitOne(); if(args==null||args.Length < 7) throw new ArgumentException("Write Bytes"); string path,name;long size,offset,view = 0; try { path = args[0].ToString(); } catch (FormatException) { path = Convert.ToString(args[0]); } try { size =(Convert.ToInt64(args[1]));} catch (InvalidCastException){size= 1;} try { offset =Convert.ToInt64(args[2]);} catch (FormatException) { Mtx1.ReleaseMutex(); return false; } catch(InvalidCastException) { Mtx1.ReleaseMutex(); return false; } try { name = args[5].ToString(); } catch(InvalidCastException){name="mmf";} catch(FormatException) { name = "mmf"; } if (args.Length > 7) { try { view = Convert.ToInt64(args[7]); } catch (FormatException) { view = 0; } catch (InvalidCastException) { view = 0L; } catch(OverflowException) { view = 0; } } if (!WriteBytesKernal(path, name, size, offset, view, args[3])) { Mtx1.ReleaseMutex(); return false; } Writer(path); Mtx1.ReleaseMutex(); return true; } #endregion Read/Write Bytes //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ #region Mmf: Int64 Words @ 8 bytes each. /// Server-Side Code /// Generic enough to reuse from /// either side, just watch for, /// like, file already open errors. /// Updated to return Generic List /// v4.5.7.56 04-May-2018 -JpE- /// NOTE: args[3] is now a List /// of Long Integers. Adds Reuseability. /// v4.6.9.65 29-Aug-2018 Mutex'd /// /// /// public static Collection ReadInt64(object[] array) { Mtx2.WaitOne(); if (array == null || array[2] == null || array.Length < 7) throw new ArgumentException("Read Int64"); string t, h; long s, o, v = 0L; bool r, d, b; var c = new Collection(); try{h =array[0].ToString();//[0]); s = Convert.ToInt64( array[1]); o = Convert.ToInt64( array[2]); try { b = Convert.ToBoolean( array[3]); } catch (FormatException) { b = false;} catch(InvalidCastException){b=false;} r = Convert.ToBoolean(array[4]); t = array[5].ToString(); //[5]); d = Convert.ToBoolean(array[6]); if (array.Length > 7) v = Convert.ToInt64(array[7]); } catch (InvalidCastException) { Mtx2.ReleaseMutex(); return c; } catch (FormatException) { Mtx2.ReleaseMutex(); return c; } c = ReadInt64Kernal(s, h, t, r, o, v, b); if (!r) { Mtx1.ReleaseMutex(); return c; } EndGame(d, h); Mtx2.ReleaseMutex(); return c; } /// Client-Side Code /// v4.5.6.54nab 20-May-2018 /// Generic enough to reuse from /// either side, just watch for, /// like, file already open errors in IO. /// v4.5.7.54 25-May-2018 Int64 @ 8 bytes ea. /// v4.5.7.56 04-Jun args[3] is now /// a List of Int64 = Long values. /// /// public static bool WriteInt64(object[] args) { Mtx2.WaitOne(); try { if (args == null || args[2] == null || args.Length < 7 || !args.Any()) return false; } catch(ArgumentException){return false;} const long k = 0L; const string m = "mm3"; long s, o, v = 0L; string n, h; try { h = args[0].ToString(); } catch (FormatException) { h = ""; } try { s = Convert.ToInt64(args[1]); } catch (InvalidCastException) { s = k; } catch (FormatException) { s = k; } try { o = Convert.ToInt64(args[2]); } catch (InvalidCastException){ o = 0L; } catch (FormatException) { o = 0L; } try { n = args[5].ToString(); } catch (FormatException) { n = m; } catch (InvalidCastException) { n = m; } if (args.Length > 7) { try { v = Convert.ToInt64(args[7]); } catch (FormatException) { v = 0; } catch (InvalidCastException){v = 0;} catch (OverflowException){v = 0; } } if (!WriteLongKernal( args[3], s, h, n, o, v)) { Mtx2.ReleaseMutex(); return false; } Writer(h); Mtx2.ReleaseMutex(); return true; } #endregion Mmf: Int64 Words @ 8 bytes each. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ #region Read/Write Strings /// Read in List of strings. /// -JpE- v4.5.7.56 01-Jun-18 (from Mmf ^) /// SEE DOC ABOVE FOR REQUIRED ARG VALUES. /// Returns a List of string references. /// If size arg is 0, it calculates j.i.t. /// args[6], the 7th element now contains /// a bool for delete file when finished. T/F /// v4.9.3.86 Added the 8th element: /// View Length. November 11th, 2018 -JpE- /// /// /// public static Collection ReadStrings(object[] args) { Mtx3.WaitOne(); if (args == null || args.Length < 7 || string.IsNullOrEmpty( args[0].ToString())) { Mtx3.ReleaseMutex(); return null; } string path, name; long size, offs, view = 0L; bool read, del, shred = false; try{path = args[0].ToString();//0]); size = Convert.ToInt64(args[1]); offs = Convert.ToInt64(args[2]); // Only used for Writes args[3]); BUT... read = Convert.ToBoolean(args[4]); name = args[5].ToString(); //[5]); del = Convert.ToBoolean(args[6]); if (args.Length > 7) view = Convert.ToInt64(args[7]); try // v Reused here as a Special Case. { if (args[3] != null) shred = Convert.ToBoolean(args[3]); } catch (FormatException) { shred=false; } catch(InvalidCastException){shred=false;}} catch (ArgumentException) { Mtx3.ReleaseMutex(); return null; } catch (InvalidCastException) { Mtx3.ReleaseMutex(); return null; } if (!File.Exists(path)) { Mtx3.ReleaseMutex(); return null; } var input = ReadStringsKernal( path, size, offs, name, read, view, shred); if (input == null || !read ) { Mtx3.ReleaseMutex(); return null; } EndGame(del, path); Mtx3.ReleaseMutex(); return input; } /// Write List of strings /// to memory mapped file (args[0]). /// Return true only if EVERYTHING went ok. /// REM: args[3] is a List of Strings! /// Strings to write as UNICODE encoded bytes. /// SEE DOC ABOVE FOR REQUIRED ARG VALUES. /// /// /// public static bool WriteStrings(object[] args) { if (args == null || args.Length < 7) return false; Mtx3.WaitOne(); Collection strings; try { strings = args[3] as Collection; } catch(ArgumentException) { Mtx3.ReleaseMutex(); return false; } catch(InvalidCastException) { Mtx3.ReleaseMutex(); return false; } if ( strings == null || strings.Count < 1 || string.IsNullOrEmpty(args[0].ToString())) { Mtx3.ReleaseMutex(); return false; } string file, name; long size, offs, view = 0L; try// REM: args[4] doesn't apply to writes. { file = args[0].ToString();//[0]); size = Convert.ToInt64( args[1]); offs = Convert.ToInt64( args[2]); name = args[5].ToString(); //5]); if (args.Length > 7) view = Convert.ToInt64(args[7]); } catch (ArgumentException) { Mtx3.ReleaseMutex(); return false; } catch (InvalidCastException) { Mtx3.ReleaseMutex(); return false; } if (size == 0) size = offs + CalcSize(strings); // This Call to CalcSize is ^ for AutoSize! 0 var is1 = WriteStringsKernal(file, name, size, offs, view, strings); if (is1) Writer(file); Mtx3.ReleaseMutex(); return is1; } private static long CalcSize( ICollection strings) { if (strings == null || strings.Count < 1) throw new ArgumentException("CalcSize"); long size; try { size = strings.Sum(s => s.Length); size = (size* 2) + (2* strings.Count); } catch(ArgumentNullException){size = 256; } catch (OverflowException) { size = 256; } // =-> w/Int16 UniCode it's 2 bytes per char. return size;// 2 x 8 ^ // NOTE: So 2x Chars + 2 ea. <-= <-= }// <-= EOM <-= for ^ int16 ^ lengths. //=-> =-> =-> (Length stored before ea string.) #endregion Read/Write Strings //\\//\\//\\//\\//\\//\\//\\//\\//\\// EOC } }