OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Пятница, 22 Сентябрь, 2017 03:54

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 23 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: Пример алгоритма Base64-кодирования
СообщениеДобавлено: Среда, 04 Август, 2010 14:10 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4392
Откуда: Россия, Орёл
Отделено отсюда:
viewtopic.php?f=7&t=2762

Илья Ермаков писал(а):
Galkov писал(а):
...Покажите пожалуйста пример, в котором, опираясь на Дейкстру можно увидеть "неумение программировать"...
Например, использование break внутри цикла...
Пример из практики: хотел портировать готовую реализацию Base64 с Си. Стандарт приводит в качестве примера:
Цитата:
11. ISO C99 Implementation of Base64

An ISO C99 implementation of Base64 encoding and decoding that is
believed to follow all recommendations in this RFC is available from:

http://josefsson.org/base-encoding/

This code is not normative.
...
Когда увидел, понял, что для меня спокойнее написать с нуля самому (с упором на читабельность), чем портировать тот код, которому надо либо "believe", либо сломать моск при проверянии. Процедуры кодирования:
http://cvs.savannah.gnu.org/viewvc/gnul ... ision=1.14
(пробелы с табуляциями намешаны, отступы при копировании испортились)
Код:
/* Base64 encode IN array of size INLEN into OUT array of size OUTLEN.
   If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as
   possible.  If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero
   terminate the output buffer. */
void
base64_encode (const char *restrict in, size_t inlen,
          char *restrict out, size_t outlen)
{
  static const char b64str[64] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

  while (inlen && outlen)
    {
      *out++ = b64str[(to_uchar (in[0]) >> 2) & 0x3f];
      if (!--outlen)
   break;
      *out++ = b64str[((to_uchar (in[0]) << 4)
             + (--inlen ? to_uchar (in[1]) >> 4 : 0))
            & 0x3f];
      if (!--outlen)
   break;
      *out++ =
   (inlen
    ? b64str[((to_uchar (in[1]) << 2)
         + (--inlen ? to_uchar (in[2]) >> 6 : 0))
        & 0x3f]
    : '=');
      if (!--outlen)
   break;
      *out++ = inlen ? b64str[to_uchar (in[2]) & 0x3f] : '=';
      if (!--outlen)
   break;
      if (inlen)
   inlen--;
      if (inlen)
   in += 3;
    }

  if (outlen)
    *out = '\0';
}
что получилось у меня:
Код:
   PROCEDURE Encode* (IN x: ARRAY OF SHORTCHAR; VAR y: ARRAY OF SHORTCHAR; VAR p, q: INTEGER; len: INTEGER);
      VAR   t, n: INTEGER;
   BEGIN
      ASSERT(len >= 0, 20);
      n := len DIV 3;
      WHILE n > 0 DO
         (* Encode24bit *)
         t := ORD(x[p + 2]) + ASH(ORD(x[p + 1]), 8) + ASH(ORD(x[p]), 16); INC(p, 3);
         y[q] := ctable[ASH(t, -18)]; INC(q);
         y[q] := ctable[ORD(BITS(ASH(t, -12)) * {0..5})]; INC(q);
         y[q] := ctable[ORD(BITS(ASH(t, -6)) * {0..5})]; INC(q);
         y[q] := ctable[ORD(BITS(t) * {0..5})]; INC(q);
         DEC(n)
      END;
      CASE len MOD 3 OF
      | 0:
      | 1:   (* Encode8bit *)
         t := 0 + ASH(0, 8) + ASH(ORD(x[p]), 16); INC(p);
         y[q] := ctable[ASH(t, -18)]; INC(q);
         y[q] := ctable[ORD(BITS(ASH(t, -12)) * {0..5})]; INC(q);
         y[q] := ctable[64]; INC(q);
         y[q] := ctable[64]; INC(q)
      | 2:   (* Encode16bit *)
         t := 0 + ASH(ORD(x[p + 1]), 8) + ASH(ORD(x[p]), 16); INC(p, 2);
         y[q] := ctable[ASH(t, -18)]; INC(q);
         y[q] := ctable[ORD(BITS(ASH(t, -12)) * {0..5})]; INC(q);
         y[q] := ctable[ORD(BITS(ASH(t, -6)) * {0..5})]; INC(q);
         y[q] := ctable[64]; INC(q)
      END
   END Encode;


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 04 Август, 2010 14:38 

