Пример #1
0
        public SaneOptionCollection Parse(StreamReader streamReader)
        {
            input   = streamReader;
            options = new SaneOptionCollection();
            state   = OptionParseState.NonDeviceOptions;
            line    = null;

            NextLine();
            while (line != null)
            {
                switch (state)
                {
                case OptionParseState.NonDeviceOptions:
                    if (line.StartsWith("Options specific to device", StringComparison.InvariantCultureIgnoreCase))
                    {
                        state = OptionParseState.LookingForOption;
                    }
                    NextLine();
                    break;

                case OptionParseState.LookingForOption:
                    if (line.StartsWith("    -", StringComparison.InvariantCultureIgnoreCase))
                    {
                        ParseOption();
                        state = OptionParseState.ReadingDescription;
                    }
                    NextLine();
                    break;

                case OptionParseState.ReadingDescription:
                    if (line.StartsWith("        ", StringComparison.InvariantCultureIgnoreCase))
                    {
                        string descLine = line.Substring(8).Trim();
                        if (lastOption.Desc == null)
                        {
                            lastOption.Desc = descLine;
                        }
                        else
                        {
                            lastOption.Desc += " " + descLine;
                        }
                        NextLine();
                    }
                    else
                    {
                        state = OptionParseState.LookingForOption;
                    }
                    break;
                }
            }

            return(options);
        }
Пример #2
0
        private void ParseOption()
        {
            int i      = 4;
            var option = new SaneOption
            {
                Capabilities = SaneCapabilities.SoftSelect
            };
            var optionValueList = new List <string>();
            var builder         = new StringBuilder();

            state = OptionParseState.ReadingName;
            while (i < line.Length)
            {
                char c = line[i];
                switch (state)
                {
                case OptionParseState.ReadingName:
                    if (char.IsLetter(c) || c == '-')
                    {
                        builder.Append(c);
                        i += 1;
                        break;
                    }
                    option.Name = builder.ToString();
                    builder.Clear();

                    if (c == '[')
                    {
                        option.Type = SaneValueType.Bool;
                        i          += 3;
                        state       = OptionParseState.ReadingBooleanValues;
                    }
                    else if (c == ' ')
                    {
                        i    += 1;
                        state = OptionParseState.ReadingValues;
                    }
                    else if (c == '\n')
                    {
                        option.Type = SaneValueType.Button;
                        i          += 1;
                    }
                    else
                    {
                        return;
                    }
                    break;

                case OptionParseState.ReadingBooleanValues:
                    if (c == 'a')
                    {
                        option.Capabilities |= SaneCapabilities.Automatic;
                        i += 1;
                    }
                    else if (c == ')')
                    {
                        i += 1;
                    }
                    else
                    {
                        i += 1;
                    }
                    break;

                case OptionParseState.ReadingValues:
                    if (char.IsLetterOrDigit(c) || c == '.' || c == '%')
                    {
                        builder.Append(c);
                        i += 1;
                        break;
                    }
                    string optionValue = builder.ToString();
                    builder.Clear();
                    if (c == ' ' || c == '\n')
                    {
                        foreach (var unitKvp in Units)
                        {
                            if (optionValue.EndsWith(unitKvp.Key, StringComparison.InvariantCultureIgnoreCase))
                            {
                                optionValue = optionValue.Substring(0, optionValue.Length - unitKvp.Key.Length);
                                option.Unit = unitKvp.Value;
                                break;
                            }
                        }
                    }
                    else if (line.Substring(i, 4) == ",...")
                    {
                        option.Type = SaneValueType.Group;
                        i          += 3;
                    }
                    else if (c != '|')
                    {
                        return;
                    }

                    if (optionValue == "auto")
                    {
                        option.Capabilities |= SaneCapabilities.Automatic;
                    }
                    else if (optionValue.Contains(".."))
                    {
                        var parts = optionValue.Split(new[] { ".." }, StringSplitOptions.None);
                        if (!decimal.TryParse(parts[0], out var min) || !decimal.TryParse(parts[1], out var max))
                        {
                            return;
                        }
                        if (option.Type == SaneValueType.None)
                        {
                            option.Type = SaneValueType.Numeric;
                        }
                        option.ConstraintType = SaneConstraintType.Range;
                        option.Range          = new SaneRange
                        {
                            Min = min,
                            Max = max
                        };
                    }
                    else
                    {
                        if (option.Type == SaneValueType.None)
                        {
                            // Assume numeric until proven otherwise
                            option.Type           = SaneValueType.Numeric;
                            option.ConstraintType = SaneConstraintType.WordList;
                        }
                        if (optionValue.Any(c1 => !char.IsDigit(c1) && c1 != '.'))
                        {
                            option.Type           = SaneValueType.String;
                            option.ConstraintType = SaneConstraintType.StringList;
                        }
                        if (optionValue != "")
                        {
                            optionValueList.Add(optionValue);
                        }
                    }

                    if (c == ' ')
                    {
                        if (option.ConstraintType == SaneConstraintType.WordList)
                        {
                            option.WordList = optionValueList.Select(decimal.Parse).ToList();
                        }
                        if (option.ConstraintType == SaneConstraintType.StringList)
                        {
                            option.StringList = optionValueList;
                        }
                        state = option.ConstraintType == SaneConstraintType.Range ? OptionParseState.LookingForQuant : OptionParseState.LookingForDefaultValue;
                    }
                    i += 1;
                    break;

                case OptionParseState.LookingForQuant:
                    if (c == ' ')
                    {
                        i += 1;
                        break;
                    }
                    if (c == '[')
                    {
                        state = OptionParseState.LookingForDefaultValue;
                        break;
                    }
                    if (c == '\n')
                    {
                        i += 1;
                        break;
                    }
                    if (line.Substring(i, 13) != "(in steps of ")
                    {
                        return;
                    }
                    i    += 13;
                    state = OptionParseState.ReadingQuant;
                    break;

                case OptionParseState.ReadingQuant:
                    if (c != ')')
                    {
                        builder.Append(c);
                        i += 1;
                        break;
                    }
                    if (!decimal.TryParse(builder.ToString(), out var quant))
                    {
                        return;
                    }
                    builder.Clear();
                    option.Range.Quant = quant;
                    i    += 1;
                    state = OptionParseState.LookingForDefaultValue;
                    break;

                case OptionParseState.LookingForDefaultValue:
                    if (c == ' ')
                    {
                        i += 1;
                        break;
                    }
                    if (c == '\n')
                    {
                        i += 1;
                        break;
                    }
                    if (c != '[')
                    {
                        return;
                    }
                    i    += 1;
                    state = OptionParseState.ReadingDefaultValue;
                    break;

                case OptionParseState.ReadingDefaultValue:
                    if (c != ']')
                    {
                        builder.Append(c);
                        i += 1;
                        break;
                    }

                    string current = builder.ToString();
                    builder.Clear();

                    if (current == "inactive")
                    {
                        option.Capabilities |= SaneCapabilities.Inactive;
                    }
                    else if (current == "hardware")
                    {
                        option.Capabilities |= SaneCapabilities.HardSelect;
                    }
                    else if (current == "read-only")
                    {
                        option.Capabilities &= ~SaneCapabilities.SoftSelect;
                        option.Capabilities |= SaneCapabilities.SoftDetect;
                    }
                    else if (option.Type == SaneValueType.Numeric)
                    {
                        if (!decimal.TryParse(current, out var currentNumeric))
                        {
                            return;
                        }
                        option.CurrentNumericValue = currentNumeric;
                    }
                    else
                    {
                        option.CurrentStringValue = current;
                    }

                    i    += 1;
                    state = OptionParseState.Idle;
                    break;

                case OptionParseState.Idle:
                    i += 1;
                    break;
                }
            }

            options.Add(option);
            lastOption = option;
            state      = OptionParseState.ReadingDescription;
        }