37! ≈ 1,37×10⁴³

13-го сентября рано утром, 37 лет назад родился я. Хорошо, что сегодня этот день я провожу со своей женой, были все шансы провести его в Москве, куда я уехал в четверг в купе №13 поездом по работе, но сегодня ночью я вернулся, сидя в самолёте на 13-м ряду. Забавный символизм. Я (47.81КБ) Итак, что же произошло у меня в жизни за минувший год, с прошлого Дня рождения: Вцелом, кажется, стал меньше писать в блог и бо́льшую часть своей творческой энергии отдавать в проект, разработкой которого я руковожу — это система облачного документооборота.
9 комментариев
13 сентября 2014 12:40

Преобразование tnsnames.ora в JSON

По работе сделал разбор файла tnsnames.ora — файла оракловой конфигурации на ПХП в массив:
function Ora2Array($str)
{
    // убираю комментарии
    $str = preg_replace('/^\s*#.*$/m', '', $str);

    // преобразование скаляров
    $str = preg_replace('/\((\w+)\s*=\s*([^()]+)\)/m', '"$1": "$2", ', $str);

    // преобразование ассоциативных массивов
    do {
        $str = preg_replace('/\((\w+)\s*=\s*([^()]+?)[\s,]*\)/sS', '"$1": { $2 },', $str, -1, $count);
    } while ($count);

    // преобразование верхнеуровневых значений
    $str = preg_replace('/(\w+)\s*=\s*([^()]+?)[\s,]*(?:(?=\w+\s*=)|\s*$)/s', '"$1": { $2 },', $str);

    return json_decode('{' . trim($str, ' ,') . '}', true);
}
Не разбираются значения в кавычках — такого в наших конфигурациях не встречается, но добавляется несложно.
Комментировать
11 сентября 2014 15:34

Сцорпероба

«Сцорпероба» — в дословном переводе означает «ровные по цвету». Молодой мужчина может в своей деревне выбрать себе девушку «ровней» конечно только с ее личного согласия. Это означает, что у них могут быть романтические отношения, он может ей дарить подарки, а она например вязать для него одежду и прочее.

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

Как правило, у этих пар платонические отношения и вечера, и ночи они проводят в беседе о радости жизни. А под утро засыпают или спиной друг к другу, или мужчина на спине, а женщина на грудь кладет ему голову. Когда наступает утро, есть правило, что женщина подает своему «ровне» рог водки (в горной Грузии нет виноградников, и там нет культуры вина как в долинной) и еду, он выпивает, благодарит и уходит по делам. Ровни не могут женится и создать семью, они должны оставить между собой чистые, романтические отношения.
Цитата из комментариев к видео, где три девушки поют по-грузински песню про двух «ровней».
7 комментариев
9 сентября 2014 07:15

Memcached и UDP

Когда я написал про поддержку модулем Мемкешед для ПХП протокола UDP, я ещё не знал многих подробностей. Например, я думал, что ребятам из Мемкешед чем-то не понравился TCP/IP и они написали поверх UDP свой протокол гарантированной доставки. В приципе, так бывает, например так работает гугловский «КВИК».

Оказывается ничего подобного — UDP нужен только тогда, когда вас устраивает негарантированная доставка, т.е. вы швырнули пакет, а дойдёт ли он до кеша — неважно, при чтении это будет считаться промахом кеша.

В интернете есть статья, которая кратко раскрывает что это даёт, в ней же приводится патч «multi UDP», который Мемкешеду уже не нужен — я смотрел в код, всё там нормально давно.

Кстати, обнаружились две подробности в поддержке UDP модулем Мемкешед ПХП. Во-первых, указывать в конструкторе persistent_id нельзя — ничего работать не будет без каких-либо ошибок. Во-вторых, реализована только операция записи (при попытке сделать get получим ошибку ACTION NOT SUPPORTED), читать придётся через TCP/IP.

Работоспособный тест выглядит так:
$m = new Memcached('SomeID');
$m->addServer('127.0.0.1', 11211, 1);

$m_udp = new Memcached();
$m_udp->setOption(Memcached::OPT_USE_UDP, true);
$m_udp->addServer('127.0.0.1', 11211, 1);

var_dump($m_udp->set('foo', "test string"));
sleep (1);
var_dump($m->get('foo'));
Комментировать
7 сентября 2014 16:15

Недвижимая лестница

Недвижимая лестница (188.87КБ) Когда мы с женой несколько лет назад были в Иерусалиме, около храма Гроба Господня, возможно я и видел на карнизе эту деревянную лестницу, но внимания точно не обратил — ну мало ли строительного инвентаря встречается у храмов? Я специально не стал вырезать из фото нужное место, чтобы было заметно насколько не цепляется глаз за эту деталь.

Оказывается, эта лестница стоит там по меньшей мере с 1834 года. Причина того, что она простояла там так долго — договорённость шести конфессий, владеющих храмом — ничего не менять, не двигать, не ремонтировать в храме без согласия всех шести владельцев.

На всех фотографиях этого храма, я с тех пор как узнал эту историю, обязательно замечаю эту лестницу.
2 комментария
3 сентября 2014 13:10