Зарегистрирован: Вторник, 25 Апрель, 2006 16:21
Сообщения: 2178
Откуда: Нижний Новгород
Евгений Темиргалеев писал(а):
Когда увидел, понял, что для меня спокойнее написать с нуля самому (с упором на читабельность), чем портировать тот код, которому надо либо "believe", либо сломать моск при проверянии.

Абсолютно то же самое могу сказать о вашем коде. Если бы у меня возникла нужда написать оную функцию на неком языке Х, где её ещё нет, то мне было бы намного проще и приятней написать её с нуля по спеке, нежели вслепую копировать ваше, либо референсное, затем делать "belive" или же ломать мозг при проверянии этого дела.

Оберонов код тут ничуть не легче читается. Особенно доставляют по два оператора на строке. При первом прочтении я эти INC(x) в конце строк не увидел вообще. Зато в Сишном примере все точки выхода из цикла увидел сразу при первом же взгляде.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 04 Август, 2010 15:23 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4392
Откуда: Россия, Орёл
Alexey Veselovsky писал(а):
Абсолютно то же самое могу сказать о вашем коде...
И какой смысл говорить о моём коде, когда я предложил сравнить алгоритмы. Разные алгоритмы для решения одной задачи. Вы могли перевести мой код на Си (я думал это и в уме можно), отформатировать как Вам нравится, и сравнивать.
Код:
 // ctable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
void Encode (const unsigned char *x, unsigned char *y, int &p, int &q, int len)
{
   int t, n;
   assert(len >= 0);
   n = len / 3;
   while (n > 0) {
      /* Encode24bit */
      t = x[p + 2] + (x[p + 1] << 8) + (x[p] << 16);
      p += 3;
      y[q++] = ctable[t >> 18];
      y[q++] = ctable[(t >> 12) & 0x3F];
      y[q++] = ctable[(t >> 6) & 0x3F];
      y[q++] = ctable[t & 0x3F];
      --n;
   }
   switch (len % 3) {
   case 0:
      break;
   case 1:   /* Encode8bit */
      t = 0 + (0 << 8) + (x[p] << 16);
      ++p;
      y[q++] = ctable[t >> 18];
      y[q++] = ctable[(t >> 12) & 0x3F];
      y[q++] = ctable[64];
      y[q++] = ctable[64];
      break;
   case 2:   /* Encode16bit */
      t = 0 + (x[p + 1] << 8) + (x[p] << 16);
      p += 2;
      y[q++] = ctable[t >> 18];
      y[q++] = ctable[(t >> 12) & 0x3F];
      y[q++] = ctable[(t >> 6) & 0x3F];
      y[q++] = ctable[64];
      break;
   }
}
Хотелось бы услышать мнения касательно сложности проверки соответствия алгоритмов стандарту (но не придирки к переводу кода).


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Август, 2010 03:39 

Зарегистрирован: Вторник, 25 Апрель, 2006 16:21
Сообщения: 2178
Откуда: Нижний Новгород
Евгений Темиргалеев писал(а):
Alexey Veselovsky писал(а):
Абсолютно то же самое могу сказать о вашем коде...
И какой смысл говорить о моём коде, когда я предложил сравнить алгоритмы. Разные алгоритмы для решения одной задачи. Вы могли перевести мой код на Си (я думал это и в уме можно), отформатировать как Вам нравится, и сравнивать.

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

