D868UV: parse CSV files downloaded from amateurradio.digital.
This commit is contained in:
parent
08ae731218
commit
46203f940e
62
d868uv.c
62
d868uv.c
@ -2687,7 +2687,7 @@ static int d868uv_verify_config(radio_device_t *radio)
|
||||
//
|
||||
// Read and dump the callsign database.
|
||||
//
|
||||
static void read_csv(radio_device_t *radio)
|
||||
static void dump_csv(radio_device_t *radio)
|
||||
{
|
||||
callsign_sizes_t sz = {0};
|
||||
|
||||
@ -2809,52 +2809,30 @@ static void d868uv_write_csv(radio_device_t *radio, FILE *csv)
|
||||
// Need to rearrange the fields like:
|
||||
// Radio ID, Name, City, Callsign, State, Country, Remarks
|
||||
//
|
||||
char line[256];
|
||||
unsigned nbytes = 0;
|
||||
char *radioid, *callsign, *name, *city, *state, *country, *remarks;
|
||||
|
||||
while (fgets(line, sizeof(line), csv)) {
|
||||
trim_spaces(line, 255);
|
||||
if (line[0] < '0' || line[0] > '9') {
|
||||
// Eastern egg: when file contains a line "dump",
|
||||
// read the callsign database from the radio
|
||||
// and save to a file.
|
||||
if (strcmp(line, "dump") == 0) {
|
||||
free(data);
|
||||
read_csv(radio);
|
||||
return;
|
||||
}
|
||||
// Skip header.
|
||||
continue;
|
||||
}
|
||||
if (csv_init(csv) < 0) {
|
||||
free(data);
|
||||
return;
|
||||
}
|
||||
while (csv_read(csv, &radioid, &callsign, &name, &city, &state, &country, &remarks)) {
|
||||
//printf("%s,%s,%s,%s,%s,%s,%s\n", radioid, callsign, name, city, state, country, remarks);
|
||||
|
||||
// Replace non-ASCII characters with '?'.
|
||||
char *p;
|
||||
for (p=line; *p; p++) {
|
||||
if (*p < ' ' || *p > '~')
|
||||
*p = '?';
|
||||
}
|
||||
|
||||
char *callsign = strchr(line, ','); if (! callsign) continue; *callsign++ = 0;
|
||||
char *name = strchr(callsign, ','); if (! name) continue; *name++ = 0;
|
||||
char *city = strchr(name, ','); if (! city) continue; *city++ = 0;
|
||||
char *state = strchr(city, ','); if (! state) continue; *state++ = 0;
|
||||
char *country = strchr(state, ','); if (! country) continue; *country++ = 0;
|
||||
char *remarks = strchr(country, ','); if (! remarks) continue; *remarks++ = 0;
|
||||
if ((p = strchr(remarks, ',')) != 0)
|
||||
*p = 0;
|
||||
callsign = trim_spaces(callsign, 16);
|
||||
name = trim_spaces(name, 16);
|
||||
city = trim_spaces(city, 15);
|
||||
state = trim_spaces(state, 16);
|
||||
country = trim_spaces(country, 16);
|
||||
remarks = trim_spaces(remarks, 16);
|
||||
//printf("%s,%s,%s,%s,%s,%s,%s\n", line, callsign, name, city, state, country, remarks);
|
||||
|
||||
unsigned id = strtoul(line, 0, 10);
|
||||
unsigned id = strtoul(radioid, 0, 10);
|
||||
if (id < 1 || id > 0xffffff) {
|
||||
fprintf(stderr, "Bad id: %d\n", id);
|
||||
fprintf(stderr, "Line: '%s,%s,%s,%s,%s,%s,%s'\n",
|
||||
line, callsign, name, city, state, country, remarks);
|
||||
radioid, callsign, name, city, state, country, remarks);
|
||||
return;
|
||||
}
|
||||
|
||||
// Eastern egg: when file contains id 1 with callsign 'dump',
|
||||
// read the callsign database from the radio
|
||||
// and save to a file.
|
||||
if (id == 1 && strcmp(callsign, "dump") == 0) {
|
||||
free(data);
|
||||
dump_csv(radio);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2872,7 +2850,7 @@ static void d868uv_write_csv(radio_device_t *radio, FILE *csv)
|
||||
m->offset = nbytes;
|
||||
|
||||
// Fill data.
|
||||
p = &data[nbytes];
|
||||
char *p = &data[nbytes];
|
||||
|
||||
// Radio ID.
|
||||
*p++ = 0;
|
||||
|
111
util.c
111
util.c
@ -142,6 +142,22 @@ char *trim_spaces(char *line, int limit)
|
||||
return line;
|
||||
}
|
||||
|
||||
//
|
||||
// Strip optional quotes around the string.
|
||||
//
|
||||
char *trim_quotes(char *line)
|
||||
{
|
||||
if (*line == '"') {
|
||||
int last = strlen(line) - 1;
|
||||
|
||||
if (line[last] == '"') {
|
||||
line[last] = 0;
|
||||
return line+1;
|
||||
}
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
//
|
||||
// Delay in milliseconds.
|
||||
//
|
||||
@ -722,3 +738,98 @@ void print_tone(FILE *out, unsigned data)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize CSV parser.
|
||||
// Check header for correctness.
|
||||
// Return negative on error.
|
||||
//
|
||||
static int csv_skip_field1;
|
||||
|
||||
int csv_init(FILE *csv)
|
||||
{
|
||||
char line[256];
|
||||
|
||||
if (!fgets(line, sizeof(line), csv))
|
||||
return -1;
|
||||
|
||||
char *field1 = line;
|
||||
char *field2 = strchr(field1, ','); if (! field2) return -1; *field2++ = 0;
|
||||
char *field3 = strchr(field2, ','); if (! field3) return -1; *field3++ = 0;
|
||||
char *field4 = strchr(field3, ','); if (! field4) return -1; *field4++ = 0;
|
||||
|
||||
field1 = trim_quotes(field1);
|
||||
field2 = trim_quotes(field2);
|
||||
field3 = trim_quotes(field3);
|
||||
//printf("Line: %s,%s,%s\n", field1, field2, field3);
|
||||
|
||||
if (strcmp(field1, "Radio ID") == 0 &&
|
||||
strcmp(field2, "Callsign") == 0) {
|
||||
// Correct format:
|
||||
// Radio ID,Callsign,Name,City,State,Country,Remarks
|
||||
csv_skip_field1 = 0;
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(field2, "Radio ID") == 0 &&
|
||||
strcmp(field3, "Callsign") == 0) {
|
||||
// Correct format:
|
||||
// "No.","Radio ID","Callsign","Name","City","State","Country","Remarks"
|
||||
csv_skip_field1 = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//TODO
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse one line of CSV file.
|
||||
// Return 1 on success, 0 on EOF.
|
||||
//
|
||||
int csv_read(FILE *csv, char **radioid, char **callsign, char **name,
|
||||
char **city, char **state, char **country, char **remarks)
|
||||
{
|
||||
static char line[256];
|
||||
|
||||
again:
|
||||
if (!fgets(line, sizeof(line), csv))
|
||||
return 0;
|
||||
//printf("Line: '%s'\n", line);
|
||||
|
||||
// Replace non-ASCII characters with '?'.
|
||||
char *p;
|
||||
for (p=line; *p; p++) {
|
||||
if ((uint8_t)*p > '~')
|
||||
*p = '?';
|
||||
}
|
||||
|
||||
if (csv_skip_field1) {
|
||||
*radioid = strchr(line, ',');
|
||||
if (! *radioid)
|
||||
return 0;
|
||||
*(*radioid)++ = 0;
|
||||
} else
|
||||
*radioid = line;
|
||||
|
||||
*callsign = strchr(*radioid, ','); if (! *callsign) return 0; *(*callsign)++ = 0;
|
||||
*name = strchr(*callsign, ','); if (! *name) return 0; *(*name)++ = 0;
|
||||
*city = strchr(*name, ','); if (! *city) return 0; *(*city)++ = 0;
|
||||
*state = strchr(*city, ','); if (! *state) return 0; *(*state)++ = 0;
|
||||
*country = strchr(*state, ','); if (! *country) return 0; *(*country)++ = 0;
|
||||
*remarks = strchr(*country, ','); if (! *remarks) return 0; *(*remarks)++ = 0;
|
||||
if ((p = strchr(*remarks, ',')) != 0)
|
||||
*p = 0;
|
||||
|
||||
*radioid = trim_spaces(trim_quotes(*radioid), 16);
|
||||
*callsign = trim_spaces(trim_quotes(*callsign), 16);
|
||||
*name = trim_spaces(trim_quotes(*name), 16);
|
||||
*city = trim_spaces(trim_quotes(*city), 15);
|
||||
*state = trim_spaces(trim_quotes(*state), 16);
|
||||
*country = trim_spaces(trim_quotes(*country), 16);
|
||||
*remarks = trim_spaces(trim_quotes(*remarks), 16);
|
||||
//printf("%s,%s,%s,%s,%s,%s,%s\n", *radioid, *callsign, *name, *city, *state, *country, *remarks);
|
||||
|
||||
if (**radioid < '1' || **radioid > '9')
|
||||
goto again;
|
||||
return 1;
|
||||
}
|
||||
|
19
util.h
19
util.h
@ -49,6 +49,25 @@ void print_hex_addr_data(unsigned addr, const unsigned char *data, int len);
|
||||
//
|
||||
char *trim_spaces(char *line, int limit);
|
||||
|
||||
//
|
||||
// Strip optional quotes around the string.
|
||||
//
|
||||
char *trim_quotes(char *line);
|
||||
|
||||
//
|
||||
// Initialize CSV parser.
|
||||
// Check header for correctness.
|
||||
// Return -1 on error.
|
||||
//
|
||||
int csv_init(FILE *csv);
|
||||
|
||||
//
|
||||
// Parse one line of CSV file.
|
||||
// Return 1 on success, 0 on EOF.
|
||||
//
|
||||
int csv_read(FILE *csv, char **radioid, char **callsign, char **name,
|
||||
char **city, char **state, char **country, char **remarks);
|
||||
|
||||
//
|
||||
// DFU functions.
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user