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

Last change on this file since 705 was 705, checked in by Thomas Schmid, 12 years ago
  • added new IControl event IControlStatusChangedEventHandler
File size: 35.2 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(inputFunction, null, 0);
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(string function, bool[] inputVariables, int switchInputs)
348        {
349            // if function is empty, use input funtion (could happen in case of a master/slave call) or quickwatch function
350            // get quickwatch function
351            string quickwatchFunction = (string)this.booleanFunctionParserPresentation.textBoxInputFunction.Dispatcher.Invoke(DispatcherPriority.Normal, (DispatcherOperationCallback)delegate
352            {
353                return booleanFunctionParserPresentation.textBoxInputFunction.Text;
354            }, booleanFunctionParserPresentation);
355            string quickwatchFunctionCube = (string)this.booleanFunctionParserPresentation.textBoxInputFunction2.Dispatcher.Invoke(DispatcherPriority.Normal, (DispatcherOperationCallback)delegate
356            {
357                return booleanFunctionParserPresentation.textBoxInputFunction2.Text;
358            }, booleanFunctionParserPresentation);
359
360            if (function == null || function == string.Empty)
361            {
362                if (inputFunction != null && inputFunction != string.Empty)
363                    function = inputFunction;
364                else if (quickwatchFunction != null && quickwatchFunction != string.Empty && switchInputs == 1)
365                    function = quickwatchFunction;
366                else if (quickwatchFunctionCube != null && quickwatchFunctionCube != string.Empty && switchInputs == 2)
367                    function = quickwatchFunctionCube;
368                else if (quickwatchFunction != null && quickwatchFunction != string.Empty)
369                    function = quickwatchFunction;
370                else
371                    return -1;
372            }
373            // replace variables with data
374            string strExpression = ReplaceVariables(function, inputVariables, switchInputs);
375            // test if function is valid
376            string strExpressionTested = TestFunction(strExpression);
377            if (strExpressionTested == "foo")
378            {
379                GuiLogMessage(strExpression + " is not a binary expression (e.g. 1 + 0 * 1). Aborting now.", NotificationLevel.Error);
380                return -1;
381            }
382            else
383            {
384                //GuiLogMessage("Your expression with variables replaced: " + strExpression, NotificationLevel.Info);
385                output = EvaluateString(strExpressionTested);
386            }
387            // Just testing
388            //bool[] test = (bool[])getCurrentValue("Input 2");
389            //GuiLogMessage("InputTest: " + test[0].ToString(), NotificationLevel.Info);
390
391            return Convert.ToInt32(output);
392        }
393
394        #region private functions
395
396        private string makeStarsInText(Match m)
397        {
398            // Get the matched string.
399            string x = m.ToString();
400            // insert an * before the i
401            x = x.Insert(x.Length - 1, "*");
402            // a new star is born
403            return x;
404        }
405
406        private string ReplaceVariables(string strExpressionWithVariables, bool[] externData, int switchData)
407        {
408            // remove spaces
409            string strExpression = strExpressionWithVariables.Replace(" ", "");
410            // add * if there aren't any (and should be)
411            // example: x^2+x^2x^3 ==> x^2+x^2*x^3
412            Regex makeStars = new Regex("([0-9])i");
413            strExpression = makeStars.Replace(strExpression, new MatchEvaluator(makeStarsInText));
414
415            // replace variables with value and get numeric values from boolean inputs (if there are any)
416            /*if (inputOneFlag == 1 && inputVariableOne != null)
417            {
418                char[] strInputVariableOne = new char[inputVariableOne.Length];
419                for (int i = inputVariableOne.Length - 1; i >= 0; i--)
420                {
421                    // get numeric values from bool inputs
422                    strInputVariableOne[i] = inputVariableOne[i] ? '1' : '0';
423                    // replace variables with value
424                    string replacement = "i_1." + i;
425                    strExpression = strExpression.Replace(replacement, strInputVariableOne[i].ToString());
426                }
427            }
428            if (inputTwoFlag == 1 && inputVariableTwo != null)
429            {
430                char[] strInputVariableTwo = new char[inputVariableTwo.Length];
431                for (int i = inputVariableTwo.Length - 1; i >= 0; i--)
432                {
433                    // get numeric values from bool inputs
434                    strInputVariableTwo[i] = inputVariableTwo[i] ? '1' : '0';
435                    string replacement = "i_2." + i;
436                    strExpression = strExpression.Replace(replacement, strInputVariableTwo[i].ToString());
437                }
438            }
439            if (inputThreeFlag == 1 && inputVariableThree != null)
440            {
441                char[] strInputVariableThree = new char[inputVariableThree.Length];
442                for (int i = inputVariableThree.Length - 1; i >= 0; i--)
443                {
444                    // get numeric values from bool inputs
445                    strInputVariableThree[i] = inputVariableThree[i] ? '1' : '0';
446                    string replacement = "i_3." + i;
447                    strExpression = strExpression.Replace(replacement, strInputVariableThree[i].ToString());
448                }
449            }*/
450            // replace additional inputs data (if there are any)
451            for (int i = 0; i < inputs; i++)
452            {
453                if (getCurrentValue("Input " + i) != null)
454                {
455                    bool[] additionalTempValueBool = (bool[])methodGetValue("Input " + i);
456                    char[] strInputVariableAditionalTemp = new char[additionalTempValueBool.Length];
457                    for (int j = additionalTempValueBool.Length - 1; j >= 0; j--)
458                    {
459                        // get numeric values from bool inputs
460                        strInputVariableAditionalTemp[j] = additionalTempValueBool[j] ? '1' : '0';
461                        string replacement = "i_" + (i) + "." + j;
462                        strExpression = strExpression.Replace(replacement, strInputVariableAditionalTemp[j].ToString());
463                    }
464                }
465            }
466            // replace extern data (i_0.*) (if there is any)
467            if (externData != null && externData.Length != 0)
468            {
469                char[] strInputVariableExtern = new char[externData.Length];
470                for (int i = strInputVariableExtern.Length - 1; i >= 0; i--)
471                {
472                    // get numeric values from bool inputs
473                    strInputVariableExtern[i] = externData[i] ? '1' : '0';
474                    string replacement = "i_0." + i;
475                    strExpression = strExpression.Replace(replacement, strInputVariableExtern[i].ToString());
476                }
477            }
478            // replace quickwatch data (i_q.*) (if there is any)
479            if (switchData == 1 || switchData == 0)
480            {
481                string quickwatchData = (string)this.booleanFunctionParserPresentation.textBoxInputData.Dispatcher.Invoke(DispatcherPriority.Normal, (DispatcherOperationCallback)delegate
482                {
483                    return booleanFunctionParserPresentation.textBoxInputData.Text;
484                }, booleanFunctionParserPresentation);
485                if (quickwatchData == null || quickwatchData != string.Empty)
486                {
487                    char[] strInputVariableQuickwatch = new char[quickwatchData.Length];
488                    strInputVariableQuickwatch = quickwatchData.ToCharArray();
489                    for (int i = strInputVariableQuickwatch.Length - 1; i >= 0 ; i--)
490                    {
491                        string replacement = "i_q." + i;
492                        strExpression = strExpression.Replace(replacement, strInputVariableQuickwatch[i].ToString());
493                    }
494                }
495            } if (switchData == 2)
496            {
497                string quickwatchDataCube = (string)this.booleanFunctionParserPresentation.textBoxInputData2.Dispatcher.Invoke(DispatcherPriority.Normal, (DispatcherOperationCallback)delegate
498                {
499                    return booleanFunctionParserPresentation.textBoxInputData2.Text;
500                }, booleanFunctionParserPresentation);
501                if (quickwatchDataCube == null || quickwatchDataCube != string.Empty)
502                {
503                    char[] strInputVariableQuickwatch = new char[quickwatchDataCube.Length];
504                    strInputVariableQuickwatch = quickwatchDataCube.ToCharArray();
505                    for (int i = strInputVariableQuickwatch.Length - 1; i >= 0; i--)
506                    {
507                        string replacement = "i_q." + i;
508                        strExpression = strExpression.Replace(replacement, strInputVariableQuickwatch[i].ToString());
509                    }
510                }
511            }
512           
513
514            // replace AND, NAND, OR, NOR, XOR, NXOR with symbols
515            // NAND => -
516            strExpression = strExpression.Replace("NAND", "-");
517            // AND => *
518            strExpression = strExpression.Replace("AND", "*");
519
520            // NOR => _
521            strExpression = strExpression.Replace("NOR", "_");
522
523            // NXOR => °
524            strExpression = strExpression.Replace("NXOR", "°");
525            // XOR => *
526            strExpression = strExpression.Replace("XOR", "+");
527
528            // OR => |
529            strExpression = strExpression.Replace("OR", "|");
530
531            // replace ^ and & with symbols
532            // ^ => XOR => +
533            strExpression = strExpression.Replace("^", "+");
534
535            // & => AND => *
536            strExpression = strExpression.Replace("&", "*");
537
538            return strExpression;
539        }
540
541        // validates expression in function
542        private string TestFunction(string strExpression)
543        {
544            // remove spaces from given expression
545            string strExpressionNormalized = strExpression.Replace(" ", "");
546            char tab = '\u0009';
547            strExpressionNormalized = strExpressionNormalized.Replace(tab.ToString(), "");
548
549            // test if count of '(' equals count of ')'
550            Regex countLeftPRegEx = new Regex(@"\(");
551            Regex countRightPRegEx = new Regex(@"\)");
552            if (countLeftPRegEx.Matches(strExpressionNormalized).Count != countRightPRegEx.Matches(strExpressionNormalized).Count)
553            {
554                GuiLogMessage("The count of ( is not equal to the count of )", NotificationLevel.Error);
555                return "foo";
556            }
557
558            // test expression
559            Regex objBoolExpression = new Regex(@"([\(]?[\!]?)([0-1]([\\*]|[\\+]|[\\|]|[\\-]|[_]|[°]|[v]|[\\^]|[\\!])+[0-1]{1})");
560            if (!objBoolExpression.IsMatch(strExpressionNormalized))
561            {
562                GuiLogMessage("That's not a legal function", NotificationLevel.Error);
563                return "foo";
564            }
565            else
566            {
567                return strExpressionNormalized;
568            }
569        }
570
571        // solves string with variables replaced by values
572        private bool EvaluateString(string function)
573        {
574            string temp;
575
576            // test for parenthesis
577            int positionLeftParenthesis = function.IndexOf("(");
578            int positionRightParenthesis = function.LastIndexOf(")");
579
580            //GuiLogMessage("Position ( & ): " + positionLeftParenthesis + ", " + positionRightParenthesis, NotificationLevel.Debug);
581
582            if (positionLeftParenthesis != -1 && positionRightParenthesis != -1)
583            {
584                temp = function.Substring(positionLeftParenthesis + 1, positionRightParenthesis - positionLeftParenthesis - 1);
585                //GuiLogMessage("New function: " + temp, NotificationLevel.Debug);
586                bool parenthesisResult = EvaluateString(temp);
587                function = function.Remove(positionLeftParenthesis, positionRightParenthesis - positionLeftParenthesis + 1);
588                function = function.Insert(positionLeftParenthesis, Convert.ToInt32(parenthesisResult).ToString());
589            }
590
591            //GuiLogMessage("Function after '(':  " + function, NotificationLevel.Debug);
592
593            // test for exclamation mark aka 'NOT'
594            int positionExclamationMark = function.IndexOf("!");
595
596            while (positionExclamationMark != -1)
597            {
598                //GuiLogMessage("Position of '!': " + positionExclamationMark, NotificationLevel.Debug);
599
600                // remove exclamation mark
601                function = function.Remove(positionExclamationMark, 1);
602
603                // invert the binary digit following the excl. mark
604                string toInvert = function.Substring(positionExclamationMark, 1);
605                //GuiLogMessage("toInvert: " + toInvert, NotificationLevel.Debug);
606
607                if (toInvert == "1") toInvert = "0";
608                else toInvert = "1";
609                // remove old value
610                function = function.Remove(positionExclamationMark, 1);
611                // insert new value
612                function = function.Insert(positionExclamationMark, toInvert);
613
614                // any other NOTs in there?
615                positionExclamationMark = function.IndexOf("!");
616            }
617
618            //GuiLogMessage("Function after '!':  " + function, NotificationLevel.Debug);
619
620            // test for AND aka '*'
621            int positionAND = function.IndexOf("*");
622
623            while (positionAND != -1)
624            {
625                //GuiLogMessage("Position of '*': " + positionAND, NotificationLevel.Debug);
626
627                // get both operands
628                string operator1 = function.Substring(positionAND - 1, 1);
629                string operator2 = function.Substring(positionAND + 1, 1);
630                //GuiLogMessage("op1 and op2: " + operator1 + ", " + operator2, NotificationLevel.Info);
631
632                string sum = null;
633                try
634                {
635                    sum = (Int32.Parse(operator1) & Int32.Parse(operator2)).ToString();
636                }
637                catch (Exception ex)
638                {
639                    GuiLogMessage("sum fehlgeschlagen:", NotificationLevel.Info);
640                    GuiLogMessage("op1 and op2: " + operator1 + ", " + operator2, NotificationLevel.Info);
641                }
642               
643                //GuiLogMessage("sum: " + sum, NotificationLevel.Debug);
644
645                // remove old values
646                function = function.Remove(positionAND - 1, 3);
647
648                // insert new value
649                function = function.Insert(positionAND - 1, sum);
650                //GuiLogMessage("function: " + function, NotificationLevel.Debug);
651
652                // any other ANDs in there?
653                positionAND = function.IndexOf("*");
654            }
655
656            // test for XOR aka '+'
657            int positionXOR = function.IndexOf("+");
658
659            while (positionXOR != -1)
660            {
661                //GuiLogMessage("Position of '+': " + positionXOR, NotificationLevel.Debug);
662
663                // get both operands
664                string operator1 = function.Substring(positionXOR - 1, 1);
665                string operator2 = function.Substring(positionXOR + 1, 1);
666                //GuiLogMessage("op1 and op2: " + operator1 + ", " + operator2, NotificationLevel.Debug);
667
668                string product = (Int32.Parse(operator1) ^ Int32.Parse(operator2)).ToString();
669               
670                //GuiLogMessage("product: " + product, NotificationLevel.Debug);
671
672                // remove old values
673                function = function.Remove(positionXOR - 1, 3);
674
675                // insert new value
676                function = function.Insert(positionXOR - 1, product);
677                //GuiLogMessage("function: " + function, NotificationLevel.Debug);
678
679                // any other XORs in there?
680                positionXOR = function.IndexOf("+");
681            }
682
683            bool result = Convert.ToBoolean(Int32.Parse(function));
684
685            return result;
686        }
687
688        private object getCurrentValue(string name)
689        {
690            if (DicDynamicProperties.ContainsKey(name))
691            {
692                return DicDynamicProperties[name].Value;
693            }
694            return null;
695        }
696       
697        private void AddInput(string name, string toolTip)
698        {
699            inputs++;
700            if (name == null || name == string.Empty) name = "Input " + inputs;
701            DicDynamicProperties.Add(name,
702              new DynamicProperty(name, typeof(bool[]),
703                new PropertyInfoAttribute(Direction.InputData, name, toolTip, "", false, true, DisplayLevel.Beginner, QuickWatchFormat.None, null))
704            );
705        }
706
707        #endregion
708
709        [MethodImpl(MethodImplOptions.Synchronized)]
710        public object methodGetValue(string propertyKey)
711        {
712            // set flag of input <-- is now set in Execute()
713            //int numberInPropertyKey = Int32.Parse(propertyKey.Substring(propertyKey.Length - 1));
714            //additionalInputsFlag[numberInPropertyKey] = 0;
715
716            return getCurrentValue(propertyKey); // QuickWatchDataCall to Input values
717        }
718
719        [MethodImpl(MethodImplOptions.Synchronized)]
720        public void methodSetValue(string propertyKey, object value)
721        {
722            try
723            {
724                if (DicDynamicProperties.ContainsKey(propertyKey))
725                {
726                    DicDynamicProperties[propertyKey].Value = value;
727                    // set flag of input
728                    int numberInPropertyKey = Int32.Parse(propertyKey.Substring(6));
729                    additionalInputsFlag[numberInPropertyKey] = 1;
730                }
731
732                OnPropertyChanged(propertyKey);
733            }
734            catch (Exception ex)
735            {
736                GuiLogMessage(ex.Message, NotificationLevel.Error);
737            }
738        }
739
740        public System.Windows.Controls.UserControl QuickWatchPresentation
741        {
742            get { return Presentation; }
743        }
744
745        public UserControl Presentation { get; private set; }
746
747        public ISettings Settings
748        {
749            get
750            {
751                return (ISettings)this.settings;
752            }
753            set
754            {
755                this.settings = (BooleanFunctionParserSettings)value;
756            }
757        }
758
759        public void Stop()
760        {
761           
762        }
763
764        public Dictionary<string, DynamicProperty> dicDynamicProperties = new Dictionary<string, DynamicProperty>();
765
766        [DynamicPropertyInfo("methodGetValue", "methodSetValue", "CanChangeDynamicProperty", "OnDynamicPropertiesChanged", "CanSendPropertiesChangedEvent")]
767        public Dictionary<string, DynamicProperty> DicDynamicProperties
768        {
769            get { return dicDynamicProperties; }
770            set { dicDynamicProperties = value; }
771        }
772
773        public bool CanChangeDynamicProperty
774        {
775            get { return settings.CanChangeProperty; }
776            set { settings.CanChangeProperty = value; }
777        }
778
779        public bool CanSendPropertiesChangedEvent
780        {
781            get { return canSendPropertiesChangedEvent; }
782            set { canSendPropertiesChangedEvent = value; }
783        }
784
785        private void DynamicPropertiesChanged()
786        {
787            if (OnDynamicPropertiesChanged != null) OnDynamicPropertiesChanged(this);
788        }
789
790        #endregion
791
792        #region INotifyPropertyChanged Members
793
794        public event PropertyChangedEventHandler PropertyChanged;
795
796        public void OnPropertyChanged(string name)
797        {
798            if (PropertyChanged != null)
799            {
800                PropertyChanged(this, new PropertyChangedEventArgs(name));
801            }
802        }
803
804        #endregion
805
806        #region IControl
807
808        private IControlSolveFunction bfpSlave;
809        [PropertyInfo(Direction.ControlSlave, "BFP Slave", "Direct access to BFP.", "", DisplayLevel.Beginner)]
810        public IControlSolveFunction BFPSlave
811        {
812            get
813            {
814                if (bfpSlave == null)
815                    bfpSlave = new BFPControl(this);
816                return bfpSlave;
817            }
818        }
819
820        #endregion
821    }
822
823    #region BFPControl : IControlSolveFunction
824
825    public class BFPControl : IControlSolveFunction
826    {
827        public event IControlStatusChangedEventHandler OnStatusChanged;
828        private BooleanFunctionParser plugin;
829
830        public BFPControl(BooleanFunctionParser Plugin)
831        {
832            this.plugin = Plugin;
833        }
834
835        #region IControlEncryption Members
836
837        // here comes the slave side implementation of SolveFunction
838        public int SolveFunction(string function, bool[] data, int switchInputs)
839        {
840            int resultInt;
841
842            // the result is computed by calling the ParseBooleanFunction (step into it with F11)
843            // returns -1 on error (e.g. not a valid function)
844            resultInt = plugin.ParseBooleanFunction(function, data, switchInputs);
845
846            return resultInt;
847        }
848
849        #endregion
850    }
851
852    #endregion
853}
Note: See TracBrowser for help on using the repository browser.