Няшная / Говнокод #27067 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
  62. 62
  63. 63
  64. 64
  65. 65
  66. 66
  67. 67
  68. 68
  69. 69
  70. 70
  71. 71
  72. 72
  73. 73
  74. 74
  75. 75
  76. 76
  77. 77
  78. 78
  79. 79
  80. 80
  81. 81
  82. 82
  83. 83
  84. 84
  85. 85
  86. 86
  87. 87
  88. 88
  89. 89
  90. 90
  91. 91
  92. 92
  93. 93
  94. 94
  95. 95
  96. 96
  97. 97
  98. 98
  99. 99
jsonObj_t *__jsonLoad(const char *_str_json, size_t _len_str_json, jsonErr_t *_error) {
	jsonObj_t *obj_json = NULL;
	jsonObj_t *obj_json_children = NULL;	// Тут будет зиждется объект
	jsonObj_t *obj_json_tmp = NULL;	// Тут будет зиждется объект

	size_t index_in_json_str = 0;
	size_t len_key = 0;				// Размер извлекаемого ключа
	size_t len_value = 0;			// Размер извлекаемого значения
	size_t count_hooks = 0;			// Счётчик скобок, чтобы игнорировать их при чтении объекта

	uint8_t flag_found_separator = 0;		// Флаг чтения ключа
	uint8_t flag_found_start = 0;	// Флаг начало JSON-объекта
	// uint8_t flag_found_end = 0;		// Флаг окончания JSON-объекта
	uint8_t flag_read_key = 0;		// Флаг чтения ключа
	uint8_t flag_read_force_read = 0;	// Флаг-костыль для ситуаций, когда число последнее в массиве
	uint8_t flag_read_value = 0;	// Флаг чтения значения
	uint8_t flag_read_array = 0;	// Флаг чтения и обработки массива
	uint8_t flag_want_value = 0;	// Флаг ожидания значения
									// 	(выставляется после успешно прочитанного ключа)

	jsonErr_t json_err = JSON_OK;

	int res = 0;

	jsonValueType_t type_expected_value = JSON_VALUE_NONE;	// Ожидаемы тип считываемого значения

	char chr_open = '\0';
	char chr_close = '\0';

	const char *ptr_key = NULL;		// Указатель на начало извлекаемого ключа
	const char *ptr_value = NULL;	// Указатель на начало извлекаемого значения

	if (_error != NULL)
	{
		*_error = JSON_OK;
	}

	for (index_in_json_str = 0; index_in_json_str < _len_str_json; ++index_in_json_str)
	{
		// Если начало JSON-объекта не найдено, то пропускать
		if (flag_found_start == 0)
		{
			// Поиск начала JSON-объекта
			if (_str_json[index_in_json_str] == '{')
			{
				flag_found_start = 1;
			}

			if (_str_json[index_in_json_str] == '[')
			{
				flag_found_start = 1;
				flag_read_array = 1;
				flag_want_value = 1;
				flag_found_separator = 1;	// Сразу после знака "[" ожидается значение
			}

			continue;
		}

		// Обработка ключа 
		if ((flag_read_key == 0) &&\
			(flag_read_value == 0) &&\
			(flag_want_value == 0) &&\
			(flag_read_array == 0))
		{
			if (((_str_json[index_in_json_str] == '\"') || (_str_json[index_in_json_str] == '\'')))
			{
				chr_close = _str_json[index_in_json_str];
				flag_read_key = 1;	// Флаг начало чтения ключа

				if ((index_in_json_str + 1) != _len_str_json)
				{
					ptr_value = (const char *)(_str_json + index_in_json_str + 1);
					len_value = 1;
				}
				else
				{
					if (_error != NULL)
					{
						*_error = JSON_ERR_BAD_JSON;
					}

					jsonFree(obj_json);
					return (NULL);
				}
			}

			continue;
		}

		// Обработка значения
		if ((flag_want_value == 1) && (flag_read_value == 0))
		{
			// Поиск разделителя ключа и значения
			if (flag_found_separator == 0)
			{
				if ((_str_json[index_in_json_str] == ']') && (flag_read_array == 1))
				{
					// flag_found_end = 1;

Либа продакшеновая, эта функция около 470 строк кода, всё не вместилось... Нет, индусов у нас нет, как и ответственного за качество кода тоже) и да это ещё один парсер. Опирается ли он на спецификацию JSON? Нет конечно же, боже упаси, зачем? Зато она прекрасно понимает TRUE как true и FALSE как false, а ваши жалкие либы такого не могут

Запостил: viktorokh96 viktorokh96, (Updated )

Комментарии (32) RSS

  • Я тебя услышал. Теперь смотрим, как это делается в языке для белых:
    json_decode($json);
    Ответить
  • char для utf-8? куча байтовых полей для флагов? это точно сишник писал?
    Ответить
    • Как называется программист на C++? Сиплюсплюсник?
      Ответить
    • > char для utf-8

      Вай нот? При парсинге жсона нету особого смысла декодить utf-8, всякие кавычки да слеши всё равно однобайтовые и с теми же кодами, что и в ascii. Достаточно проверить, что битых и неканоничных последовательностей нету. Ну и \u и \x раскрыть в utf-8 последовательности.
      Ответить
      • бикоз потому, что питух потом наверняка начнет подстроку искать итд
        Ответить
        • Подстроки в utf-8 вполне нормально ищутся, если тебя binary collation устраивает. Да и клеятся норм.

          А если дело до реальной поддержки юникода дойдёт, то перевод во всякие wchar_t ничем тебе не поможет. Всё равно понадобится какое-нибудь icu. А оно и utf-8 хавает.
          Ответить
          • и как ты впихнешь в один чар русскую букву, чтобы искать ее в строке?
            Ответить
            • А зачем мне впихивать её в 'char'?

              strstr(s, u8"хуй") без проблем работает.
              Ответить
              • а, всё, я понял) то есть "char" тут надо рассматривать как "байт" а не как "символ"?
                Тогда всё ок
                Ответить
                • Да, именно так. Поэтому я и писал выше про "binary collation".
                  Ответить
                • Ну ктсати в "питоне" и "жс" ведь так и сделано. Ты берёшь "символ" str[i], а получаешь... опять строку. В которой лежит один "символ".
                  Ответить
                  • Да, но в питоне (третьем), перле, js, java, c# и еще очень много где есть четкое разделение на

                    * чары
                    * байты

                    конвертация между ними всегда происходит явно, и с указанием кодировки (чарсета).

                    Так что в этих языках я бы увидел там byte, и не триггернулся бы так)
                    Ответить
                    • В крестах тоже чоткое разделение... В них нет "строк". Вообще.

                      Ну разве что icu::UnicodeString или QString.
                      Ответить
                      • однако же есть char, и даже пачка их называется std::string вроде

                        это было заебись во времена однобаайтовых кодировок, но сейчас это путает питухов
                        Ответить
                        • Ну считай это вторым питоном. Там тоже str был пачкой байт, а юникод хранился в unicode. Просто кресты и няшная - не питон, они не могут себе позволить переименование.
                          Ответить
                          • да, и это было плохо

                            вот у MS есть define чтобы char называть BYTE, это удобно.
                            typedef unsigned char BYTE, *PBYTE, *LPBYTE;
                            Ответить
                            • В новых крестах спохватились и сделали std::byte. Но вот арифметические операции для него не подвезли, только бинарные можно.
                              Ответить
                              • > арифметические операции для него не подвезли

                                Ну и правильно. Это же байт, а не число.
                                Ответить
                              • ну звучит логично: явно отпилили байт от букв и цифр
                                но немного пугает to_integer
                                Ответить
            • З.Ы. Ну и что ты предлагаешь юзать вместо char'ов? wchar_t неизвестной длины? char16_t, в котором эмодзи два слота занимают? char32_t, который жрёт кучу места, а полноценной работы с юникодом всё равно не даёт?
              Ответить
    • емнип по спеке в жсоне кроме аскии ничего и нет, юникодные последовательности обязаны кодироваться как \uXXXX
      Ответить
      • чет там странное немношк

        A string begins and ends with
        quotation marks. All Unicode characters may be placed within the
        quotation marks, except for the characters that MUST be escaped:
        quotation mark, reverse solidus, and the control characters (U+0000
        through U+001F).


        но в то же время

        When all the strings represented in a JSON text are composed entirely
        of Unicode characters [UNICODE] (however escaped), then that JSON
        text is interoperable in the sense that all software implementations
        that parse it will agree on the contents of names and of string
        values in objects and arrays.


        https://tools.ietf.org/html/rfc8259#section-7
        Ответить
        • Ну я так понял, что независимо от экранировки (т.е. хоть utf'ом сри, хоть аской со \u) все реализации должны получить одинаковый документ в итоге.
          Ответить
          • а я так понял, что interoperable считается только эскейпнутый (и у меня есть опыт с поджаренной задницей по этому поводу на стыке java(jackson) и json_decode из пшп)
            Ответить
            • Ну там было ещё старое rfc, где любые кодировки разрешались. Возможно, что какие-то парсеры, которые сделаны по старому rfc, брали кодировку из локали. Хуй знает.
              Ответить
      • ты может с SMTP перепутал семибитным?
        Ответить

Добавить комментарий

Переведи на "PHP", guest!

    А не использовать ли нам bbcode?


    8