Skip to content

Commit

Permalink
Support Simulationarchive files with version < 3.18
Browse files Browse the repository at this point in the history
  • Loading branch information
hannorein committed Jun 24, 2024
1 parent b8d14b7 commit e2e8e18
Showing 1 changed file with 58 additions and 4 deletions.
62 changes: 58 additions & 4 deletions src/simulationarchive.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ struct reb_simulation* reb_simulation_create_from_simulationarchive(struct reb_s
return r; // might be null if error occured
}

// Old 16 bit offsets. Used only to read old files.
struct reb_simulationarchive_blob16 {
int32_t index;
int16_t offset_prev;
int16_t offset_next;
};

void reb_read_simulationarchive_from_stream_with_messages(struct reb_simulationarchive* sa, struct reb_simulationarchive* sa_index, enum reb_simulation_binary_error_codes* warnings){
// Assumes sa->inf is set to an open stream
const int debug = 0;
Expand All @@ -111,7 +118,9 @@ void reb_read_simulationarchive_from_stream_with_messages(struct reb_simulationa
struct reb_binary_field field = {0};
sa->version = 0;
double t0 = 0;

int version_major = 0; // will be overwritten unless there is an error
int version_minor = 0;
int uses32bitoffsets = 1;
// Cache descriptors
struct reb_binary_field_descriptor fd_header = reb_binary_field_descriptor_for_name("header");
struct reb_binary_field_descriptor fd_t = reb_binary_field_descriptor_for_name("t");
Expand All @@ -137,6 +146,35 @@ void reb_read_simulationarchive_from_stream_with_messages(struct reb_simulationa
sprintf(curvbuf,"%s%s",header+sizeof(struct reb_binary_field), reb_version_str);

objects += fread(readbuf,sizeof(char),bufsize,sa->inf);
// Finding version_major/version_minor version
int c1=0, c2=0, c3=0;
for (int c=0; c<bufsize; c++){
if (c2 != 0 && c3 == 0 && readbuf[c] == '.'){
c3 = c;
}
if (c1 != 0 && c2 == 0 && readbuf[c] == '.'){
c2 = c;
}
if (c1 == 0 && readbuf[c] == ':'){
c1 = c;
}
}
if (c1==0 || c2==0 || c3==0){
if (debug) printf("SA Error. Cannot determine version.\n");
*warnings |= REB_SIMULATION_BINARY_WARNING_CORRUPTFILE;
}else{
char cminor[64];
char cmajor[64];
strncpy(cminor, readbuf+c2+1, c3-c2-1);
cminor[c3-c2-1] = '\0';
strncpy(cmajor, readbuf+c1+1, c2-c1-1);
cmajor[c2-c1-1] = '\0';
version_minor = atoi(cminor);
version_major = atoi(cmajor);
if (version_major <= 3 || version_minor < 18){
uses32bitoffsets = 0; // fallback to 16 bit
}
}
if (objects < 1){
*warnings |= REB_SIMULATION_BINARY_WARNING_CORRUPTFILE;
}else{
Expand Down Expand Up @@ -224,7 +262,17 @@ void reb_read_simulationarchive_from_stream_with_messages(struct reb_simulationa
}
// Everything looks normal so far. Attempt to read next blob
struct reb_simulationarchive_blob blob = {0};
size_t r3 = fread(&blob, sizeof(struct reb_simulationarchive_blob), 1, sa->inf);
size_t r3;
if (uses32bitoffsets){
r3 = fread(&blob, sizeof(struct reb_simulationarchive_blob), 1, sa->inf);
}else{
// Workaround for versions < 3.18
struct reb_simulationarchive_blob16 blob16 = {0};
r3 = fread(&blob16, sizeof(struct reb_simulationarchive_blob16), 1, sa->inf);
blob.index = blob16.index;
blob.offset_prev = blob16.offset_prev;
blob.offset_next = blob16.offset_next;
}
int next_blob_is_corrupted = 0;
if (r3!=1){ // Next snapshot is definitly corrupted.
// Assume we have reached the end of the file.
Expand All @@ -234,10 +282,16 @@ void reb_read_simulationarchive_from_stream_with_messages(struct reb_simulationa
*warnings |= REB_SIMULATION_BINARY_WARNING_CORRUPTFILE;
}
if (i>0){
size_t blobsize;
if (uses32bitoffsets){
blobsize = sizeof(struct reb_simulationarchive_blob);
}else{
blobsize = sizeof(struct reb_simulationarchive_blob16);
}
// Checking the offsets. Acts like a checksum.
if (((int64_t)blob.offset_prev )+ ((int64_t)sizeof(struct reb_simulationarchive_blob)) != ftell(sa->inf) - ((int64_t)sa->offset[i]) ){
if (((int64_t)blob.offset_prev )+ ((int64_t)blobsize) != ftell(sa->inf) - ((int64_t)sa->offset[i]) ){
// Offsets don't work. Next snapshot is definitly corrupted. Assume current one as well.
if (debug) printf("SA Error. Offset mismatch: %lu != %" PRIu64 ".\n",blob.offset_prev + sizeof(struct reb_simulationarchive_blob), (uint64_t)(ftell(sa->inf) - sa->offset[i]) );
if (debug) printf("SA Error. Offset mismatch: %lu != %" PRIu64 ".\n",blob.offset_prev + blobsize, (uint64_t)(ftell(sa->inf) - sa->offset[i]) );
read_error = 1;
break;
}
Expand Down

0 comments on commit e2e8e18

Please sign in to comment.