Interface:Выражение фильтра посылок

From EjudgeWiki

Навигация: Главная страница/Система ejudge/Использование/Веб-интерфейс пользователя/Выражение фильтра посылок

Выражение фильтра посылок позволяет задать условия, которым должны удовлетворять параметры посылок, чтобы быть показанными в списке посылок, генерируемом CGI-программами master и judge. Выражение фильтра должно иметь тип bool, а в противном случае генерируется ошибка.

При генерации страницы привилегированного пользователя в CGI-программе judge или master выражение фильтра используется следующим образом. Выражение фильтра применяется ко всем записям в базе посылок, и если на некоторой записи результат вычисления выражения равен true, то данная запись помечается как удовлетворяющая фильтру. Если при вычислении выражения фильтра хотя бы для одной посылки возникла ошибка, отображается информация об ошибке, а не результаты фильтрации. Если при вычислении выражения фильтра для всех записей завершилось успешно, из записей, удовлетворяющих выражению фильтра, отображаются записи в соответствии с заданным номером первой и номером последней записей. Выражение фильтра посылок имеет Си-подобный синтаксис. Пробельные символы, разделяющие элементы выражения, игнорируются. В именах типов и полей регистр символов является значимым.

Типы данных

Выражение фильтра посылок строго типизировано. Выражение может состоять из операций над значениями следующих типов:

  • Булевский. Булевский тип имеет имя bool. Литералы булевского типа обозначаются false и true соответственно.
  • Целый. Целый тип имеет имя int. В текущей реализации целый тип является 32-битным знаковым типом. Литералы целого типа могут записываться в восьмеричной, десятичной и шестнадцатеричной системах счисления как в языке Си. Знак «минус» перед числом не является частью числа, а рассматривается как унарная операция изменения знака.
  • Строковой. Строковой тип имеет имя string. Литералы строкового типа записываются либо в кавычках ("), либо в апострофах (’). Литералы первого вида не могут содержать внутри себя символ кавычки, а литералы второго вида — символ апострофа.
  • Календарный. Календарный тип имеет имя date_t и предназначен для записи астрономического времени. Литералов календарного типа не существует. Астрономическое время при расчётах представляется в формате POSIX, то есть как количество секунд, прошедших с 1 января 1970 года.
  • Длительностный. Длительностный тип имеет имя dur_t и предназначен для записи длительностей. При расчётах длительностный тип рассматривается как целый тип, и все длительности представляются в секундах. Литералов длительностного типа не существует.
  • Размерный. Размерный тип имеет имя size_t и предназначен для представления размеров объектов. Литералов размерного типа не существует. При расчётах размерный тип рассматривается как беззнаковый целый тип.
  • Статусный. Статусный тип имеет имя result_t и предназначен для представления статуса посылки. Статусный тип — это перечислимый тип, состоящий из литералов OK, CE, RT, TL, PE, WA, CF, PT, AC, IG, RU, CD, CG, AV, EM (см. таблицу Допустимые статусы посылок).
  • Контрольный. Контрольный тип имеет имя hash_t и предназначен для представления значений контрольной суммы SHA1. Литералов контрольного типа не существует.
  • Адресный. Адресный тип имеет имя ip_t и предназначен для представления IP-адресов. Литералов адресного типа не существует.

Преобразования типов

Выражение фильтра посылок строго типизировано, но для преобразований значений одного типа в значения другого типа могут использоваться операции преобразования типа.

Операция преобразования типа записывается в стиле Си++, то есть следующим образом:

type-cast-op = type-name "(" expr ")"

Здесь type-name — имя типа, одно из перечисленных выше bool, int, string, date_t, dur_t, size_t, result_t, hash_t, ip_t. Не все возможные преобразования типов допустимы. Возможные комбинации исходного типа и целевого типа показаны в таблице Допустимые комбинации типов в операции преобразования типов.

В строках таблицы записан исходный тип, а в столбцах таблицы — целевой тип.

Рассмотрим подробнее каждое нетривиальное преобразование типов.

  • int к bool. Даёт результат false, если приводимое целое значение равно нулю, и true иначе.
  • string к bool. Даёт результат false, если значение строки равно false (без учёта регистра), и результат true, если значение строки равно true (без учёта регистра). Если значение строки не может быть распознано как булевский литерал, генерируется ошибка вычисления выражения.
  • date_t к bool. Даёт результат false, если значение астрономического времени во внутреннем формате равно нулю, и true иначе. На практике астрономическое время может быть равно нулю (то есть 0:00:00 1 января 1970 года по Гринвичу), когда значение соответствующей переменной или поля не установлено.
  • dur_t к bool. Даёт результат false, если значение длительности равно 0 секундам, true иначе.
  • size_t к bool. Даёт результат false, если значение размера равно 0 байтам, и true иначе.
  • result_t к bool. Даёт результат true, если значение статуса равно OK, и false иначе. Обратите внимание на отличие семантики этой операции от других операций преобразования в булевский тип.
  • hash_t к bool. Даёт результат false, если значение хэш-кода равно нулю, то есть все 20 байт хэш-кода равны нулю, и true иначе. Нулевой хэш-код означает, что значение соответствующего поля или переменной не установлено.
  • ip_t к bool. Даёт результат false, если значение IP-адреса равно нулю, то есть все 4 байта IP-адреса нулевые, и true иначе. Нулевой IP-адрес означает, то значение соответствующего поля или переменной не установлено.
  • bool к int. Булевское значение false преобразуется в целое значение 0, а булевское значение true — в целое значение 1.
  • string к int. Строка рассматривается как запись числа в восьмеричной, десятичной или шестнадцатеричной нотации (в синтаксисе Си), возможно со знаком. Если число записано корректно и при переводе в 32-битный знаковый тип не возникает переполнения, результатом операции является соответствующее число. В противном случае генерируется ошибка.
  • date_t к int. Поскольку в настоящее время внутреннее представление типа date_t — это 32-битное знаковое число, то значением такого преобразования типов будет внутреннее представление астрономического времени.
  • dur_t к int. Поскольку в настоящее время внутреннее представление типа dur_t — это 32-битное знаковое число, то значением такого преобразования типов будет внутреннее представление промежутка времени, то есть число секунд в нём.
  • size_t к int. В настоящее время тип size_t — это 32-битный беззнаковый целый тип. Если значение размера при переводе из беззнакового представления в знаковое не вызывает переполнение (то есть значение размера не превосходит 2^31 − 1 , выполняется преобразование из беззнакового типа в знаковый без изменения представления числа. В противном случае генерируется ошибка.
  • result_t к int. Результатом такого преобразования является числовое значение, соответствующее коду статуса (см. таблицу Допустимые статусы посылок).
  • hash_t к int. Результатом такого преобразования является целое значение, составленное из первых 4 байтов хэш-кода. Предполагается, что байты в числе записываются в порядке от младшего к старшему (litte-endian).
  • ip_t к int. Поскольку IP-адрес (IPv4) состоит из 4 байт, эти 4 байта рассматриваются как целое число со знаком, записанное в порядке байт от старшего к младшему.
  • bool к string. Значение false преобразовывается в строку false, а значение true — в строку true.
  • int к string. Целое значение преобразуется в строку, содержащую запись десятичного целого числа со знаком.
  • date_t к string. Астрономическое время преобразуется в строку вида
YYYY/MM/DD hh:mm:ss

Здесь YYYY — год, MM — месяц (от 01 до 12), DD — день месяца (от 01 до 31), hh — час (от 00 до 23), mm — минута (от 00 до 59), ss — секунда (от 00 до 59).

  • dur_t к string. Продолжительность преобразуется в строку вида
#h:mm:ss

Здесь # — знак продолжительности (для положительной продолжительности знак не выводится, а для отрицательной печатается знак -), h — число полных часов, mm — число минут в последнем неполном часе (от 00 до 59), ss — число секунд в последней неполной минуте (от 00 до 59).

  • size_t к string. Значение размера преобразуется в строку, содержащую запись десятичного целого числа без знака.
  • result_t к string. Значение статуса преобразовывается в строку в соответствии с таблицей Допустимые статусы посылок (столбец «Выражение фильтра»). Например, значение статуса RUN_TIME_ERR преобразуется в строке RT.
  • hash_t к string. Значение хэш-кода распечатывается в виде 40 шестнадцатеричных цифр (по два символа на байт от первого байта хэш-кода к последнему). В качестве шестнадцатеричных цифр используются десятичные цифры и строчные латинские буквы от a до f.
  • ip_t к string. IP-адрес переводится в строку, содержащую запись адреса в стандартной точечной нотации (то есть 4 десятичных числа от 0 до 255, разделённые точками).
  • int к date_t. Поскольку тип date_t представляется как 32-битное целое знаковое число, при данном преобразование целое значение рассматривается как внутреннее представление астрономического времени.
  • string к date_t. Для преобразования строки к типу астрономического времени строка должна иметь значение, удовлетворяющее следующему формату
Y / M / D [ h [ : m [ : s ] ] ]

Здесь запись [ X ], означает, что элемент X может отсутствовать, символы / и : представляют сами себя, а Y, M, D, h, m, s — это целые десятичные числа. Они могут отделяться от / и : произвольным количеством пробельных символов. Y — это год, который должен находиться в интервале от 1900 до 2100, M — порядковый номер месяца (от 1 до 12), D — порядковый номер дня в месяце (от 1 до 31), h — час суток (от 0 до 23), m — минута (от 0 до 59), s — секунда (от 0 до 59). Если часы, минуты или секунды опущены, они полагаются равными 0. Кроме того, дата должна находится в диапазоне представимых в POSIX дат (то есть примерно от 1906 до 2038 года). Если все условия выполняются, строковая запись астрономического времени конвертируется во внутреннее представление, а в противном случае генерируется ошибка.

  • int к dur_t. Поскольку тип dur_t представляется как 32-битное целое знаковое число, при данном преобразование целое значение рассматривается как внутреннее представление промежутка времени.
  • string к dur_t. Для преобразования строки к длительностному значению строка должна иметь значение, удовлетворяющее следующему формату.
[ # ] h [ : m [ : s ] ]

Здесь запись [ X ], означает, что элемент X может отсутствовать. # — это знак + или -. h, m и s — положительные целые числа. h — количество часов, m — количество минут (от 0 до 59), s — количество секунд (от 0 до 59). Если минуты или секунды опущены, их число полагается равным 0. После перевода в секунды длительность должна находится в диапазоне целых чисел, представимых 32-битными знаковыми числами. Если все условия выполняются, то строковая запись длительностного значения конвертируется во внутреннее представление, а в противном случае генерируется ошибка.

  • int к size_t. Поскольку int — это 32-битный знаковый тип, а size_t — 32-битный беззнаковый тип, неотрицательные значения типа int преобразовываются в значения типа size_t тривиально. При попытке преобразования отрицательных чисел генерируется ошибка.
  • string к size_t. Строка должна содержать запись беззнакового целого числа в восьмеричной, десятичной или шестнадцатеричной системе (как в языке Си). Число должно быть представимо 32-битным беззнаковым числом. Если эти условия выполняются, происходит преобразование строки в значение типа size_t, а в противном случае генерируется ошибка.
  • int к result_t. Целое значение должно быть равным одному из значений статусов, перечисленных в таблице Допустимые статусы посылок. В этом случае выполняется преобразование типа, а иначе генерируется ошибка.
  • string к result_t. Строка должна быть равна одной из строк, перечисленных в таблице Допустимые статусы посылок в столбце «Выражение фильтра». В этом случае выполняется преобразование, в иначе генерируется ошибка.
  • string к hash_t. Строка должна содержать 40 шестнадцатеричных цифр (буквы от a до f могут быть как заглавными, так и строчными). Пробельные символы в начале и конце строки игнорируются. 40 шестнадцатеричных цифр конвертируются в 20-байтное значение хэш-кода. Предполагается, что порядок байт в слове — от младшего к старшему (little-endian).
  • int к ip_t. Поскольку значения типа ip_t представляются 32-битными числами, преобразование из типа int не изменяет представления данных, то есть целое число рассматривается как запись IP-адреса во внутреннем представлении.
  • string к ip_t. Для преобразования строки к типу ip_t строка должна иметь значение, удовлетворяющее следующему шаблону.
A.B.C.D

Здесь . — это символ «точка», а A, B, C и D — целые беззнаковые числа от 0 до 255. Если эти условия выполняются строка конвертируется в соответствующее значение типа ip_t, а в противном случае генерируется ошибка.

Примитивы доступа к базе посылок

Текущей посылкой назовём обрабатываемую при вычислении выражения фильтра посылку. На основании результата вычисления выражения фильтра определяется, может ли быть отображена текущая посылка.

Примитивы доступа к базе посылок позволяют получать значения полей как текущей посылки, так и любой другой посылки с заданным номером. Примитивы имеют следующий общий вид:

f [ ( expr ) ]

Здесь в квадратных скобках [ и ] записана необязательная часть. Круглые скобки ( и ) обозначают сами себя. f — это имя примитива, а expr — это выражение целого типа. Если выражение в скобках не задано, то берётся значение поля, соответствующего имени примитива f, текущей посылки. Если выражение в скобках не является выражением целого типа, генерируется ошибка. В противном случае выражение вычисляется, и пусть при вычислении выражения ошибок не возникло, а n — результат вычисления выражения.

Если n < 0, то n задаёт номер посылки начиная от последней, то есть n′ = N +n, где N — общее количество посылок в базе посылок в данный момент. В противном случае предполагаем, что n задаёт номер посылки начиная от нулевой, то есть n′ = n. Если теперь n′ < 0 или n′N, то генерируется ошибка вычисления выражения фильтра. Если же n′ удовлетворяет ограничениям, берётся значение поля, соответствующего имени примитива f, в посылке с номером n′. Примитивы доступа к базе посылок перечислены в таблице Примитивы доступа к базе посылок.

Другие примитивы

В выражении фильтра можно использовать примитивы для получения текущего времени, текущей продолжительности турнира и некоторые другие. Все такие примитивы рассмотрены в данном разделе. Примитивы имеют следующий общий вид:

p

где p — это имя примитива. Примитивы перечислены в таблице Прочие примитивы.

Приоритеты операций

В данном разделе перечислены все операции, допустимые в выражении фильтра. Операции перечисляются в порядке убывания приоритета от наиболее приоритетных к наименее приоритетным.

  • Все литеральные значения (булевские, целые, строковые, статусные), все примитивы, операции преобразования типа, операция записи выражения в скобках (expr).
  • Префиксные операции ˜, !, -, +. Префиксные операции читаются справа налево.
  • Мультипликативные операции *, /, %. Мультипликативные операции левоассоциативны, то есть читаются слева направо.
  • Аддитивные операции +, -. Они читаются также слева направо.
  • Операции сдвига << и >>. Читаются слева направо.
  • Операции отношений ==, !=, <, >, <=, >=. Читаются слева направо.
  • Операция побитового «и» &. Читается слева направо.
  • Операция побитового исключающего «или» ^. Читается слева направо.
  • Операция побитового «или» |. Читается слева направо.
  • Операция логического «и» && или and (эти формы записи синонимичны). Читается слева направо.
  • Операция логического «или» || или or (эти формы записи синонимичны). Читается слева направо.

Далее рассмотрим все перечисленные операции.

Операция побитового отрицания ˜

Операция применима только к значению типа int. Результат операции — значение типа int, получаемое побитовым отрицанием первого значения.

логического отрицания !

Операция применима только к значению типа bool. Результат операции — значение типа bool, получаемое логическим отрицанием исходного значения.

Операция смены знака -

Унарная операция смены знака применима только к значению типа int. Результат операции — значение типа int с противоположным знаком. Если результат операции не представим в типе int (то есть 32-битным знаковым числом), диагностируется ошибка переполнения.

«Пустая» операция +

Данная операция применима только к значению типа int и даёт результат типа int. Результирующее значение равно исходному.

Операция умножения *

Для операции умножения возможны следующие комбинации типов операндов.

  • Оба аргумента имеют тип int. Результат имеет тип int. Если результат не представим в типе int диагностируется переполнение.
  • Один аргумент имеет тип int, а другой — dur_t. В этом случае результат имеет тип dur_t. Если произведение аргументов не представимо в типе dur_t, диагностируется переполнение.
  • Один аргумент имеет тип int, а другой — size_t. Значение аргумента целого типа в данном случае должно быть больше нуля. Произведение имеет тип size_t. Если значение произведения не представимо в типе size_t, диагностируется переполнение.

Операция целочисленного деления /

Для операции целочисленного деления возможны следующие комбинации типов операндов. Если делитель равен нулю, диагностируется ошибка деления на ноль. Если результат операции не представим в типе результата, диагностируется ошибка переполнения. Например, при делении минимального значения типа int, равного −2^31 на -1 получается значение 2^31, не представимое в типе int.

  • Оба аргумента имеют тип int. Тогда результат имеет тип int.
  • Оба аргумента имеют тип dur_t. Тогда результат имеет тип int.
  • Оба аргумента имеют тип size_t. Тогда результат имеет тип int.
  • Делимое имеет тип size_t, а делитель — тип int. Результат в этом случае имеет тип size_t. Делитель должен быть положителен.

Операция взятия остатка от деления %

Операция взятия остатка поддерживает несколько комбинаций типов аргументов. Если делитель равен нулю, диагностируется ошибка деления на ноль. Если тип делителя — какой-либо знаковый тип (например, int или dur_t), и делитель отрицателен, диагностируется ошибка неверного аргумента. Если результат операции не представим в типе результата, диагностируется ошибка переполнения. Допустимые комбинации типов операндов перечислены ниже.

  • Оба аргумента имеют тип int. Тогда результат имеет тип int.
  • Оба аргумента имеют тип dur_t. Тогда результат имеет тип int.
  • Оба аргумента имеют тип size_t. Тогда результат имеет тип int.
  • Делимое имеет тип dur_t, а делитель — тип int. Тогда результат имеет тип dur_t.
  • Делимое имеет тип size_t, а делитель — тип int. Результат в этом случае имеет тип size_t.

Операция сложения +

Операция сложения применима ко многим комбинациям типов операндов. В любом случае, если результат операции не представим в типе результата, генерируется ошибка переполнения. Допустимые комбинации типов операндов перечислены ниже.

  • Оба аргумента имеют тип int. Результат также имеет тип int.
  • Оба аргумента имеют тип string. Результат имеет тип string и равен конкатенации двух строк.
  • Оба аргумента имеют тип dur_t. Результат также имеет тип dur_t.
  • Оба аргумента имеют тип size_t. Результат также имеет тип size_t.
  • Один аргумент имеет тип int, а другой — time_t. Результат имеет тип time_t.
  • Один аргумент имеет тип int, а другой — dur_t. Результат имеет тип dur_t.
  • Один аргумент имеет тип time_t, а другой — dur_t. Результат имеет тип time_t.

Операция вычитания -

Операция вычитания применима ко многим комбинациям типов операндов. В любом случае, если результат операции не представим в типе результата, генерируется ошибка переполнения. Допустимые комбинации типов операндов перечислены ниже.

  • Оба аргумента операции имеют тип int. Результат также имеет тип int.
  • Первый аргумент операции имеет тип time_t, а второй — int. Результат операции имеет тип time_t.
  • Оба аргумента операции имеют тип time_t. В этом случае результат имеет тип dur_t.
  • Первый аргумент операции имеет тип time_t, а второй — dur_t. Результат имеет тип time_t.
  • Первый аргумент имеет тип dur_t, а второй — int. Результат имеет тип dur_t.
  • Оба аргумента операции имеют тип dur_t. В этом случае результат имеет тип dur_t.
  • Первый аргумент операции имеет тип size_t, а второй — int. Тогда результат имеет тип size_t.
  • Оба аргумента операции имеют тип size_t. В этом случае результат имеет тип int.

Операции сдвига << и >>

Операции побитового сдвига влево << и побитового сдвига вправо >> применимы только к операндам типа int. Результат операции имеет тип int. Второй аргумент операции (количество бит сдвига) должен находиться в отрезке от 0 до 32 включительно. Если это условие не выполняется, генерируется ошибка недопустимого аргумента операции. Сдвиг вправо выполняется как побитовый сдвиг, то есть на место старших разрядов числа помещаются нулевые биты. Переполнения при сдвиге влево не диагностируется.

Операции отношения == и !=

Операции проверки на равенство или неравенство применимы ко всем типам данных. Оба аргумента должны иметь один и тот же тип. Неявных преобразований типа не производится. Результат операции имеет тип bool.

Операции отношения <, >, <=, >=

Данные операции применимы ко всем типам данных, кроме result_t, hash_t и ip_t. Оба аргумента операции должны иметь один и тот же тип данных. Результат операции имеет тип bool.

Побитовые операции ˆ, &, |

Побитовые операции применимы только к аргументам типа int и в результате дают значение типа int.

Логические операции && и ||

Логические операции применимы только к аргументам типа bool и дают в результате значение типа bool. Как и в языке Си значение второго аргумента операции не вычисляется, если значение всего выражение известно.