source: trunk/CrypPlugins/BooleanFunctionParser/BooleanFunctionParser.cs @ 752

Last change on this file since 752 was 752, checked in by Sören Rinne, 12 years ago
  • new CubeAttackParser-Sample.cte
  • BFP now needs only one presentation for Cube Attack
  • adjusted Trivium
File size: 35.7 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5
6using Cryptool.PluginBase;
7using System.IO;
8using System.ComponentModel;
9using System.Windows.Controls;
10using Cryptool.PluginBase.Cryptography;
11using Cryptool.PluginBase.IO;
12using Cryptool.PluginBase.Miscellaneous;
13using System.Security.Cryptography;
14// for [MethodImpl(MethodImplOptions.Synchronized)]
15using System.Runtime.CompilerServices;
16// for RegEx
17using System.Text.RegularExpressions;
18// for IControl
19using Cryptool.PluginBase.Control;
20// reference to the BFPController interface (own dll)
21using Cryptool.BooleanFunctionParserController;
22// for QuickwatchPresentaton
23using System.Windows.Threading;
24using System.Threading;
25
26namespace Cryptool.BooleanFunctionParser
27{
28    [Author("Soeren Rinne", "soeren.rinne@cryptool.de", "Ruhr-Universitaet Bochum, Chair for System Security", "http://www.trust.rub.de/")]
29    [PluginInfo(false, "Boolean Function Parser", "Boolean Function Parser (BFP). Computes the result of a boolean function f(i).", "BooleanFunctionParser/DetailedDescription/Description.xaml", "BooleanFunctionParser/Images/icon2.png")]
30    public class BooleanFunctionParser : IThroughput
31    {
32        #region Private variables
33
34        private BooleanFunctionParserPresentation booleanFunctionParserPresentation;
35        private BooleanFunctionParserSettings settings;
36        private string inputFunction;
37        //private bool[] inputVariableOne;
38        //private bool[] inputVariableTwo;
39        //private bool[] inputVariableThree;
40        private bool output;
41        private bool lastInputWasFunction = false;
42        private int inputs = 1;
43        //private string fillValue;
44        private bool canSendPropertiesChangedEvent = true;
45
46        #endregion
47
48        #region Events
49        public event DynamicPropertiesChanged OnDynamicPropertiesChanged;
50        #endregion
51
52        #region Public variables
53
54        public int inputOneFlag = 0;
55        public int inputTwoFlag = 0;
56        public int inputThreeFlag = 0;
57        public int[] additionalInputsFlag = null;
58
59        #endregion
60
61        #region Public interfaces
62
63        /// <summary>
64        /// Contructor
65        /// </summary>
66        public BooleanFunctionParser()
67        {
68            this.settings = new BooleanFunctionParserSettings();
69            settings.PropertyChanged += settings_PropertyChanged;
70
71            booleanFunctionParserPresentation = new BooleanFunctionParserPresentation();
72            Presentation = booleanFunctionParserPresentation;
73            booleanFunctionParserPresentation.textBoxInputFunction.TextChanged += textBoxInput_TextChanged;
74            booleanFunctionParserPresentation.textBoxInputData.TextChanged += textBoxInput_TextChanged;
75
76            CanChangeDynamicProperty = true;
77            // Thomas says:
78            // No dynProp event in constructor - editor will read the property initial without the event.
79            // event can cause problems when using save files and is processed after
80            // connections have been restored.
81            CreateInputOutput(false);
82        }
83
84        void textBoxInput_TextChanged(object sender, TextChangedEventArgs e)
85        {
86            settings.HasChanges = true;
87        }
88
89        [PropertyInfo(Direction.InputData, "Boolean Function f(i)", "Boolean function f(i) to compute.", "", true, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
90        public String InputFunction
91        {
92            [MethodImpl(MethodImplOptions.Synchronized)]
93            get { return inputFunction; }
94            [MethodImpl(MethodImplOptions.Synchronized)]
95            set
96            {
97                inputFunction = value;
98                lastInputWasFunction = true;
99                OnPropertyChanged("InputFunction");
100            }
101        }
102
103        /*[PropertyInfo(Direction.InputData, "Function Variable One (i_1.j)", "Input a boolean value to be processed by the function", "", false, true, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
104        public bool[] InputOne
105        {
106            [MethodImpl(MethodImplOptions.Synchronized)]
107            get
108            {
109                return this.inputVariableOne;
110            }
111
112            [MethodImpl(MethodImplOptions.Synchronized)]
113            set
114            {
115                this.inputVariableOne = value;
116                lastInputWasFunction = false;
117                OnPropertyChanged("InputOne");
118                // clean inputOne
119                inputOneFlag = 1;
120            }
121        }
122
123        [PropertyInfo(Direction.InputData, "Function Variable Two (i_2.j)", "Input a boolean value to be processed by the function", "", false, true, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
124        public bool[] InputTwo
125        {
126            [MethodImpl(MethodImplOptions.Synchronized)]
127            get
128            {
129                return this.inputVariableTwo;
130            }
131
132            [MethodImpl(MethodImplOptions.Synchronized)]
133            set
134            {
135                this.inputVariableTwo = value;
136                lastInputWasFunction = false;
137                OnPropertyChanged("InputTwo");
138                // clean inputOne
139                inputTwoFlag = 1;
140            }
141        }
142
143        [PropertyInfo(Direction.InputData, "Function Variable Three (i_3.j)", "Input a boolean value to be processed by the function", "", false, true, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
144        public bool[] InputThree
145        {
146            [MethodImpl(MethodImplOptions.Synchronized)]
147            get
148            {
149                return this.inputVariableThree;
150            }
151
152            [MethodImpl(MethodImplOptions.Synchronized)]
153            set
154            {
155                this.inputVariableThree = value;
156                lastInputWasFunction = false;
157                OnPropertyChanged("InputThree");
158                // clean inputOne
159                inputThreeFlag = 1;
160            }
161        }*/
162
163        [PropertyInfo(Direction.OutputData, "Function output", "Output after procesing the given function.", "", false, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
164        public bool Output
165        {
166            [MethodImpl(MethodImplOptions.Synchronized)]
167            get
168            {
169                return output;
170            }
171            set
172            {   // is readonly
173            }
174        }
175
176        #endregion
177
178        #region IPlugin Members
179
180        public void Dispose()
181        {
182            settings.Function = (string)booleanFunctionParserPresentation.textBoxInputFunction.Dispatcher.Invoke(
183                DispatcherPriority.Normal, (DispatcherOperationCallback)delegate
184                {
185                    return booleanFunctionParserPresentation.textBoxInputFunction.Text;
186                }, null);
187            settings.Data = (string)booleanFunctionParserPresentation.textBoxInputData.Dispatcher.Invoke(
188               DispatcherPriority.Normal, (DispatcherOperationCallback)delegate
189               {
190                   return booleanFunctionParserPresentation.textBoxInputData.Text;
191               }, null);
192            settings.FunctionCube = (string)booleanFunctionParserPresentation.textBoxInputFunction2.Dispatcher.Invoke(
193                DispatcherPriority.Normal, (DispatcherOperationCallback)delegate
194                {
195                    return booleanFunctionParserPresentation.textBoxInputFunction2.Text;
196                }, null);
197            settings.DataCube = (string)booleanFunctionParserPresentation.textBoxInputData2.Dispatcher.Invoke(
198               DispatcherPriority.Normal, (DispatcherOperationCallback)delegate
199               {
200                   return booleanFunctionParserPresentation.textBoxInputData2.Text;
201               }, null);
202        }
203
204        public void Execute()
205        {
206            try
207            {
208                // do calculation only, if all input flags are clean (= 1) or last event was from the function and all inputs are dirty (= 0)
209                int sumOfFlags = 0;
210                //string allFlags = null;
211                foreach (int flag in additionalInputsFlag) {
212                    sumOfFlags += flag;
213                    //allFlags += flag.ToString();
214                }
215                //GuiLogMessage("sumOfFlags: " + sumOfFlags + ", addIFl: " + allFlags, NotificationLevel.Info);
216
217                //if (sumOfFlags == additionalInputsFlag.Length || (lastInputWasFunction == true && sumOfFlags == 0))
218                if (sumOfFlags == additionalInputsFlag.Length)
219                {
220                    // set all flags to zero
221                    for (int flagIteration = 0; flagIteration < additionalInputsFlag.Length; flagIteration++)
222                    {
223                        additionalInputsFlag[flagIteration] = 0;
224                    }
225                    // revert also state of inputFunction flag
226                    lastInputWasFunction = false;
227
228                    int intOutput = ParseBooleanFunction(null, null);
229                    if (intOutput == -1) return;
230                    else
231                    {
232                        output = Convert.ToBoolean(intOutput);
233                        OnPropertyChanged("Output");
234                    }
235                }
236            }
237            catch (Exception exception)
238            {
239                GuiLogMessage(exception.Message, NotificationLevel.Error);
240            }
241            finally
242            {
243                ProgressChanged(1, 1);
244            }
245        }
246
247        public void Initialize()
248        {
249            if (booleanFunctionParserPresentation.textBoxInputFunction != null)
250                booleanFunctionParserPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
251                {
252                    booleanFunctionParserPresentation.textBoxInputFunction.Text = settings.Function;
253                }, null);
254            if (booleanFunctionParserPresentation.textBoxInputData != null)
255                booleanFunctionParserPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
256                {
257                    booleanFunctionParserPresentation.textBoxInputData.Text = settings.Data;
258                }, null);
259            if (booleanFunctionParserPresentation.textBoxInputFunction2 != null)
260                booleanFunctionParserPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
261                {
262                    booleanFunctionParserPresentation.textBoxInputFunction2.Text = settings.FunctionCube;
263                }, null);
264            if (booleanFunctionParserPresentation.textBoxInputData2 != null)
265                booleanFunctionParserPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
266                {
267                    booleanFunctionParserPresentation.textBoxInputData2.Text = settings.DataCube;
268                }, null);
269            booleanFunctionParserPresentation.SwitchCubeView(settings.UseBFPforCube);
270        }
271
272        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
273        private void GuiLogMessage(string message, NotificationLevel logLevel)
274        {
275            EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(message, this, logLevel));
276        }
277
278        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
279        private void ProgressChanged(double value, double max)
280        {
281            EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(value, max));
282        }
283
284        public event StatusChangedEventHandler OnPluginStatusChanged;
285
286        // catches PropertyChanged event from settings
287        void settings_PropertyChanged(object sender, PropertyChangedEventArgs e)
288        {
289            // if the count of inputs has been change, renew all inputs
290            if (e.PropertyName == "CountOfInputs")
291            {
292                CreateInputOutput(true);
293            }
294            else if (e.PropertyName == "UseBFPforCube")
295            {
296                booleanFunctionParserPresentation.SwitchCubeView(settings.UseBFPforCube);
297            }
298        }
299
300        public void Pause()
301        {
302           
303        }
304
305        public void PostExecution()
306        {
307           
308        }
309
310        public void PreExecution()
311        {
312           
313        }
314
315        public void CreateInputOutput(bool announcePropertyChange)
316        {
317            try
318            {
319                DicDynamicProperties.Clear();
320                inputs = 0;
321                additionalInputsFlag = new int[settings.CountOfInputs];
322                for (int i = 0; i < settings.CountOfInputs; i++)
323                {
324                    AddInput("Input " + i, "Boolean[] Input " + i);
325                    additionalInputsFlag[i] = 0;
326                }
327                // Event should be fired even if no additional inputs are set, because when
328                // setting back to zero editor needs the event to remove the input.
329                if (announcePropertyChange) DynamicPropertiesChanged();
330            }
331            catch (Exception exception)
332            {
333                GuiLogMessage(exception.Message, NotificationLevel.Error);
334            }
335        }
336
337        /* *******************************************************************************
338         * Main function to be used in the M/S mode and in general
339         * inputs:
340         * string function - the boolean function to be computed with variables
341         * bool[] inputVariables - a boolean array to replace the variables
342         *
343         * ouput:
344         * int - the one bit long result of the given function; returns -1 on any failure
345         * *******************************************************************************
346        */
347        public int ParseBooleanFunction(bool[] inputVariables, bool[] dataTwo)
348        {
349            string function = null;
350            // if function is empty, use input funtion (could happen in case of a master/slave call) or quickwatch function
351            // get quickwatch function
352            string quickwatchFunction = (string)this.booleanFunctionParserPresentation.textBoxInputFunction.Dispatcher.Invoke(DispatcherPriority.Normal, (DispatcherOperationCallback)delegate
353            {
354                return booleanFunctionParserPresentation.textBoxInputFunction.Text;
355            }, booleanFunctionParserPresentation);
356            string quickwatchFunctionCube = (string)this.booleanFunctionParserPresentation.textBoxInputFunction2.Dispatcher.Invoke(DispatcherPriority.Normal, (DispatcherOperationCallback)delegate
357            {
358                return booleanFunctionParserPresentation.textBoxInputFunction2.Text;
359            }, booleanFunctionParserPresentation);
360
361            if (inputFunction != null && inputFunction != string.Empty)
362                function = inputFunction;
363            else if (quickwatchFunction != null && quickwatchFunction != string.Empty)
364                function = quickwatchFunction;
365            else if (quickwatchFunctionCube != null && quickwatchFunctionCube != string.Empty && settings.UseBFPforCube == true)
366                function = quickwatchFunctionCube;
367            else
368                return -1;
369
370            // replace variables with data
371            string strExpression = ReplaceVariables(function, inputVariables, dataTwo);
372            // test if function is valid
373            string strExpressionTested = TestFunction(strExpression);
374            if (strExpressionTested == "foo")
375            {
376                GuiLogMessage(strExpression + " is not a binary expression (e.g. 1 + 0 * 1). Aborting now.", NotificationLevel.Error);
377                return -1;
378            }
379            else
380            {
381                //GuiLogMessage("Your expression with variables replaced: " + strExpression, NotificationLevel.Info);
382                output = EvaluateString(strExpressionTested);
383            }
384            // Just testing
385            //bool[] test = (bool[])getCurrentValue("Input 2");
386            //GuiLogMessage("InputTest: " + test[0].ToString(), NotificationLevel.Info);
387
388            return Convert.ToInt32(output);
389        }
390
391        #region private functions
392
393        private string makeStarsInText(Match m)
394        {
395            // Get the matched string.
396            string x = m.ToString();
397            // insert an * before the i
398            x = x.Insert(x.Length - 1, "*");
399            // a new star is born
400            return x;
401        }
402
403        private string ReplaceVariables(string strExpressionWithVariables, bool[] externDataOne, bool []externDataTwo)
404        {
405            // remove spaces
406            string strExpression = strExpressionWithVariables.Replace(" ", "");
407            // add * if there aren't any (and should be)
408            // example: x^2+x^2x^3 ==> x^2+x^2*x^3
409            Regex makeStars = new Regex("([0-9])i");
410            strExpression = makeStars.Replace(strExpression, new MatchEvaluator(makeStarsInText));
411
412            // replace variables with value and get numeric values from boolean inputs (if there are any)
413            /*if (inputOneFlag == 1 && inputVariableOne != null)
414            {
415                char[] strInputVariableOne = new char[inputVariableOne.Length];
416                for (int i = inputVariableOne.Length - 1; i >= 0; i--)
417                {
418                    // get numeric values from bool inputs
419                    strInputVariableOne[i] = inputVariableOne[i] ? '1' : '0';
420                    // replace variables with value
421                    string replacement = "i_1." + i;
422                    strExpression = strExpression.Replace(replacement, strInputVariableOne[i].ToString());
423                }
424            }
425            if (inputTwoFlag == 1 && inputVariableTwo != null)
426            {
427                char[] strInputVariableTwo = new char[inputVariableTwo.Length];
428                for (int i = inputVariableTwo.Length - 1; i >= 0; i--)
429                {
430                    // get numeric values from bool inputs
431                    strInputVariableTwo[i] = inputVariableTwo[i] ? '1' : '0';
432                    string replacement = "i_2." + i;
433                    strExpression = strExpression.Replace(replacement, strInputVariableTwo[i].ToString());
434                }
435            }
436            if (inputThreeFlag == 1 && inputVariableThree != null)
437            {
438                char[] strInputVariableThree = new char[inputVariableThree.Length];
439                for (int i = inputVariableThree.Length - 1; i >= 0; i--)
440                {
441                    // get numeric values from bool inputs
442                    strInputVariableThree[i] = inputVariableThree[i] ? '1' : '0';
443                    string replacement = "i_3." + i;
444                    strExpression = strExpression.Replace(replacement, strInputVariableThree[i].ToString());
445                }
446            }*/
447            // replace additional inputs data (if there are any)
448            for (int i = 0; i < inputs; i++)
449            {
450                if (getCurrentValue("Input " + i) != null)
451                {
452                    bool[] additionalTempValueBool = (bool[])methodGetValue("Input " + i);
453                    char[] strInputVariableAditionalTemp = new char[additionalTempValueBool.Length];
454                    for (int j = additionalTempValueBool.Length - 1; j >= 0; j--)
455                    {
456                        // get numeric values from bool inputs
457                        strInputVariableAditionalTemp[j] = additionalTempValueBool[j] ? '1' : '0';
458                        string replacement = "i_" + (i) + "." + j;
459                        strExpression = strExpression.Replace(replacement, strInputVariableAditionalTemp[j].ToString());
460                    }
461                }
462            }
463            // replace extern data (i_0.*) (if there is any)
464            if (externDataOne != null && externDataOne.Length != 0)
465            {
466                char[] strInputVariableExtern = new char[externDataOne.Length];
467                for (int i = strInputVariableExtern.Length - 1; i >= 0; i--)
468                {
469                    // get numeric values from bool inputs
470                    strInputVariableExtern[i] = externDataOne[i] ? '1' : '0';
471                    string replacement = "i_0." + i;
472                    strExpression = strExpression.Replace(replacement, strInputVariableExtern[i].ToString());
473                }
474            }
475            // replace quickwatch data (i_q.*) (if there is any)
476            if (settings.UseBFPforCube == false)
477            {
478                string quickwatchData = (string)this.booleanFunctionParserPresentation.textBoxInputData.Dispatcher.Invoke(DispatcherPriority.Normal, (DispatcherOperationCallback)delegate
479                {
480                    return booleanFunctionParserPresentation.textBoxInputData.Text;
481                }, booleanFunctionParserPresentation);
482                if (quickwatchData != null && quickwatchData != string.Empty)
483                {
484                    char[] strInputVariableQuickwatch = new char[quickwatchData.Length];
485                    strInputVariableQuickwatch = quickwatchData.ToCharArray();
486                    for (int i = strInputVariableQuickwatch.Length - 1; i >= 0 ; i--)
487                    {
488                        string replacement = "i_q." + i;
489                        strExpression = strExpression.Replace(replacement, strInputVariableQuickwatch[i].ToString());
490                    }
491                }
492            } else if (settings.UseBFPforCube == true)
493            {
494                string quickwatchDataCube = (string)this.booleanFunctionParserPresentation.textBoxInputData2.Dispatcher.Invoke(DispatcherPriority.Normal, (DispatcherOperationCallback)delegate
495                {
496                    return booleanFunctionParserPresentation.textBoxInputData2.Text;
497                }, booleanFunctionParserPresentation);
498                // Cube Attack Online Phase
499                if (externDataTwo != null && externDataTwo.Length != 0)
500                {
501                    char[] strInputVariableExtern = new char[externDataOne.Length];
502                    for (int i = strInputVariableExtern.Length - 1; i >= 0; i--)
503                    {
504                        // get numeric values from bool inputs
505                        strInputVariableExtern[i] = externDataTwo[i] ? '1' : '0';
506                        string replacement = "i_q." + i;
507                        strExpression = strExpression.Replace(replacement, strInputVariableExtern[i].ToString());
508                    }
509                }
510                // Cube Attack Preprocessing Phase
511                else if (quickwatchDataCube != null && quickwatchDataCube != string.Empty)
512                {
513                    char[] strInputVariableQuickwatch = new char[quickwatchDataCube.Length];
514                    strInputVariableQuickwatch = quickwatchDataCube.ToCharArray();
515                    for (int i = strInputVariableQuickwatch.Length - 1; i >= 0; i--)
516                    {
517                        string replacement = "i_q." + i;
518                        strExpression = strExpression.Replace(replacement, strInputVariableQuickwatch[i].ToString());
519                    }
520                }
521               
522            }
523           
524
525            // replace AND, NAND, OR, NOR, XOR, NXOR with symbols
526            // NAND => -
527            strExpression = strExpression.Replace("NAND", "-");
528            // AND => *
529            strExpression = strExpression.Replace("AND", "*");
530
531            // NOR => _
532            strExpression = strExpression.Replace("NOR", "_");
533
534            // NXOR => °
535            strExpression = strExpression.Replace("NXOR", "°");
536            // XOR => *
537            strExpression = strExpression.Replace("XOR", "+");
538
539            // OR => |
540            strExpression = strExpression.Replace("OR", "|");
541
542            // replace ^ and & with symbols
543            // ^ => XOR => +
544            strExpression = strExpression.Replace("^", "+");
545
546            // & => AND => *
547            strExpression = strExpression.Replace("&", "*");
548
549            return strExpression;
550        }
551
552        // validates expression in function
553        private string TestFunction(string strExpression)
554        {
555            // remove spaces from given expression
556            string strExpressionNormalized = strExpression.Replace(" ", "");
557            char tab = '\u0009';
558            strExpressionNormalized = strExpressionNormalized.Replace(tab.ToString(), "");
559
560            // test if count of '(' equals count of ')'
561            Regex countLeftPRegEx = new Regex(@"\(");
562            Regex countRightPRegEx = new Regex(@"\)");
563            if (countLeftPRegEx.Matches(strExpressionNormalized).Count != countRightPRegEx.Matches(strExpressionNormalized).Count)
564            {
565                GuiLogMessage("The count of ( is not equal to the count of )", NotificationLevel.Error);
566                return "foo";
567            }
568
569            // test expression
570            Regex objBoolExpression = new Regex(@"([\(]?[\!]?)([0-1]([\\*]|[\\+]|[\\|]|[\\-]|[_]|[°]|[v]|[\\^]|[\\!])+[0-1]{1})");
571            if (!objBoolExpression.IsMatch(strExpressionNormalized))
572            {
573                GuiLogMessage("That's not a legal function", NotificationLevel.Error);
574                return "foo";
575            }
576            else
577            {
578                return strExpressionNormalized;
579            }
580        }
581
582        // solves string with variables replaced by values
583        private bool EvaluateString(string function)
584        {
585            string temp;
586
587            // test for parenthesis
588            int positionLeftParenthesis = function.IndexOf("(");
589            int positionRightParenthesis = function.LastIndexOf(")");
590
591            //GuiLogMessage("Position ( & ): " + positionLeftParenthesis + ", " + positionRightParenthesis, NotificationLevel.Debug);
592
593            if (positionLeftParenthesis != -1 && positionRightParenthesis != -1)
594            {
595                temp = function.Substring(positionLeftParenthesis + 1, positionRightParenthesis - positionLeftParenthesis - 1);
596                //GuiLogMessage("New function: " + temp, NotificationLevel.Debug);
597                bool parenthesisResult = EvaluateString(temp);
598                function = function.Remove(positionLeftParenthesis, positionRightParenthesis - positionLeftParenthesis + 1);
599                function = function.Insert(positionLeftParenthesis, Convert.ToInt32(parenthesisResult).ToString());
600            }
601
602            //GuiLogMessage("Function after '(':  " + function, NotificationLevel.Debug);
603
604            // test for exclamation mark aka 'NOT'
605            int positionExclamationMark = function.IndexOf("!");
606
607            while (positionExclamationMark != -1)
608            {
609                //GuiLogMessage("Position of '!': " + positionExclamationMark, NotificationLevel.Debug);
610
611                // remove exclamation mark
612                function = function.Remove(positionExclamationMark, 1);
613
614                // invert the binary digit following the excl. mark
615                string toInvert = function.Substring(positionExclamationMark, 1);
616                //GuiLogMessage("toInvert: " + toInvert, NotificationLevel.Debug);
617
618                if (toInvert == "1") toInvert = "0";
619                else toInvert = "1";
620                // remove old value
621                function = function.Remove(positionExclamationMark, 1);
622                // insert new value
623                function = function.Insert(positionExclamationMark, toInvert);
624
625                // any other NOTs in there?
626                positionExclamationMark = function.IndexOf("!");
627            }
628
629            //GuiLogMessage("Function after '!':  " + function, NotificationLevel.Debug);
630
631            // test for AND aka '*'
632            int positionAND = function.IndexOf("*");
633
634            while (positionAND != -1)
635            {
636                //GuiLogMessage("Position of '*': " + positionAND, NotificationLevel.Debug);
637
638                // get both operands
639                string operator1 = function.Substring(positionAND - 1, 1);
640                string operator2 = function.Substring(positionAND + 1, 1);
641                //GuiLogMessage("op1 and op2: " + operator1 + ", " + operator2, NotificationLevel.Info);
642
643                string sum = null;
644                try
645                {
646                    sum = (Int32.Parse(operator1) & Int32.Parse(operator2)).ToString();
647                }
648                catch (Exception ex)
649                {
650                    GuiLogMessage("sum fehlgeschlagen:", NotificationLevel.Info);
651                    GuiLogMessage("op1 and op2: " + operator1 + ", " + operator2, NotificationLevel.Info);
652                }
653               
654                //GuiLogMessage("sum: " + sum, NotificationLevel.Debug);
655
656                // remove old values
657                function = function.Remove(positionAND - 1, 3);
658
659                // insert new value
660                function = function.Insert(positionAND - 1, sum);
661                //GuiLogMessage("function: " + function, NotificationLevel.Debug);
662
663                // any other ANDs in there?
664                positionAND = function.IndexOf("*");
665            }
666
667            // test for XOR aka '+'
668            int positionXOR = function.IndexOf("+");
669
670            while (positionXOR != -1)
671            {
672                //GuiLogMessage("Position of '+': " + positionXOR, NotificationLevel.Debug);
673
674                // get both operands
675                string operator1 = function.Substring(positionXOR - 1, 1);
676                string operator2 = function.Substring(positionXOR + 1, 1);
677                //GuiLogMessage("op1 and op2: " + operator1 + ", " + operator2, NotificationLevel.Debug);
678
679                string product = (Int32.Parse(operator1) ^ Int32.Parse(operator2)).ToString();
680               
681                //GuiLogMessage("product: " + product, NotificationLevel.Debug);
682
683                // remove old values
684                function = function.Remove(positionXOR - 1, 3);
685
686                // insert new value
687                function = function.Insert(positionXOR - 1, product);
688                //GuiLogMessage("function: " + function, NotificationLevel.Debug);
689
690                // any other XORs in there?
691                positionXOR = function.IndexOf("+");
692            }
693
694            bool result = Convert.ToBoolean(Int32.Parse(function));
695
696            return result;
697        }
698
699        private object getCurrentValue(string name)
700        {
701            if (DicDynamicProperties.ContainsKey(name))
702            {
703                return DicDynamicProperties[name].Value;
704            }
705            return null;
706        }
707       
708        private void AddInput(string name, string toolTip)
709        {
710            inputs++;
711            if (name == null || name == string.Empty) name = "Input " + inputs;
712            DicDynamicProperties.Add(name,
713              new DynamicProperty(name, typeof(bool[]),
714                new PropertyInfoAttribute(Direction.InputData, name, toolTip, "", false, true, DisplayLevel.Beginner, QuickWatchFormat.None, null))
715            );
716        }
717
718        #endregion
719
720        [MethodImpl(MethodImplOptions.Synchronized)]
721        public object methodGetValue(string propertyKey)
722        {
723            // set flag of input <-- is now set in Execute()
724            //int numberInPropertyKey = Int32.Parse(propertyKey.Substring(propertyKey.Length - 1));
725            //additionalInputsFlag[numberInPropertyKey] = 0;
726
727            return getCurrentValue(propertyKey); // QuickWatchDataCall to Input values
728        }
729
730        [MethodImpl(MethodImplOptions.Synchronized)]
731        public void methodSetValue(string propertyKey, object value)
732        {
733            try
734            {
735                if (DicDynamicProperties.ContainsKey(propertyKey))
736                {
737                    DicDynamicProperties[propertyKey].Value = value;
738                    // set flag of input
739                    int numberInPropertyKey = Int32.Parse(propertyKey.Substring(6));
740                    additionalInputsFlag[numberInPropertyKey] = 1;
741                }
742
743                OnPropertyChanged(propertyKey);
744            }
745            catch (Exception ex)
746            {
747                GuiLogMessage(ex.Message, NotificationLevel.Error);
748            }
749        }
750
751        public System.Windows.Controls.UserControl QuickWatchPresentation
752        {
753            get { return Presentation; }
754        }
755
756        public UserControl Presentation { get; private set; }
757
758        public ISettings Settings
759        {
760            get
761            {
762                return (ISettings)this.settings;
763            }
764            set
765            {
766                this.settings = (BooleanFunctionParserSettings)value;
767            }
768        }
769
770        public void Stop()
771        {
772           
773        }
774
775        public Dictionary<string, DynamicProperty> dicDynamicProperties = new Dictionary<string, DynamicProperty>();
776
777        [DynamicPropertyInfo("methodGetValue", "methodSetValue", "CanChangeDynamicProperty", "OnDynamicPropertiesChanged", "CanSendPropertiesChangedEvent")]
778        public Dictionary<string, DynamicProperty> DicDynamicProperties
779        {
780            get { return dicDynamicProperties; }
781            set { dicDynamicProperties = value; }
782        }
783
784        public bool CanChangeDynamicProperty
785        {
786            get { return settings.CanChangeProperty; }
787            set { settings.CanChangeProperty = value; }
788        }
789
790        public bool CanSendPropertiesChangedEvent
791        {
792            get { return canSendPropertiesChangedEvent; }
793            set { canSendPropertiesChangedEvent = value; }
794        }
795
796        private void DynamicPropertiesChanged()
797        {
798            if (OnDynamicPropertiesChanged != null) OnDynamicPropertiesChanged(this);
799        }
800
801        #endregion
802
803        #region INotifyPropertyChanged Members
804
805        public event PropertyChangedEventHandler PropertyChanged;
806
807        public void OnPropertyChanged(string name)
808        {
809            if (PropertyChanged != null)
810            {
811                PropertyChanged(this, new PropertyChangedEventArgs(name));
812            }
813        }
814
815        #endregion
816
817        #region IControl
818
819        private IControlSolveFunction bfpSlave;
820        [PropertyInfo(Direction.ControlSlave, "BFP Slave", "Direct access to BFP.", "", DisplayLevel.Beginner)]
821        public IControlSolveFunction BFPSlave
822        {
823            get
824            {
825                if (bfpSlave == null)
826                    bfpSlave = new BFPControl(this);
827                return bfpSlave;
828            }
829        }
830
831        #endregion
832    }
833
834    #region BFPControl : IControlSolveFunction
835
836    public class BFPControl : IControlSolveFunction
837    {
838        public event IControlStatusChangedEventHandler OnStatusChanged;
839        private BooleanFunctionParser plugin;
840
841        public BFPControl(BooleanFunctionParser Plugin)
842        {
843            this.plugin = Plugin;
844        }
845
846        #region IControlEncryption Members
847
848        // here comes the slave side implementation of SolveFunction
849        public int SolveFunction(bool[] dataOne, bool[] dataTwo)
850        {
851            int resultInt;
852
853            // the result is computed by calling the ParseBooleanFunction (step into it with F11)
854            // returns -1 on error (e.g. not a valid function)
855            resultInt = plugin.ParseBooleanFunction(dataOne, dataTwo);
856
857            return resultInt;
858        }
859
860        #endregion
861    }
862
863    #endregion
864}
Note: See TracBrowser for help on using the repository browser.