Beispiel #1
0
        internal unsafe CSSPseudoClass_Nth(byte* data, byte* dataEnd, CSSPseudoClass pseudoClass, out bool success)
        {
            success = true;

            #region odd/even?
            if (toLower(*data) == 'o' &&
                toLower(*(data + 1)) == 'd' &&
                toLower(*(data + 2)) == 'd') {
                    p_Odd = true;
                    return;
            }
            if (toLower(*data) == 'e' &&
                toLower(*(data + 1)) == 'v' &&
                toLower(*(data + 2)) == 'e' &&
                toLower(*(data + 3)) == 'n') {
                    p_Even = true;
                    return;
            }

            #endregion

            //parse the data as an arithmetic expression
            p_Expression = ArithmeticQueue.Parse(ref data, dataEnd);
            ArithmeticQueue flatten = p_Expression.Flatten();

            //does the expression contain any substitutes?
            //if so, we add "n" as a substitute (IF it is n, if
            //it isn't then it is an invalid nth* class.
            LinkedListNode<ArithmeticOperand> currentOperand = flatten.Operands.First;
            while (currentOperand != null) {
                //is the operand a substitute?
                ArithmeticOperand current = currentOperand.Value;
                if (!current.IsSubstitution) {
                    currentOperand = currentOperand.Next;
                    continue;
                }

                //invalid? (the name has to be "n")
                if ((char)current.Value != 'n') {
                    success = false;
                    break;
                }

                p_HasNSubstitute = true;
                break;
            }

            //if there is no "n" substitute, pre-calculate the expression
            //so we don't have to constantly calculate everytime we check.
            if (success && !p_HasNSubstitute) {
                p_ExpressionResult = (int)p_Expression.Calculate();
            }
        }
Beispiel #2
0
        private void processBIDMAS(ArithmeticOperator op)
        {
            //iterate through the operators
            LinkedListNode<ArithmeticOperator> currentOperator = p_Operators.First;
            LinkedListNode<ArithmeticOperand> currentOperand = p_Operands.First;
            while (currentOperator != null) {
                //operator we want to process?
                ArithmeticOperator currentOp = currentOperator.Value;
                if (op != currentOp) {
                    currentOperator = currentOperator.Next;
                    currentOperand = currentOperand.Next;
                    continue;
                }

                //get the 2 operands for the operator
                ArithmeticOperand opAnd1 = currentOperand.Value;
                ArithmeticOperand opAnd2 = currentOperand.Next.Value;

                //group this operator into a scope
                ArithmeticQueue queue = new ArithmeticQueue();
                queue.AddOperation(currentOp, opAnd1, opAnd2);

                //replace the operand with the queue
                currentOperand.Value = new ArithmeticOperand(queue);

                //since we have processed the second operand and
                //the operator, remove it
                LinkedListNode<ArithmeticOperator> nextOp = currentOperator.Next;
                p_Operands.Remove(currentOperand.Next);
                p_Operators.Remove(currentOperator);
                currentOperator = nextOp;
            }
        }