Мне кажется, что вот так, чуточку наглядней и читабельней. Хотя и чуть менее эффективно:
Код:
void encode(const char* const in, const size_t in_len, char* const out, const size_t out_len) {
    const unsigned long m1 = BIN24(11111100,00000000,00000000);
    const unsigned long m2 = BIN24(00000011,11110000,00000000);
    const unsigned long m3 = BIN24(00000000,00001111,11000000);
    const unsigned long m4 = BIN24(00000000,00000000,00111111);
   
    long value = 0;
    char* p_value = (char*)&value;   
   
    for (int i =0, j=0; i<in_len && j<out_len; i+=3, j+=4) {
        int i_shift = 0;
        value = 0;
        switch (in_len - i ) {
            default:
            case 3: p_value[0] = in[i + i_shift++];
            case 2: p_value[1] = in[i + i_shift++];
            case 1: p_value[2] = in[i + i_shift++];
        }

        switch (out_len - j) {
            default:
            case 4: out[j+3] = b64str[(value & m4) >> (6*0)  ];
            case 3: out[j+2] = b64str[(value & m3) >> (6*1)  ];
            case 2: out[j+1] = b64str[(value & m2) >> (6*2)  ];
            case 1: out[j+0] = b64str[(value & m1) >> (6*3)  ];
        }       
    }
   
    if (in_len/3 < out_len/4)
        switch (in_len%3) {
            case 1: out[in_len*4/3+2]='=';
            case 2: out[in_len*4/3+1]='=';
        }
}

По крайней мере, читабельней мне.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Август, 2010 04:05 

Зарегистрирован: Пятница, 24 Апрель, 2009 16:28
Сообщения: 524
Откуда: Москва
Евгений Темиргалеев писал(а):
Хотелось бы услышать мнения касательно сложности проверки соответствия алгоритмов стандарту (но не придирки к переводу кода).
Честно говоря, не врубился в проблему (да и нет желания врубаться), но где гарантия, что индекс не выйдет за границы x:
Код:
t := ORD(x[p + 2]) + ASH(ORD(x[p + 1]), 8) + ASH(ORD(x[p]), 16); INC(p, 3);
P.S. А нуль в конце не надо добавлять?
Кроме того, в сишных алгоритмах мне непонятно: если размер выходной строки (буфера) меньше чем требуется, нахрена заполнять ее началом правильного результата, причем без нуля в конце? Кому нужен такой обрубок? Надо возвращать неуспех, и дело с концом. Поправьте, кто знает.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Август, 2010 09:53 

Зарегистрирован: Вторник, 25 Апрель, 2006 16:21
Сообщения: 2178
Откуда: Нижний Новгород
Peter Almazov писал(а):
Кроме того, в сишных алгоритмах мне непонятно: если размер выходной строки (буфера) меньше чем требуется, нахрена заполнять ее началом правильного результата, причем без нуля в конце? Кому нужен такой обрубок? Надо возвращать неуспех, и дело с концом. Поправьте, кто знает.

Для потокового кодирования. Представьте себе, что входящая последовательность данных бесконечна.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Август, 2010 10:42 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4392
Откуда: Россия, Орёл
Peter Almazov писал(а):
но где гарантия, что индекс не выйдет за границы x:
Код:
t := ORD(x[p + 2]) + ASH(ORD(x[p + 1]), 8) + ASH(ORD(x[p]), 16); INC(p, 3);
P.S. А нуль в конце не надо добавлять?
1) В ББ гарантия - трэп "неверный индекс". В Си гарантий нет. Алгоритмически - проблема клиента, который запрашивает кодирование куска буфера длины len.
2) Нуль добавляет клиент, если он ему нужен.
Код:
X.Encode(ss, dd, p, q, LEN(ss$)); dd[q] := 0X;
Log.String(dd$);


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Август, 2010 11:34 

Зарегистрирован: Вторник, 11 Август, 2009 11:44
Сообщения: 516
Откуда: Бердск
Можно попробовать исходить из шаблонов второго уровня: "надо делать так, чтобы тебя лучше понимали коллеги", а не из неких "правил фоматирования", которые конечно же являются следствиями первых.

