/***************************************
Error log data type functions.
Part of the Routino routing software.
******************/ /******************
This file Copyright 2013, 2019, 2020 Andrew M. Bishop
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
***************************************/
#include
#include
#include "types.h"
#include "errorlog.h"
#include "files.h"
/*++++++++++++++++++++++++++++++++++++++
Load in an error log list from a file.
ErrorLogs *LoadErrorLogs Returns the error log list.
const char *filename The name of the file to load.
++++++++++++++++++++++++++++++++++++++*/
ErrorLogs *LoadErrorLogs(const char *filename)
{
ErrorLogs *errorlogs;
errorlogs=(ErrorLogs*)malloc(sizeof(ErrorLogs));
#if !SLIM
errorlogs->data=MapFile(filename);
/* Copy the ErrorLogsFile header structure from the loaded data */
errorlogs->file=*((ErrorLogsFile*)errorlogs->data);
/* Set the pointers in the ErrorLogs structure. */
errorlogs->offsets =(index_t* )(errorlogs->data+sizeof(ErrorLogsFile));
errorlogs->errorlogs_geo =(ErrorLog*)(errorlogs->data+sizeof(ErrorLogsFile)+(errorlogs->file.latbins*errorlogs->file.lonbins+1)*sizeof(index_t));
errorlogs->errorlogs_nongeo=(ErrorLog*)(errorlogs->data+sizeof(ErrorLogsFile)+(errorlogs->file.latbins*errorlogs->file.lonbins+1)*sizeof(index_t)+errorlogs->file.number_geo*sizeof(ErrorLog));
errorlogs->strings =(char* )(errorlogs->data+sizeof(ErrorLogsFile)+(errorlogs->file.latbins*errorlogs->file.lonbins+1)*sizeof(index_t)+errorlogs->file.number*sizeof(ErrorLog));
#else
errorlogs->fd=SlimMapFile(filename);
/* Copy the ErrorLogsFile header structure from the loaded data */
SlimFetch(errorlogs->fd,&errorlogs->file,sizeof(ErrorLogsFile),0);
errorlogs->offsetsoffset =sizeof(ErrorLogsFile);
errorlogs->errorlogsoffset_geo =sizeof(ErrorLogsFile)+(errorlogs->file.latbins*errorlogs->file.lonbins+1)*sizeof(index_t);
errorlogs->errorlogsoffset_nongeo=sizeof(ErrorLogsFile)+(errorlogs->file.latbins*errorlogs->file.lonbins+1)*sizeof(index_t)+errorlogs->file.number_geo*sizeof(ErrorLog);
errorlogs->stringsoffset =sizeof(ErrorLogsFile)+(errorlogs->file.latbins*errorlogs->file.lonbins+1)*sizeof(index_t)+errorlogs->file.number*sizeof(ErrorLog);
#endif
return(errorlogs);
}
/*++++++++++++++++++++++++++++++++++++++
Destroy the node list.
ErrorLogs *errorlogs The node list to destroy.
++++++++++++++++++++++++++++++++++++++*/
void DestroyErrorLogs(ErrorLogs *errorlogs)
{
#if !SLIM
errorlogs->data=UnmapFile(errorlogs->data);
#else
errorlogs->fd=SlimUnmapFile(errorlogs->fd);
#endif
free(errorlogs);
}
/*++++++++++++++++++++++++++++++++++++++
Get the latitude and longitude associated with an error log.
ErrorLogs *errorlogs The set of error logs to use.
index_t index The errorlog index.
ErrorLog *errorlogp A pointer to the error log.
double *latitude Returns the latitude.
double *longitude Returns the logitude.
++++++++++++++++++++++++++++++++++++++*/
void GetErrorLogLatLong(ErrorLogs *errorlogs,index_t index,ErrorLog *errorlogp,double *latitude,double *longitude)
{
ll_bin_t latbin,lonbin;
ll_bin2_t bin=-1;
ll_bin2_t start,end,mid;
index_t offset;
/* Search for offset */
start=0;
end=errorlogs->file.lonbins*errorlogs->file.latbins;
/* Binary search - search key exact match is wanted else lower bound is acceptable.
*
* # <- start | Check mid and exit if it matches else move start or end.
* # |
* # | Since a lower bound match is wanted we can set end=mid-1 or
* # <- mid | start=mid if mid doesn't exactly match.
* # |
* # | Eventually either end=start or end=start+1 and one of
* # <- end | start or end is an exact match or the lower bound.
*/
while((end-start)>1)
{
mid=start+(end-start)/2; /* Choose mid point (avoid overflow) */
offset=LookupErrorLogOffset(errorlogs,mid);
if(offsetindex) /* Mid point is too high */
end=mid-1;
else /* Mid point is correct */
{bin=mid;break;}
}
if(bin==-1)
{
offset=LookupErrorLogOffset(errorlogs,end);
if(offset>index)
bin=start;
else
bin=end;
}
while(bin<=(errorlogs->file.lonbins*errorlogs->file.latbins) &&
LookupErrorLogOffset(errorlogs,bin)==LookupErrorLogOffset(errorlogs,bin+1))
bin++;
latbin=bin%errorlogs->file.latbins;
lonbin=bin/errorlogs->file.latbins;
/* Return the values */
if(errorlogp==NULL)
errorlogp=LookupErrorLog(errorlogs,index,2);
*latitude =latlong_to_radians(bin_to_latlong(errorlogs->file.latzero+latbin)+off_to_latlong(errorlogp->latoffset));
*longitude=latlong_to_radians(bin_to_latlong(errorlogs->file.lonzero+lonbin)+off_to_latlong(errorlogp->lonoffset));
}