Beispiel #3
0
        public static ArithmeticQueue Parse(ref byte* data, byte* dataEnd, bool useBIDMAS, LinkedList<ArithmeticFunction> functions)
        {
            //define the list of scopes, operators and operands
            LinkedList<ArithmeticOperator> operators = new LinkedList<ArithmeticOperator>();
            LinkedList<ArithmeticOperand> operands = new LinkedList<ArithmeticOperand>();

            //define the size of the numerical object the queue will return when
            //the calculate function is called (default of 1 (byte))
            sbyte resultSize = 1;
            bool containsDecimal = false;

            //any functions in the list?
            bool functionsListed = functions.Count != 0;

            //iterate through the data
            bool negativeFlag = false;
            while (data < dataEnd) {
                //skip whitespaces so we are on a character
                if (Helpers.SkipWhitespaces(ref data, dataEnd)) { break; }

                //end the scope?
                if (*data == ')') { data++; break; }

                #region operator?
                ArithmeticOperator op = parseOperator(*data);
                if (op != ArithmeticOperator.None) {
                    //if it's division, we make sure we don't lose
                    //precision when dividing operators (e.g 1/3)
                    if (op == ArithmeticOperator.Divide) { containsDecimal = true; }

                    //make sure we do not process a negative number
                    //and treat it as an operator
                    bool isNegative = false;
                    if (op == ArithmeticOperator.Subtract) {
                        isNegative = operators.Count == operands.Count;
                        negativeFlag = isNegative;
                    }

                    if (!isNegative) {
                        operators.AddLast(op);
                    }
                    data++;
                    continue;
                }
                #endregion

                #region function?
                if (functionsListed && isAlphabetic(*data)) {
                    //read until an open queue
                    byte* functionNameStart = data;
                    byte* functionNameEnd = (byte*)0;
                    byte* dataCopy = data;
                    bool foundScope = false;
                    while (dataCopy < dataEnd) {
                        //scope?
                        if (*dataCopy == '(') {
                            foundScope = true;
                            functionNameEnd = dataCopy - 1;
                            dataCopy++;
                            break;
                        }

                        //not a whitespace?
                        if (*dataCopy != ' ' &&
                            *dataCopy != '\n' &&
                            *dataCopy != '\r' &&
                            *dataCopy != '\t' &&
                            !isAlphabetic(*dataCopy)) {
                            break;
                        }
                        dataCopy++;
                    }

                    //did we find a scope?
                    if (foundScope) {
                        //trim the function name to remove whitespace
                        while (functionNameEnd > data &&
                               !isAlphabetic(*functionNameEnd)) { functionNameEnd--; }

                        //name must be at least 2 characters wide
                        if (functionNameStart != functionNameEnd) {
                            //it's a function, lookup its name
                            data = dataCopy;
                            string functionName = Helpers.ReadString(functionNameStart, functionNameEnd, Encoding.ASCII);

                            //find the function from the functions list
                            IEnumerator<ArithmeticFunction> e = functions.GetEnumerator();
                            ArithmeticFunction functionBase = null;
                            while (e.MoveNext()) {
                                ArithmeticFunction current = e.Current;
                                if (current.Name == functionName) {
                                    functionBase = current;
                                    break;
                                }
                            }

                            //found the function?
                            if (functionBase == null) {
                                throw new Exception("Function \"" + functionName + "\" does not exist!");
                            }

                            //was there an operand behind the substitute?
                            //if not, (e.g 5(5)) we multiple the previous operand with the scope
                            if (operands.Count != operators.Count) {
                                operators.AddLast(ArithmeticOperator.Multiply);
                            }

                            //parse the function call arguments
                            ArithmeticQueue args = ArithmeticQueue.Parse(ref data, dataEnd, useBIDMAS, functions);

                            //add the function as an operand
                            ArithmeticFunction function = functionBase.Create(args);
                            operands.AddLast(new ArithmeticOperand(function, negativeFlag));
                            negativeFlag = false;
                            continue;
                        }
                    }
                }

                #endregion

                #region queue
                if (*data == '(') {
                    //was there an operand behind the substitute?
                    //if not, (e.g 5(5)) we multiple the previous operand with the scope
                    if (operands.Count != operators.Count) {
                        operators.AddLast(ArithmeticOperator.Multiply);
                    }

                    data++;
                    ArithmeticQueue scope = Parse(ref data, dataEnd, functions);
                    operands.AddLast(new ArithmeticOperand(scope, negativeFlag));
                    negativeFlag = false;
                    continue;
                }
                #endregion

                #region numeric?
                if (*data >= '0' && *data <= '9') {
                    byte* numPtr = data;
                    byte* numPtrEnd = dataEnd - 1;

                    //read the numeric
                    bool isDecimal = false;
                    while (data < dataEnd) {
                        //decimal?
                        if (*data == '.') {
                            isDecimal = true;
                            containsDecimal = true;
                            data++;
                            continue;
                        }

                        //end of numerical?
                        if (!((*data >= '0' && *data <= '9'))) {
                            numPtrEnd = data - 1;
                            break;
                        }

                        data++;
                    }

                    //calculate how much memory this number will take
                    //and see if the current result size can fit it, if
                    //not, expand it
                    byte charLength = (byte)((numPtrEnd - numPtr) + 1);
                    sbyte memSize = ArithmeticNumeric.RequiredMemory(charLength, isDecimal);
                    if (memSize > resultSize) { resultSize = memSize; }

                    //add the number as an operand
                    string numStr = Helpers.ReadString(numPtr, numPtrEnd, Encoding.ASCII);
                    ArithmeticNumeric opValue = ArithmeticNumeric.FromString(numStr, isDecimal, charLength);
                    operands.AddLast(new ArithmeticOperand(opValue, negativeFlag));
                    negativeFlag = false;
                    continue;
                }
                #endregion

                #region substitute?
                else {
                    //was there an operand behind the substitute?
                    //if not, (e.g 5n) we multiple the previous operand with n
                    if (operands.Count != operators.Count) {
                        operators.AddLast(ArithmeticOperator.Multiply);
                    }

                    operands.AddLast(new ArithmeticOperand((char)*data, negativeFlag));
                    negativeFlag = false;
                    data++;
                }
                #endregion
            }

            ArithmeticQueue buffer = new ArithmeticQueue(resultSize, containsDecimal, operators, operands);

            //bidmas?
            if (useBIDMAS) {
                buffer.SortBIDMAS();
            }

            return buffer;
        }
