source: branches/eraser6/Manager/PRNG.cs @ 905

Revision 905, 6.7 KB checked in by lowjoel, 5 years ago (diff)

Ran static code analysis on Manager.

-Do not initialise class members to default values (runtime will handle that)
-Deserialisation constructors should be marked protected for unsealed classes
-Classes implementing ICollection should end with Collection (Mainly fixed here is ErasureTargetsCollection?)
-ISerializable.GetObjectData? should be marked virtual
-Use proper camel casing (Prng, Guid, FileName? etc)
-Enumeration values should be Camel casing
-Bitfields should be marked with the [Flags] attribute
-Implement the proper IDisposable pattern - one Dispose() and one Dispose(bool) - the latter doing the clean ups for both Dispose and finalisers
-public variables should instead be properties
-Abstract classes should have protected constructors
-Renamed Schedule.Type to Schedule.ScheduleType? to prevent ambiguity with GetType?()
-There shouldn't be a need to pass reference variables by reference

  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 * Copyright 2008 The Eraser Project
4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By: Kasra Nassiri <cjax@users.sourceforge.net>
6 * Modified By:
7 *
8 * This file is part of Eraser.
9 *
10 * Eraser is free software: you can redistribute it and/or modify it under the
11 * terms of the GNU General Public License as published by the Free Software
12 * Foundation, either version 3 of the License, or (at your option) any later
13 * version.
14 *
15 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
16 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 *
19 * A copy of the GNU General Public License can be found at
20 * <http://www.gnu.org/licenses/>.
21 */
22
23using System;
24using System.Collections.Generic;
25using System.Text;
26
27using System.Threading;
28using System.Security.Cryptography;
29using System.Runtime.InteropServices;
30using System.Diagnostics;
31using System.Reflection;
32using System.IO;
33using Microsoft.Win32.SafeHandles;
34using Eraser.Util;
35
36namespace Eraser.Manager
37{
38    /// <summary>
39    /// An interface class for all pseudorandom number generators used for the
40    /// random data erase passes.
41    /// </summary>
42    public abstract class Prng
43    {
44        public override string ToString()
45        {
46            return Name;
47        }
48
49        /// <summary>
50        /// The name of this erase pass, used for display in the UI
51        /// </summary>
52        public abstract string Name
53        {
54            get;
55        }
56
57        /// <summary>
58        /// The GUID for this PRNG.
59        /// </summary>
60        public abstract Guid Guid
61        {
62            get;
63        }
64
65        /// <summary>
66        /// Reseeds the PRNG. This can be called by inherited classes, but its most
67        /// important function is to provide new seeds regularly. The PRNGManager
68        /// will call this function once in a whle to maintain the quality of
69        /// generated numbers.
70        /// </summary>
71        /// <param name="seed">An arbitrary length of information that will be
72        /// used to reseed the PRNG</param>
73        protected internal abstract void Reseed(byte[] seed);
74
75        #region Random members
76        /// <summary>
77        /// Returns a nonnegative random number less than the specified maximum.
78        /// </summary>
79        /// <param name="maxValue">The exclusive upper bound of the random number
80        /// to be generated. maxValue must be greater than or equal to zero.</param>
81        /// <returns>A 32-bit signed integer greater than or equal to zero, and
82        /// less than maxValue; that is, the range of return values ordinarily
83        /// includes zero but not maxValue. However, if maxValue equals zero,
84        /// maxValue is returned.</returns>
85        public int Next(int maxValue)
86        {
87            if (maxValue == 0)
88                return 0;
89            return Next() % maxValue;
90        }
91
92        /// <summary>
93        /// Returns a random number within a specified range.
94        /// </summary>
95        /// <param name="minValue">The inclusive lower bound of the random number
96        /// returned.</param>
97        /// <param name="maxValue">The exclusive upper bound of the random number
98        /// returned. maxValue must be greater than or equal to minValue.</param>
99        /// <returns>A 32-bit signed integer greater than or equal to minValue and
100        /// less than maxValue; that is, the range of return values includes minValue
101        /// but not maxValue. If minValue equals maxValue, minValue is returned.</returns>
102        public int Next(int minValue, int maxValue)
103        {
104            if (minValue > maxValue)
105                throw new ArgumentOutOfRangeException("minValue", minValue,
106                    S._("minValue is greater than maxValue"));
107            else if (minValue == maxValue)
108                return minValue;
109            return (Next() % (maxValue - minValue)) + minValue;
110        }
111
112        /// <summary>
113        /// Returns a nonnegative random number.
114        /// </summary>
115        /// <returns>A 32-bit signed integer greater than or equal to zero and less
116        /// than System.Int32.MaxValue.</returns>
117        public unsafe int Next()
118        {
119            //Declare a return variable
120            int result;
121            int* fResult = &result;
122
123            //Get the random-valued bytes to fill the int.
124            byte[] rand = new byte[sizeof(int)];
125            NextBytes(rand);
126
127            //Copy the random buffer into the int.
128            fixed (byte* fRand = rand)
129            {
130                byte* pResult = (byte*)fResult;
131                byte* pRand = fRand;
132                for (int i = 0; i != sizeof(int); ++i)
133                    *pResult++ = *pRand++;
134            }
135
136            return Math.Abs(result);
137        }
138
139        /// <summary>
140        /// Fills the elements of a specified array of bytes with random numbers.
141        /// </summary>
142        /// <param name="buffer">An array of bytes to contain random numbers.</param>
143        public abstract void NextBytes(byte[] buffer);
144        #endregion
145    }
146
147    /// <summary>
148    /// Class managing all the PRNG algorithms.
149    /// </summary>
150    public class PrngManager
151    {
152        /// <summary>
153        /// Constructor.
154        /// </summary>
155        public PrngManager()
156        {
157        }
158
159        /// <summary>
160        /// Retrieves all currently registered erasure methods.
161        /// </summary>
162        /// <returns>A mutable list, with an instance of each PRNG.</returns>
163        public static Dictionary<Guid, Prng> GetAll()
164        {
165            lock (ManagerLibrary.Instance.PRNGManager.prngs)
166                return ManagerLibrary.Instance.PRNGManager.prngs;
167        }
168
169        /// <summary>
170        /// Retrieves the instance of the PRNG with the given GUID.
171        /// </summary>
172        /// <param name="guid">The GUID of the PRNG.</param>
173        /// <returns>The PRNG instance.</returns>
174        public static Prng GetInstance(Guid guid)
175        {
176            try
177            {
178                lock (ManagerLibrary.Instance.PRNGManager.prngs)
179                    return ManagerLibrary.Instance.PRNGManager.prngs[guid];
180            }
181            catch (KeyNotFoundException)
182            {
183                throw new FatalException(S._("PRNG not found: {0}", guid.ToString()));
184            }
185        }
186
187        /// <summary>
188        /// Allows plug-ins to register PRNGs with the main program. Thread-safe.
189        /// </summary>
190        /// <param name="method"></param>
191        public static void Register(Prng prng)
192        {
193            lock (ManagerLibrary.Instance.PRNGManager.prngs)
194                ManagerLibrary.Instance.PRNGManager.prngs.Add(prng.Guid, prng);
195        }
196
197        /// <summary>
198        /// Allows the EntropyThread to get entropy to the PRNG functions as seeds.
199        /// </summary>
200        /// <param name="entropy">An array of bytes, being entropy for the PRNG.</param>
201        internal void AddEntropy(byte[] entropy)
202        {
203            lock (ManagerLibrary.Instance.PRNGManager.prngs)
204                foreach (Prng prng in prngs.Values)
205                    prng.Reseed(entropy);
206        }
207
208        /// <summary>
209        /// Gets entropy from the EntropyThread.
210        /// </summary>
211        /// <returns>A buffer of arbitrary length containing random information.</returns>
212        public static byte[] GetEntropy()
213        {
214            return ManagerLibrary.Instance.EntropySourceManager.Poller.GetPool();
215        }
216
217        /// <summary>
218        /// The list of currently registered erasure methods.
219        /// </summary>
220        private Dictionary<Guid, Prng> prngs = new Dictionary<Guid, Prng>();
221    }
222}
Note: See TracBrowser for help on using the repository browser.