Тогда для ЭТОГО КОНКРЕТНОГО примера (у меня нет намерения обобщать это на все разновидности кодов!!!):
  • шаблон *out++ = <формула> смотрится таки понятнее чем в Обероне. Думаю, что это от того, что в коде нет ИНЫХ использований данной переменной.
  • но инженер - это наемник. Надо писать на C - будет на C. Если стандарт предприятия (например) предписывает Оберон - ну ладно. Но при этом я все равно постарался бы уложить этот маленький же шаблончик - максимально компактно. Не потому, что это где-то на скрижалях записано (типа базовая техника), а потому-что мне кажется (что всегда будет субъективным факторам), что именно так будет понятнее (уровень более высокий чем базовый). Может так ???
    Код:
      tmp := <длинная формула 1>;
      y[q] := ctable[tmp]; INC(q);
      tmp := <очень длинная формула 2>;
      y[q] := ctable[tmp]; INC(q);
      tmp := <не очень длинная формула 3>;
      y[q] := ctable[tmp]; INC(q);
  • Скобки в этих формУлах раза по три считал. Понимаю головой, что не мог я три раза ошибиться, а внутренней уверенности все равно нет. Пока не перенес в редактор, который на автомате подсвечивает парную - появилась таки. Думаю, что если мы заботимся от том, что это будет читать другой человек, тогда (для данного конкретного случая!!!) разбивать надо. Даже если такого правила нет в списке базовых техник

В общем как-то так. Надо уж мне ставить некую мифическую технику, или нет... Но соображения для данного конкретного случая у меня таковы (про break правда ничего не сказал... ну пока ладно)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Август, 2010 13:10 

Зарегистрирован: Пятница, 24 Апрель, 2009 16:28
Сообщения: 524
Откуда: Москва
Евгений Темиргалеев писал(а):
Peter Almazov писал(а):
но где гарантия, что индекс не выйдет за границы x:
Код:
t := ORD(x[p + 2]) + ASH(ORD(x[p + 1]), 8) + ASH(ORD(x[p]), 16); INC(p, 3);
P.S. А нуль в конце не надо добавлять?
1) В ББ гарантия - трэп "неверный индекс". В Си гарантий нет. Алгоритмически - проблема клиента, который запрашивает кодирование куска буфера длины len.
Я немного не об этом. Вы пишете на входе ASSERT(len >= 0, 20). А в p можно, выходит, передавать любой бред. Кстати, не пойму, зачем там передавать что-то отличное от нуля.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Август, 2010 14:27 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 8781
Откуда: Россия, Орёл
Peter Almazov писал(а):
Я немного не об этом. Вы пишете на входе ASSERT(len >= 0, 20). А в p можно, выходит, передавать любой бред. Кстати, не пойму, зачем там передавать что-то отличное от нуля.


Тут тонкая практическая грань уже идёт. Если предусловие на невыход позиции за границы, то оно и так неявно будет проверено при попытке выхода, для функций, которые "узкое место", проверять смысла нет явно.
Неверный же len спровоцирует "странности".

Зачем передавать - функция может ставиться на интенсивной потоковой обработке, там разные ситуации бывают.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Август, 2010 17:52 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 8781
Откуда: Россия, Орёл
Евгений Темиргалеев писал(а):
P.P.S. Вариант, который привёл Alexey Veselovsky, я бы стал портировать...

(процитировано в связи с тем, что сообщение при разделении тем ушло в другую ветку)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Август, 2010 17:55 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 8781
Откуда: Россия, Орёл
Обсуждение оформления кода табуляциями для данного примера отделено -
viewtopic.php?f=1&t=2770&p=50362


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Август, 2010 21:06 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4392
Откуда: Россия, Орёл
Нда... целую ветку наболтали про оформление, а на исходный вопрос, ничего... :roll:

Попробую ещё раз: есть разные реализации процедур кодирования массива (куска массива) алгоритмом base64.
* неструктурная реализация (четыре break основного цикла), которую приводит в качестве примера стандарт
* два структурных варианта: 1 и 2.

Вопрос: как вы считаете - какую реализацию проще проверить на соотвествие стандарту Base64 --- структурную или неструктурную --- на примере этих вариантов? Можно привести свои варианты и дать второй ответ с их учётом.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Август, 2010 21:14 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4392
Откуда: Россия, Орёл
Лично я считаю, что проверка неструктурного варианта на порядок более сложная и является примером неумения программировать:
Galkov писал(а):
...Покажите пожалуйста пример, в котором, опираясь на Дейкстру можно увидеть "неумение программировать"...
Что Вы скажете, тов. Galkov?

