LINUX.ORG.RU

Подсчёт XOR-суммы

 


1

2

XOR-сумма - это результат последовательного XOR всех байт строки, один из самых примитивных, если не самый примитивный, методов контроля целостности.
Применительно к NMEA 0183, где это как раз используется, я реализовал алгоритм так (см. функцию проверки validateS):

ord() { 
 LC_CTYPE=C printf '%d' «'$1»
}

validateS () {
 local S=«$@» lS 
 local i origXSum myXSum
 [[ $S =~ ^\$.+\*[0-9A-F]{2}$ ]] || return 1
 lS=${#S}
 origXSum=${S:$((lS-2)):2}
 S=${S:1:$((lS-4))}
 myXSum=0
 for ((i=0; i<${#S}; i++)); do
  (( myXSum^=$(ord ${S:$i:1}) ))
 done
 [[ $(printf '%.2X\n' $myXSum) == $origXSum ]] || return 2
 [[ ${S:1:5} == 'GPRMC' && $S =~ ',V,' ]] && return 3
 
 return 0
}
В NMEA 0183 строка начинается с $, а заканчивается *XORSUM, где XORSUM - это hex-представление (2 символа то бишь) одного байта XOR-суммы всех байт между $ и *.

Собственно, вопрос о том, можно ли реализовать это быстрее? Есть, например, вариант сразу преобразовывать строку полностью к hex-виду, и уже после этого считать XOR-сумму, не вызывая каждый раз ord(). Но, полагаю, как это часто бывает в BASH, есть какой-то способ сделать это на несколько порядков быстрее, только я его пока не вижу :)

★★★★★

Последнее исправление: DRVTiny (всего исправлений: 1)

Ответ на: комментарий от Harald

Я на Си не пишу, мне по-любому не проще. Хотя на википедии выложен уже кусок кода, его только скомпилировать остаётся.
Вот:

#include <stdio.h>
#include <string.h>
 
int checksum(char *s) {
    int c = 0;
 
    while(*s)
        c ^= *s++;
 
    return c;
}
Источник:
статья об NMEA 0183 в англ. википедии.

DRVTiny ★★★★★
() автор топика
echo -n 'Hello, world!' | gawk 'BEGIN{RS="\0"}END{for(i=0;i<256;i++){ord[sprintf("%c",i)]=i};a=0;for(i=1;i<=length($0);i++){a=xor(a,ord[substr($0,i,1)])}printf("%02X",a);print""}'
i-rinat ★★★★★
()

Но, полагаю, как это часто бывает в BASH, есть какой-то способ сделать это на несколько порядков быстрее

Да, есть: не делать на баше то, для чего он явно не предназначен. Особенно учитывая, что perl или python есть в большинстве линукс-систем, не говоря уже о компиляторе си.

quantum-troll ★★★★★
()
Ответ на: комментарий от Kalashnikov

Так, а сравнительные размеры и читаемость кусков кода тебя ни на какие мысли не наталкивает?

Ну так прочтите внимательно: мой код на BASH не только XOR считает.

DRVTiny ★★★★★
() автор топика

У hexdump формат вывода очень гибко настраивается

echo "преобразовывать строку полностью к hex-виду," | hexdump -ve '1/1 "%.2x"'
d0bfd180d0b5d0bed0b1d180d0b0d0b7d0bed0b2d18bd0b2d0b0d182d18c20d181d182d180d0bed0bad18320d0bfd0bed0bbd0bdd0bed181d182d18cd18e20d0ba206865782dd0b2d0b8d0b4d1832c0a

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

Во, спасибо, идея интересная!

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