예제 #1
0
 internal RangeDescriptor(RangeDescriptor other)
 {
     fStartChar    = other.fStartChar;
     fEndChar      = other.fEndChar;
     fNum          = other.fNum;
     fIncludesSets = new JCG.List <RBBINode>(other.fIncludesSets);
 }
예제 #2
0
            //-------------------------------------------------------------------------------------
            //
            //          RangeDesriptor::split()
            //
            //-------------------------------------------------------------------------------------
            internal virtual void Split(int where)
            {
                Assert.Assrt(where > fStartChar && where <= fEndChar);
                RangeDescriptor nr = new RangeDescriptor(this);

                //  RangeDescriptor copy constructor copies all fields.
                //  Only need to update those that are different after the split.
                nr.fStartChar = where;
                this.fEndChar = where - 1;
                nr.fNext      = this.fNext;
                this.fNext    = nr;

                // TODO:  fIncludesSets is not updated.  Check it out.
                //         Probably because they haven't been populated yet,
                //         but still sloppy.
            }
예제 #3
0
        //------------------------------------------------------------------------
        //
        //           build          Build the list of non-overlapping character ranges
        //                          from the Unicode Sets.
        //
        //------------------------------------------------------------------------
        internal virtual void Build()
        {
            RangeDescriptor rlRange;

            if (fRB.fDebugEnv != null && fRB.fDebugEnv.IndexOf("usets", StringComparison.Ordinal) >= 0)
            {
                PrintSets();
            }

            //  Initialize the process by creating a single range encompassing all characters
            //  that is in no sets.
            //
            fRangeList            = new RangeDescriptor();
            fRangeList.fStartChar = 0;
            fRangeList.fEndChar   = 0x10ffff;

            //
            //  Find the set of non-overlapping ranges of characters
            //
            foreach (RBBINode usetNode in fRB.fUSetNodes)
            {
                UnicodeSet inputSet           = usetNode.fInputSet;
                int        inputSetRangeCount = inputSet.RangeCount;
                int        inputSetRangeIndex = 0;
                rlRange = fRangeList;

                for (; ;)
                {
                    if (inputSetRangeIndex >= inputSetRangeCount)
                    {
                        break;
                    }
                    int inputSetRangeBegin = inputSet.GetRangeStart(inputSetRangeIndex);
                    int inputSetRangeEnd   = inputSet.GetRangeEnd(inputSetRangeIndex);

                    // skip over ranges from the range list that are completely
                    //   below the current range from the input unicode set.
                    while (rlRange.fEndChar < inputSetRangeBegin)
                    {
                        rlRange = rlRange.fNext;
                    }

                    // If the start of the range from the range list is before with
                    //   the start of the range from the unicode set, split the range list range
                    //   in two, with one part being before (wholly outside of) the unicode set
                    //   and the other containing the rest.
                    //   Then continue the loop; the post-split current range will then be skipped
                    //     over
                    if (rlRange.fStartChar < inputSetRangeBegin)
                    {
                        rlRange.Split(inputSetRangeBegin);
                        continue;
                    }

                    // Same thing at the end of the ranges...
                    // If the end of the range from the range list doesn't coincide with
                    //   the end of the range from the unicode set, split the range list
                    //   range in two.  The first part of the split range will be
                    //   wholly inside the Unicode set.
                    if (rlRange.fEndChar > inputSetRangeEnd)
                    {
                        rlRange.Split(inputSetRangeEnd + 1);
                    }

                    // The current rlRange is now entirely within the UnicodeSet range.
                    // Add this unicode set to the list of sets for this rlRange
                    if (rlRange.fIncludesSets.IndexOf(usetNode) == -1)
                    {
                        rlRange.fIncludesSets.Add(usetNode);
                    }

                    // Advance over ranges that we are finished with.
                    if (inputSetRangeEnd == rlRange.fEndChar)
                    {
                        inputSetRangeIndex++;
                    }
                    rlRange = rlRange.fNext;
                }
            }

            if (fRB.fDebugEnv != null && fRB.fDebugEnv.IndexOf("range", StringComparison.Ordinal) >= 0)
            {
                PrintRanges();
            }

            //
            //  Group the above ranges, with each group consisting of one or more
            //    ranges that are in exactly the same set of original UnicodeSets.
            //    The groups are numbered, and these group numbers are the set of
            //    input symbols recognized by the run-time state machine.
            //
            //    Numbering: # 0  (state table column 0) is unused.
            //               # 1  is reserved - table column 1 is for end-of-input
            //               # 2  is reserved - table column 2 is for beginning-in-input
            //               # 3  is the first range list.
            //
            RangeDescriptor rlSearchRange;

            for (rlRange = fRangeList; rlRange != null; rlRange = rlRange.fNext)
            {
                for (rlSearchRange = fRangeList; rlSearchRange != rlRange; rlSearchRange = rlSearchRange.fNext)
                {
                    if (ListEqualityComparer <RBBINode> .Default.Equals(rlRange.fIncludesSets, rlSearchRange.fIncludesSets))
                    {
                        rlRange.fNum = rlSearchRange.fNum;
                        break;
                    }
                }
                if (rlRange.fNum == 0)
                {
                    fGroupCount++;
                    rlRange.fNum = fGroupCount + 2;
                    rlRange.SetDictionaryFlag();
                    AddValToSets(rlRange.fIncludesSets, fGroupCount + 2);
                }
            }

            // Handle input sets that contain the special string {eof}.
            //   Column 1 of the state table is reserved for EOF on input.
            //   Column 2 is reserved for before-the-start-input.
            //            (This column can be optimized away later if there are no rule
            //             references to {bof}.)
            //   Add this column value (1 or 2) to the equivalent expression
            //     subtree for each UnicodeSet that contains the string {eof}
            //   Because {bof} and {eof} are not a characters in the normal sense,
            //   they doesn't affect the computation of ranges or TRIE.

            string eofString = "eof";
            string bofString = "bof";

            foreach (RBBINode usetNode in fRB.fUSetNodes)
            {
                UnicodeSet inputSet = usetNode.fInputSet;
                if (inputSet.Contains(eofString))
                {
                    AddValToSet(usetNode, 1);
                }
                if (inputSet.Contains(bofString))
                {
                    AddValToSet(usetNode, 2);
                    fSawBOF = true;
                }
            }


            if (fRB.fDebugEnv != null && fRB.fDebugEnv.IndexOf("rgroup", StringComparison.Ordinal) >= 0)
            {
                PrintRangeGroups();
            }
            if (fRB.fDebugEnv != null && fRB.fDebugEnv.IndexOf("esets", StringComparison.Ordinal) >= 0)
            {
                PrintSets();
            }

            fTrie = new Trie2Writable(0,       //   Initial value for all code points.
                                      0);      //   Error value for out-of-range input.

            for (rlRange = fRangeList; rlRange != null; rlRange = rlRange.fNext)
            {
                fTrie.SetRange(
                    rlRange.fStartChar,         // Range start
                    rlRange.fEndChar,           // Range end (inclusive)
                    rlRange.fNum,               // value for range
                    true                        // Overwrite previously written values
                    );
            }
        }
