LINUX.ORG.RU
решено ФорумTalks

Я люблю тебя, PHP!

 ,


0

2

Написал серверное приложение на чистом С. Оно слушает порт, а PHP с ним соединяется и получает данные в json-формате.

Несколько часов убил на то, чтобы понять почему PHP не может сделать json_decode. Наконец, написал минимальный пример:

$ cat test.php 
<?php

$s1 = '["1", "2"]';
echo "1 ", var_dump(json_decode($s1)), "\n";

$s2 = $s1 . "\0";
echo "2 ", var_dump(json_decode($s2)), "\n";

$ php test.php
1 array(2) {
  [0]=>
  string(1) "1"
  [1]=>
  string(1) "2"
}

2 NULL

Да это же просто феерично! Я добавил нулевой символ в конец строки, а она перестала быть корректным json, твою мать! Я даже сравнил побайтово две строки, вывев их в файл: отличие только в \0 на конце.

Что за специалист писал такой парсер json-а в php?!

---

Отныне это тред о впечатлениях, оставшихся после встречи с неочевидными, глупыми и неграмотными решениями в разных ЯП. Делись своими впечатлениями, лоровец.

★★

Последнее исправление: CYB3R (всего исправлений: 1)
Ответ на: комментарий от bk_

Пусть бы и добавили в стандарт, мне не жалко, но зря ты начал чморить PHP на эту тему, как раз в PHP оказалось все формально правильно)

goingUp ★★★★★
()
Ответ на: комментарий от bk_

Я тебя понял, отлично. Ты перекладываешь ответственность со стандарта языка на местную библиотеку, которая оперирует строками + местный парсер, написанный по этому стандарту - Я ВЕРНО ПОНЯЛ?

я перекладываю ответвенность за работу со строками на местную библиотеку, т.е. библиотека имеет на входе последовательность любых байт в виде нативной для языка «строки», а на выходе выдаёт нативный для языка «объект». + обратная операция. Входящая строка должна содержать в себе корректный поток данных (любых в т.ч. \0). Т.е. в пхп строка S\0 != S, а \0 не является корректным токеном, поэтому должна быть ошибка.

Если так, то теперь давай представим, если бы в стандарте это прописали. Исчезли бы *все* недомолвки.

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

Я понимаю, если бы это было редкая последовательность символов типа \1\0\0\5\0\0\,

ты понимаешь, что это валидная последовательность в json?

Получается, что это просто недосмотр автора стандарта. А все комментаторы, которые мне приводят мне контраргументы, я уверен, оперируют лишь одним фактом: в моем любимым ЯП это работает точно также, значит - это правильно, а то, что у ТСа - по определению неверно, чем бы оно ни было.

оно работает как я описываю в C, haskell, php. Я тебе объяснил почему оно должно быть написанно именно так, как написано и почему это language independent, в отличии от твоего варианта. И да твой случай неверен, но не потому, что у меня оно работает.

qnikst ★★★★★
()
Ответ на: комментарий от bk_

А то, что utf-8 с успехом опирается на это говно мамонта?

И так. Есть юникод — таблица символов. Есть string — последовательность символов. Есть utf-8 — описание того, как преобразовать string → []byte (или наоборот), то есть последовательность символов в последовательность байт (или наоборот). В этом string на любой позиции может встретиться \0 как корректный символ из таблицы юникода, который в случае utf8 будет представлен как байт 0x00.

При этом в нултерминейтед строке байт \0 никак не соответствует какому-либо символу строки, это деталь внутреннего представления строки в компьютере в виде последовательности байт. Что в общем-то не должно волновать программиста, кроме некоторых узких случаев.

В случае си у нас смешиваются аж три сущности. Строка (массив символов), внутреннее представление (массив байт в памяти в момент работы программы, соответствующей строке в какой-либо удобной для работы кодировке, вполне возможно, что это вряд ли будет utf-8) и заенкоженная строка для внешнего представления (массив байт, который в определённой кодировке соответствует набору символов) для передачи по сети или записи в файл.

PolarFox ★★★★★
()
Ответ на: комментарий от bk_

С _какой целью_ новые языки сломали роль \0 как терминала строки?

Какие, в баню, новые? Форт и Паскаль ровесники Си, Бейсик старше лет на пять. Подозреваю, что Лисп тоже не обязан быть знакомым с проблемой \0. Что ещё за _новые_ языки? Проблема нулевого символа — это частная сишная проблема. Почему на неё должны ориентироваться остальные?

Вопрос: _зачем_ было ломать это правило, что \0 - признак конца строки, если никакой пользы оно не дает?

