Example #1
0
 /// <summary>
 ///     Builds an Answer String from the Specified FsdStatus Object
 /// </summary>
 /// <param name="fsdStatus"></param>
 /// <returns></returns>
 public ReadOnlySpan <byte> BuildAnswerString(FsdStatus fsdStatus)
 {
     using var result = new MemoryStream(fsdStatus.Fields.Sum(field => field.Name.Length + field.Value.Length + 4));
     foreach (var field in fsdStatus.Fields)
     {
         result.Write(Encoding.ASCII.GetBytes($"{field.Name}={field.Value}\0"));
     }
     result.WriteByte(0);
     return(result.ToArray());
 }
Example #2
0
        /// <summary>
        ///     Parses through the template looking for leading ANSI formatting on field specifications
        /// </summary>
        /// <param name="template"></param>
        /// <param name="status"></param>
        public void GetFieldAnsi(ReadOnlySpan <byte> template, FsdStatus status)
        {
            var currentField        = 0;
            var foundFieldCharacter = 0xFF;

            for (var i = 0; i < template.Length; i++)
            {
                var c = template[i];

                //If it's the character we previously found, keep going
                if (c == foundFieldCharacter)
                {
                    continue;
                }

                //We're past the field now, reset the character
                foundFieldCharacter = '\xFF';

                //If it's a new line, increment Y and set X back to -1
                if (c == '\r')
                {
                    continue;
                }

                //If we're not in a field definition, keep moving
                if (c != '?' && c != '$' && c != '!')
                {
                    continue;
                }

                //Found a field definition character, check to see if the next character is the same
                if (template[i + 1] != c)
                {
                    continue;
                }

                //Assume the ANSI format specification is within the first 10 characters
                var extractedAnsi = ExtractFieldAnsi(template.Slice(i - 10, 10));

                //Error Fields are their own special little snowflakes
                if (c == '!')
                {
                    status.ErrorField.FieldAnsi = extractedAnsi;
                }
                else
                {
                    status.Fields[currentField].FieldAnsi = extractedAnsi;
                    currentField++;
                }

                //Set our Position
                foundFieldCharacter = c;
            }
        }
Example #3
0
        /// <summary>
        ///     Determines the X,Y coordinates of specified template fields by stripping ANSI from the field template
        ///     and parsing each character, each new line increments Y and sets X back to 1.
        ///
        ///     Note: X,Y for ANSI starts at 1,1 being the top left of the terminal (not 0,0)
        /// </summary>
        /// <param name="template"></param>
        /// <param name="status"></param>
        public void GetFieldPositions(ReadOnlySpan <byte> template, FsdStatus status)
        {
            //Get Template and Strip out ANSI Characters
            var templateString = Encoding.ASCII.GetString(StripAnsi(template));


            var currentY           = 1; //ANSI x/y positions are 1 based, so first loop these will be 1,1
            var currentX           = 0;
            var currentField       = 0;
            var currentFieldLength = 0;

            var foundFieldCharacter = '\xFF';

            for (var i = 0; i < templateString.Length; i++)
            {
                var c = templateString[i];

                //Increment the X Position
                currentX++;

                //If it's the character we previously found, keep going
                if (c == foundFieldCharacter)
                {
                    currentFieldLength++;
                    continue;
                }

                //If we're past it, and the previous field Character wasn't the default, mark the length
                if (foundFieldCharacter != '\xFF')
                {
                    //Special Case for Error Field
                    if (foundFieldCharacter == '!')
                    {
                        status.ErrorField.FieldLength = currentFieldLength + 1;
                    }
                    else
                    {
                        //Standard Fields
                        status.Fields[currentField - 1].FieldLength = currentFieldLength + 1;
                    }

                    currentFieldLength = 0;
                }

                //We're past the field now, reset the character
                foundFieldCharacter = '\xFF';

                //If it's a new line, increment Y and set X back to -1
                if (c == '\n')
                {
                    currentY++;
                    currentX = 0;
                    continue;
                }

                if (c != '?' && c != '$' && c != '!')
                {
                    continue;
                }

                //If the next character is a known control character, then we're in a field definition
                switch (templateString[i + 1])
                {
                case '?':
                case '$':
                case '!':
                    break;

                default:
                    //Otherwise keep searching
                    continue;
                }

                //Define the field based on the field specification character used
                switch (c)
                {
                case '!':     //Error Message Field
                    //Add a new field for the Error, as it's not included in the Field Spec
                    status.ErrorField = new FsdFieldSpec {
                        FsdFieldType = EnumFsdFieldType.Error, X = currentX, Y = currentY
                    };
                    foundFieldCharacter = c;
                    continue;

                case '$':     //Numeric Field
                    status.Fields[currentField].FsdFieldType = EnumFsdFieldType.Numeric;
                    status.Fields[currentField].X            = currentX;
                    status.Fields[currentField].Y            = currentY;
                    break;

                default:     //Text or Multiple Choice
                    status.Fields[currentField].X = currentX;
                    status.Fields[currentField].Y = currentY;
                    break;
                }

                currentField++;
                foundFieldCharacter = c;
            }
        }