В Delphi XE2 отыскался баг в TIdCookie.ParseServerCookie. Смотрим код:
functionGetLastValueOf(const AName: String; var VValue: String): Boolean; var I: Integer; begin Result := False; for I := CookieProp.Count-1downto0do begin if TextIsSame(CookieProp.Names[I], AName) then begin {$IFDEF HAS_TStrings_ValueFromIndex} VValue := CookieProp.ValueFromIndex[I]; {$ELSE} VValue := Copy(CookieProp[I], Pos('=', CookieProp[I])+1, MaxInt); {Do not Localize} {$ENDIF} Result := True; Exit; end; end; end; ... if GetLastValueOf('MAX-AGE', S) thenbegin{Do not Localize} FPersistent := True; FExpires := StrToFloat(S); end elseif GetLastValueOf('EXPIRES', S) then{Do not Localize} begin FPersistent := True; FExpires := StrToFloat(S); endelse begin FPersistent := False; FExpires := EncodeDate(9999, 12, 31) + EncodeTime(23, 59, 59, 999); end; if GetLastValueOf('DOMAIN', S) then{Do not Localize} begin { If the user agent is configured to reject "public suffixes" and the domain-attribute is a public suffix: If the domain-attribute is identical to the canonicalized request-host: Let the domain-attribute be the empty string. Otherwise: Ignore the cookie entirely and abort these steps. NOTE: A "public suffix" is a domain that is controlled by a public registry, such as "com", "co.uk", and "pvt.k12.wy.us". This step is essential for preventing attacker.com from disrupting the integrity of example.com by setting a cookie with a Domain attribute of "com". Unfortunately, the set of public suffixes (also known as "registry controlled domains") changes over time. If feasible, user agents SHOULD use an up-to-date public suffix list, such as the one maintained by the Mozilla project at . } end; if Length(S) > 0then begin ifnot IsDomainMatch(AURI.Host, S) thenbegin Exit; end; FHostOnly := False; FDomain := S; endelse begin FHostOnly := True; FDomain := CanonicalizeHostName(AURI.Host); end;
Ошибка происходит если строка S после вызова GetLastValueOf(‘EXPIRES’, S) содержит что-нибудь (Length(S) > 0), а GetLastValueOf(‘DOMAIN’, S) возвращает False.
Такое случается, если на вход TIdCookie.ParseServerCookie поступает строка ACookieText типа такой:
Интересно, что ошибки бы не случилось, если бы параметр VValue у функции GetLastValueOf был объявлен как out, а не как var.
Fix. Для исправления этого бага я сделал класс TVCookieManager, который служит заменой для TIdCookieManager. Взять можно тут: https://github.com/coolsoftware/VCookieManager. Использовать так:
f = open("f1.txt") lines = f.read().split() f.close() defsort(array): equal = [] greater = [] less = [] iflen(array) <= 1: return array linem = array[int((len(array)-1)/2)] for line in array: if linem < line: greater.append(line) elif linem > line: less.append(line) elif linem == line: equal.append(line) return sort(less) + equal + sort(greater) sorted_lines = sort(lines) print(sorted_lines) defnode(C, P): print(P + C) return P + " " defR(P, K, I0, J0): I = I0 Si = sorted_lines[I] Li = len(Si) if K >= Li and I == J0: return if K < Li: C = Si[K] else: C = "{0}" X = node(C, P) J = I whileTrue: if J == J0 or sorted_lines[J+1][K] != C: R(X, K+1, I, J) if J == J0: break I = J + 1 Si = sorted_lines[I] Li = len(Si) C = Si[K] X = node(C, P) J = J + 1 N = len(sorted_lines) X = node("[ROOT_NODE]", "") R(X, 0, 0, N-1)
f1.txt:
BC ABBA ABC ABA ABB BAC A
Вывод:
['A', 'ABA', 'ABB', 'ABBA', 'ABC', 'BAC', 'BC'] [ROOT_NODE] A {0} B A B {0} A C B A C C
=== Перепечатка материалов блога разрешается с обязательной ссылкой на blog.coolsoftware.ru
Задача: имеется два больших (100 000+) списка строк, и требуется отфильтровать первый список (Source List) таким образом, чтобы в нем остались только строки, содержащие подстроки из второго списка (Search List).
Решать эту задачу будем следующим образом: для каждой строки Z из Source List будем искать строку S из Search List, такую, что S является подстрокой Z.
Примитивный алгоритм
Можно решить задачу нахождения подстроки из списка Search List при помощи следующего очевидного (примитивного), но крайне медленного алгоритма: будем последовательно перебирать все строки S из Search List до тех пор, пока не окажется, что S является подстрокой Z. При этом, алгоритм поиска подстроки в строке можно использовать либо примитивный, либо один из более продвинутых (например, Бойера-Мура, см. https://ru.wikipedia.org/wiki/Поиск_подстроки). Однако, использование более быстрого алгоритма поиска подстроки в строке не сильно ускоряет поиск подстроки из списка, т.к. все-равно требуется перебрать в среднем N/2 строк (здесь N - количество строк в Search List).
Дерево цифрового поиска
Дерево цифрового поиска (также бор, Trie, Префиксное дерево) - структура данных, которая используется для осуществления поразрядного поиска. Каждый узел дерева содержит значение одного “разряда” (в нашем случае - строковый символ). Вся строка представлена последовательностью узлов от корня до листа дерева. Пример - дерево цифрового поиска для строк A, ABA, ABB, ABBA, ABC, BAC, BC:
[ROOT NODE] / \ A B / \ / \ {0} B A C / | \ / A B C C / \ {0} A
1. Пусть L = длина строки S. 2. Если L = 0 (“пустая” строка), то выход: префикс не найден. 3. Если дерево не содержит узлов (“пустое” дерево), то выход: префикс не найден. 4. Терминальный узел T = NULL. 5. Текущий узел P = корень дерева ( [ROOT NODE] ). 6. Цикл по K = 1..L: 7. Если у текущего узла нет дочернего, соответствующего символу S[K], то выход из цикла. 8. Текущий узел P = дочерний, узел, соответствующий символу S[K]. 9. Если у узла P есть дочерний узел с терминальным символом {0}, то присваиваем его T. 10. Конец цикла. 11. Если узел P - лист, то выход: префикс найден. 12. Если T не равно NULL, то выход: префикс найден. 13. Префикс не найден.
В качестве терминального символа {0} как правило используется символ NUL с ASCII-кодом 0, который не может встретиться в строке.
Алгоритм A2 поиска подстроки строки S по дереву.
1. Пусть L = длина строки S. 2. Если L = 0 (“пустая” строка), то выход: подстрока не найдена. 3. Если дерево не содержит узлов (“пустое” дерево), то выход: подстрока не найдена. 4. Цикл по K = 1..L: 5. Пусть Sk - суффикс строки S, начиная с K-го символа (суффикс длины L-K+1). 6. Используем алгоритм A1 для поиска префикса строки Sk по дереву; если префикс найден, то выход: подстрока найдена. 7. Конец цикла. 8. Подстрока не найдена.
В алгоритмах A1 и A2 использованы определения префикса и суффикса строки из статьи: https://ru.wikipedia.org/wiki/Подстрока. По-простому: префикс строки длины X - это первые X символов строки, суффикс строки длины Y - последние Y символов строки.
Построение дерева цифрового поиска
Обозначения:
N - количество строк. Si - i-я строка, i = 1..N. Li - длина i-ой строки. [ROOT NODE] - корневой узел.
Рекурсивная процедура R (параметры: P - узел-родитель, K - позиция текущего символа, I0, J0 - индексы строк; I0<=J0):
1. Индекс i = I0. 2. Если K > Li и i = J0, то выход из процедуры R. 3. Если K <= Li, то символ C = Si[K], иначе C = {0}. 4. Создать X = узел (C, P). 5. Индекс j = i. 6. Цикл: 7. Если j = J0 или S(j+1)[K] не равно C, то: 8. Вызвать R (X, K+1, i, j) 9. Если j = J0, то выход из цикла. 10. i = j+1. 10. C = Si[K]. 11. Создать X = узел (C, P). 12. Конец если. 13. j = j + 1. 14. Конец цикла.
Решил сравнить скорость двух беспроводных сетевых USB-адаптеров: ASUS N10 Nano и TP-LINK TL-WN823N. На первом написно до 150 Mbps, на втором - до 300 Mbps.
Оба адаптера втыкались в Raspberry Pi B+. Для тестов использовался iperf.
Результаты тестов представлены на Рис. 1,2. Как видим, ASUS показывает скорость около 42 Mbit/sec, TP-LINK - около 74 Mbit/sec.
Рис.1. ASUS N10 Nano.
Рис.2. TP-LINK TL-WN823N.
=== Перепечатка материалов блога разрешается с обязательной ссылкой на blog.coolsoftware.ru
Мой компьютер (контекстное меню) –> Управление -> Службы (Рис. 1): Вспомогательная служба IP –> Тип запуска –> Выбираем из списка: Автоматически
Пуск –> Выполнить –> regedit
В реестре по адресу HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Dnscache\Parameters создать ключ AddrConfigControl типа DWORD со значением 0 (Рис. 2).
Пуск –> Панель управления –> Сеть и Интернет –> Сетевые подключения –> Подключение по локальной сети –> Свойства (Рис. 3): Протокол Интернета версии 6 (TCP/IPv6) –> включить и в Свойствах указать: Использовать следующие адреса DNS-серверов: Предпочитаемый DNS-сервер: 2001:4860:4860::8888 Альтернативный DNS-сервер: 2001:4860:4860::8844
Пуск –> Выполнить –> gpedit.msc
Конфигурация компьютера –> Административные шаблоны –> Сеть –> Параметры TCP/IP –> Технологии Туннелирования IPv6 (Рис. 4): Классификация Teredo по умолчанию –> Включить –> Включенное состояние Частота обновления Teredo –> Включить –> 10 Состояние Teredo –> Включить –> Корпоративный клиент Порт клиента Teredo -> Не задано Имя сервера Teredo –> Включить –> Выбираем из списка: teredo.remlab.net
Пуск – Выполнить – cmd: netsh int ipv6 delete route ::/0 Teredo netsh int ipv6 add route ::/0 Teredo
Полезные ссылки, касающиеся разработки под Raspberry Pi. Пишу главным образом для себя, чтобы не забыть :) Пост будет время от времени дополнятся (я надеюсь :)
б) сперва лучше (imho) залить образ на флешку ( sudo dd bs=1M if=2015-02-16-raspbian-wheezy.img of=/dev/sdb ), вставить флешку в Raspberry Pi, установить апдейты и библиотеки (например, для разработки под X11: http://doc.qt.io/qt-5/linux-requirements.html), потом сделать образ этой флешки ( sudo dd bs=1M if=/dev/sdb of=rasp-pi.img ) и уже с ним работать дальше.
в) “Магическое” число 62914560 ( sudo mount -o loop,offset=62914560 rasp-pi.img/mnt/rasp-pi-rootfs ) можно вычислить следующим образом:
[vitaly@localhost opt]$ sudo fdisk -l rasp-pi.img
Disk rasp-pi.img: 7892 MB, 7892631552 bytes, 15415296 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk label type: dos Disk identifier: 0x0009bf4f
Устр-во Загр Начало Конец Блоки Id Система rasp-pi.img1 8192 122879 57344 c W95 FAT32 (LBA) rasp-pi.img2 122880 6399999 3138560 83 Linux
122880 - это начало раздела (номер первого сектора раздела), который нужно подмонтировать. 122880 * 512 = 62914560.