Example #1
0
        public static CSSSheet Parse(ref byte* data, byte* dataEnd, Encoding encoder)
        {
            CSSSheet sheet = new CSSSheet();

            //read the declarations
            while (data < dataEnd) {
                //block comment? (/**/)
                if (*data == '/' && data < dataEnd - 2 && *(data + 1) == '*') {
                    //skip to the end of the block comment
                    while (data < dataEnd - 2) {
                        if (*data == '*' && *(data + 1) == '/') { data += 2; break; }
                        data++;
                    }
                }

                //skip to the beginning of data
                Helpers.SkipWhitespaces(ref data, dataEnd);

                #region at-rule?
                if (*data == '@') {
                    data++;

                    //define the list which will contains all the arguments
                    LinkedList<STRPTR> arguments = new LinkedList<STRPTR>();

                    //if the definition has a scope, this is where it's declarations will be stored
                    ICSSScope scope = null;

                    //skip to beginning of the data
                    if (Helpers.SkipWhitespaces(ref data, dataEnd)) { break; }

                    #region read the name
                    byte* namePtr = data;
                    byte* nameEndPtr = (byte*)0;
                    while (data < dataEnd) {
                        if (!(
                            (*data >= 'A' && *data <= 'Z') ||
                            (*data >= 'a' && *data <= 'z') ||
                            *data == '-')) {
                                nameEndPtr = data - 1;
                                Helpers.SkipWhitespaces(ref data, dataEnd);
                                break;
                        }
                        data++;
                    }
                    #endregion

                    #region read arguments
                    byte* strPtr = data;
                    byte* strPtrEnd = (byte*)0;
                    while (data < dataEnd) {
                        #region skip comments
                        //block comment? (/**/)
                        if (*data == '/' && data < dataEnd - 2 && *(data + 1) == '*') {
                            //skip to the end of the block comment
                            while (data < dataEnd - 2) {
                                if (*data == '*' && *(data + 1) == '/') { data += 2; break; }
                                data++;
                            }
                        }
                        #endregion

                        #region scope for declarations?
                        if (*data == '{') {
                            //add whatever was before the scope beginning
                            strPtrEnd = data - 1;
                            if (!isBlank(strPtr, strPtrEnd)) {
                                arguments.AddLast(new STRPTR(strPtr, strPtrEnd));
                            }
                            data++;

                            //deturmine whether we process the scope as a ruleset
                            //or a declaration by sampling the upcoming data
                            //and seeing if we hit a tell-tail sign of a ruleset
                            //or a declaration
                            bool isRuleset = false;
                            byte* dataSamplePtr = data;
                            while (dataSamplePtr < dataEnd) {
                                if (*dataSamplePtr == ':') { isRuleset = true; break; }
                                if (*dataSamplePtr == '{') { break; }
                                dataSamplePtr++;
                            }

                            #region ruleset?
                            if (isRuleset) {
                                scope = CSSRuleSet.Parse(ref data, dataEnd, encoder);
                                if (*data == '}') { data++; }
                            }
                            #endregion

                            #region declarations?
                            else {
                                //read it as a CSSSheet to support nested at-rules
                                scope = Parse(ref data, dataEnd, encoder);
                                if (*data == '}') { data++; }
                            }
                            #endregion

                            break;
                        }
                        #endregion

                        #region string?
                        if (*data == '"' || *data == '\'') {
                            //read the string
                            byte strTerminate = *data++;
                            while (data < dataEnd) {
                                if (*data == '\\') { data += 2; continue; }
                                if (*data == strTerminate) {
                                    strPtrEnd = data - 1;
                                    data++;
                                    break;
                                }
                                data++;
                            }
                        }
                        #endregion

                        #region space/end of line
                        if (*data == ' ' || *data == ';') {
                            strPtrEnd = data - 1;

                            if (!isBlank(strPtr, strPtrEnd)) {
                                arguments.AddLast(new STRPTR(strPtr, strPtrEnd));
                            }

                            //end of line?
                            if (*data == ';') { data++; break; }
                            data++;

                            //skip the beginning of the next component
                            if (Helpers.SkipWhitespaces(ref data, dataEnd)) { break; }
                            strPtr = data;
                            strPtrEnd = (byte*)0;
                            continue;
                        }
                        #endregion

                        data++;
                    }
                    #endregion

                    handleAtRule(
                        sheet,
                        new STRPTR(namePtr, nameEndPtr),
                        arguments,
                        scope,
                        encoder);
                    continue;
                }
                #endregion

                //close already?
                if (*data == '}') { break; }

                //read the declaration
                CSSDeclaration declaration = CSSDeclaration.Parse(ref data, dataEnd, encoder);
                if (declaration == null) { break; }

                //add the declaration
                sheet.AddDeclaration(declaration);

                //at the end?
                if (Helpers.SkipWhitespaces(ref data, dataEnd)) { break; }
                if (*data == '}') { data++; }
            }

            return sheet;
        }
Example #2
0
        private static void handleAtRule(CSSSheet sheet, STRPTR name, LinkedList<STRPTR> arguments, ICSSScope scope, Encoding encoder)
        {
            string nameStr = name;

            return;
        }