예제 #4
0
        private static void Finish200(IHostServer server, WebContext context, IWebFileRecord staticdescriptor)
        {
            var filetime = context.SetLastModified(staticdescriptor.Version);

            if (filetime <= context.GetIfModifiedSince())
            {
                context.Finish("", status: 304);
            }
            else
            {
                context.SetHeader("Qorpent-Disposition", staticdescriptor.FullName);
                if (server.Config.Cached.Contains(Path.GetFileName(staticdescriptor.FullName)))
                {
                    context.SetHeader("Cache-Control", "public, max-age=86400");
                }
                else if (server.Config.ForceNoCache)
                {
                    context.SetHeader("Cache-Control", "no-cache, must-revalidate");
                }
                else
                {
                    context.SetHeader("Cache-Control", "public");
                }

                RangeDescriptor range = null;
                if (0 < staticdescriptor.Length && (staticdescriptor.MimeType.StartsWith("image/") || staticdescriptor.MimeType.StartsWith("video/")))
                {
                    context.Response.ConentLength = staticdescriptor.Length;
                    if (staticdescriptor.Length > 4096)
                    {
                        context.Response.SetHeader("Accept-Ranges", "bytes");
                    }
                    var rangeHeader = context.Request.GetHeader("Range");
                    if (!string.IsNullOrWhiteSpace(rangeHeader))
                    {
                        var rangeparts = rangeHeader.Substring(6).SmartSplit(false, true, '-');
                        range = new RangeDescriptor {
                            Total = staticdescriptor.Length
                        };
                        range.Finish = range.Total - 1;
                        range.Start  = rangeparts[0].ToInt();
                        if (rangeparts.Count > 1)
                        {
                            range.Finish = rangeparts[1].ToInt();
                        }
                    }
                }

                try {
                    if (staticdescriptor.IsFixedContent)
                    {
                        if (null != staticdescriptor.FixedData)
                        {
                            context.Finish(staticdescriptor.FixedData, staticdescriptor.MimeType, range: range);
                        }
                        else
                        {
                            context.Finish(staticdescriptor.FixedContent, staticdescriptor.MimeType, range: range);
                        }
                    }
                    else
                    {
                        using (var s = staticdescriptor.Open()) {
                            context.Finish(s, staticdescriptor.MimeType, range: range);
                        }
                    }
                }
                catch (Exception e) {
                    Console.WriteLine(e.GetType().Name);
                    context.Finish(e.ToString(), status: 500);
                }
                finally {
                    context.Response.Close();
                }
            }
        }