예제 #1
0
     protected Reply <string> ParseRestOfString(CharStream <TUserState> stream, char firstChar, ErrorMessageList error)
     {
 #if LOW_TRUST
         var sb = new StringBuilder(16);
         sb.Append(firstChar);
 #else
         _16CharBuffer buffer_; // produces more efficient code on .NET than stackalloc char[16]
         char *        buffer = (char *)(&buffer_);
         buffer[0] = firstChar;
         char[] chars = null;
         uint   n     = 1;
 #endif
         for (;;)
         {
             var tag   = stream.StateTag;
             var reply = CharParser.Invoke(stream);
             if (reply.Status == ReplyStatus.Ok)
             {
                 if (tag == stream.StateTag)
                 {
                     throw Internal.ParserCombinatorInInfiniteLoopHelper.CreateException("manyChars", stream);
                 }
                 error = reply.Error;
         #if LOW_TRUST
                 sb.Append(reply.Result);
         #else
                 var i = n % 16;
                 if (i != 0)
                 {
                     buffer[i] = reply.Result;
                     ++n;
                 }
                 else
                 {
                     if (chars == null)
                     {
                         chars = new char[32];
                     }
                     else if (n == chars.Length)
                     {
                         var newChars = new char[2 * chars.Length];
                         Array.Copy(chars, newChars, chars.Length);
                         chars = newChars;
                     }
                     for (i = 0; i < 16; ++i)
                     {
                         chars[n - 16 + i] = buffer[i];
                     }
                     buffer[0] = reply.Result;
                     ++n;
                 }
         #endif
             }
             else if (reply.Status == ReplyStatus.Error && tag == stream.StateTag)
             {
                 string str;
         #if LOW_TRUST
                 str = sb.ToString();
         #else
                 if (n <= 16)
                 {
                     str = new String(buffer, 0, (int)n);
                 }
                 else
                 {
                     for (uint i = (n - 1) & 0x7ffffff0u; i < n; ++i)
                     {
                         chars[i] = buffer[i % 16];
                     }
                     str = new string(chars, 0, (int)n);
                 }
         #endif
                 error = ErrorMessageList.Merge(error, reply.Error);
                 return(new Reply <string> {
                     Status = ReplyStatus.Ok, Result = str, Error = error
                 });
             }
             else
             {
                 error = tag == stream.StateTag ? ErrorMessageList.Merge(error, reply.Error) : reply.Error;
                 return(new Reply <string> {
                     Status = reply.Status, Error = error
                 });
             }
         }
     }
예제 #2
0
파일: Helper.cs 프로젝트: hackme3/Fing
internal unsafe static T RunParserOnSubstream<T,TUserState,TSubStreamUserState>(
                             Microsoft.FSharp.Core.FSharpFunc<State<TSubStreamUserState>,T> parser,
                             TSubStreamUserState userState,
                             State<TUserState> stateBeforeSubStream, State<TUserState> stateAfterSubStream)
{
    CharStream.Anchor subStreamAnchor;
    var s0 = stateBeforeSubStream;
    var data0 = s0.data;
    var data = new State<TSubStreamUserState>.Data{Line = data0.Line, LineBegin = data0.LineBegin,
                                                   UserState = userState, StreamName = data0.StreamName};
    var state = new State<TSubStreamUserState>{data = data}; // the Iter member is assigned below
    CharStream.Anchor* anchor = s0.Iter.Anchor;
    var s1 = stateAfterSubStream;
    if (anchor != s1.Iter.Anchor)
        throw new ArgumentException("The states are associated with different CharStreams.");
    if (anchor->LastBlock == 0) {
        // the CharStream has only one block, so its safe to
        // construct a new CharStream from a pointer into the original buffer
        char* ptr = s0.Iter.Ptr;
        if (ptr == null) ptr = anchor->BufferEnd;
        char* end = s1.Iter.Ptr;
        if (end == null) end = anchor->BufferEnd;
        if (end < ptr) throw new ArgumentException("The position of the second state lies before the position of the first state.");
        int length = CharStream.PositiveDistance(ptr, end);
        CharStream stream = (CharStream)anchor->StreamHandle.Target;
        using (var subStream = new CharStream(stream.BufferString, stream.BufferStringPointer, ptr, length, s0.Index, &subStreamAnchor)) {
            // state.Iter = subStream.Begin
            state.Iter.Anchor = &subStreamAnchor;
            state.Iter.Ptr    = subStreamAnchor.BufferBegin; // will be null if length is 0
            state.Iter.Block  = length == 0 ? -1 : 0;
            return parser.Invoke(state);
        }
    } else if (s0.Iter.Block == s1.Iter.Block && anchor->Block == s1.Iter.Block) {
        char* ptr = s0.Iter.Ptr;
        char* end = s1.Iter.Ptr;
        if (end < ptr) throw new ArgumentException("The position of the second state lies before the position of the first state.");
        int length = CharStream.PositiveDistance(ptr, end);
        string subString = new String(ptr, 0, length);
        fixed (char* pSubString = subString)
        using (var subStream = new CharStream(subString, pSubString, pSubString, length, s0.Index, &subStreamAnchor)) {
            // state.Iter = subStream.Begin
            state.Iter.Anchor = &subStreamAnchor;
            state.Iter.Ptr    = subStreamAnchor.BufferBegin; // will be null if length is 0
            state.Iter.Block  = length == 0 ? -1 : 0;
            return parser.Invoke(state);
        }
    } else {
        ulong index1 = (ulong)s0.Iter.Index;
        ulong index2 = (ulong)s1.Iter.Index;
        if (index2 < index1) throw new ArgumentException("The position of the second state lies before the position of the first state.");
        ulong length_ = index2 - index1;
        // length >= Int32.MaxValue will trigger an exception anyway (because the string is too large)
        int length = length_ > (uint)System.Int32.MaxValue ? System.Int32.MaxValue : (int)length_;
        string subString = new String('\u0000', length);
        fixed (char* pSubString = subString) {
            s0.Iter.Read(pSubString, length);
            using (var subStream = new CharStream(subString, pSubString, pSubString, length, s0.Index, &subStreamAnchor)) {
                // state.Iter = subStream.Begin
                state.Iter.Anchor = &subStreamAnchor;
                state.Iter.Ptr    = subStreamAnchor.BufferBegin; // will be null if length is 0
                state.Iter.Block  = length == 0 ? -1 : 0;
                return parser.Invoke(state);
            }
        }
    }
}