Мнение тов. Alexey Veselovsky тоже хотелось бы услышать, т.к. он свой вариант уже привёл...


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 06 Август, 2010 08:21 

Зарегистрирован: Вторник, 11 Август, 2009 11:44
Сообщения: 516
Откуда: Бердск
Хм... де-жа-вю какое-то... отвечал же вроде. Типа: тильки шо було, та раптом зникло :shock:

Найду, или восстановлю. Ближе к вечеру (запарка сейчас какая-то :( )


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 06 Август, 2010 14:03 

Зарегистрирован: Вторник, 25 Апрель, 2006 16:21
Сообщения: 2178
Откуда: Нижний Новгород
Galkov писал(а):
Хм... де-жа-вю какое-то... отвечал же вроде. Типа: тильки шо було, та раптом зникло :shock:
Найду, или восстановлю. Ближе к вечеру (запарка сейчас какая-то :( )

У меня тоже не то что запарка, а зоопарка какая-то. Так что тоже попозже отвечу.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 06 Август, 2010 20:46 

Зарегистрирован: Вторник, 25 Апрель, 2006 16:21
Сообщения: 2178
Откуда: Нижний Новгород
Итак, моё мнение (точнее не мнение, а мой опыт. внимание info21 тут нет квантора всеобщности! (вообще его нигде нет, если это не указано явно) ):

1) Обе реализации очень плохо читаются и воспринмаются, до того как прочтешь документацию по base64 и не попытаешься реализовать что-то своё. Т.е. реально до написания своей реализации оба исходника представлялись одинаково низкоуровневой абракадаброй. Т.о. они не самодкументирующиеся.
2) После чтения док и написания своей реализации, оба исходника воспринимаются и понимаются нормально. Т.е. нет проблем с верификацией там и там.
3) С99 алгоритм сделан более прямолинейно и дубово. Соответственно читается абсолютно линейно. Основное отличие от реализации на КП (и, возможно, достоинство) -- он пишет в выходной буфер ASAP, т.е. как только что-то сложилось, так сразу и написали. Не дожидаясь пока прочтутся все 3 байта. Также не используется дополнительный буфер. Т.о. нет фазы копирования в промежуточный буфер.
4) В С99 варианте на каждую итерацию цикла существенно больше проверок. Насколько это скажется на производительности -- затрудняюсь оценить. Но вообще, это не хорошо.
5) В обоих реализация используется цикл while. В обоих релизациях соответственно где-то в потрохах цикла меняется счетчик цикла. Но это не страшно. В обоих случаях он меняется в одном месте. Страшно другое -- всякие разные указатели и индексы в обоих реализациях, которые, вообще говоря, связаны со счетчиком, скачут как бешаные лошади. Т.е. их изменение тонким слоем размазано по всему телу цикла. Верифицировать когда и в каких случаях индексы/указатели смогут вылезти за границы дозволенного -- сложно. Нужно считать и думать.
6) В С99 явный перебор со скобочками и операторами. К тому же вариант форматирования выбран не самый удачный.
7) Вообще в обоих вариантах всё слишком низкоуровнево. Впрочем я уже говорил ;-)
8) В КП-варианте имеем два непонятных аргумента у функции, который используется вроде как локальные переменные. Предполагается что там будет вначале ноль. Но почему бы их не обнулить явно?
9) Возвращаемые значения всё же лучше передавать в виде результата функции.
10) В КП-вариенте предполагается, что выходной буфер всегда достаточного размера, что, в общем то, не очевидно. И может привести к ошибкам. (да, словленный AV это тоже ошибка, трапы в Обероне -- деталь реализации, равно также как и в С99, так что отмазкой не являются).
11) Про thread safe... Интересно в КП варианте, если в процессе кодирования, кто-то слегка чуть-чуть поиграется с p,q. Ведь они переданы по ссылке.
12) В КП варианте увлекаются множеством операций на одной строке. Плохо сказывается на читабельности.