99 бутылок пива на стене

Потихоньку возобновил наполнение раздела «99 бутылок пива на стене» — там я пишу американскую считалочку про пиво на различных языках программирования. Добавились языки VIM script и Batsh. Первый используется в консольном редакторе vim для написания внутренних скриптов, второй — для кроссплатформенного написания шелл-скриптов.

Batsh мне вообще понравился своей идеей — простой Си-подобный язык, который умеет транслироваться и в баш (Линукс, МакОС и так далее) и в бат-файлы (Виндоуз). Не уверен нужно ли это в жизни, но абстрактно идея хороша.
4 комментария
3 сентября 2014 10:25

is_numeric

Функция is_numeric одна из традиционно неверно понимаемых программистами на ПХП. Её, обычно, понимаю как «посмотреть содержится ли в переменной что-то похожее на число». Например, таким образом проверяют пришло ли число в строке для последующего его преобразования в численный тип.

Беда в том, что понятия числа у ПХП и человека различаются. Посмотрите, все эти вызовы рассматриваемой функции вернут «true»:
var_dump(is_numeric("123e123")); // true — десятичное число в экспоненциальной записи
var_dump(is_numeric("0123")); // true — восьмеричное число
var_dump(is_numeric("0XDeadBeef")); // true — шестнадцатеричное число
var_dump(is_numeric(NAN)); // true — специальное численное значение «не число»
Особенно не везёт восьмеричным числам, которые во многих языках (и в ПХП) тоже начинаются с нуля: формально выглядят как обычное десятичное (только начинается с нуля), проходят все проверки, а после преобразования теряют ведущий ноль и это может быть важно.

С незапамятных времён существует хак, который позволяет убедиться, что перед нами именно десятичное число, пусть и в строковой форме:
function is_number($var) { return (string) (int) $var === (string) $var; }
Принцип очень простой — переменная преобразуется в целый тип (можно преобразовывать и в тип с плавающей точкой, если это нужно), потом берётся строковое представление получившегося числа. На этом этапе восьмеричные, шестнадцатеричные и прочие виды записи чисел будут преобразованы в целочисленный тип, строковое представление которого — десятичное число. Справа же пришедшее остаётся в первозданном виде.

Далее мы сравниваем левую и правую часть и, если они совпадают, значит к нам пришло именно десятичное число, так как никаких преобразований с ним не произошло.

Добавлено позднее: в документации к функции написано, что она так же понимает двоичную форму записи введёную недавно (число должно начинаться с «0b»), к сожалению, это неправда — в коде поддержки нет, баг заведён и в нём написано, что это проблема документации, а не функции.

Интересно ещё, что is_numeric пропускает любое количество пробельных символов слева, но плохо относится к ним справа:
var_dump(is_numeric("\f\f\t0xBadBabe")); // true
var_dump(is_numeric("1\t")); //false
8 комментариев
28 августа 2014 10:25

Мокрая вода, твёрдый алмаз, быстрый фотон

Ребята, ну нет никакого «нижнего подчёркивания». Подчёркивание всегда внизу, под чем-то. Это ↘_↙ просто подчёркивание. Оно по определению нижнее, не бывает ни среднего, ни верхнего. Уточнение, что оно внизу лишнее.
18 комментариев
27 августа 2014 22:19

Велодорога домой

Бо́льшая часть моих велопрогулок — это примерно 15 километров совокупной дороги с работы и на неё. Езжу почти каждый день, если нет дождя, а они пока ещё не так уж и часты. Сегодня случился своеобразный рекорд — моя средняя скорость была 20 км/ч. Учитывая пешеходов, светофоры и пересечённый характер местности, совсем немало. Велодорога домой (125.47КБ)
3 комментария
27 августа 2014 20:54

Недокументированные возможности модулья Memcached (для PHP)

Читая на досуге исходники модуля Memcached для ПХП, наткнулся на неожиданное: оказывается этот модуль поддерживает соединение по протоколу UDP, причём документация молчит об этом.

Делается это вот так:
$udp = new Memcached();
$udp->setOption(Memcached::OPT_USE_UDP, true);
$udp->addServer($host, $port);
В частности, это позволит нам перейти на multi-UDP схему, если добавить разные порты как несколько серверов. Надо пробовать.

Другая вещь, которая никак не раскрывается документацией — пользовательские флаги (UDF — user defined flag). К каждому значению можно прикрепить один или несколько флагов, которые при получении значения будут складываться в заданную переменную:
const FLAG = 1;
const ANOTHER_FLAG = 2;

$m->set($key, 'value', 0, FLAG | ANOTHER_FLAG); // установили флаг
$m->get($key, null, null, $flags); // флаги будут лежать в переменной $flags
У каждой функции установки и получения значений (а их несколько, этих функций) в конце есть необязательный параметр для работы с флагами. Так что во всех вариантах использования значения можно как-то пометить, а потом эти пометки получить.

Позднее дополнение: похоже memcached больше не нуждается в multiport UDP patch, он и без него теперь с UDP работает нормально.
4 комментария
27 августа 2014 16:13

Короткий способ определить есть ли поддержка dataURI

