Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Faster tagblock updates #43

Open
wants to merge 16 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ais_tools/aivdm.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from ais_tools.ais import AISMessageTranscoder
from ais_tools.nmea import split_multipart
from ais_tools.nmea import expand_nmea
from ais_tools.checksum import checksumstr
from ais_tools.core import checksum_str
from ais_tools.message import Message


Expand Down Expand Up @@ -166,7 +166,7 @@ def safe_encode(self, message):
def encode(self, message):
body, pad = self.encode_payload(message)
sentence = "AIVDM,1,1,,A,{},{}".format(body, pad)
return Message("!{}*{}".format(sentence, checksumstr(sentence)))
return Message("!{}*{}".format(sentence, checksum_str(sentence)))

def encode_payload(self, message):
return self.encoder.encode_payload(message)
103 changes: 0 additions & 103 deletions ais_tools/checksum.c

This file was deleted.

83 changes: 83 additions & 0 deletions ais_tools/core/checksum.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// checksum module

#include <Python.h>
#include <stdbool.h>
#include <string.h>
#include "core.h"
#include "checksum.h"

/*
* Compute the checksum value of a string. This is
* computed by xor-ing the integer value of each character in the string
* sequentially.
*/
int checksum(const char *s)
{
int c = 0;
while (*s)
c = c ^ *s++;
return c;
}

/*
* Get the checksum value of a string as a 2-character hex string
* This is always uppercase. The destination buffer must be at least 3 chars
* (one for the terminating null character)
*
* Returns a pointer to the destination buffer
* Returns null if the dest buffer is too small
*/
char* checksum_str(char * __restrict dst, const char* __restrict src, size_t dsize)
{
if (dsize < 3)
return NULL;

int c = checksum(src);
sprintf(dst, "%02X", c);
return dst;
}


/*
* Compute the checksum value of the given string and compare it to the checksum
* that appears at the end of the string.
* the checksum should be a 2 character hex value at the end separated by a '*'
*
* For example:
* c:1000,s:old*5A
*
* If the string starts with any of these characrters ?!\ then the first character is ignored
* for purposes of computing the checksum
*
* If no checksum is found at at the end of the string then the return is false
*
* Returns true if the checksum at the end of the string matches the computed checksum, else false
*
* NOTE: The given string will be modified to separate it into the body portion and the checksum portion
*/
bool is_checksum_valid(char* s)
{
const char * skip_chars = "!?\\";
const char separator = '*';

char* body = s;
char* c_str = NULL;
char computed_checksum[3];

if (*body && strchr(skip_chars, body[0]))
body++;

char* ptr = body;
while (*ptr != '\0' && *ptr != separator)
ptr++;

if (*ptr == '*')
*ptr++ = '\0';
c_str = ptr;

if (c_str == NULL || strlen(c_str) != 2)
return false;

checksum_str(computed_checksum, body, ARRAY_LENGTH(computed_checksum));
return strcasecmp(c_str, computed_checksum) == 0;
}
5 changes: 5 additions & 0 deletions ais_tools/core/checksum.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* AIS Tools checksum functions */

int checksum(const char *s);
char* checksum_str(char * __restrict dst, const char* __restrict src, size_t dsize);
bool is_checksum_valid(char* s);
37 changes: 37 additions & 0 deletions ais_tools/core/core.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* AIS Tools core functions implemented in C */

#define PY_SSIZE_T_CLEAN /* Make "s#" use Py_ssize_t rather than int. */

#define SUCCESS 0
#define FAIL -1
#define FAIL_STRING_TOO_LONG -101
#define FAIL_TOO_MANY_FIELDS -102


#define ARRAY_LENGTH(array) (sizeof((array))/sizeof((array)[0]))

#define ERR_TAGBLOCK_DECODE "Unable to decode tagblock string"
#define ERR_TAGBLOCK_TOO_LONG "Tagblock string too long"
#define ERR_TOO_MANY_FIELDS "Too many fields"
#define ERR_NMEA_TOO_LONG "NMEA string too long"
#define ERR_UNKNOWN "Unknown error"

#define MAX_TAGBLOCK_FIELDS 8 // max number of fields allowed in a tagblock
#define MAX_TAGBLOCK_STR_LEN 1024 // max length of a tagblock string
#define MAX_KEY_LEN 32 // max length of a single key in a tagblock
#define MAX_VALUE_LEN 256 // max length of a single value in a tagblock
#define MAX_SENTENCE_LENGTH 1024 // max length of a single nmea sentence (tagblock + AIVDM)

#define TAGBLOCK_SEPARATOR "\\"
#define CHECKSUM_SEPARATOR "*"
#define FIELD_SEPARATOR ","
#define KEY_VALUE_SEPARATOR ":"
#define GROUP_SEPARATOR "-"
#define AIVDM_START "!"
#define EMPTY_STRING ""


// string copy utils
char * unsafe_strcpy(char * __restrict dest, const char * __restrict est_end, const char * __restrict src);
size_t safe_strcpy(char * __restrict dst, const char * __restrict src, size_t dsize);

Loading