Beispiel #4
0
        private void flattenQueue(LinkedList<ArithmeticOperator> newOperators, LinkedList<ArithmeticOperand> newOperands, ArithmeticQueue q)
        {
            LinkedListNode<ArithmeticOperator> currentOperator = q.p_Operators.First;
            LinkedListNode<ArithmeticOperand> currentOperand = q.p_Operands.First;

            //no operands?
            if (currentOperand == null) {
                return;
            }

            //add the first operand
            if (currentOperand.Value.IsQueue) {
                flattenQueue(
                    newOperators,
                    newOperands,
                    (ArithmeticQueue)currentOperand.Value.Value);
            }
            else {
                newOperands.AddLast(currentOperand.Value);
            }
            currentOperand = currentOperand.Next;

            //no operators?
            if (currentOperator == null) {
                return;
            }

            //iterate over the operators
            while (currentOperator != null) {

                //add the operator
                newOperators.AddLast(currentOperator.Value);

                //grab the operand
                ArithmeticOperand operand = currentOperand.Value;

                //queue?
                if (operand.IsQueue) {
                    flattenQueue(
                        newOperators,
                        newOperands,
                        (ArithmeticQueue)operand.Value);
                }
                else {
                    newOperands.AddLast(operand);
                }

                currentOperand = currentOperand.Next;
                currentOperator = currentOperator.Next;
            }
        }
Beispiel #5
0
 public abstract ArithmeticFunction Create(ArithmeticQueue queue);
Beispiel #6
0
 public ArithmeticNumeric Call(ArithmeticQueue queue, LinkedList<ArithmeticSubstitute> substitutes)
 {
     return OnCall(queue.Calculate(substitutes));
 }
Beispiel #7
0
 public ArithmeticNumeric Call(ArithmeticQueue queue)
 {
     return OnCall(queue.Calculate());
 }
Beispiel #8
0
 public override ArithmeticFunction Create(ArithmeticQueue queue)
 {
     return new arithmeticFunctionDelegation(p_Name, p_Handler, queue);
 }
Beispiel #9
0
 private arithmeticFunctionDelegation(string name, OnCallHandler handler, ArithmeticQueue queue)
     : base(name)
 {
     p_Queue = queue;
     p_Handler = handler;
 }