Придумал короткий способ определить поддержку data URI в браузере:
<script src="data:text/javascript,self.dataURI=1"></script>
Потом просто проверяете у window свойство dataURI, если оно есть, то есть и поддержка. Способ не работает в IE8 и IE9 — тот и другой не умеют загружать Джаваскрипт этим образом. Собственно, меня это не волнует — мне как раз и нужно определить, что Джаваскрипт так работает, но если вам нужно не это, то должен работать вот такой способ:
<link rel="stylesheet" href="data:text/css,html{font-size:99px}">
То есть устанавливаем у тега HTML какое-нибудь свойство, которое потом в BODY перекроем, а позже, чтобы убедиться, что поддержка дата-ури есть, смоторим что вышло (тут я при помощи jQuery это делаю):
/99/.test($('html').css('font')); // true, если есть поддержка dataURI

PHP7

Всё, PHPNG отправился в «мастер», по всей видимости, это означает, что он появится сразу после версии 5.6, которую мы увидим буквально на днях (я уже немного писал о том, что в ней нового).

PHPNG — новая версия интерпретатора, которая, по всей видимости, будет носить номер семь, чтобы избежать путаницы с PHP6 — неудавшейся попыткой перевести ПХП на Юникод, которую широко в своё время освещали, но сообщество решило от неё отказаться — большинство разработчиков англоязычны и выгоды от этого трудоёмкого процесса не видели.

Новая версия ПХП интересна переработанными внутренностями, изменение которых связано со скоростью. Установленный «ВордПресс» работает на новой версии в два раза быстрее, что впечатляет, конечно. Плохая новость — придётся переделать бо́льшую часть модулей (если не вообще все). Процесс этот сейчас движется, но только для модулей, входящих в язык, несколько модулей (в том числе важный для меня OCI8) пока ещё не поправлены.

Думаю, что миграция авторских модулей произойдёт довольно быстро.
7 комментариев
25 августа 2014 13:47

Странное с Флешем

Я с «Флешем» в последние годы не сталкивался, но и прежде подобного поведения не наблюдал. В общем, решил я вчера обновить в нашем продукте библиотеку ВебКамДжиЭс, она у нас для получения фотографии с камеры используется. Прежняя была 0.9, а тут я случайно обнаружил, что релиз вышел.

В прежней изображение с камеры получалось через Флеш, а релизная умеет использовать АПИ браузера, если таковое имеется. Правда, в «Сафари», которым я пользуюсь, этого АПИ нет и всё равно используется Флеш. Вот тут-то и столкнулся с трудностями — прежняя версия работала прекрасно, а новая отказывалась — в окне Флеша изображение с камеры есть, но ДжаваСкрипт был уверен, что всё плохо и, самое главное, не мог достучаться до Флеша.

В принципе, можно было откатиться на предыдущую версию, но смущало, что на демо-сайте ВебКама в «Сафари» всё работало нормально. Я попробовал несколько вариантов, прежде чем мне пришла в голову идея посмотреть заголовки запросов. И заметил разницу, показавшуюся несущественной, но всё-таки я решил попробовать её устранить — mime type различался.

У нас сервер отдавал Флеш с типом «application/x-shockwave-flash», а в демо-примере был «binary/octet-stream». Стоило поменять этот заголовок, и всё заработало.

Беглое гугление света не пролило, но если столкнётесь с похожей проблемой, имейте ввиду, возможное решение — смена типа для отдаваемого флеш-ролика.
Комментировать
23 августа 2014 12:36

Короткий способ определять IE

А какой сейчас самый короткий способ определять Эксплорер? Я понимаю, что привязываться к браузеру нехорошо, но у меня конкретная задача, которую никак не обойти — нужно проиграть звук в браузере (PCM wave), а ИЕ на запрос «сможешь проиграть?» к тегу AUDIO, говорит maybe. Т.е. давайте сюда свой звук, может и смогу. Я-то знаю, что не сможет — аудиотег в этом браузере «вавки» не играет, нужен EMBED.

Все короткие способы, которые раньше работали (условная компиляция, сравнение вертикального пробела с буквой v, хитрый хак с массивом и прочее) в 11-й версии работать перестали. Даже строку агента поменяли — там теперь нет MSIE.

В общем, я пока остановился на такой версии:
if (top.VBArray) {
    // IE
} else {
    // остальные браузеры
}
Но буду признателен за что-то более короткое или очевидное.
8 комментариев
19 августа 2014 14:14

ANSI-коды в имени точки вайфай

Давно интересно было посмотреть отфильтруются ли АНСИ-последовательности из имён вайфай-точек в утилитах командной строки. Оказалось, что в «Маке» фильтра нет и, посмотрев список предпочтительных сетей, можно в этом убедиться: ANSI-последовательности в имени вайфай-сети (20.31КБ) Естественно, в графическом интерфейсе ничего такого нет: ANSI-последовательности в графическом интерфейсе (44.04КБ) Судя по спецификации, в имени должна быть строка до 32 байт, заканчивающаяся символом с кодом ноль. Других ограничений нет, так что и такое странное имя можно задать.
6 комментариев
16 августа 2014 23:04