Какое же это «правило», когда его только Си и ориентированные на него соблюдали?

KRoN73 ★★★★★
()
Ответ на: комментарий от goingUp

но зря ты начал чморить PHP на эту тему, как раз в PHP оказалось все формально правильно)

Это называется не «правильно», а «в соответствии со стандартом». А в стандарте по этому поводу сказано просто - «все остальные символы - ошибка парсинга». Очевидно, что \0 в конце строки не должен рассматриваться как ошибка парсинга. А наличие \0 где-то в середине json-строки намекает на ее некорректность.

bk_ ★★
() автор топика
Ответ на: комментарий от bk_

Я хочу

_байты_ в _строках_

Иди-ка лесом, быдлокодер.

PolarFox ★★★★★
()
Ответ на: комментарий от bk_

Очевидно, что \0 в конце строки не должен рассматриваться как ошибка парсинга

Не очевидно.

KRoN73 ★★★★★
()
Ответ на: комментарий от bk_

Очевидно, что \0 в конце строки не должен рассматриваться как ошибка парсинга.

Должен. Из-за кривой работы со строками в си ты почему-то сам того не замечая передаёшь байт \0, не относящийся к строке, а потом жалуешься, что не работает. С паскалевскими строками тоже можно было бы набыдлокодить, отсылая не ютф8, а внутреннее представление строки в виде массива байт, где первым байтом будет чёрти что.

PolarFox ★★★★★
()
Ответ на: комментарий от bk_

Есть очевиднейший формат строки, которому уже почти полвека.

Есть чудовищно устаревший формат строки, которому уже полвека и который был актуален лет так 20-30 назад. В современном мире этот стандарт смотрится как мушкет среди всей линейки оружия

Приходят дяди с книжками пхп и js в руках и говорят, что

php? js? Увольте :) Всего лишь приходят дядьки, которые начинают понимать, что кроме ортодоксальных latin-1 и производных однобайтных кодировок есть туча других алфавитов. В том числе и иероглифов и мёртвых языков.

«На Си свет клином не сошёлся»

:) Вывод очевиден

Да, вывод очевиден. Целевая ниша Си - низкоуровневое программирование. А обработку JSON нужно доверить более другим приложениям, написанным на более высокоуровневых языках, на которых правило «language-independ» соблюсти проще. Или же можно реализовать всё то же самое на чистом Си, но при этом нужно также уважать правило «language-independ», а не кичиться полувековой историей костылей.

Slavaz ★★★★★
()
Последнее исправление: Slavaz (всего исправлений: 1)
Ответ на: комментарий от bk_

«все остальные символы - ошибка парсинга»

\0 в конце строки как раз и включает в себя «все остальные символы».

А наличие \0 где-то в середине json-строки намекает на ее некорректность.

Если в кавычках, то нет, через json можно передавать и бинарные данные, например картинку.

goingUp ★★★★★
()
Ответ на: комментарий от KRoN73

Если тебе не нравится слово «правило», назови это как угодно. Вопрос в том, зачем было ломать на тот момент устоявшийся признак \0 конца строки, если это ничего не приносило полезного? Какая польза от «свободного» \0?

bk_ ★★
() автор топика
Ответ на: комментарий от PolarFox

Если кратко.

В виде нултерминейтедстринг где-то в памяти по смещению 0x002fc598 лежит у тебя «ABC\0». Но строка в виде UTF8 (а в данном случае и ASCII) — «ABC». Так вот. Стандарт требует строку в определённой кодировке, а не то, что у тебя по смещению 0x002fc598, включая мусор.

PolarFox ★★★★★
()
Ответ на: комментарий от goingUp

через json можно передавать и бинарные данные, например картинку.

Сферический конь в вакууме. Кто так делает?

Я говорю о реальном примере, когда я открыл файл, а там нулевой символ в конце. А пхп зафейлился его парсить, хотя \0 нечитабельный.

bk_ ★★
() автор топика
Ответ на: комментарий от bk_

я открыл файл, а там нулевой символ в конце

А кто его туда записал? Ну и да, файл, пока у него нет кодировки — последовательность байт. Не символов, бл^W, а байт.

PolarFox ★★★★★
()
Ответ на: комментарий от bk_

Какая польза от «свободного» \0?

он может встречаться в символах многобайтных кодировок.

Теперь встречный вопрос: а какой вред от «свободного» \0?

Slavaz ★★★★★
()
Ответ на: комментарий от bk_

Сферический конь в вакууме. Кто так делает?

А как ты предлагаешь передать картинку? Городить кроме json-rpc еще что-то? Я так не хочу.

А пхп зафейлился его парсить, хотя \0 нечитабельный.