Резюме -- в качестве референсной реализации rfc-писателям не стоило указывать эту C99 реализацию, КП-реализация в качестве референсной также не подошла бы. Слишком много низкоуровневых деталей.

Что касается моей реализации, наверно лучше не мне судить. Но она мне не слишком нравится.
Во-первых используются C-style hasks (см. как я работаю со switch'ами), это не портабельно на другие языки (не С-семейства в плане синтаксиса), т.о. на референсную реализацию для императивных языков не тянет.
Во-вторых всё ещё много низкоуровневых деталей. Реверансы в сторону быстродействия. Те же switch'и например. Т.о. оно не тянет и на общую референсную реализацию (в которой должно быть кристально ясно что такое base64 и без чтения спек).
В-третьих мне не удалось достичь макимальной производительности. Т.е. по паре лишних сравнений на итерацию всё же есть. Т.о. для сурово-промышленной эксплуатации также возможно не лучший вариант.

Что хорошо: переменные циклов и прочее от них зависящее меняется только в потрохах for'a, т.е. не в теле цикла. Проще читать. Больше уверенности, что не будет нагажено в память. Вроде бы получилось создать достаточно человекочитабельный код в плане работы с масками. Т.е. не нужно вспоминать что такое есть 3F и почему это в данном случае хорошо. Это видно просто визуально. Ну и быстродействие всё же не столь ужасное как могло бы быть.

Резюме -- я пытался достичь сразу трех целей одновременно: компактности кода (по возможности не должны повторяться одни и те же блоки кода), скорости работы алгоритма (желательно чтобы скорость не уступала любым другим реализациям), хорошей человекочитабельности (в коде должен присутствовать некий ритм помогающий его читать). В резельтате от кода несет компромисом.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 06 Август, 2010 20:51 

Зарегистрирован: Вторник, 25 Апрель, 2006 16:21
Сообщения: 2178
Откуда: Нижний Новгород
В качестве общего референсного кода, где нет таких низкоуровневых вещей. как указатели, индексы, какие-то там маски, побитовые операции (в т.ч. сдвига) и прочего подобного, я бы предложил вот этот код на erlang'e (моего авторства). По моему, тут удалось достичь цели. (кстати, производительность также не слишком ужасная).

Код:
encode_bin(<<>>,ResStr)-> lists:reverse(ResStr);
encode_bin(Bin, ResStr)->
    {HeadBin,TailBin,Zero} = case Bin of
                                 <<B:24, RestBin/binary>> -> {<<B:24>>     ,RestBin, 0};
                                 <<B:16                >> -> {<<B:16,0:8>> ,<<>>   , 1};
                                 <<B: 8                >> -> {<<B:8 ,0:16>>,<<>>   , 2}
                             end,
    <<A1:6,A2:6,A3:6,A4:6>> = HeadBin,
    encode_bin(TailBin,to_str([A1,A2,A3,A4],ResStr,4-Zero)).

to_str([],ResStr,_)         -> ResStr;
to_str([H|T],ResStr,NonZero)->
    case NonZero of 0 -> to_str(T,[$=|ResStr],NonZero);
                    _ -> to_str(T,[b64e(H)|ResStr],NonZero-1)
    end.


Полный текст модуля можно взять тут: http://paste.org.ru/?k86ho9 или тут: http://erlang.pastebin.com/6fAa8WEW
(откровенно говоря, мне и там и там не нравится подсветка синтаксиса).

Синтаксис работы с бинарными даннами в ерланге превосходен. Особенно в сочетании с сопоставлением с образцом.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Суббота, 07 Август, 2010 09:23 

Зарегистрирован: Пятница, 25 Ноябрь, 2005 12:02
Сообщения: 7616
Откуда: Троицк, Москва
Alexey Veselovsky писал(а):
Итак, моё мнение (точнее не мнение, а мой опыт. внимание info21 тут нет квантора всеобщности!
Вы это не мне, а публике сообщайте. Публике.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Суббота, 07 Август, 2010 16:57 

Зарегистрирован: Четверг, 23 Апрель, 2009 18:01
Сообщения: 219
Публике и так всё ясно. А вот вам приходится объяснять.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 23 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2017, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB