/// <summary> /// Проверяем время на корректность данных /// Время может быть задано в секундах и в долях секунд /// 0; 0.230; 33.675. /// Миллисекунды должны быть от 0 до 999. /// Значение секунд не должно быть больше 65535 /// /// TODO: избавиться от дубликата проверки секунд /// </summary> /// <param name="timeStr">распознанное время из команды</param> private void tryParseTimeToken(string timeStr) { string[] timeTokens = timeStr.Split('.'); // timeTokens[0] - значение секунд, timeTokens[1] - значение мс, если задано // дробное значение не задано, считаем, что заданы секунды if (timeTokens.Length == 1) { try { int tempSec = Int32.Parse(timeTokens[0]); if ((tempSec < 0) || (tempSec > MAX_SECONDS_VALUE)) { CyclogramParsingException exc = new CyclogramParsingException("Ошибка преобразования времени выполнения команды: " + timeStr + ". Секунды должны быть заданы от 0 до " + MAX_SECONDS_VALUE.ToString()); throw exc; } _curCommand.DelayMs = tempSec * 1000; _curCommand.DelayOriginal = _curCommand.DelayMs; } catch (FormatException) { CyclogramParsingException exc = new CyclogramParsingException("Ошибка преобразования времени выполнения команды: " + timeStr); throw exc; } } // задано и дробное значение else if (timeTokens.Length == 2) { try { int tempSec = Int32.Parse(timeTokens[0]); if ((tempSec < 0) || (tempSec > MAX_SECONDS_VALUE)) { CyclogramParsingException exc = new CyclogramParsingException("Ошибка преобразования времени выполнения команды: " + timeStr + ". Секунды должны быть заданы от 0 до " + MAX_SECONDS_VALUE.ToString()); throw exc; } int ms = Int32.Parse(timeTokens[1]); if ((ms < 0) && (ms > 999)) { CyclogramParsingException exc = new CyclogramParsingException("Ошибка преобразованя времени выполнения команды: " + timeStr + ". Милисекунды должны быть от 0 до 999."); throw exc; } _curCommand.DelayMs = tempSec * 1000 + ms; _curCommand.DelayOriginal = _curCommand.DelayMs; } catch (FormatException) { CyclogramParsingException exc = new CyclogramParsingException("Ошибка преобразованя времени выполнения команды: " + timeStr); throw exc; } } // ошибка задания времени (время разделено более одной точкой) else { CyclogramParsingException exc = new CyclogramParsingException("Ошибка преобразованя времени выполнения команды: " + timeStr); throw exc; } }
/// <summary> /// Проверяем, что команда существует в списке доступных команд /// Если команда не находится в списке, вызывается исключение CyclogramParsingException /// Если команда в списке находится, переменной _curCommand присваиваются значения id, execFunction и testFunction /// Выставляется флаг cmdExists /// </summary> /// <param name="cmdStr">Название команды</param> private void tryParseCmdToken(string cmdStr) { Debug.Assert(_availableCommands != null, "Список доступных команд циклограммы пуст!"); bool cmdExists = false; foreach (var cmd in _availableCommands) { if (cmd.Key == cmdStr) { cmdExists = true; _curCommand.Id = cmd.Value.Id; _curCommand.ExecFunction = cmd.Value.ExecFunction; _curCommand.TestFunction = cmd.Value.TestFunction; break; } } if (!cmdExists) { CyclogramParsingException exc = new CyclogramParsingException("Команды " + cmdStr + " нет в списке поддерживаемых команд!"); throw exc; } }
/// <summary> /// загружаем файл циклограмм /// Даже в случае ошибки, команда добавляется в список команд, но выставляется признак наличия ошибки /// </summary> /// <param name="cycFName">Путь к файлу циклограмм</param> /// <param name="availableCommands">Список доступных команд</param> public void TryLoad(string cycFName, CyclogramCommands availableCommands) { Debug.Assert(availableCommands != null, "Список доступных команд циклограммы пуст!"); string cycLine; int curLineNum = 0; _availableCommands = availableCommands; _wasError = false; if (!File.Exists(cycFName)) { _wasError = true; CyclogramParsingException exc = new CyclogramParsingException("Файл " + cycFName + " не существует!"); throw exc; } FileName = cycFName; commands.Clear(); using (StreamReader sr = new StreamReader(cycFName)) { // читам файл по строкам while (sr.Peek() >= 0) { cycLine = sr.ReadLine(); try { TryParseString(cycLine); } catch (CyclogramParsingException e) { _wasError = true; _curCommand.ErrorInCommand += e.Message + "\t"; } catch { _wasError = true; _curCommand.ErrorInCommand += " Общая ошибка проверки команды."; } finally { _curCommand.Line = curLineNum; commands.Add(_curCommand); // начинаем "собирать" новую команду _curCommand = new CyclogramLine(); } curLineNum++; } } }
/// <summary> /// Функция парсинга строки /// Работаем на исключениях, в вызывающей функции, необходимо проверять исключения от этой функции /// </summary> /// <param name="cycStr">Строка циклограммы</param> public void TryParseString(string cycStr) { _curCommand.Reset(); // убираем лишнее пробелы из строки cycStr.Trim(); // сохраняем на случай, если эта строка - только комментарий _curCommand.Str = cycStr; // убираем комментарии, сохраняя их в специальной переменной _curCommand.Comments += TakeComments(ref cycStr) + "\t"; // вся строка - комментарий, выходим, нам здесь больше делать нечего if (cycStr == String.Empty) return; // кроме комментариев есть еще что-то, пытаемся понять, что, но в любом случае. считаем что должна быть команда _curCommand.IsCommand = true; // разделяем строку по словам (разделитель - пробел) string[] strTokens = cycStr.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries); // если нашли только одно слово, то генерим исключение об ошибке if (strTokens.Length <= 1) { CyclogramParsingException exc = new CyclogramParsingException("Ошибка в строке " + cycStr + ". Формат задания команд: ВРЕМЯ КОМАНДА ПАРАМЕТРЫ #КОММЕНТАРИИ"); throw exc; } // пытаемся разобрать время tryParseTimeToken(strTokens[0]); // пытаемся разобрать команду tryParseCmdToken(strTokens[1]); // составляем строку команды для отображения в циклограмме (выкидываем из исходной строки время, так как оно у нас в отдельном столбце) _curCommand.Str = strTokens[1]; // копируем параметры, если они есть в массив параметров команды if (strTokens.Length - 2 > 0) { _curCommand.Parameters = new string[strTokens.Length - 2]; System.Array.Copy(strTokens, 2, _curCommand.Parameters, 0, _curCommand.Parameters.Length); for (UInt16 i = 2; i < strTokens.Length; i++) { _curCommand.Str += " " + strTokens[i]; } } // добавляем комментарии к строке, если они есть _curCommand.Str += " " + _curCommand.Comments; // выполняем функцию тестирования параметров команды if (!_curCommand.RunTestFunction()) { CyclogramParsingException exc = new CyclogramParsingException(); // "Ошибка при проверке команды " + _curCommand.CmdName); throw exc; } }
/// <summary> /// Загружаем циклограмму /// В случае ошмибки загрузки циклограммы, генерируем исключение /// </summary> /// <param name="fName">Путь к файлу циклограмм</param> /// <param name="availableCommands">Список доступных команд</param> public void Load(string fName, CyclogramCommands availableCommands) { try { CycFile.TryLoad(fName, availableCommands); if (CycFile.WasError) { CyclogramParsingException exc = new CyclogramParsingException("Ошибки в циклограмме"); throw exc; } else { ChangeState(CurState.csLoaded); CycFile.CalcAbsoluteTime(); _cPos.SetToLine(0, true); } } catch { ChangeState(CurState.csLoadedWithErrors); // throw; } }