Ты о первом своем сообщении? Пхп распарсил его, и выдал ошибку, что невалидный json, как и следовало по стандарту

goingUp ★★★★★
()
Ответ на: комментарий от Slavaz

он может встречаться в символах многобайтных кодировок.

Ещё один, не различающий символы и байты?

\0 может встретиться и в однобайтовом ASCII и означает ровным счётом тоже самое — символ под нумером 0 в ASCII. Невозможность простым образом записать эту корректную ASCII-строку в си — проблемы си и больше ничьи.

PolarFox ★★★★★
()
Ответ на: комментарий от PolarFox

Из-за кривой работы со строками в си ты почему-то сам того не замечая передаёшь байт \0, не относящийся к строке, а потом жалуешься, что не работает

Я специально передаю strlen+1 для пущей безопасности. Твоя проблема, что ты ставишь \0 и \Ы на одну планку, мол и то, и то - символ в кодировке XXX. Моя позиция такова, что в utf-8 и в asciiz символ \0 - символ конца строки.

json_encode/decode гласит, что он принимает строки в utf-8 и только в этой кодировке. Значит, сферическая проблема в вакууме со 100500 кодировками отпадает. Далее - следствие предыдущего абзаца: \0 должен мягко «выключать» парсер, а не выдергивать его с ошибкой.

Ты пытаешься сделать универсальную картину, которая здесь не нужна: \0 - не такой же символ, как и все, а специальный терминал конца строки.

Тут приводят примеры языков, где это не так. Отлично, но мне никто до сих пор не может ответить на простой вопрос: какой смысл от \0 в середине строки? Если он не нужен, то не употребляйте его. Если нужен, то ставьте только в конце строки как терминал.

bk_ ★★
() автор топика
Ответ на: комментарий от goingUp

Городить кроме json-rpc еще что-то? Я так не хочу.

Конечно, епта! Последняя задача, что я делал, именно так и была реализована.

bk_ ★★
() автор топика
Ответ на: комментарий от goingUp

Бинарные данные как-то стрёмно в json в строку засовывать, не думаю, что это хорошая практика. Разве что в виде base64.

PolarFox ★★★★★
()
Ответ на: комментарий от goingUp

Пхп распарсил его, и выдал ошибку, что невалидный json, как и следовало по стандарту

Вопросов нет. Но стандарт упустил этот важный и очевидный момент, связанный с \0. Почему ни у кого не возникло вопроса к автору стандарта: «а почему ты не описал поведение при \0»?

bk_ ★★
() автор топика
Ответ на: комментарий от bk_

Символа конца строки в юникоде и ascii нет. Есть нулевой символ, от которого ожидают ничего-не-делание. А есть сишные функции, которые работают с массивом байт, последний из которых 0, как со строкой, которая содержит все символы, кроме этого 0. Этого 0 нет в строке! НЕТ! В СТРОКЕ НЕТ ЭТОГО НУЛЯ! Он есть в массиве байт, А НЕ В СТРОКЕ.

PolarFox ★★★★★
()
Ответ на: комментарий от PolarFox

Разве что в виде base64.

+100500 к траффику. Плохо, лучше юзать старый проверенный multipart/form-data

bk_ ★★
() автор топика
Ответ на: комментарий от PolarFox

Кавычка ескейпится, а больше ничего и не надо для корректной работы

goingUp ★★★★★
()
Ответ на: комментарий от bk_

при \0

А также при \x01 и в остальных N символах юникода.

PolarFox ★★★★★
()
Ответ на: комментарий от PolarFox

Что-то мне подсказывает, что мы не спорим, а утверждаем одно и то же ;)

Невозможность простым образом записать эту корректную ASCII-строку в си — проблемы си и больше ничьи.

я именно про это и пытаюсь втолковать уважаемому bk_...

Slavaz ★★★★★
()
Ответ на: комментарий от goingUp

Прикидываешься дурачком, что ли (это не переход на личности)? Какая разница между тем, чтобы передать multipart/form-data-ой 700КБ и 2МБ через json-rpc-base64?

bk_ ★★
() автор топика
Ответ на: комментарий от bk_

\0 не отличается от любого другого символа.

qnikst ★★★★★
()
Ответ на: комментарий от bk_

+100500 к траффику.

Man любой алгоритм сжатия, который мало того, что уберёт оверхед в 4 раза от base64, так ещё и сожмёт данные сильнее, чем если бы они были без base64.

PolarFox ★★★★★
()
Ответ на: комментарий от PolarFox

Невозможность простым образом записать эту корректную ASCII-строку в си — проблемы си и больше ничьи.

