Обсуждение:Конвертер Base64 - макрос без ActiveX (на массивах) и ActiveX, реализующий всю логику
0 (0)
Обсуждение:Конвертер Base64 - макрос без ActiveX (на массивах) и ActiveX, реализующий всю логику ( Обсуждение примера 01.06.2006 03:12 )
0(0)В архиве макрос, реализующий все те же функции, но на основе массивов, а так же СОМ-объект и пример его использования (на vbs).
Посмотреть пример
>> ОтветитьТем не менее, не самая эффективная реализация... ( Иванов Александр 01.06.2006 08:54 )
0(0)Хотя в свете новых парадигм программирования, типа "теперь вычислительных ресурсов девать некуда..." может оно и правильно...
>> ОтветитьЕсли это про реализацию на массивах, то... ( Izmajlov 01.06.2006 09:27 )
0(0)Александр, вчера день был очень тяжелый, устали все, поэтому сильно обижаться не буду. Скажу только, что кто может, пусть напишет лучше, я знаю много людей, которые пишут и лучше, быстрее меня. Но.. два варианта было создано мною практически за полтора дня, один день из которого пришелся на 31-е. Все рисовалось между часовыми висениями на телефоне с поддержкой по Инкаунтингу, и разруливанием ситуаций по банкоматам. Есть еще руководство надо мной, есть еще Управление ИТ, которым надо управлять :))
Я бы не стал и дергаться на массивы, если бы не моя уступчивость в некоторых вопросах. Если обещал переписать алгоритм, надо выполнять. Чем не понравилось использование механизма скриптинга - не понятно. Если используют СОМ-объекты ворда, екселя, то чем этот хуже?? На вкус и цвет - товарищей нет, если ПО работает, и выдает правильный результат, то дело вкуса юзера - пользоваться или нет.
А насчет профнепригодности.. сильно сказано :))
С уважением,
Измайлов Ф.В.
>> ОтветитьФеликс, ради бога извините :) В качестве компенсации примерный алгоритм кодирования в подарок ! ( Иванов Александр 01.06.2006 09:51 )
0(0)Если конструктивно, то ассоциативный массив вообще лишний... Преобразование в base64 должно выглядеть примерно так:
macro base64sym(code: Integer): String if(code < 26) return MkStr(code + 65, 1); end; if(code < 52) return MkStr(code + 71, 1); end; if(code < 62) return MkStr(code - 4, 1); end; if(code < 63) return "+"; end; return "/"; end; macro base64encode(src: String): String var dst: String = ""; var acc: Integer = 0; var i: Integer = 0; var j: Integer = 0; var n: Integer = StrLen(src); var ndx: Integer; while(i < n) i = i + 1; j = j + 8; acc = acc * 256 + CodeFor(SubStr(src, i, 1)); if(j == 24) while(j) ndx = acc / 262144; dst = dst + base64sym(ndx); acc = (acc - ndx * 262144) * 64; j = j - 6; end; acc = 0; end; end; if(j) i = (j + 5) / 6; while(j < 24) acc = acc * 256; j = j + 8; end; j = i; while(j) ndx = acc / 262144; dst = dst + base64sym(ndx); acc = (acc - ndx * 262144) * 64; j = j - 1; end; dst = dst + MkStr("=", 4 - i); end; return dst; end;
Использование вместо функции base64sym массива кодов выбираемых по индексу теоретически ускорило бы процесс, но только в том случае, если инициализация этого массива производится один раз где-то снаружи, а не при каждом вызове макроса...
>> ОтветитьДа я и том же... ( Izmajlov 01.06.2006 09:57 )
0(0)Что написано на быструю руку.. алгоритм примитивный получился. Просто некогда было думать, работали, не приходя в сознание :))
Давайте общими усилиями добъем макрос до кондиции :)) Массивы выкинем, переведем на вычисление кодов, и в сборку.
Пригодится в штатной конфигурации РСБанка.
Кстати, Александр, никаких проблем и обид :)))
Феликс.
>> ОтветитьНу раз без обид, тогда еще чуть-чуть критики... ( Иванов Александр 01.06.2006 10:04 )
0(0)Феликс, ну пожалуйста, на пишите больше никогда while(i < StrLen(a)) и другим не давайте. И не только в RSL :)
>> ОтветитьКритика принята :)) ( Izmajlov 01.06.2006 10:18 )
0(0)я старый солдат,и не знаю слов ....
а как надо?
действительно, я пишу так, как привык. Руководствуюсь все тем же принципом - работает? значит так и действуй. Хотя не чужд и новых веяний :))
Давно не читал доку по РСЛю, новинки некогда применять, поэтому и отстал в синтаксисе.
Феликс
>> ОтветитьТут дело в том, что если строка в цикле не меняется... ( Иванов Александр 01.06.2006 10:23 )
0(0)Значит вычисление ее длины совершенно излишне выполнять при каждой проверке условия. Это время занимает... Инвариант цикла должен быть вынесен за пределы цикла:
i = 0; n = StrLen(a); while(i < n)
Оптимизирующий компилятор мог бы в очевидных случаях это сам сделать, но в RSL такового не предвидится. Да и компилятор при желании обмануть не сложно :)
Так что это как раз не новое веяние, я хорошо забытое старое правило :)
>> Ответить
Ну я вот выше типа приложил своих усилий ! ( Иванов Александр 01.06.2006 11:30 )
0(0)Декодирование оставляю Вам в качестве упражнения :)
>> Ответить
capicom.dll ( Григорий 01.06.2006 10:35 )
0(0)Делал декодирование на VB этим алгоритмом. Тормоза при количестве платежей в пакете больше 100 невероятные. При количестве символов в коде base64 (наш стандартный рейс) около 500'000 умирает на 7-9 минут.
Нашел в 2.0 capicome "Base64Decode", работает гораздо быстрее, но выдает мусор в виде ?????.??? и т.д
Может кто знает что такое с капикомом?
>> ОтветитьА не затруднит проверить эффективность данных макросов ? ( Иванов Александр 01.06.2006 13:30 )
0(0)macro base64encode(src: String): String macro base64sym(code: Integer): String if(code < 26) return MkStr(code + 65, 1); end; if(code < 52) return MkStr(code + 71, 1); end; if(code < 62) return MkStr(code - 4, 1); end; if(code < 63) return "+"; end; return "/"; end; var dst: String = ""; var acc: Integer = 0; var i: Integer = 0; var j: Integer = 0; var n: Integer = StrLen(src); var ndx: Integer; while(i < n) i = i + 1; j = j + 8; acc = acc * 256 + CodeFor(SubStr(src, i, 1)); if(j == 24) while(j) ndx = acc / 262144; dst = dst + base64sym(ndx); acc = (acc - ndx * 262144) * 64; j = j - 6; end; acc = 0; end; end; if(j) i = (j + 5) / 6; while(j < 24) acc = acc * 256; j = j + 8; end; j = i; while(j) ndx = acc / 262144; dst = dst + base64sym(ndx); acc = (acc - ndx * 262144) * 64; j = j - 1; end; dst = dst + MkStr("=", 4 - i); end; return dst; end; macro base64decode(src: String): String macro base64bin(code: Integer): Integer if(code == 61) return 64; end; if(code < 48) if(code == 47) return 63; end; if(code == 43) return 62; end; if(code == 42) return 63; end; if(code == 33) return 62; end; elif(code < 58) return code + 4; elif(code < 91) if(code > 64) return code - 65; end; elif(code < 123) if(code > 96) return code - 71; end; end; return 65; end; var dst: String = ""; var acc: Integer = 0; var i: Integer = 0; var j: Integer = 0; var n: Integer = StrLen(src); var ndx: Integer; while(i < n) i = i + 1; ndx = base64bin(CodeFor(SubStr(src, i, 1))); if(ndx < 64) acc = acc * 64 + ndx; j = j + 6; if(j == 24) while(j) ndx = acc / 65536; dst = dst + StrFor(ndx); acc = (acc - ndx * 65536) * 256; j = j - 8; end; acc = 0; end; elif(ndx == 64) i = n; end; end; if(j) i = j / 8; while(j < 24) acc = acc * 64; j = j + 6; end; while(i) ndx = acc / 65536; dst = dst + strFor(ndx); acc = (acc - ndx * 65536) * 256; i = i - 1; end; end; return dst; end;
>> ОтветитьУ нас таких объемов нет, Григория надо попросить :)) ( Izmajlov 01.06.2006 13:34 )
0(0)Not specified
>> ОтветитьТак я Григория и прошу... ( Иванов Александр 01.06.2006 13:35 )
0(0)
Есть новшества! ( Григорий 01.06.2006 14:44 )
0(0)коллега сбацал com (в виде dll) на дельфях. Там (в дельфи) есть встроенная функция декодирования. Полтора мега кода base64 разбирает за доли секунды.
Процесс идет дальше по разбору полученных xml, поэтому пока весь там, да и конец месяца навалился, поэтому смогу потестить попозже (мы делаем первичный разбор НЕ В RS).
Мы делаем разбор в два этапа.
1. Конва - декодирование - новый xml с пакетами ED и ESID- тексты удобочитаемые по приходам и результатам
2. чтение xml-пакетов ED в RS "отложенные"+свою систему "ведения коррсчетов"
>> ОтветитьТот факт, что на нормальном языке кодирование/декодирование base64 проходит моментально... ( Иванов Александр 01.06.2006 14:51 )
0(0)Никто собственно и не оспаривал. Я собственно сразу написал, что если использовать ActiveX, то лучше сразу все там делать. Но вопрос состоит в принципиальной возможности эффективной реализации на чистом RSL...
>> ОтветитьПотестил(+) ( Григорий 01.06.2006 15:09 )
0(0)Import "..\\mac\\lgxse.d32";
var ob_xml = TlgActiveX("Microsoft.XMLDOM");
ob_xml.async = False;
ob_xml.load("\\\\server\\temp\\tst.xml");/*переименовал чтобы с именами не мучаться*/
if(ob_xml.parseError.errorCode != 0)
[Error descript
Code #############
line #############
linepos #############
reas #
Text #
]
(ob_xml.parseError.errorCode,
ob_xml.parseError.line ,
ob_xml.parseError.linePos ,
ob_xml.parseError.reason ,
ob_xml.parseError.srcText );
Exit(0);
end;/*if*/
var ob_doc = ob_xml.getElementsByTagName("sen:Object");
[#](base64encode(ob_doc.item(0).text));
на этом все умерло с выкидыванием из RS и вин мессаджем Программа выполнила и т.д.
Сократил руками длину sen:Object, все хорошо, но никому не интересно.
Могу выслать файл для тестов (500 кил).
>> ОтветитьНет, файл не надо, у меня просто познавательный интерес был... ( Иванов Александр 01.06.2006 15:19 )
0(0)А исследовать, что там ломется внутри, честно говоря нету желания. А если возникнет, то уж нагенерировать строк длиной по полмега я и сам смогу :)
>> ОтветитьНе совсем корректно (-) ( григ 01.06.2006 16:32 )
0(0)При использовании lgxs имеется ограничение на длину данных - зависит от текущей версии терминала-сервера, но даже в лучшем случае - это 16 кбт. А ты пытаешься 500 кило засунуть.
Лучше всего скопировать файл на сервер и сделать тоже самое через rslx.d32.
>> ОтветитьА все равно, данная реализация на таких объемах не жилец... ( Иванов Александр 01.06.2006 16:38 )
0(0)Хоть через что ее используй. Конечно можно попробовать таки извернуться, но мне лично оно не нужно. А кому нужно, тот сам сделает...
>> ОтветитьПо и-нету уже бродят стихи: ( Григорий 01.06.2006 17:51 )
0(0)Я на Житной щас сижу,
В МЦИ корячуся.
И могу я всем насрать,
И от всех я прячуся!
Я макет изобрету,
Самый зашебатый!
Parser в Штатах утащу,
Пусть не ждут оплаты!
Что же, мне его писать?
Очень трудно это.
Буду кнопки расставлять,
Где возможно это.
XML - моя любовь!
Сплю в обнимку с книжкой.
С ней и сру я, и курю,
Стала мне братишкой!
Опишу Конву Дельфой,
Си-Шарпей не катит!
Мозгу столько у меня,
Мне на Дельфу хватит.
Ну и что ж что GPF?
Не секу я в этом!
В Microsoft я всех пошлю!
Требуйте ответа!
Мне Exception незнаком!
Я не знал об этом!
Что там? Catch?
Пошлю пинком! Ух! Достало ЭТО!
Clipper раньше мной владел,
Так спокойно было,
Но величия мне в нём,
В жопе не хватило!
Диагностика в Конве
Выше всяких правил!
Валидацией я все
Дырки затыкаю!
Чё? В какой это строке…
Файла замутилось?
Ну не знаю это я!
Мне их Parser выдал!
Я с ошибками дружу!
Смело их клепаю!
Обработку не пишу,
Мозгу не хватает!
Про модальное окно
Ничего не знаю!
Клюкнул мышкой,
Вот оно! Получай, татарин!
Смело можно мне писать
Код и для ракеты!
Тока бункер поглубжей
Выдайте мне где-то!
Крутость жизни мне даёт
Внутренние силы!
Виндузёвый программист-
Это очень мило!
А теперь, мои друзья,
Подведём итоги,
Вышел в Астру было я,
Чтоб не слезть с дороги.
И увидел там простор
Я Руси Великой,
Где разгул макетов есть,
Есть и был старинный!!!!
Вот в Поволжье молодцы!
Конвы нет в Самаре!
Шлют они платежки там,
Файлами Тамаре!
Не подумай, что Тамар,
Это БИК Московский,
Там фидошник всем рулит!
Парень бестолковский.
И уж коли то Fido,
Создал «их» любитель,
Так и Банкам нашим там
Он и есть Учитель!
А народ кавказский наш
Что meddok-ом грешен!
DBF-ом он живёт,
Им он и утешен!
Не пасёт овцу Махмуд,
XML рюхает!
А Кавказ над ним теперь,
Тихо угорает.
Позабудет DBF
Мудрый сын Эльбруса,
Назовёт овцу ,
Там такие вкусы!
Всем хорош идей шальной,
С славным тем макетом,
Чтобы был один, родной,
В целом на планету.
Но вот дядя с МЦИ,
Он наш друг заклятый!!!!
Он конву нам написал,
Программист проклятый
(с) Ice362
>> Ответить
Вышли мне файлик, если не трудно, тоже хочу потестить (-) ( григ 02.06.2006 08:02 )
0(0)Not specified
>> ОтветитьДа не нужен там специальный файл. Любые данные сначала закодировать... ( Иванов Александр 02.06.2006 09:00 )
0(0)А потом раскодировать. При больших объемах оно умрет по очевидным причинам...
>> ОтветитьТы, Александр, не прав, файл нужен (+) ( григ 02.06.2006 09:21 )
1(1)Помимо base64 интересно еще посмотреть саму структуру закодированного xml-файла, т.к. кодируется он не весь.
>> ОтветитьЯ утром выслал. Дошел? ( Григорий 02.06.2006 09:47 )
0(0)Not specified
>> ОтветитьДошел, спасибо (-) ( григ 02.06.2006 11:15 )
0(0)Not specified
>> ОтветитьПодскажи, как формируется имя файла для отправки в ЦБ и (+) ( григ 02.06.2006 11:41 )
0(0)имя файла из ЦБ.
>> ОтветитьЯ формирую как попало :-) ( Григорий 06.06.2006 08:27 )
0(0)На самом деле не как попало, а как всегда было раньше для R-макета.
Потом приходит КОНВА и делает все по своему.
Поэтому могу сказать только то что известно из общей ЦБ-шной документации.
>> ОтветитьЯ в длм-ку doctor.d32 включил функции (+) ( григ 06.06.2006 08:47 )
0(0)dcAsciiToBase64 и dcBase64ToAscii - попробуй потестить на своих файликах. Пробовал я на твоем файлике первый вариант Феликса - не дождался, Александра Иванова - 15-19 сек с загрузкой проца 25%, doctor.d32 - 0-1 сек.
>> ОтветитьНа самом деле ( Григорий 06.06.2006 09:41 )
0(0)тестить после автора уже стоит ли :-)
Уверен на 100% в том что получу 0-1 сек.
Но нам это на самом деле неактуально, т.к. мы работаем вне RS.
Первичная обработка идет сразу после приема файлов, с декодированием и созданием человекочитаемой формы выписки и прочих результатов.
А из опердня подгружаем уже декодированный xml.
>> Ответить
Ну это может тебе интересно... ( Иванов Александр 02.06.2006 10:16 )
0(0)А мне не очень :) Физика процесса мне понятна и я таки добился от реализации на чистом RSL чтобы процесс занимал приемлимое время. Так блок 1МБайт закодировался и раскодировался за 106 секунд, что составляет примерно 9,5 кб/c... При этом контрольный пример кодируется/декодируется со скоростью 15 кб/с при тех же настройках алгоритма. Правда на больших блоках память на пике поджирается не по детски, но это уже особенность инструмента...
А если схитрить с передачей параметров, то скорость возрастает еще как минимум вдвое и расход памяти становится практически незаметным...
>> ОтветитьО том, как зайцев учат курить... ( Иванов Александр 02.06.2006 12:33 )
0(0)Даже если они этого не хотят :) Приведенный код на чистом RSL по крайней мере не умирает на мегабайте данных. А вообще из кода очевидны причины торможения на больших объемах. И неэффективные вычисления тут совсем даже не при чем...
Кеширование вычисленных кодов существенного влияния на эффективность не оказывает и может быть без сожаления выкинуто.
Если кто вдруг захочет угостить меня пивом или еще чем, я не против...
class TcBase64 private var encodetab = TArray(64); private var decodetab = TArray(256); private var bufsize; if(not (GetParm(1, bufsize) and (valtype(bufsize) == V_INTEGER) and (bufsize > 255))) bufsize = 1024; end; macro encode(src: String): String private macro toChar(val: Integer): Integer if(ValType(encodetab[val]) == V_INTEGER) return encodetab[val]; end; if(val < 26) return encodetab[val] = val + 65; end; if(val < 52) return encodetab[val] = val + 71; end; if(val < 62) return encodetab[val] = val - 4; end; if(val < 63) return encodetab[val] = 43; end; return encodetab[val] = 47; end; var acc: Integer = 0; var i: Integer = 0; var n: Integer = StrLen(src); var tmp = TArray(n / bufsize); var j: Integer = 0; var k: Integer = -1; var l: Integer; var d: Integer; var ndx: Integer; var buf: String; var dst: String = ""; while(i < n) d = n - i; k = k + 1; if(k) tmp[k - 1] = dst; dst = ""; end; if(d > bufsize) d = bufsize; end; buf = SubStr(src, i + 1, d); i = i + d; l = 0; while(l < d) l = l + 1; j = j + 8; acc = acc * 256 + CodeFor(SubStr(buf, l, 1)); if(j == 24) while(j) ndx = acc / 262144; acc = (acc - ndx * 262144) * 64; j = j - 6; dst = dst + StrFor(toChar(ndx)); end; acc = 0; end; end; end; if(j) i = (j + 5) / 6; while(j < 24) acc = acc * 256; j = j + 8; end; j = i; while(j) ndx = acc / 262144; acc = (acc - ndx * 262144) * 64; j = j - 1; dst = dst + StrFor(toChar(ndx)); end; dst = dst + MkStr("=", 4 - i); end; while(k > 0) k = k - 1; dst = tmp[k] + dst; end; return dst; end; macro decode(src: String): String private macro toCode(val: Integer): Integer if(ValType(decodetab[val]) == V_INTEGER) return decodetab[val]; end; if(val == 61) return decodetab[val] = 64; end; if(val < 48) if(val == 47) return decodetab[val] = 63; end; if(val == 43) return decodetab[val] = 62; end; if(val == 42) return decodetab[val] = 63; end; if(val == 33) return decodetab[val] = 62; end; elif(val < 58) return decodetab[val] = val + 4; elif(val < 91) if(val > 64) return decodetab[val] = val - 65; end; elif(val < 123) if(val > 96) return decodetab[val] =val - 71; end; end; return decodetab[val] = 65; end; var acc: Integer = 0; var i: Integer = 0; var n: Integer = StrLen(src); var tmp = TArray(n / bufsize); var j: Integer = 0; var k: Integer = -1; var l: Integer; var d: Integer; var ndx: Integer; var buf: String; var dst: String = ""; while(i < n) d = n - i; k = k + 1; if(k) tmp[k - 1] = dst; dst = ""; end; if(d > bufsize) d = bufsize; end; buf = SubStr(src, i + 1, d); i = i + d; l = 0; while(l < d) l = l + 1; ndx = toCode(CodeFor(SubStr(buf, l, 1))); if(ndx < 64) acc = acc * 64 + ndx; j = j + 6; if(j == 24) while(j) ndx = acc / 65536; acc = (acc - ndx * 65536) * 256; j = j - 8; dst = dst + StrFor(ndx); end; acc = 0; end; elif(ndx == 64) i = n; end; end; end; if(j) i = j; while(j < 24) acc = acc * 64; j = j + 6; end; while(i > 7) ndx = acc / 65536; acc = (acc - ndx * 65536) * 256; i = i - 8; dst = dst + StrFor(ndx); end; end; while(k > 0) k = k - 1; dst = tmp[k] + dst; end; return dst; end; end;
>> Ответить