Я этот вопрос «пощу» всем, но все отмалчиваются. Какой смысл \0 в середине строки? ЗАЧЕМ создавать такую строку, н-р, в паскале, где это можно? КАКОЙ В ЭТОМ СМЫСЛ?

bk_ ★★
() автор топика
Ответ на: комментарий от bk_

Это, дорогой мой, не пхп, это просто C — убогий язык, проблемы которого ты принимаешь за стандарт. \0 допустимый символ, это тебе не магия :}

Deleted
()
Ответ на: комментарий от note173

Нет, не все. Если быть педантом, то число _в компьютерном представлении_ - последовательность байт. Число степени 10 _в строковом представлении_ - последовательность символов от '0' (не '\0') до '9'.

bk_ ★★
() автор топика
Ответ на: комментарий от bk_

man любой алгоритм сжатия base64 --VS-- man любой алгоритм сжатия raw data (multipart/form-data)

denis@denis-laptop:~/Картинки$ cat yolka.png | bzip2 | wc -c
23568
denis@denis-laptop:~/Картинки$ cat yolka.png | base64 | bzip2 | wc -c
23883

И что теперь, из-за 315 байт из 23 кб усраться?

PolarFox ★★★★★
()
Последнее исправление: PolarFox (всего исправлений: 1)
Ответ на: комментарий от bk_

Если тебе не нравится слово «правило»

Это особенность лишь одного из многих языков. Ни первого, ни последнего, ни самого массового.

Вопрос в том, зачем было ломать на тот момент устоявшийся признак \0 конца строки

Вопрос в том, что этот «устоявшийся признак» является таковым лишь для определённой прослойки языков. Ни первых, ни последних, ни самых сегодня массовых. Скажем, когда я впервые столкнулся с таким признаком, я уже знал 3-4 языка, в которых такого поведения не было. Я просто воспринял это как данность конкретного языка. Но выводить из этого глобальные обобщения? Помилуй Бог...

Какая польза от «свободного» \0?

man бритва Оккама.

KRoN73 ★★★★★
()
Ответ на: комментарий от Deleted

\0 допустимый символ, это тебе не магия

О, новый человек в беседе. Ответь на такой вопрос, пожалуйста:

Какой смысл \0 в середине строки? ЗАЧЕМ создавать такую строку, н-р, в паскале, где это можно? КАКОЙ В ЭТОМ СМЫСЛ?

Если в этом найдется смысл, тогда я с вами соглашусь. А пока все ваши утверждения - это утверждения о сферических \0 в вакууме, которые могут, якобы, присутствовать в любом месте любой строки.

bk_ ★★
() автор топика
Ответ на: комментарий от bk_

Я говорю о реальном примере, когда я открыл файл, а там нулевой символ в конце.

Это ты сейчас про невалидный JSON или про сферического коня в вакууме?

KRoN73 ★★★★★
()
Ответ на: комментарий от bk_

ЗАЧЕМ создавать такую строку, н-р, в паскале, где это можно? КАКОЙ В ЭТОМ СМЫСЛ?

Потому что «строка» - это набор символов. Любых. нулевых, килиллических, управляющих, печатаемых/непечатаемых и т.д.

То, что в настоящее время для символа '\0' нет никакого смысла - это не заслуга составителей ASCII-таблицы, но это недостаток изобретателей Си-стандарта, которые на корню убили любые потуги назначить смысловую нагрузку такому символу.

Slavaz ★★★★★
()
Ответ на: комментарий от KRoN73

бритва Оккама

Как раз таки бритва говорит не городить лишних сущностей. Возможность появления \0 в середине строки - лишняя сущность, не несущая в себе никакого практического смысла. Все остальные языке наворачивают сложности, позволяя это делать.

bk_ ★★
() автор топика
Ответ на: комментарий от bk_

А почему ему там не быть? Из-за проблем Си? Это его личные половые проблемы. Если тебя волнует именно печатность символа, то я хочу направить тебя в сторону, хотя бы, ZWSP и NBSP.

Deleted
()
Ответ на: комментарий от PolarFox

\0 может встретиться и в однобайтовом ASCII и означает ровным счётом тоже самое — символ под нумером 0 в ASCII

Кстати, да. Символ ASCII: «NUL, 00 — Null, пустой. Всегда игнорировался. На перфолентах 1 представлялась отверстием, 0 — отсутствием отверстия. Поэтому пустые части перфоленты до начала и после конца сообщения состояли из таких символов»

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

Я таким образом проверял парсер json-а: записал в файл, прочел его через hexeditor, потом его прочел пхп и обделался на парсинге.

bk_ ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.