30#include <wx/hashmap.h>
40#include "model/georef.h"
49time_t s_next_epoch = TIDE_BAD_TIME;
50time_t s_this_epoch = TIDE_BAD_TIME;
53double time2dt_tide(time_t t,
int deriv,
IDX_entry *pIDX);
54int yearoftimet(time_t t);
55void happy_new_year(
IDX_entry *pIDX,
int new_year);
58double time2tide(time_t t,
IDX_entry *pIDX) {
return time2dt_tide(t, 0, pIDX); }
64double BOGUS_amplitude(
double mpy,
IDX_entry *pIDX) {
67 if (!pmsd->have_BOGUS)
78double time2atide(time_t t,
IDX_entry *pIDX) {
79 return BOGUS_amplitude(time2tide(t, pIDX), pIDX) + pIDX->
pref_sta_data->DATUM;
90int next_big_event(time_t *tm,
IDX_entry *pIDX) {
92 int flags = 0, slope = 0;
93 p = time2atide(*tm, pIDX);
95 q = time2atide(*tm, pIDX);
99 if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
101 flags |= (1 << slope);
115 if ((p > marklev && q <= marklev) || (p < marklev && q >= marklev)) {
131 q = time2atide(*tm, pIDX);
132 if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
134 flags |= (1 << slope);
146 if (flags < 4) *tm -= 60;
150 q = time2atide(*tm, pIDX);
159double time2mean(time_t t,
IDX_entry *pIDX) {
162 int new_year = yearoftimet(t);
163 if (pIDX->
epoch_year != new_year) happy_new_year(pIDX, new_year);
165 for (a = 0; a < pIDX->
num_csts; a++) {
182double time2asecondary(time_t t,
IDX_entry *pIDX) {
186 if (!(pIDX->
have_offsets))
return time2atide(tadj, pIDX);
193#define intervalwidth 15
194#define stretchfactor 3
196 static time_t lowtime = 0, hightime = 0;
197 static double lowlvl, highlvl;
199 double S, Z, HI, HS, magicnum;
200 time_t interval = 3600 * intervalwidth;
201 long difflow, diffhigh;
202 int badlowflag = 0, badhighflag = 0;
217 Z = time2mean(T, pIDX);
218 S = time2tide(T, pIDX) - Z;
240 difflow = T - lowtime;
242 difflow = lowtime - T;
244 diffhigh = T - hightime;
246 diffhigh = hightime - T;
249 if (difflow > interval * stretchfactor) badlowflag = 1;
250 if (badlowflag || (difflow > interval && S > 0)) {
254 next_big_event(&tt, pIDX);
255 lowlvl = time2tide(tt, pIDX);
257 while (tt < T + interval) {
258 next_big_event(&tt, pIDX);
259 tl = time2tide(tt, pIDX);
260 if (tl < lowlvl && tt < T + interval) {
267 if (diffhigh > interval * stretchfactor) badhighflag = 1;
268 if (badhighflag || (diffhigh > interval && S < 0)) {
272 next_big_event(&tt, pIDX);
273 highlvl = time2tide(tt, pIDX);
275 while (tt < T + interval) {
276 next_big_event(&tt, pIDX);
277 tl = time2tide(tt, pIDX);
278 if (tl > highlvl && tt < T + interval) {
298 magicnum = 0.5 * S / fabs(highlvl - Z);
300 magicnum = 0.5 * S / fabs(lowlvl - Z);
304 HI = time2tide(T, pIDX);
307 double ht_off, lt_off;
320 double RH = 1.0, RL = 1.0, HH = 0.0, HL = 0.0;
329 HS = HI * ((RH + RL) / 2 + (RH - RL) * magicnum) + (HH + HL) / 2 +
330 (HH - HL) * magicnum;
384double _time2dt_tide(time_t t,
int deriv,
IDX_entry *pIDX) {
385 double dt_tide = 0.0;
389 tempd = M_PI / 2.0 * deriv;
390 for (a = 0; a < pIDX->
num_csts; a++) {
397 for (b = deriv; b > 0; b--) term *= pIDX->
m_cst_speeds[a];
420static double blend_weight(
double x,
int deriv) {
423 if (x2 >= 1.0)
return deriv == 0 && x > 0.0 ? 1.0 : 0.0;
427 return ((3.0 * x2 - 10.0) * x2 + 15.0) * x / 16.0 + 0.5;
429 return ((x2 - 2.0) * x2 + 1.0) * (15.0 / 16.0);
431 return (x2 - 1.0) * x * (15.0 / 4.0);
440double blend_tide(time_t t,
unsigned int deriv,
int first_year,
double blend,
442 double fl[TIDE_MAX_DERIV + 1];
443 double fr[TIDE_MAX_DERIV + 1];
445 double w[TIDE_MAX_DERIV + 1];
454 int year = yearoftimet(t);
455 if (year == first_year + 1)
457 else if (year != first_year)
458 happy_new_year(pIDX, first_year);
459 for (n = 0; n <= deriv; n++) fp[n] = _time2dt_tide(t, n, pIDX);
466 happy_new_year(pIDX, first_year + 1);
469 happy_new_year(pIDX, first_year);
472 for (n = 0; n <= deriv; n++) {
473 fp[n] = _time2dt_tide(t, n, pIDX);
474 w[n] = blend_weight(blend, n);
482 for (n = 0; n <= deriv; n++) {
483 f += fact * w[n] * (fr[deriv - n] - fl[deriv - n]);
484 fact *= (double)(deriv - n) / (n + 1) * (1.0 / TIDE_BLEND_TIME);
486 printf(
" %ld %g %g %g %g\n", (
long)t, blend, fr[0], fl[0], f);
490double time2dt_tide(time_t t,
int deriv,
IDX_entry *pIDX) {
492 int yott = yearoftimet(t);
496 if (new_year != s_this_year) {
498 set_epoch(pIDX, new_year + 1);
499 s_next_epoch = pIDX->
epoch;
501 s_next_epoch = TIDE_BAD_TIME;
503 happy_new_year(pIDX, s_this_year = new_year);
504 s_this_epoch = pIDX->
epoch;
511 if (t - s_this_epoch <= TIDE_BLEND_TIME && s_this_year > pIDX->
first_year)
512 return blend_tide(t, deriv, s_this_year - 1,
513 (
double)(t - s_this_epoch) / TIDE_BLEND_TIME, pIDX);
514 else if (s_next_epoch - t <= TIDE_BLEND_TIME &&
516 return blend_tide(t, deriv, s_this_year,
517 -(
double)(s_next_epoch - t) / TIDE_BLEND_TIME, pIDX);
522 if (pIDX->
epoch_year != new_year) happy_new_year(pIDX, new_year);
524 return _time2dt_tide(t, deriv, pIDX);
529void figure_max_amplitude(
IDX_entry *pIDX) {
534 double year_amp = 0.0;
536 for (a = 0; a < pIDX->
num_csts; a++)
544void figure_multipliers(
IDX_entry *pIDX,
int year) {
547 figure_max_amplitude(pIDX);
548 for (a = 0; a < pIDX->
num_csts; a++) {
556#define compare_int(a, b) (((int)(a)) - ((int)(b)))
557int compare_tm(
struct tm *a,
struct tm *b) {
565 temp = compare_int(a->tm_year, b->tm_year);
566 if (temp)
return temp;
567 temp = compare_int(a->tm_mon, b->tm_mon);
568 if (temp)
return temp;
569 temp = compare_int(a->tm_mday, b->tm_mday);
570 if (temp)
return temp;
571 temp = compare_int(a->tm_hour, b->tm_hour);
572 if (temp)
return temp;
573 temp = compare_int(a->tm_min, b->tm_min);
574 if (temp)
return temp;
575 return compare_int(a->tm_sec, b->tm_sec);
581time_t tm2gmt(
struct tm *ht) {
582 time_t guess, newguess, thebit;
583 int loopcounter, compare;
587 loopcounter = (
sizeof(time_t) * 8) - 1;
588 thebit = ((time_t)1) << (loopcounter - 1);
593 if ((
signed long)thebit < (time_t)(0)) {
596 thebit = ((time_t)1) << (loopcounter - 1);
599 for (; loopcounter; loopcounter--) {
600 newguess = guess | thebit;
601 gt = gmtime(&newguess);
603 compare = compare_tm(gt, ht);
604 if (compare <= 0) guess = newguess;
612int yearoftimet(time_t t) {
return ((gmtime(&t))->tm_year) + 1900; }
615void set_epoch(
IDX_entry *pIDX,
int year) {
618 ht.tm_year = year - 1900;
619 ht.tm_sec = ht.tm_min = ht.tm_hour = ht.tm_mon = 0;
621 pIDX->
epoch = tm2gmt(&ht);
625void happy_new_year(
IDX_entry *pIDX,
int new_year) {
627 figure_multipliers(pIDX, new_year);
628 set_epoch(pIDX, new_year);
634TCMgr::~TCMgr() { PurgeData(); }
636void TCMgr::PurgeData() {
637 m_Combined_IDX_array.clear();
640 m_source_array.Clear();
643TC_Error_Code TCMgr::LoadDataSources(std::vector<std::string> &sources) {
647 m_sourcefile_array.clear();
648 m_sourcefile_array = sources;
652 for (
auto src : sources) {
654 TC_Error_Code r = s->LoadData(src);
655 if (r != TC_NO_ERROR) {
657 msg.Printf(_T(
" Error loading Tide/Currect data source %s "),
659 if (r == TC_FILE_NOT_FOUND)
660 msg += _T(
"Error Code: TC_FILE_NOT_FOUND");
663 msg1.Printf(_T(
"Error code: %d"), r);
669 m_source_array.Add(s);
671 for (
int k = 0; k < s->GetMaxIndex(); k++) {
675 m_Combined_IDX_array.push_back(pIDX);
682 if (m_Combined_IDX_array.empty())
684 NULL, _(
"It seems you have no tide/current harmonic data installed."),
685 _(
"OpenCPN Info"), wxOK | wxCENTER);
687 ScrubCurrentDepths();
691void TCMgr::ScrubCurrentDepths() {
696 WX_DECLARE_STRING_HASH_MAP(
int, currentDepth_index_hash);
698 currentDepth_index_hash hash1;
700 for (
int i = 1; i < Get_max_IDX() + 1; i++) {
715 currentDepth_index_hash::iterator it = hash1.find(key1);
716 if (it == hash1.end()) {
725 if (depth_a < depth_b) {
737const IDX_entry *TCMgr::GetIDX_entry(
int index)
const {
738 if ((
unsigned int)index < m_Combined_IDX_array.size())
739 return m_Combined_IDX_array[index];
744bool TCMgr::GetTideOrCurrent(time_t t,
int idx,
float &tcvalue,
float &dir) {
750 IDX_entry *pIDX = m_Combined_IDX_array[idx];
765 if (pIDX->
pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
return false;
769 int yott = yearoftimet(t);
771 happy_new_year(pIDX, yott);
775 double level = time2asecondary(t + (00 * 60), pIDX);
786extern wxDateTime gTimeSource;
788bool TCMgr::GetTideOrCurrent15(time_t t_d,
int idx,
float &tcvalue,
float &dir,
791 IDX_entry *pIDX = m_Combined_IDX_array[idx];
800 wxDateTime this_now = gTimeSource;
801 if (this_now.IsValid() ==
false) this_now = wxDateTime::Now();
802 wxDateTime this_gmt = this_now.ToGMT();
803 wxTimeSpan diff = this_gmt.Subtract(this_now);
804 int diff_mins = diff.GetMinutes();
807 if (this_now.IsDST()) station_offset += 60;
808 int corr_mins = station_offset - diff_mins;
810 wxDateTime today_00 = this_now;
811 today_00.ResetTime();
812 int t_today_00 = today_00.GetTicks();
813 int t_today_00_at_station = t_today_00 - (corr_mins * 60);
816 this_gmt.GetTicks() - (station_offset * 60) + (corr_mins * 60);
818 int t_mins = (t_at_station - t_today_00_at_station) / 60;
819 int t_15s = t_mins / 15;
823 int tref1 = t_today_00_at_station + t_15s * 15 * 60;
830 int tref = t_today_00_at_station + t_15s * 15 * 60;
831 ret = GetTideOrCurrent(tref, idx, tcvalue, dir);
836 pIDX->
Ret15 = !(ret == 0);
844 int tref = t_today_00_at_station + t_15s * 15 * 60;
845 ret = GetTideOrCurrent(tref, idx, tcvalue, dir);
850 pIDX->
Ret15 = !(ret == 0);
857bool TCMgr::GetTideFlowSens(time_t t,
int sch_step,
int idx,
float &tcvalue_now,
858 float &tcvalue_prev,
bool &w_t) {
865 IDX_entry *pIDX = m_Combined_IDX_array[idx];
867 if (!pIDX)
return false;
872 if (pIDX->
pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
return false;
876 int yott = yearoftimet(t);
877 happy_new_year(pIDX, yott);
881 tcvalue_now = time2asecondary(t, pIDX);
882 tcvalue_prev = time2asecondary(t + sch_step, pIDX);
885 tcvalue_now > tcvalue_prev;
890void TCMgr::GetHightOrLowTide(time_t t,
int sch_step_1,
int sch_step_2,
891 float tide_val,
bool w_t,
int idx,
float &tcvalue,
898 IDX_entry *pIDX = m_Combined_IDX_array[idx];
905 if (pIDX->
pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
return;
921 int yott = yearoftimet(t);
922 happy_new_year(pIDX, yott);
925 double newval = tide_val;
926 double oldval = (w_t) ? newval - 1 : newval + 1;
930 while ((newval > oldval) == w_t)
934 ttt = t + (sch_step_1 * j);
935 newval = time2asecondary(ttt, pIDX);
937 oldval = (w_t) ? newval - 1 : newval + 1;
938 while ((newval > oldval) == w_t)
942 ttt = t + (sch_step_1 * j) - (sch_step_2 * k);
943 newval = time2asecondary(ttt, pIDX);
946 tctime = ttt + sch_step_2;
965int TCMgr::GetNextBigEvent(time_t *tm,
int idx) {
970 int flags = 0, slope = 0;
971 ret = GetTideOrCurrent(*tm, idx, tcvalue[0], dir);
974 ret = GetTideOrCurrent(*tm, idx, tcvalue[0], dir);
977 if (p < q) slope = 1;
979 if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
981 flags |= (1 << slope);
985 if (flags < 4) *tm -= 60;
989 ret = GetTideOrCurrent(*tm, idx, tcvalue[0], dir);
996std::wstring TCMgr::GetTidalEventStr(
int station_id, wxDateTime ref_dt,
997 double lat,
double lon,
int dt_type) {
999 time_t dtmtt = ref_dt.FromUTC().GetTicks();
1000 int event = GetNextBigEvent(&dtmtt, station_id);
1001 wxDateTime event_dt = wxDateTime(dtmtt).MakeUTC();
1003 std::wstring event_str;
1005 event_str = _(
"LW").ToStdWstring();
1006 }
else if (event == 2) {
1007 event_str = _(
"HW").ToStdWstring();
1009 event_str = _(
"Unavailable").ToStdWstring();
1013 event_str.append(L
": ");
1015 toUsrDateTime(event_dt, dt_type, lon).FormatISOCombined(
' '));
1021std::map<double, const IDX_entry *> TCMgr::GetStationsForLL(
double xlat,
1022 double xlon)
const {
1023 std::map<double, const IDX_entry *> x;
1026 for (
int j = 1; j < Get_max_IDX() + 1; j++) {
1027 lpIDX = GetIDX_entry(j);
1031 if (type ==
't' || type ==
'T') {
1033 DistanceBearingMercator(xlat, xlon, lpIDX->
IDX_lat, lpIDX->
IDX_lon, &brg,
1035 x.emplace(std::make_pair(dist, lpIDX));
1042int TCMgr::GetStationIDXbyName(
const wxString &prefix,
double xlat,
1043 double xlon)
const {
1047 double distx = 100000.;
1049 int jmax = Get_max_IDX();
1051 for (
int j = 1; j < Get_max_IDX() + 1; j++) {
1052 lpIDX = GetIDX_entry(j);
1056 if (((type ==
't') || (type ==
'T'))
1057 && (locnx.StartsWith(prefix))) {
1059 DistanceBearingMercator(xlat, xlon, lpIDX->
IDX_lat, lpIDX->
IDX_lon, &brg,
1071int TCMgr::GetStationIDXbyNameType(
const wxString &prefix,
double xlat,
1072 double xlon,
char type)
const {
1076 double distx = 100000.;
1080 int jmax = Get_max_IDX();
1082 for (
int j = 1; j < Get_max_IDX() + 1; j++) {
1083 lpIDX = GetIDX_entry(j);
1087 if ((type == typep) && (locnx.StartsWith(prefix))) {
1089 DistanceBearingMercator(xlat, xlon, lpIDX->
IDX_lat, lpIDX->
IDX_lon, &brg,
1115#define DEFAULT_HEADER_SIZE 4096
1116#define DEFAULT_NUMBER_OF_RECORDS 0
1117#define DEFAULT_LEVEL_UNIT_TYPES 5
1118#define DEFAULT_DIR_UNIT_TYPES 3
1119#define DEFAULT_RESTRICTION_TYPES 2
1120#define DEFAULT_RESTRICTION_BITS 4
1121#define DEFAULT_TZFILES 406
1122#define DEFAULT_TZFILE_BITS 10
1123#define DEFAULT_COUNTRIES 240
1124#define DEFAULT_COUNTRY_BITS 9
1125#define DEFAULT_DATUM_TYPES 61
1126#define DEFAULT_DATUM_BITS 7
1127#define DEFAULT_LEGALESES 1
1128#define DEFAULT_LEGALESE_BITS 4
1129#define DEFAULT_SPEED_SCALE 10000000
1130#define DEFAULT_EQUILIBRIUM_SCALE 100
1131#define DEFAULT_NODE_SCALE 10000
1132#define DEFAULT_AMPLITUDE_BITS 19
1133#define DEFAULT_AMPLITUDE_SCALE 10000
1134#define DEFAULT_EPOCH_BITS 16
1135#define DEFAULT_EPOCH_SCALE 100
1136#define DEFAULT_RECORD_TYPE_BITS 4
1137#define DEFAULT_LATITUDE_BITS 25
1138#define DEFAULT_LATITUDE_SCALE 100000
1139#define DEFAULT_LONGITUDE_BITS 26
1140#define DEFAULT_LONGITUDE_SCALE 100000
1141#define DEFAULT_RECORD_SIZE_BITS 16
1142#define DEFAULT_STATION_BITS 18
1143#define DEFAULT_DATUM_OFFSET_BITS 28
1144#define DEFAULT_DATUM_OFFSET_SCALE 10000
1145#define DEFAULT_DATE_BITS 27
1146#define DEFAULT_MONTHS_ON_STATION_BITS 10
1147#define DEFAULT_CONFIDENCE_VALUE_BITS 4
1148#define DEFAULT_NUMBER_OF_CONSTITUENTS_BITS 8
1149#define DEFAULT_TIME_BITS 13
1150#define DEFAULT_LEVEL_ADD_BITS 17
1151#define DEFAULT_LEVEL_ADD_SCALE 1000
1152#define DEFAULT_LEVEL_MULTIPLY_BITS 16
1153#define DEFAULT_LEVEL_MULTIPLY_SCALE 1000
1154#define DEFAULT_DIRECTION_BITS 9
1155#define DEFAULT_CONSTITUENT_SIZE 10
1156#define DEFAULT_LEVEL_UNIT_SIZE 15
1157#define DEFAULT_DIR_UNIT_SIZE 15
1158#define DEFAULT_RESTRICTION_SIZE 30
1159#define DEFAULT_DATUM_SIZE 70
1160#define DEFAULT_LEGALESE_SIZE 70
1161#define DEFAULT_TZFILE_SIZE 30
1162#define DEFAULT_COUNTRY_SIZE 50
1166#define INFERRED_SEMI_DIURNAL_COUNT 10
1167#define INFERRED_DIURNAL_COUNT 10
1170#pragma warning(disable : 4305)
1173const NV_CHAR *inferred_semi_diurnal[INFERRED_SEMI_DIURNAL_COUNT] = {
1174 "N2",
"NU2",
"MU2",
"2N2",
"LDA2",
"T2",
"R2",
"L2",
"K2",
"KJ2"};
1175const NV_CHAR *inferred_diurnal[INFERRED_DIURNAL_COUNT] = {
1176 "OO1",
"M1",
"J1",
"RHO1",
"Q1",
"2Q1",
"P1",
"PI1",
"PHI1",
"PSI1"};
1177NV_FLOAT32 semi_diurnal_coeff[INFERRED_SEMI_DIURNAL_COUNT] = {
1178 .1759, .0341, .0219, .0235, .0066, .0248, .0035, .0251, .1151, .0064};
1179NV_FLOAT32 diurnal_coeff[INFERRED_DIURNAL_COUNT] = {
1180 .0163, .0209, .0297, .0142, .0730, .0097, .1755, .0103, .0076, .0042};
1184NV_FLOAT32 coeff[2] = {.9085, .3771};
1194NV_CHAR level_unit[DEFAULT_LEVEL_UNIT_TYPES][DEFAULT_LEVEL_UNIT_SIZE] = {
1195 "Unknown",
"feet",
"meters",
"knots",
"knots^2"};
1199NV_CHAR dir_unit[DEFAULT_DIR_UNIT_TYPES][DEFAULT_DIR_UNIT_SIZE] = {
1200 "Unknown",
"degrees true",
"degrees"};
1204NV_CHAR restriction[DEFAULT_RESTRICTION_TYPES][DEFAULT_RESTRICTION_SIZE] = {
1205 "Public Domain",
"DoD/DoD Contractors Only"};
1209NV_CHAR legalese[DEFAULT_LEGALESES][DEFAULT_LEGALESE_SIZE] = {
"NULL"};
1213NV_CHAR datum[DEFAULT_DATUM_TYPES][DEFAULT_DATUM_SIZE] = {
1217 "Mean Lower Low Water",
1219 "Mean Higher High Water",
1220 "Mean Lower High Water",
1221 "Mean Higher Low Water",
1222 "Mean Low Water Springs",
1223 "Mean Lower Low Water Springs",
1224 "Mean Low Water Neaps",
1225 "Mean High Water Neaps",
1226 "Mean High Water Springs",
1227 "Mean Higher High Water Springs",
1228 "Indian Spring Low Water",
1229 "Equatorial Spring Low Water",
1230 "Lowest Normal Low Water",
1232 "Lowest Possible Low Water",
1233 "Lowest Astronomical Tide",
1234 "International Great Lakes Datum(1955)",
1235 "Lower Low Water, Large Tide",
1236 "Lowest Normal Tide",
1237 "Higher High Water, Large Tide",
1239 "Higher High Water, Mean Tide",
1240 "Lower Low Water, Mean Tide",
1242 "World Geodetic System (1984)",
1243 "National Geodetic Vertical Datum",
1244 "Gulf Coast Low Water Datum",
1245 "Approximate Level of Mean Sea Level",
1246 "Approximate Level of Mean Low Water",
1247 "Approximate Level of Mean Lower Low Water",
1248 "Approximate Level of Mean High Water",
1249 "Approximate Level of Mean Higher High Water",
1250 "Approximate Level of Mean Lower High Water",
1251 "Approximate Level of Mean Higher Low Water",
1252 "Approximate Level of Mean Low Water Springs",
1253 "Approximate Level of Mean Lower Low Water Springs",
1254 "Approximate Level of Mean Low Water Neaps",
1255 "Approximate Level of Mean High Water Neaps",
1256 "Approximate Level of Mean High Water Springs",
1257 "Approximate Level of Mean Higher High Water Springs",
1258 "Approximate Level of Indian Spring Low Water",
1259 "Approximate Level of Equatorial Spring Low Water",
1260 "Approximate Level of Lowest Normal Low Water",
1261 "Approximate Level of Lowest Low Water",
1262 "Approximate Level of Lowest Possible Low Water",
1263 "Approximate Level of Lowest Astronomical Tide",
1264 "Approximate Level of International Great Lakes Datum (1955)",
1265 "Approximate Level of Lower Low Water, Large Tide",
1266 "Approximate Level of Lowest Normal Tide",
1267 "Approximate Level of Higher High Water, Large Tide",
1268 "Approximate Level of Mean Water Level",
1269 "Approximate Level of Higher High Water, Mean Tide",
1270 "Approximate Level of Lower Low Water, Mean Tide",
1271 "Approximate Level of Mean Tide Level",
1272 "Approximate Level of World Geodetic System (1984)",
1273 "Approximate Level of National Geodetic Vertical Datum",
1274 "Approximate Level of Gulf Coast Low Water Datum"};
1278NV_CHAR country[DEFAULT_COUNTRIES][DEFAULT_COUNTRY_SIZE] = {
1287 "Antigua & Barbuda",
1305 "Bosnia & Herzegovina",
1310 "British Indian Ocean Territory",
1320 "Central African Rep.",
1325 "Cocos (Keeling) Islands",
1328 "Congo (Dem. Rep.)",
1340 "Dominican Republic",
1345 "Equatorial Guinea",
1356 "French Southern & Antarctic Lands",
1373 "Heard Island & McDonald Islands",
1430 "Netherlands Antilles",
1438 "Northern Mariana Islands",
1461 "Sao Tome & Principe",
1472 "South Georgia & the South Sandwich Islands",
1478 "St Pierre & Miquelon",
1482 "Svalbard & Jan Mayen",
1494 "Trinidad & Tobago",
1498 "Turks & Caicos Is",
1502 "United Arab Emirates",
1505 "US minor outlying islands",
1511 "Virgin Islands (UK)",
1512 "Virgin Islands (US)",
1522NV_CHAR tzfile[DEFAULT_TZFILES][DEFAULT_TZFILE_SIZE] = {
1526 ":Africa/Addis_Ababa",
1534 ":Africa/Brazzaville",
1535 ":Africa/Bujumbura",
1537 ":Africa/Casablanca",
1541 ":Africa/Dar_es_Salaam",
1548 ":Africa/Johannesburg",
1554 ":Africa/Libreville",
1557 ":Africa/Lubumbashi",
1563 ":Africa/Mogadishu",
1568 ":Africa/Nouakchott",
1569 ":Africa/Ouagadougou",
1570 ":Africa/Porto-Novo",
1577 ":America/Anchorage",
1578 ":America/Anguilla",
1580 ":America/Araguaina",
1582 ":America/Asuncion",
1584 ":America/Barbados",
1587 ":America/Boa_Vista",
1590 ":America/Buenos_Aires",
1591 ":America/Cambridge_Bay",
1594 ":America/Catamarca",
1598 ":America/Chihuahua",
1600 ":America/Costa_Rica",
1603 ":America/Danmarkshavn",
1605 ":America/Dawson_Creek",
1608 ":America/Dominica",
1609 ":America/Edmonton",
1610 ":America/Eirunepe",
1611 ":America/El_Salvador",
1612 ":America/Ensenada",
1613 ":America/Fortaleza",
1614 ":America/Glace_Bay",
1616 ":America/Goose_Bay",
1617 ":America/Grand_Turk",
1619 ":America/Guadeloupe",
1620 ":America/Guatemala",
1621 ":America/Guayaquil",
1625 ":America/Hermosillo",
1626 ":America/Indiana/Knox",
1627 ":America/Indiana/Marengo",
1628 ":America/Indianapolis",
1629 ":America/Indiana/Vevay",
1635 ":America/Kentucky/Monticello",
1638 ":America/Los_Angeles",
1639 ":America/Louisville",
1643 ":America/Martinique",
1644 ":America/Mazatlan",
1646 ":America/Menominee",
1648 ":America/Mexico_City",
1649 ":America/Miquelon",
1650 ":America/Monterrey",
1651 ":America/Montevideo",
1652 ":America/Montreal",
1653 ":America/Montserrat",
1655 ":America/New_York",
1659 ":America/North_Dakota/Center",
1661 ":America/Pangnirtung",
1662 ":America/Paramaribo",
1664 ":America/Port-au-Prince",
1665 ":America/Port_of_Spain",
1666 ":America/Porto_Velho",
1667 ":America/Puerto_Rico",
1668 ":America/Rainy_River",
1669 ":America/Rankin_Inlet",
1672 ":America/Rio_Branco",
1673 ":America/Santiago",
1674 ":America/Santo_Domingo",
1675 ":America/Sao_Paulo",
1676 ":America/Scoresbysund",
1677 ":America/Shiprock",
1678 ":America/St_Johns",
1679 ":America/St_Kitts",
1680 ":America/St_Lucia",
1681 ":America/St_Thomas",
1682 ":America/St_Vincent",
1683 ":America/Swift_Current",
1684 ":America/Tegucigalpa",
1686 ":America/Thunder_Bay",
1689 ":America/Vancouver",
1690 ":America/Whitehorse",
1691 ":America/Winnipeg",
1693 ":America/Yellowknife",
1694 ":Antarctica/Casey",
1695 ":Antarctica/Davis",
1696 ":Antarctica/DumontDUrville",
1697 ":Antarctica/Mawson",
1698 ":Antarctica/McMurdo",
1699 ":Antarctica/Palmer",
1700 ":Antarctica/South_Pole",
1701 ":Antarctica/Syowa",
1702 ":Antarctica/Vostok",
1703 ":Arctic/Longyearbyen",
1740 ":Asia/Krasnoyarsk",
1741 ":Asia/Kuala_Lumpur",
1750 ":Asia/Novosibirsk",
1772 ":Asia/Ulaanbaatar",
1775 ":Asia/Vladivostok",
1777 ":Asia/Yekaterinburg",
1780 ":Atlantic/Bermuda",
1782 ":Atlantic/Cape_Verde",
1784 ":Atlantic/Jan_Mayen",
1785 ":Atlantic/Madeira",
1786 ":Atlantic/Reykjavik",
1787 ":Atlantic/South_Georgia",
1788 ":Atlantic/Stanley",
1789 ":Atlantic/St_Helena",
1790 ":Australia/Adelaide",
1791 ":Australia/Brisbane",
1792 ":Australia/Broken_Hill",
1793 ":Australia/Darwin",
1794 ":Australia/Hobart",
1795 ":Australia/Lindeman",
1796 ":Australia/Lord_Howe",
1797 ":Australia/Melbourne",
1799 ":Australia/Sydney",
1829 ":Europe/Amsterdam",
1835 ":Europe/Bratislava",
1837 ":Europe/Bucharest",
1840 ":Europe/Copenhagen",
1842 ":Europe/Gibraltar",
1845 ":Europe/Kaliningrad",
1848 ":Europe/Ljubljana",
1850 ":Europe/Luxembourg",
1862 ":Europe/San_Marino",
1864 ":Europe/Simferopol",
1867 ":Europe/Stockholm",
1877 ":Europe/Zaporozhye",
1879 ":Indian/Antananarivo",
1881 ":Indian/Christmas",
1884 ":Indian/Kerguelen",
1887 ":Indian/Mauritius",
1891 ":Pacific/Auckland",
1895 ":Pacific/Enderbury",
1898 ":Pacific/Funafuti",
1899 ":Pacific/Galapagos",
1901 ":Pacific/Guadalcanal",
1903 ":Pacific/Honolulu",
1904 ":Pacific/Johnston",
1905 ":Pacific/Kiritimati",
1907 ":Pacific/Kwajalein",
1909 ":Pacific/Marquesas",
1915 ":Pacific/Pago_Pago",
1917 ":Pacific/Pitcairn",
1919 ":Pacific/Port_Moresby",
1920 ":Pacific/Rarotonga",
1924 ":Pacific/Tongatapu",
1939#define require(expr) \
1942 require_expr = (int)(expr); \
1943 assert(require_expr); \
2263NV_U_INT32 calculate_bits(NV_U_INT32 value);
2264void bit_pack(NV_U_BYTE *, NV_U_INT32, NV_U_INT32, NV_INT32);
2265NV_U_INT32 bit_unpack(NV_U_BYTE *, NV_U_INT32, NV_U_INT32);
2266NV_INT32 signed_bit_unpack(NV_U_BYTE buffer[], NV_U_INT32 start,
2267 NV_U_INT32 numbits);
2273 NV_U_INT32 record_size;
2275 NV_INT32 reference_station;
2278 NV_U_BYTE record_type;
2282static FILE *fp = NULL;
2284static NV_BOOL modified = NVFalse;
2285static NV_INT32 current_record, current_index;
2286static NV_CHAR filename[MONOLOGUE_LENGTH];
2296static void chk_fread(
void *ptr,
size_t size,
size_t nmemb, FILE *stream) {
2298 ret = fread(ptr, size, nmemb, stream);
2306static void chk_fwrite(
const void *ptr,
size_t size,
size_t nmemb,
2309 ret = fwrite(ptr, size, nmemb, stream);
2341 LOG_ERROR(
"\n\nRecord number = %d\n", rec->header.record_number);
2342 LOG_ERROR(
"Record size = %u\n", rec->header.record_size);
2343 LOG_ERROR(
"Record type = %u\n", rec->header.record_type);
2344 LOG_ERROR(
"Latitude = %f\n", rec->header.latitude);
2345 LOG_ERROR(
"Longitude = %f\n", rec->header.longitude);
2346 LOG_ERROR(
"Reference station = %d\n", rec->header.reference_station);
2347 LOG_ERROR(
"Tzfile = %s\n", get_tzfile(rec->header.tzfile));
2348 LOG_ERROR(
"Name = %s\n", rec->header.name);
2350 LOG_ERROR(
"Country = %s\n", get_country(rec->country));
2351 LOG_ERROR(
"Source = %s\n", rec->source);
2352 LOG_ERROR(
"Restriction = %s\n", get_restriction(rec->restriction));
2353 LOG_ERROR(
"Comments = %s\n", rec->comments);
2354 LOG_ERROR(
"Notes = %s\n", rec->notes);
2355 LOG_ERROR(
"Legalese = %s\n", get_legalese(rec->legalese));
2356 LOG_ERROR(
"Station ID context = %s\n", rec->station_id_context);
2357 LOG_ERROR(
"Station ID = %s\n", rec->station_id);
2358 LOG_ERROR(
"Date imported = %d\n", rec->date_imported);
2359 LOG_ERROR(
"Xfields = %s\n", rec->xfields);
2361 LOG_ERROR(
"Direction units = %s\n", get_dir_units(rec->direction_units));
2362 LOG_ERROR(
"Min direction = %d\n", rec->min_direction);
2363 LOG_ERROR(
"Max direction = %d\n", rec->max_direction);
2364 LOG_ERROR(
"Level units = %s\n", get_level_units(rec->level_units));
2366 if (rec->header.record_type == REFERENCE_STATION) {
2367 LOG_ERROR(
"Datum offset = %f\n", rec->datum_offset);
2368 LOG_ERROR(
"Datum = %s\n", get_datum(rec->datum));
2369 LOG_ERROR(
"Zone offset = %d\n", rec->zone_offset);
2370 LOG_ERROR(
"Expiration date = %d\n", rec->expiration_date);
2371 LOG_ERROR(
"Months on station = %d\n", rec->months_on_station);
2372 LOG_ERROR(
"Last date on station = %d\n", rec->last_date_on_station);
2373 LOG_ERROR(
"Confidence = %d\n", rec->confidence);
2374 for (i = 0; i < hd.pub.constituents; ++i) {
2375 if (rec->amplitude[i] != 0.0 || rec->epoch[i] != 0.0) {
2376 LOG_ERROR(
"Amplitude[%d] = %f\n", i, rec->amplitude[i]);
2377 LOG_ERROR(
"Epoch[%d] = %f\n", i, rec->epoch[i]);
2382 else if (rec->header.record_type == SUBORDINATE_STATION) {
2383 LOG_ERROR(
"Min time add = %d\n", rec->min_time_add);
2384 LOG_ERROR(
"Min level add = %f\n", rec->min_level_add);
2385 LOG_ERROR(
"Min level multiply = %f\n", rec->min_level_multiply);
2386 LOG_ERROR(
"Max time add = %d\n", rec->max_time_add);
2387 LOG_ERROR(
"Max level add = %f\n", rec->max_level_add);
2388 LOG_ERROR(
"Max level multiply = %f\n", rec->max_level_multiply);
2389 LOG_ERROR(
"Flood begins = %d\n", rec->flood_begins);
2390 LOG_ERROR(
"Ebb begins = %d\n", rec->ebb_begins);
2403static void write_protect() {
2404 if (hd.pub.major_rev < LIBTCD_MAJOR_REV) {
2406 "libtcd error: can't modify TCD files created by earlier version. "
2407 "Use\nrewrite_tide_db to upgrade the TCD file.\n");
2431const NV_CHAR *get_country(NV_INT32 num) {
2434 "libtcd error: attempt to access database when database not open\n");
2437 if (num >= 0 && num < (NV_INT32)hd.pub.countries)
return (hd.country[num]);
2458const NV_CHAR *get_tzfile(NV_INT32 num) {
2461 "libtcd error: attempt to access database when database not open\n");
2464 if (num >= 0 && num < (NV_INT32)hd.pub.tzfiles)
return (hd.tzfile[num]);
2485const NV_CHAR *get_station(NV_INT32 num) {
2488 "libtcd error: attempt to access database when database not open\n");
2491 if (num >= 0 && num < (NV_INT32)hd.pub.number_of_records)
2492 return (tindex[num].name);
2514const NV_CHAR *get_constituent(NV_INT32 num) {
2517 "libtcd error: attempt to access database when database not open\n");
2520 if (num >= 0 && num < (NV_INT32)hd.pub.constituents)
2521 return (hd.constituent[num]);
2543const NV_CHAR *get_level_units(NV_INT32 num) {
2546 "libtcd error: attempt to access database when database not open\n");
2549 if (num >= 0 && num < (NV_INT32)hd.pub.level_unit_types)
2550 return (hd.level_unit[num]);
2572const NV_CHAR *get_dir_units(NV_INT32 num) {
2575 "libtcd error: attempt to access database when database not open\n");
2578 if (num >= 0 && num < (NV_INT32)hd.pub.dir_unit_types)
2579 return (hd.dir_unit[num]);
2601const NV_CHAR *get_restriction(NV_INT32 num) {
2604 "libtcd error: attempt to access database when database not open\n");
2607 if (num >= 0 && num < (NV_INT32)hd.pub.restriction_types)
2608 return (hd.restriction[num]);
2631NV_CHAR *get_pedigree(NV_INT32 num) {
return "Unknown"; }
2651const NV_CHAR *get_datum(NV_INT32 num) {
2654 "libtcd error: attempt to access database when database not open\n");
2657 if (num >= 0 && num < (NV_INT32)hd.pub.datum_types)
return (hd.datum[num]);
2664const NV_CHAR *get_legalese(NV_INT32 num) {
2667 "libtcd error: attempt to access database when database not open\n");
2670 if (num >= 0 && num < (NV_INT32)hd.pub.legaleses)
return (hd.legalese[num]);
2692NV_FLOAT64 get_speed(NV_INT32 num) {
2695 "libtcd error: attempt to access database when database not open\n");
2698 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
2699 return hd.speed[num];
2721NV_FLOAT32 get_equilibrium(NV_INT32 num, NV_INT32 year) {
2724 "libtcd error: attempt to access database when database not open\n");
2727 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
2728 year < (NV_INT32)hd.pub.number_of_years);
2729 return hd.equilibrium[num][year];
2735NV_FLOAT32 *get_equilibriums(NV_INT32 num) {
2738 "libtcd error: attempt to access database when database not open\n");
2741 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
2742 return hd.equilibrium[num];
2764NV_FLOAT32 get_node_factor(NV_INT32 num, NV_INT32 year) {
2767 "libtcd error: attempt to access database when database not open\n");
2770 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
2771 year < (NV_INT32)hd.pub.number_of_years);
2772 return hd.node_factor[num][year];
2778NV_FLOAT32 *get_node_factors(NV_INT32 num) {
2781 "libtcd error: attempt to access database when database not open\n");
2784 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
2785 return hd.node_factor[num];
2814 "libtcd error: attempt to access database when database not open\n");
2818 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return (NVFalse);
2822 rec->record_number = num;
2823 rec->record_size = tindex[num].record_size;
2824 rec->record_type = tindex[num].record_type;
2825 rec->latitude = (NV_FLOAT64)tindex[num].lat / hd.latitude_scale;
2826 rec->longitude = (NV_FLOAT64)tindex[num].lon / hd.longitude_scale;
2827 rec->reference_station = tindex[num].reference_station;
2828 rec->tzfile = tindex[num].tzfile;
2829 strcpy(rec->name, tindex[num].name);
2831 current_index = num;
2855 if (!get_partial_tide_record(current_index + 1, rec))
return (-1);
2857 return (current_index);
2880NV_INT32 get_nearest_partial_tide_record(NV_FLOAT64 lat, NV_FLOAT64 lon,
2882 NV_FLOAT64 diff, min_diff, lt, ln;
2883 NV_U_INT32 i, shortest = 0;
2885 min_diff = 999999999.9;
2886 for (i = 0; i < hd.pub.number_of_records; ++i) {
2887 lt = (NV_FLOAT64)tindex[i].lat / hd.latitude_scale;
2888 ln = (NV_FLOAT64)tindex[i].lon / hd.longitude_scale;
2890 diff = sqrt((lat - lt) * (lat - lt) + (lon - ln) * (lon - ln));
2892 if (diff < min_diff) {
2898 if (!get_partial_tide_record(shortest, rec))
return (-1);
2920NV_INT32 get_time(
const NV_CHAR *
string) {
2921 NV_INT32 hour, minute, hhmm;
2924 sscanf(
string,
"%d:%d", &hour, &minute);
2928 if (
string[0] ==
'-') {
2929 if (hour < 0) hour = -hour;
2931 hhmm = -(hour * 100 + minute);
2933 hhmm = hour * 100 + minute;
2957NV_CHAR *ret_time(NV_INT32 time) {
2958 NV_INT32 hour, minute;
2959 static NV_CHAR tname[16];
2961 hour = abs(time) / 100;
2962 assert(hour <= 99999 && hour >= -99999);
2963 minute = abs(time) % 100;
2966 sprintf(tname,
"-%02d:%02d", hour, minute);
2968 sprintf(tname,
"+%02d:%02d", hour, minute);
2977NV_CHAR *ret_time_neat(NV_INT32 time) {
2978 NV_INT32 hour, minute;
2979 static NV_CHAR tname[16];
2981 hour = abs(time) / 100;
2982 assert(hour <= 99999 && hour >= -99999);
2983 minute = abs(time) % 100;
2986 sprintf(tname,
"-%d:%02d", hour, minute);
2988 sprintf(tname,
"+%d:%02d", hour, minute);
2990 strcpy(tname,
"0:00");
2998NV_CHAR *ret_date(NV_U_INT32 date) {
2999 static NV_CHAR tname[30];
3001 strcpy(tname,
"NULL");
3008 sprintf(tname,
"%4u-%02u-%02u", y, m, d);
3032 "libtcd error: attempt to access database when database not open\n");
3042static void boundscheck_monologue(
const NV_CHAR *
string) {
3044 if (strlen(
string) >= MONOLOGUE_LENGTH) {
3058static void boundscheck_oneliner(
const NV_CHAR *
string) {
3060 if (strlen(
string) >= ONELINER_LENGTH) {
3088static NV_CHAR *clip_string(
const NV_CHAR *
string) {
3089 static NV_CHAR new_string[MONOLOGUE_LENGTH];
3090 NV_INT32 i, l, start = -1, end = -1;
3092 boundscheck_monologue(
string);
3093 new_string[0] =
'\0';
3095 l = (int)strlen(
string);
3097 for (i = 0; i < l; ++i) {
3098 if (
string[i] !=
' ') {
3103 for (i = l - 1; i >= start; --i) {
3104 if (
string[i] !=
' ' &&
string[i] != 10 &&
string[i] != 13) {
3109 if (start > -1 && end > -1 && end >= start) {
3110 strncpy(new_string,
string + start, end - start + 1);
3111 new_string[end - start + 1] =
'\0';
3138NV_INT32 search_station(
const NV_CHAR *
string) {
3139 static NV_CHAR last_search[ONELINER_LENGTH];
3140 static NV_U_INT32 j = 0;
3142 NV_CHAR name[ONELINER_LENGTH], search[ONELINER_LENGTH];
3146 "libtcd error: attempt to access database when database not open\n");
3150 boundscheck_oneliner(
string);
3152 for (i = 0; i < strlen(
string) + 1; ++i) search[i] =
tolower(
string[i]);
3154 if (strcmp(search, last_search)) j = 0;
3156 strcpy(last_search, search);
3158 while (j < hd.pub.number_of_records) {
3159 for (i = 0; i < strlen(tindex[j].name) + 1; ++i)
3160 name[i] =
tolower(tindex[j].name[i]);
3163 if (strstr(name, search))
return (j - 1);
3188NV_INT32 find_station(
const NV_CHAR *name) {
3193 "libtcd error: attempt to access database when database not open\n");
3198 for (i = 0; i < hd.pub.number_of_records; ++i) {
3199 if (!strcmp(name, tindex[i].name))
return (i);
3223NV_INT32 find_tzfile(
const NV_CHAR *name) {
3230 "libtcd error: attempt to access database when database not open\n");
3234 temp = clip_string(name);
3237 for (i = 0; i < hd.pub.tzfiles; ++i) {
3238 if (!strcmp(temp, get_tzfile(i))) {
3265NV_INT32 find_country(
const NV_CHAR *name) {
3272 "libtcd error: attempt to access database when database not open\n");
3276 temp = clip_string(name);
3279 for (i = 0; i < hd.pub.countries; ++i) {
3280 if (!strcmp(temp, get_country(i))) {
3307NV_INT32 find_level_units(
const NV_CHAR *name) {
3314 "libtcd error: attempt to access database when database not open\n");
3318 temp = clip_string(name);
3321 for (i = 0; i < hd.pub.level_unit_types; ++i) {
3322 if (!strcmp(get_level_units(i), temp)) {
3349NV_INT32 find_dir_units(
const NV_CHAR *name) {
3356 "libtcd error: attempt to access database when database not open\n");
3360 temp = clip_string(name);
3363 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
3364 if (!strcmp(get_dir_units(i), temp)) {
3392NV_INT32 find_pedigree(
const NV_CHAR *name) {
return 0; }
3413NV_INT32 find_datum(
const NV_CHAR *name) {
3420 "libtcd error: attempt to access database when database not open\n");
3424 temp = clip_string(name);
3427 for (i = 0; i < hd.pub.datum_types; ++i) {
3428 if (!strcmp(get_datum(i), temp)) {
3440NV_INT32 find_legalese(
const NV_CHAR *name) {
3447 "libtcd error: attempt to access database when database not open\n");
3451 temp = clip_string(name);
3454 for (i = 0; i < hd.pub.legaleses; ++i) {
3455 if (!strcmp(get_legalese(i), temp)) {
3483NV_INT32 find_constituent(
const NV_CHAR *name) {
3489 "libtcd error: attempt to access database when database not open\n");
3493 temp = clip_string(name);
3495 for (i = 0; i < hd.pub.constituents; ++i) {
3496 if (!strcmp(get_constituent(i), temp))
return (i);
3520NV_INT32 find_restriction(
const NV_CHAR *name) {
3527 "libtcd error: attempt to access database when database not open\n");
3531 temp = clip_string(name);
3534 for (i = 0; i < hd.pub.restriction_types; ++i) {
3535 if (!strcmp(get_restriction(i), temp)) {
3561void set_speed(NV_INT32 num, NV_FLOAT64 value) {
3564 "libtcd error: attempt to access database when database not open\n");
3568 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
3570 LOG_ERROR(
"libtcd set_speed: somebody tried to set a negative speed (%f)\n",
3574 hd.speed[num] = value;
3598void set_equilibrium(NV_INT32 num, NV_INT32 year, NV_FLOAT32 value) {
3601 "libtcd error: attempt to access database when database not open\n");
3605 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
3606 year < (NV_INT32)hd.pub.number_of_years);
3607 hd.equilibrium[num][year] = value;
3631void set_node_factor(NV_INT32 num, NV_INT32 year, NV_FLOAT32 value) {
3634 "libtcd error: attempt to access database when database not open\n");
3638 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
3639 year < (NV_INT32)hd.pub.number_of_years);
3642 "libtcd set_node_factor: somebody tried to set a negative or zero node "
3647 hd.node_factor[num][year] = value;
3698 "libtcd error: attempt to access database when database not open\n");
3704 if (strlen(name) + 1 > hd.tzfile_size) {
3705 LOG_ERROR(
"libtcd error: tzfile exceeds size limit (%u).\n",
3707 LOG_ERROR(
"The offending input is: %s\n", name);
3711 if (hd.pub.tzfiles == hd.max_tzfiles) {
3712 LOG_ERROR(
"You have exceeded the maximum number of tzfile types!\n");
3713 LOG_ERROR(
"You cannot add any new tzfile types.\n");
3714 LOG_ERROR(
"Modify the DEFAULT_TZFILE_BITS and rebuild the database.\n");
3718 c_name = clip_string(name);
3720 hd.tzfile[hd.pub.tzfiles] =
3721 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3723 if (hd.tzfile[hd.pub.tzfiles] == NULL) {
3724 perror(
"Allocating new tzfile string");
3728 strcpy(hd.tzfile[hd.pub.tzfiles++], c_name);
3729 if (db) *db = hd.pub;
3731 return (hd.pub.tzfiles - 1);
3757 "libtcd error: attempt to access database when database not open\n");
3763 if (strlen(name) + 1 > hd.country_size) {
3764 LOG_ERROR(
"libtcd error: country exceeds size limit (%u).\n",
3766 LOG_ERROR(
"The offending input is: %s\n", name);
3770 if (hd.pub.countries == hd.max_countries) {
3771 LOG_ERROR(
"You have exceeded the maximum number of country names!\n");
3772 LOG_ERROR(
"You cannot add any new country names.\n");
3773 LOG_ERROR(
"Modify the DEFAULT_COUNTRY_BITS and rebuild the database.\n");
3777 c_name = clip_string(name);
3779 hd.country[hd.pub.countries] =
3780 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3782 if (hd.country[hd.pub.countries] == NULL) {
3783 perror(
"Allocating new country string");
3787 strcpy(hd.country[hd.pub.countries++], c_name);
3788 if (db) *db = hd.pub;
3790 return (hd.pub.countries - 1);
3816 "libtcd error: attempt to access database when database not open\n");
3822 if (strlen(name) + 1 > hd.datum_size) {
3823 LOG_ERROR(
"libtcd error: datum exceeds size limit (%u).\n", hd.datum_size);
3824 LOG_ERROR(
"The offending input is: %s\n", name);
3828 if (hd.pub.datum_types == hd.max_datum_types) {
3829 LOG_ERROR(
"You have exceeded the maximum number of datum types!\n");
3830 LOG_ERROR(
"You cannot add any new datum types.\n");
3831 LOG_ERROR(
"Modify the DEFAULT_DATUM_BITS and rebuild the database.\n");
3835 c_name = clip_string(name);
3837 hd.datum[hd.pub.datum_types] =
3838 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3840 if (hd.datum[hd.pub.datum_types] == NULL) {
3841 perror(
"Allocating new datum string");
3845 strcpy(hd.datum[hd.pub.datum_types++], c_name);
3846 if (db) *db = hd.pub;
3848 return (hd.pub.datum_types - 1);
3859 "libtcd error: attempt to access database when database not open\n");
3865 if (strlen(name) + 1 > hd.legalese_size) {
3866 LOG_ERROR(
"libtcd error: legalese exceeds size limit (%u).\n",
3868 LOG_ERROR(
"The offending input is: %s\n", name);
3872 if (hd.pub.legaleses == hd.max_legaleses) {
3873 LOG_ERROR(
"You have exceeded the maximum number of legaleses!\n");
3874 LOG_ERROR(
"You cannot add any new legaleses.\n");
3875 LOG_ERROR(
"Modify the DEFAULT_LEGALESE_BITS and rebuild the database.\n");
3879 c_name = clip_string(name);
3881 hd.legalese[hd.pub.legaleses] =
3882 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3884 if (hd.legalese[hd.pub.legaleses] == NULL) {
3885 perror(
"Allocating new legalese string");
3889 strcpy(hd.legalese[hd.pub.legaleses++], c_name);
3890 if (db) *db = hd.pub;
3892 return (hd.pub.legaleses - 1);
3918 "libtcd error: attempt to access database when database not open\n");
3924 if (strlen(name) + 1 > hd.restriction_size) {
3925 LOG_ERROR(
"libtcd error: restriction exceeds size limit (%u).\n",
3926 hd.restriction_size);
3927 LOG_ERROR(
"The offending input is: %s\n", name);
3931 if (hd.pub.restriction_types == hd.max_restriction_types) {
3932 LOG_ERROR(
"You have exceeded the maximum number of restriction types!\n");
3933 LOG_ERROR(
"You cannot add any new restriction types.\n");
3935 "Modify the DEFAULT_RESTRICTION_BITS and rebuild the database.\n");
3939 c_name = clip_string(name);
3941 hd.restriction[hd.pub.restriction_types] =
3942 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3944 if (hd.restriction[hd.pub.restriction_types] == NULL) {
3945 perror(
"Allocating new restriction string");
3949 strcpy(hd.restriction[hd.pub.restriction_types++], c_name);
3950 if (db) *db = hd.pub;
3952 return (hd.pub.restriction_types - 1);
3958NV_INT32 find_or_add_restriction(
const NV_CHAR *name,
DB_HEADER_PUBLIC *db) {
3960 ret = find_restriction(name);
3961 if (ret < 0) ret = add_restriction(name, db);
3971 ret = find_tzfile(name);
3972 if (ret < 0) ret = add_tzfile(name, db);
3982 ret = find_country(name);
3983 if (ret < 0) ret = add_country(name, db);
3993 ret = find_datum(name);
3994 if (ret < 0) ret = add_datum(name, db);
4004 ret = find_legalese(name);
4005 if (ret < 0) ret = add_legalese(name, db);
4036 if (rec.max_time_add == rec.min_time_add &&
4037 rec.max_level_add == rec.min_level_add &&
4038 rec.max_level_multiply == rec.min_level_multiply &&
4039 rec.max_avg_level == 0 && rec.min_avg_level == 0 &&
4040 rec.max_direction == 361 && rec.min_direction == 361 &&
4041 rec.flood_begins == NULLSLACKOFFSET && rec.ebb_begins == NULLSLACKOFFSET)
4064static NV_U_INT32 header_checksum() {
4065 NV_U_INT32 checksum, i, save_pos;
4067 NV_U_INT32 crc_table[256] = {
4068 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
4069 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
4070 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
4071 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
4072 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
4073 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
4074 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
4075 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
4076 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
4077 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
4078 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
4079 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
4080 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
4081 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
4082 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
4083 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
4084 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
4085 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
4086 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
4087 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
4088 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
4089 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
4090 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
4091 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
4092 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
4093 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
4094 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
4095 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
4096 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
4097 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
4098 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
4099 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
4100 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
4101 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
4102 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
4103 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
4104 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
4105 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
4106 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
4107 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
4108 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
4109 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
4110 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D};
4114 "libtcd error: attempt to access database when database not open\n");
4118 save_pos = ftell(fp);
4120 fseek(fp, 0, SEEK_SET);
4122 if ((buf = (NV_U_BYTE *)calloc(hd.header_size,
sizeof(NV_U_BYTE))) == NULL) {
4123 perror(
"Allocating checksum buffer");
4129 assert(hd.header_size > 0);
4130 chk_fread(buf, hd.header_size, 1, fp);
4131 for (i = 0; i < (NV_U_INT32)hd.header_size; ++i) {
4132 checksum = crc_table[(checksum ^ buf[i]) & 0xff] ^ (checksum >> 8);
4138 fseek(fp, save_pos, SEEK_SET);
4159static NV_U_INT32 old_header_checksum() {
4160 NV_U_INT32 checksum, i, save_pos;
4165 "libtcd error: attempt to access database when database not open\n");
4169 save_pos = ftell(fp);
4173 fseek(fp, 0, SEEK_SET);
4175 if ((buf = (NV_U_BYTE *)calloc(hd.header_size,
sizeof(NV_U_BYTE))) == NULL) {
4176 perror(
"Allocating checksum buffer");
4180 chk_fread(buf, hd.header_size, 1, fp);
4182 for (i = 0; i < hd.header_size; ++i) checksum += buf[i];
4186 fseek(fp, save_pos, SEEK_SET);
4196static NV_CHAR *curtime() {
4197 static NV_CHAR buf[ONELINER_LENGTH];
4198 time_t t = time(NULL);
4199 require(strftime(buf, ONELINER_LENGTH,
"%Y-%m-%d %H:%M %Z", localtime(&t)) >
4208static NV_U_INT32 bits2bytes(NV_U_INT32 nbits) {
4209 if (nbits % 8)
return nbits / 8 + 1;
4229static void write_tide_db_header() {
4230 NV_U_INT32 i, size, pos;
4231 NV_INT32 start, temp_int;
4232 static NV_CHAR zero = 0;
4233 NV_U_BYTE *buf, checksum_c[4];
4237 "libtcd error: attempt to access database when database not open\n");
4242 fseek(fp, 0, SEEK_SET);
4244 fprintf(fp,
"[VERSION] = %s\n", LIBTCD_VERSION);
4245 fprintf(fp,
"[MAJOR REV] = %u\n", LIBTCD_MAJOR_REV);
4246 fprintf(fp,
"[MINOR REV] = %u\n", LIBTCD_MINOR_REV);
4248 fprintf(fp,
"[LAST MODIFIED] = %s\n", curtime());
4250 fprintf(fp,
"[HEADER SIZE] = %u\n", hd.header_size);
4251 fprintf(fp,
"[NUMBER OF RECORDS] = %u\n", hd.pub.number_of_records);
4253 fprintf(fp,
"[START YEAR] = %d\n", hd.pub.start_year);
4254 fprintf(fp,
"[NUMBER OF YEARS] = %u\n", hd.pub.number_of_years);
4256 fprintf(fp,
"[SPEED BITS] = %u\n", hd.speed_bits);
4257 fprintf(fp,
"[SPEED SCALE] = %u\n", hd.speed_scale);
4258 fprintf(fp,
"[SPEED OFFSET] = %d\n", hd.speed_offset);
4259 fprintf(fp,
"[EQUILIBRIUM BITS] = %u\n", hd.equilibrium_bits);
4260 fprintf(fp,
"[EQUILIBRIUM SCALE] = %u\n", hd.equilibrium_scale);
4261 fprintf(fp,
"[EQUILIBRIUM OFFSET] = %d\n", hd.equilibrium_offset);
4262 fprintf(fp,
"[NODE BITS] = %u\n", hd.node_bits);
4263 fprintf(fp,
"[NODE SCALE] = %u\n", hd.node_scale);
4264 fprintf(fp,
"[NODE OFFSET] = %d\n", hd.node_offset);
4265 fprintf(fp,
"[AMPLITUDE BITS] = %u\n", hd.amplitude_bits);
4266 fprintf(fp,
"[AMPLITUDE SCALE] = %u\n", hd.amplitude_scale);
4267 fprintf(fp,
"[EPOCH BITS] = %u\n", hd.epoch_bits);
4268 fprintf(fp,
"[EPOCH SCALE] = %u\n", hd.epoch_scale);
4270 fprintf(fp,
"[RECORD TYPE BITS] = %u\n", hd.record_type_bits);
4271 fprintf(fp,
"[LATITUDE BITS] = %u\n", hd.latitude_bits);
4272 fprintf(fp,
"[LATITUDE SCALE] = %u\n", hd.latitude_scale);
4273 fprintf(fp,
"[LONGITUDE BITS] = %u\n", hd.longitude_bits);
4274 fprintf(fp,
"[LONGITUDE SCALE] = %u\n", hd.longitude_scale);
4275 fprintf(fp,
"[RECORD SIZE BITS] = %u\n", hd.record_size_bits);
4277 fprintf(fp,
"[STATION BITS] = %u\n", hd.station_bits);
4279 fprintf(fp,
"[DATUM OFFSET BITS] = %u\n", hd.datum_offset_bits);
4280 fprintf(fp,
"[DATUM OFFSET SCALE] = %u\n", hd.datum_offset_scale);
4281 fprintf(fp,
"[DATE BITS] = %u\n", hd.date_bits);
4282 fprintf(fp,
"[MONTHS ON STATION BITS] = %u\n", hd.months_on_station_bits);
4283 fprintf(fp,
"[CONFIDENCE VALUE BITS] = %u\n", hd.confidence_value_bits);
4285 fprintf(fp,
"[TIME BITS] = %u\n", hd.time_bits);
4286 fprintf(fp,
"[LEVEL ADD BITS] = %u\n", hd.level_add_bits);
4287 fprintf(fp,
"[LEVEL ADD SCALE] = %u\n", hd.level_add_scale);
4288 fprintf(fp,
"[LEVEL MULTIPLY BITS] = %u\n", hd.level_multiply_bits);
4289 fprintf(fp,
"[LEVEL MULTIPLY SCALE] = %u\n", hd.level_multiply_scale);
4290 fprintf(fp,
"[DIRECTION BITS] = %u\n", hd.direction_bits);
4292 fprintf(fp,
"[LEVEL UNIT BITS] = %u\n", hd.level_unit_bits);
4293 fprintf(fp,
"[LEVEL UNIT TYPES] = %u\n", hd.pub.level_unit_types);
4294 fprintf(fp,
"[LEVEL UNIT SIZE] = %u\n", hd.level_unit_size);
4296 fprintf(fp,
"[DIRECTION UNIT BITS] = %u\n", hd.dir_unit_bits);
4297 fprintf(fp,
"[DIRECTION UNIT TYPES] = %u\n", hd.pub.dir_unit_types);
4298 fprintf(fp,
"[DIRECTION UNIT SIZE] = %u\n", hd.dir_unit_size);
4300 fprintf(fp,
"[RESTRICTION BITS] = %u\n", hd.restriction_bits);
4301 fprintf(fp,
"[RESTRICTION TYPES] = %u\n", hd.pub.restriction_types);
4302 fprintf(fp,
"[RESTRICTION SIZE] = %u\n", hd.restriction_size);
4304 fprintf(fp,
"[DATUM BITS] = %u\n", hd.datum_bits);
4305 fprintf(fp,
"[DATUM TYPES] = %u\n", hd.pub.datum_types);
4306 fprintf(fp,
"[DATUM SIZE] = %u\n", hd.datum_size);
4308 fprintf(fp,
"[LEGALESE BITS] = %u\n", hd.legalese_bits);
4309 fprintf(fp,
"[LEGALESE TYPES] = %u\n", hd.pub.legaleses);
4310 fprintf(fp,
"[LEGALESE SIZE] = %u\n", hd.legalese_size);
4312 fprintf(fp,
"[CONSTITUENT BITS] = %u\n", hd.constituent_bits);
4313 fprintf(fp,
"[CONSTITUENTS] = %u\n", hd.pub.constituents);
4314 fprintf(fp,
"[CONSTITUENT SIZE] = %u\n", hd.constituent_size);
4316 fprintf(fp,
"[TZFILE BITS] = %u\n", hd.tzfile_bits);
4317 fprintf(fp,
"[TZFILES] = %u\n", hd.pub.tzfiles);
4318 fprintf(fp,
"[TZFILE SIZE] = %u\n", hd.tzfile_size);
4320 fprintf(fp,
"[COUNTRY BITS] = %u\n", hd.country_bits);
4321 fprintf(fp,
"[COUNTRIES] = %u\n", hd.pub.countries);
4322 fprintf(fp,
"[COUNTRY SIZE] = %u\n", hd.country_size);
4324 fprintf(fp,
"[END OF FILE] = %u\n", hd.end_of_file);
4325 fprintf(fp,
"[END OF ASCII HEADER DATA]\n");
4331 for (i = start; i < hd.header_size; ++i) chk_fwrite(&zero, 1, 1, fp);
4336 bit_pack(checksum_c, 0, 32, header_checksum());
4337 chk_fwrite(checksum_c, 4, 1, fp);
4344 size = hd.pub.level_unit_types * hd.level_unit_size;
4346 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4347 perror(
"Allocating unit write buffer");
4350 memset(buf, 0, size);
4352 for (i = 0; i < hd.pub.level_unit_types; ++i) {
4353 assert(strlen(hd.level_unit[i]) + 1 <= hd.level_unit_size);
4354 strcpy((NV_CHAR *)&buf[pos], hd.level_unit[i]);
4355 pos += hd.level_unit_size;
4358 chk_fwrite(buf, pos, 1, fp);
4364 size = hd.pub.dir_unit_types * hd.dir_unit_size;
4366 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4367 perror(
"Allocating unit write buffer");
4370 memset(buf, 0, size);
4372 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
4373 assert(strlen(hd.dir_unit[i]) + 1 <= hd.dir_unit_size);
4374 strcpy((NV_CHAR *)&buf[pos], hd.dir_unit[i]);
4375 pos += hd.dir_unit_size;
4378 chk_fwrite(buf, pos, 1, fp);
4384 size = hd.max_restriction_types * hd.restriction_size;
4386 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4387 perror(
"Allocating restriction write buffer");
4390 memset(buf, 0, size);
4392 for (i = 0; i < hd.max_restriction_types; ++i) {
4393 if (i == hd.pub.restriction_types)
break;
4394 assert(strlen(hd.restriction[i]) + 1 <= hd.restriction_size);
4395 strcpy((NV_CHAR *)&buf[pos], hd.restriction[i]);
4396 pos += hd.restriction_size;
4398 memcpy(&buf[pos],
"__END__", 7);
4400 chk_fwrite(buf, size, 1, fp);
4406 size = hd.max_tzfiles * hd.tzfile_size;
4408 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4409 perror(
"Allocating tzfile write buffer");
4412 memset(buf, 0, size);
4414 for (i = 0; i < hd.max_tzfiles; ++i) {
4415 if (i == hd.pub.tzfiles)
break;
4416 assert(strlen(hd.tzfile[i]) + 1 <= hd.tzfile_size);
4417 strcpy((NV_CHAR *)&buf[pos], hd.tzfile[i]);
4418 pos += hd.tzfile_size;
4420 memcpy(&buf[pos],
"__END__", 7);
4422 chk_fwrite(buf, size, 1, fp);
4428 size = hd.max_countries * hd.country_size;
4430 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4431 perror(
"Allocating country write buffer");
4434 memset(buf, 0, size);
4436 for (i = 0; i < hd.max_countries; ++i) {
4437 if (i == hd.pub.countries)
break;
4438 assert(strlen(hd.country[i]) + 1 <= hd.country_size);
4439 strcpy((NV_CHAR *)&buf[pos], hd.country[i]);
4440 pos += hd.country_size;
4442 memcpy(&buf[pos],
"__END__", 7);
4444 chk_fwrite(buf, size, 1, fp);
4450 size = hd.max_datum_types * hd.datum_size;
4452 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4453 perror(
"Allocating datum write buffer");
4456 memset(buf, 0, size);
4458 for (i = 0; i < hd.max_datum_types; ++i) {
4459 if (i == hd.pub.datum_types)
break;
4460 assert(strlen(hd.datum[i]) + 1 <= hd.datum_size);
4461 strcpy((NV_CHAR *)&buf[pos], hd.datum[i]);
4462 pos += hd.datum_size;
4464 memcpy(&buf[pos],
"__END__", 7);
4466 chk_fwrite(buf, size, 1, fp);
4472 size = hd.max_legaleses * hd.legalese_size;
4474 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4475 perror(
"Allocating legalese write buffer");
4478 memset(buf, 0, size);
4480 for (i = 0; i < hd.max_legaleses; ++i) {
4481 if (i == hd.pub.legaleses)
break;
4482 assert(strlen(hd.legalese[i]) + 1 <= hd.legalese_size);
4483 strcpy((NV_CHAR *)&buf[pos], hd.legalese[i]);
4484 pos += hd.legalese_size;
4486 memcpy(&buf[pos],
"__END__", 7);
4488 chk_fwrite(buf, size, 1, fp);
4494 size = hd.pub.constituents * hd.constituent_size;
4496 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4497 perror(
"Allocating constituent write buffer");
4500 memset(buf, 0, size);
4502 for (i = 0; i < hd.pub.constituents; ++i) {
4503 assert(strlen(hd.constituent[i]) + 1 <= hd.constituent_size);
4504 strcpy((NV_CHAR *)&buf[pos], hd.constituent[i]);
4505 pos += hd.constituent_size;
4508 chk_fwrite(buf, pos, 1, fp);
4516 size = bits2bytes(hd.pub.constituents * hd.speed_bits);
4518 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4519 perror(
"Allocating speed write buffer");
4522 memset(buf, 0, size);
4524 for (i = 0; i < hd.pub.constituents; ++i) {
4525 temp_int = NINT(hd.speed[i] * hd.speed_scale) - hd.speed_offset;
4526 assert(temp_int >= 0);
4527 bit_pack(buf, pos, hd.speed_bits, temp_int);
4528 pos += hd.speed_bits;
4531 chk_fwrite(buf, size, 1, fp);
4537 size = bits2bytes(hd.pub.constituents * hd.pub.number_of_years *
4538 hd.equilibrium_bits);
4540 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4541 perror(
"Allocating equilibrium write buffer");
4544 memset(buf, 0, size);
4546 for (i = 0; i < hd.pub.constituents; ++i) {
4548 for (j = 0; j < hd.pub.number_of_years; ++j) {
4549 temp_int = NINT(hd.equilibrium[i][j] * hd.equilibrium_scale) -
4550 hd.equilibrium_offset;
4551 assert(temp_int >= 0);
4552 bit_pack(buf, pos, hd.equilibrium_bits, temp_int);
4553 pos += hd.equilibrium_bits;
4557 chk_fwrite(buf, size, 1, fp);
4564 bits2bytes(hd.pub.constituents * hd.pub.number_of_years * hd.node_bits);
4566 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4567 perror(
"Allocating node write buffer");
4570 memset(buf, 0, size);
4572 for (i = 0; i < hd.pub.constituents; ++i) {
4574 for (j = 0; j < hd.pub.number_of_years; ++j) {
4575 temp_int = NINT(hd.node_factor[i][j] * hd.node_scale) - hd.node_offset;
4576 assert(temp_int >= 0);
4577 bit_pack(buf, pos, hd.node_bits, temp_int);
4578 pos += hd.node_bits;
4582 chk_fwrite(buf, size, 1, fp);
4613static void unpack_string(NV_U_BYTE *buf, NV_U_INT32 bufsize, NV_U_INT32 *pos,
4614 NV_CHAR *outbuf, NV_U_INT32 outbuflen,
4615 const NV_CHAR *desc) {
4625 for (i = 0; c; ++i) {
4626 assert(*pos < bufsize);
4627 c = bit_unpack(buf, *pos, 8);
4629 if (i < outbuflen) {
4631 }
else if (i == outbuflen) {
4634 LOG_ERROR(
"libtcd warning: truncating overlong %s\n", desc);
4635 LOG_ERROR(
"The offending string starts with:\n%s\n", outbuf);
4663static void unpack_partial_tide_record(NV_U_BYTE *buf, NV_U_INT32 bufsize,
4673 rec->header.record_size = bit_unpack(buf, *pos, hd.record_size_bits);
4674 *pos += hd.record_size_bits;
4676 rec->header.record_type = bit_unpack(buf, *pos, hd.record_type_bits);
4677 *pos += hd.record_type_bits;
4679 temp_int = signed_bit_unpack(buf, *pos, hd.latitude_bits);
4680 rec->header.latitude = (NV_FLOAT64)temp_int / hd.latitude_scale;
4681 *pos += hd.latitude_bits;
4683 temp_int = signed_bit_unpack(buf, *pos, hd.longitude_bits);
4684 rec->header.longitude = (NV_FLOAT64)temp_int / hd.longitude_scale;
4685 *pos += hd.longitude_bits;
4690 rec->header.tzfile = bit_unpack(buf, *pos, hd.tzfile_bits);
4691 *pos += hd.tzfile_bits;
4693 unpack_string(buf, bufsize, pos, rec->header.name, ONELINER_LENGTH,
4696 rec->header.reference_station = signed_bit_unpack(buf, *pos, hd.station_bits);
4697 *pos += hd.station_bits;
4699 assert(*pos <= bufsize * 8);
4722static NV_INT32 read_partial_tide_record(NV_INT32 num,
TIDE_RECORD *rec) {
4724 NV_U_INT32 maximum_possible_size, pos;
4728 "libtcd error: attempt to access database when database not open\n");
4737 maximum_possible_size = hd.record_size_bits + hd.record_type_bits +
4738 hd.latitude_bits + hd.longitude_bits +
4739 hd.tzfile_bits + (ONELINER_LENGTH * 8) +
4741 maximum_possible_size = bits2bytes(maximum_possible_size);
4743 if ((buf = (NV_U_BYTE *)calloc(maximum_possible_size,
sizeof(NV_U_BYTE))) ==
4745 perror(
"Allocating partial tide record buffer");
4749 current_record = num;
4750 fseek(fp, tindex[num].address, SEEK_SET);
4755 size_t size = fread(buf, 1, maximum_possible_size, fp);
4756 unpack_partial_tide_record(buf, size, rec, &pos);
4776static NV_BOOL read_tide_db_header() {
4778 NV_CHAR varin[ONELINER_LENGTH], *info;
4779 NV_U_INT32 utemp, i, j, pos, size, key_count;
4780 NV_U_BYTE *buf, checksum_c[5];
4785 "libtcd error: attempt to access database when database not open\n");
4789 strcpy(hd.pub.version,
"NO VERSION");
4792 key_count =
sizeof(keys) /
sizeof(
KEY);
4795 memset(&hd, 0,
sizeof(hd));
4798 while (fgets(varin,
sizeof(varin), fp) != NULL) {
4799 if (strlen(varin) == ONELINER_LENGTH - 1) {
4800 if (varin[ONELINER_LENGTH - 2] !=
'\n') {
4801 LOG_ERROR(
"libtcd error: header line too long, begins with:\n");
4802 LOG_ERROR(
"%s\n", varin);
4803 LOG_ERROR(
"in file %s\n", filename);
4804 LOG_ERROR(
"Configured limit is %u\n", ONELINER_LENGTH - 1);
4810 if (strstr(varin,
"[END OF ASCII HEADER DATA]"))
break;
4813 info = strchr(varin,
'=');
4815 LOG_ERROR(
"libtcd error: invalid tide db header line:\n");
4816 LOG_ERROR(
"%s", varin);
4817 LOG_ERROR(
"in file %s\n", filename);
4824 for (i = 0; i < key_count; ++i) {
4825 if (strstr(varin, keys[i].keyphrase)) {
4826 if (!strcmp(keys[i].datatype,
"cstr"))
4827 strcpy((
char *)keys[i].address.cstr, clip_string(info));
4828 else if (!strcmp(keys[i].datatype,
"i32")) {
4829 if (sscanf(info,
"%d", keys[i].address.i32) != 1) {
4830 LOG_ERROR(
"libtcd error: invalid tide db header line:\n");
4831 LOG_ERROR(
"%s", varin);
4832 LOG_ERROR(
"in file %s\n", filename);
4836 }
else if (!strcmp(keys[i].datatype,
"ui32")) {
4837 if (sscanf(info,
"%u", keys[i].address.ui32) != 1) {
4838 LOG_ERROR(
"libtcd error: invalid tide db header line:\n");
4839 LOG_ERROR(
"%s", varin);
4840 LOG_ERROR(
"in file %s\n", filename);
4852 if (!strcmp(hd.pub.version,
"NO VERSION")) {
4853 LOG_ERROR(
"libtcd error: no version found in tide db header\n");
4854 LOG_ERROR(
"in file %s\n", filename);
4860 if (hd.pub.major_rev > LIBTCD_MAJOR_REV) {
4862 "libtcd error: major revision in TCD file (%u) exceeds major revision "
4865 LOG_ERROR(
"libtcd (%u). You must upgrade libtcd to read this file.\n",
4872 fseek(fp, hd.header_size, SEEK_SET);
4876 chk_fread(checksum_c, 4, 1, fp);
4877 utemp = bit_unpack(checksum_c, 0, 32);
4879 if (utemp != header_checksum()) {
4881 if (utemp != old_header_checksum()) {
4882 LOG_ERROR(
"libtcd error: header checksum error in file %s\n", filename);
4884 "Someone may have modified the ASCII portion of the header (don't do that),\n\
4885or it may just be corrupt.\n");
4890 LOG_ERROR(
"libtcd error: header checksum error in file %s\n", filename);
4892 "Someone may have modified the ASCII portion of the header (don't do that),\n\
4893or it may be an ancient pre-version-1.02 TCD file, or it may just be corrupt.\n\
4894Pre-version-1.02 TCD files can be read by building libtcd with COMPAT114\n\
4900 fseek(fp, hd.header_size + 4, SEEK_SET);
4905 hd.max_restriction_types = NINT(pow(2.0, (NV_FLOAT64)hd.restriction_bits));
4909 hd.max_tzfiles = NINT(pow(2.0, (NV_FLOAT64)hd.tzfile_bits));
4913 hd.max_countries = NINT(pow(2.0, (NV_FLOAT64)hd.country_bits));
4918 hd.max_datum_types = NINT(pow(2.0, (NV_FLOAT64)hd.datum_bits));
4923 if (hd.pub.major_rev < 2)
4924 hd.max_legaleses = 1;
4926 hd.max_legaleses = NINT(pow(2.0, (NV_FLOAT64)hd.legalese_bits));
4933 (NV_CHAR **)calloc(hd.pub.level_unit_types,
sizeof(NV_CHAR *));
4935 if ((buf = (NV_U_BYTE *)calloc(hd.level_unit_size,
sizeof(NV_U_BYTE))) ==
4937 perror(
"Allocating level unit read buffer");
4941 for (i = 0; i < hd.pub.level_unit_types; ++i) {
4942 chk_fread(buf, hd.level_unit_size, 1, fp);
4944 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
4945 strcpy(hd.level_unit[i], (NV_CHAR *)buf);
4951 hd.dir_unit = (NV_CHAR **)calloc(hd.pub.dir_unit_types,
sizeof(NV_CHAR *));
4953 if ((buf = (NV_U_BYTE *)calloc(hd.dir_unit_size,
sizeof(NV_U_BYTE))) ==
4955 perror(
"Allocating dir unit read buffer");
4959 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
4960 chk_fread(buf, hd.dir_unit_size, 1, fp);
4962 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
4963 strcpy(hd.dir_unit[i], (NV_CHAR *)buf);
4971 (NV_CHAR **)calloc(hd.max_restriction_types,
sizeof(NV_CHAR *));
4973 if ((buf = (NV_U_BYTE *)calloc(hd.restriction_size,
sizeof(NV_U_BYTE))) ==
4975 perror(
"Allocating restriction read buffer");
4979 hd.pub.restriction_types = 0;
4980 for (i = 0; i < hd.max_restriction_types; ++i) {
4981 chk_fread(buf, hd.restriction_size, 1, fp);
4982 if (!strcmp((
char *)buf,
"__END__")) {
4983 hd.pub.restriction_types = i;
4987 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
4988 strcpy(hd.restriction[i], (NV_CHAR *)buf);
4991 fseek(fp, utemp + hd.max_restriction_types * hd.restriction_size, SEEK_SET);
4994 if (hd.pub.major_rev < 2)
4995 fseek(fp, hd.pedigree_size * NINT(pow(2.0, (NV_FLOAT64)hd.pedigree_bits)),
4997 hd.pub.pedigree_types = 1;
5002 hd.tzfile = (NV_CHAR **)calloc(hd.max_tzfiles,
sizeof(NV_CHAR *));
5004 if ((buf = (NV_U_BYTE *)calloc(hd.tzfile_size,
sizeof(NV_U_BYTE))) == NULL) {
5005 perror(
"Allocating tzfile read buffer");
5010 for (i = 0; i < hd.max_tzfiles; ++i) {
5011 chk_fread(buf, hd.tzfile_size, 1, fp);
5012 if (!strcmp((
char *)buf,
"__END__")) {
5016 hd.tzfile[i] = (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5017 strcpy(hd.tzfile[i], (NV_CHAR *)buf);
5020 fseek(fp, utemp + hd.max_tzfiles * hd.tzfile_size, SEEK_SET);
5025 hd.country = (NV_CHAR **)calloc(hd.max_countries,
sizeof(NV_CHAR *));
5027 if ((buf = (NV_U_BYTE *)calloc(hd.country_size,
sizeof(NV_U_BYTE))) == NULL) {
5028 perror(
"Allocating country read buffer");
5032 hd.pub.countries = 0;
5033 for (i = 0; i < hd.max_countries; ++i) {
5034 chk_fread(buf, hd.country_size, 1, fp);
5035 if (!strcmp((
char *)buf,
"__END__")) {
5036 hd.pub.countries = i;
5039 hd.country[i] = (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5040 strcpy(hd.country[i], (NV_CHAR *)buf);
5043 fseek(fp, utemp + hd.max_countries * hd.country_size, SEEK_SET);
5048 hd.datum = (NV_CHAR **)calloc(hd.max_datum_types,
sizeof(NV_CHAR *));
5050 if ((buf = (NV_U_BYTE *)calloc(hd.datum_size,
sizeof(NV_U_BYTE))) == NULL) {
5051 perror(
"Allocating datum read buffer");
5055 hd.pub.datum_types = 0;
5056 for (i = 0; i < hd.max_datum_types; ++i) {
5057 chk_fread(buf, hd.datum_size, 1, fp);
5058 if (!strcmp((
char *)buf,
"__END__")) {
5059 hd.pub.datum_types = i;
5062 hd.datum[i] = (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5063 strcpy(hd.datum[i], (NV_CHAR *)buf);
5066 fseek(fp, utemp + hd.max_datum_types * hd.datum_size, SEEK_SET);
5070 if (hd.pub.major_rev < 2) {
5071 hd.legalese = (NV_CHAR **)malloc(
sizeof(NV_CHAR *));
5072 assert(hd.legalese != NULL);
5073 hd.legalese[0] = (NV_CHAR *)malloc(5 *
sizeof(NV_CHAR));
5074 assert(hd.legalese[0] != NULL);
5075 strcpy(hd.legalese[0],
"NULL");
5076 hd.pub.legaleses = 1;
5079 hd.legalese = (NV_CHAR **)calloc(hd.max_legaleses,
sizeof(NV_CHAR *));
5081 if ((buf = (NV_U_BYTE *)calloc(hd.legalese_size,
sizeof(NV_U_BYTE))) ==
5083 perror(
"Allocating legalese read buffer");
5087 hd.pub.legaleses = 0;
5088 for (i = 0; i < hd.max_legaleses; ++i) {
5089 chk_fread(buf, hd.legalese_size, 1, fp);
5090 if (!strcmp((
char *)buf,
"__END__")) {
5091 hd.pub.legaleses = i;
5095 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5096 strcpy(hd.legalese[i], (NV_CHAR *)buf);
5099 fseek(fp, utemp + hd.max_legaleses * hd.legalese_size, SEEK_SET);
5104 hd.constituent = (NV_CHAR **)calloc(hd.pub.constituents,
sizeof(NV_CHAR *));
5106 if ((buf = (NV_U_BYTE *)calloc(hd.constituent_size,
sizeof(NV_U_BYTE))) ==
5108 perror(
"Allocating constituent read buffer");
5112 for (i = 0; i < hd.pub.constituents; ++i) {
5113 chk_fread(buf, hd.constituent_size, 1, fp);
5115 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5116 strcpy(hd.constituent[i], (NV_CHAR *)buf);
5120 if (hd.speed_offset < 0 || hd.equilibrium_offset < 0 || hd.node_offset < 0) {
5121 LOG_ERROR(
"libtcd WARNING: File: %s\n", filename);
5123 "WARNING: This TCD file was created by a pre-version-1.11 libtcd.\n\
5124Versions of libtcd prior to 1.11 contained a serious bug that can result\n\
5125in overflows in the speeds, equilibrium arguments, or node factors. This\n\
5126database should be rebuilt from the original data if possible.\n");
5133 hd.speed = (NV_FLOAT64 *)calloc(hd.pub.constituents,
sizeof(NV_FLOAT64));
5137 if (hd.pub.major_rev < 2)
5138 size = ((hd.pub.constituents * hd.speed_bits) / 8) + 1;
5140 size = bits2bytes(hd.pub.constituents * hd.speed_bits);
5142 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
5143 perror(
"Allocating speed read buffer");
5147 chk_fread(buf, size, 1, fp);
5149 for (i = 0; i < hd.pub.constituents; ++i) {
5150 temp_int = bit_unpack(buf, pos, hd.speed_bits);
5151 hd.speed[i] = (NV_FLOAT64)(temp_int + hd.speed_offset) / hd.speed_scale;
5152 pos += hd.speed_bits;
5153 assert(hd.speed[i] >= 0.0);
5160 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5162 for (i = 0; i < hd.pub.constituents; ++i) {
5164 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5169 if (hd.pub.major_rev < 2)
5171 ((hd.pub.constituents * hd.pub.number_of_years * hd.equilibrium_bits) /
5175 size = bits2bytes(hd.pub.constituents * hd.pub.number_of_years *
5176 hd.equilibrium_bits);
5178 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
5179 perror(
"Allocating equilibrium read buffer");
5183 chk_fread(buf, size, 1, fp);
5185 for (i = 0; i < hd.pub.constituents; ++i) {
5186 for (j = 0; j < hd.pub.number_of_years; ++j) {
5187 temp_int = bit_unpack(buf, pos, hd.equilibrium_bits);
5188 hd.equilibrium[i][j] =
5189 (NV_FLOAT32)(temp_int + hd.equilibrium_offset) / hd.equilibrium_scale;
5190 pos += hd.equilibrium_bits;
5198 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5200 for (i = 0; i < hd.pub.constituents; ++i) {
5202 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5207 if (hd.pub.major_rev < 2)
5209 ((hd.pub.constituents * hd.pub.number_of_years * hd.node_bits) / 8) + 1;
5212 bits2bytes(hd.pub.constituents * hd.pub.number_of_years * hd.node_bits);
5214 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
5215 perror(
"Allocating node read buffer");
5219 chk_fread(buf, size, 1, fp);
5221 for (i = 0; i < hd.pub.constituents; ++i) {
5222 for (j = 0; j < hd.pub.number_of_years; ++j) {
5223 temp_int = bit_unpack(buf, pos, hd.node_bits);
5224 hd.node_factor[i][j] =
5225 (NV_FLOAT32)(temp_int + hd.node_offset) / hd.node_scale;
5226 pos += hd.node_bits;
5227 assert(hd.node_factor[i][j] > 0.0);
5236 if (hd.pub.number_of_records) {
5237 if ((tindex = (
TIDE_INDEX *)calloc(hd.pub.number_of_records,
5239 perror(
"Allocating tide index");
5243 tindex[0].address = ftell(fp);
5247 for (i = 0; i < hd.pub.number_of_records; ++i) {
5251 if (i) tindex[i].address = tindex[i - 1].address + rec.header.record_size;
5253 read_partial_tide_record(i, &rec);
5257 tindex[i].record_size = rec.header.record_size;
5258 tindex[i].record_type = rec.header.record_type;
5259 tindex[i].reference_station = rec.header.reference_station;
5260 assert(rec.header.tzfile >= 0);
5261 tindex[i].tzfile = rec.header.tzfile;
5262 tindex[i].lat = NINT(rec.header.latitude * hd.latitude_scale);
5263 tindex[i].lon = NINT(rec.header.longitude * hd.longitude_scale);
5265 if ((tindex[i].name = (NV_CHAR *)calloc(strlen(rec.header.name) + 1,
5266 sizeof(NV_CHAR))) == NULL) {
5267 perror(
"Allocating index name memory");
5271 strcpy(tindex[i].name, rec.header.name);
5274 current_record = -1;
5297NV_BOOL open_tide_db(
const NV_CHAR *file) {
5299 current_record = -1;
5302 if (!strcmp(file, filename) && !modified)
5307 if ((fp = fopen(file,
"rb+")) == NULL) {
5308 if ((fp = fopen(file,
"rb")) == NULL)
return (NVFalse);
5310 boundscheck_monologue(file);
5311 strcpy(filename, file);
5312 return (read_tide_db_header());
5333void close_tide_db() {
5337 LOG_ERROR(
"libtcd warning: close_tide_db called when no database open\n");
5344 if (modified) write_tide_db_header();
5348 assert(hd.constituent);
5349 for (i = 0; i < hd.pub.constituents; ++i) {
5350 if (hd.constituent[i] != NULL) free(hd.constituent[i]);
5352 free(hd.constituent);
5353 hd.constituent = NULL;
5355 if (hd.speed != NULL) free(hd.speed);
5357 assert(hd.equilibrium);
5358 for (i = 0; i < hd.pub.constituents; ++i) {
5359 if (hd.equilibrium[i] != NULL) free(hd.equilibrium[i]);
5361 free(hd.equilibrium);
5362 hd.equilibrium = NULL;
5364 assert(hd.node_factor);
5365 for (i = 0; i < hd.pub.constituents; ++i) {
5366 if (hd.node_factor[i] != NULL) free(hd.node_factor[i]);
5368 free(hd.node_factor);
5369 hd.node_factor = NULL;
5371 assert(hd.level_unit);
5372 for (i = 0; i < hd.pub.level_unit_types; ++i) {
5373 if (hd.level_unit[i] != NULL) free(hd.level_unit[i]);
5375 free(hd.level_unit);
5376 hd.level_unit = NULL;
5378 assert(hd.dir_unit);
5379 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
5380 if (hd.dir_unit[i] != NULL) free(hd.dir_unit[i]);
5385 assert(hd.restriction);
5386 for (i = 0; i < hd.max_restriction_types; ++i) {
5387 if (hd.restriction[i] != NULL) free(hd.restriction[i]);
5389 free(hd.restriction);
5390 hd.restriction = NULL;
5392 assert(hd.legalese);
5393 for (i = 0; i < hd.max_legaleses; ++i) {
5394 if (hd.legalese[i] != NULL) free(hd.legalese[i]);
5400 for (i = 0; i < hd.max_tzfiles; ++i) {
5401 if (hd.tzfile[i] != NULL) free(hd.tzfile[i]);
5407 for (i = 0; i < hd.max_countries; ++i) {
5408 if (hd.country[i] != NULL) free(hd.country[i]);
5414 for (i = 0; i < hd.max_datum_types; ++i) {
5415 if (hd.datum[i] != NULL) free(hd.datum[i]);
5422 for (i = 0; i < hd.pub.number_of_records; ++i) {
5423 if (tindex[i].name) free(tindex[i].name);
5464NV_BOOL create_tide_db(
const NV_CHAR *file, NV_U_INT32 constituents,
5465 NV_CHAR
const *
const constituent[],
5466 const NV_FLOAT64 *speed, NV_INT32 start_year,
5467 NV_U_INT32 num_years,
5468 NV_FLOAT32
const *
const equilibrium[],
5469 NV_FLOAT32
const *
const node_factor[]) {
5471 NV_FLOAT64 min_value, max_value;
5476 assert(constituent);
5478 assert(equilibrium);
5479 assert(node_factor);
5480 for (i = 0; i < constituents; ++i) {
5481 if (speed[i] < 0.0) {
5483 "libtcd create_tide_db: somebody tried to set a negative speed "
5488 for (j = 0; j < num_years; ++j) {
5489 if (node_factor[i][j] <= 0.0) {
5491 "libtcd create_tide_db: somebody tried to set a negative or zero "
5492 "node factor (%f)\n",
5499 if (fp) close_tide_db();
5501 if ((fp = fopen(file,
"wb+")) == NULL) {
5508 memset(&hd, 0,
sizeof(hd));
5510 hd.pub.major_rev = LIBTCD_MAJOR_REV;
5511 hd.pub.minor_rev = LIBTCD_MINOR_REV;
5513 hd.header_size = DEFAULT_HEADER_SIZE;
5514 hd.pub.number_of_records = DEFAULT_NUMBER_OF_RECORDS;
5516 hd.pub.start_year = start_year;
5517 hd.pub.number_of_years = num_years;
5519 hd.pub.constituents = constituents;
5523 hd.constituent = (NV_CHAR **)calloc(hd.pub.constituents,
sizeof(NV_CHAR *));
5524 for (i = 0; i < hd.pub.constituents; ++i) {
5526 (NV_CHAR *)calloc(strlen(constituent[i]) + 1,
sizeof(NV_CHAR));
5527 strcpy(hd.constituent[i], constituent[i]);
5533 hd.constituent_bits = calculate_bits(hd.pub.constituents);
5537 hd.speed = (NV_FLOAT64 *)calloc(hd.pub.constituents,
sizeof(NV_FLOAT64));
5539 hd.speed_scale = DEFAULT_SPEED_SCALE;
5540 min_value = 99999999.0;
5541 max_value = -99999999.0;
5542 for (i = 0; i < hd.pub.constituents; ++i) {
5543 if (speed[i] < min_value) min_value = speed[i];
5544 if (speed[i] > max_value) max_value = speed[i];
5546 hd.speed[i] = speed[i];
5552 hd.speed_offset = (NINT(min_value * hd.speed_scale));
5553 temp_int = NINT(max_value * hd.speed_scale) - hd.speed_offset;
5554 assert(temp_int >= 0);
5555 hd.speed_bits = calculate_bits((NV_U_INT32)temp_int);
5557 assert(hd.speed_bits < 32);
5562 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5564 hd.equilibrium_scale = DEFAULT_EQUILIBRIUM_SCALE;
5565 min_value = 99999999.0;
5566 max_value = -99999999.0;
5567 for (i = 0; i < hd.pub.constituents; ++i) {
5569 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5570 for (j = 0; j < hd.pub.number_of_years; ++j) {
5571 if (equilibrium[i][j] < min_value) min_value = equilibrium[i][j];
5572 if (equilibrium[i][j] > max_value) max_value = equilibrium[i][j];
5574 hd.equilibrium[i][j] = equilibrium[i][j];
5581 hd.equilibrium_offset = (NINT(min_value * hd.equilibrium_scale));
5582 temp_int = NINT(max_value * hd.equilibrium_scale) - hd.equilibrium_offset;
5583 assert(temp_int >= 0);
5584 hd.equilibrium_bits = calculate_bits((NV_U_INT32)temp_int);
5589 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5591 hd.node_scale = DEFAULT_NODE_SCALE;
5592 min_value = 99999999.0;
5593 max_value = -99999999.0;
5594 for (i = 0; i < hd.pub.constituents; ++i) {
5596 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5597 for (j = 0; j < hd.pub.number_of_years; ++j) {
5598 if (node_factor[i][j] < min_value) min_value = node_factor[i][j];
5599 if (node_factor[i][j] > max_value) max_value = node_factor[i][j];
5601 hd.node_factor[i][j] = node_factor[i][j];
5608 hd.node_offset = (NINT(min_value * hd.node_scale));
5609 temp_int = NINT(max_value * hd.node_scale) - hd.node_offset;
5610 assert(temp_int >= 0);
5611 hd.node_bits = calculate_bits((NV_U_INT32)temp_int);
5615 hd.amplitude_bits = DEFAULT_AMPLITUDE_BITS;
5616 hd.amplitude_scale = DEFAULT_AMPLITUDE_SCALE;
5617 hd.epoch_bits = DEFAULT_EPOCH_BITS;
5618 hd.epoch_scale = DEFAULT_EPOCH_SCALE;
5620 hd.record_type_bits = DEFAULT_RECORD_TYPE_BITS;
5621 hd.latitude_bits = DEFAULT_LATITUDE_BITS;
5622 hd.latitude_scale = DEFAULT_LATITUDE_SCALE;
5623 hd.longitude_bits = DEFAULT_LONGITUDE_BITS;
5624 hd.longitude_scale = DEFAULT_LONGITUDE_SCALE;
5625 hd.record_size_bits = DEFAULT_RECORD_SIZE_BITS;
5627 hd.station_bits = DEFAULT_STATION_BITS;
5629 hd.datum_offset_bits = DEFAULT_DATUM_OFFSET_BITS;
5630 hd.datum_offset_scale = DEFAULT_DATUM_OFFSET_SCALE;
5631 hd.date_bits = DEFAULT_DATE_BITS;
5632 hd.months_on_station_bits = DEFAULT_MONTHS_ON_STATION_BITS;
5633 hd.confidence_value_bits = DEFAULT_CONFIDENCE_VALUE_BITS;
5635 hd.time_bits = DEFAULT_TIME_BITS;
5636 hd.level_add_bits = DEFAULT_LEVEL_ADD_BITS;
5637 hd.level_add_scale = DEFAULT_LEVEL_ADD_SCALE;
5638 hd.level_multiply_bits = DEFAULT_LEVEL_MULTIPLY_BITS;
5639 hd.level_multiply_scale = DEFAULT_LEVEL_MULTIPLY_SCALE;
5640 hd.direction_bits = DEFAULT_DIRECTION_BITS;
5642 hd.constituent_size = DEFAULT_CONSTITUENT_SIZE;
5643 hd.level_unit_size = DEFAULT_LEVEL_UNIT_SIZE;
5644 hd.dir_unit_size = DEFAULT_DIR_UNIT_SIZE;
5645 hd.restriction_size = DEFAULT_RESTRICTION_SIZE;
5646 hd.tzfile_size = DEFAULT_TZFILE_SIZE;
5647 hd.country_size = DEFAULT_COUNTRY_SIZE;
5648 hd.datum_size = DEFAULT_DATUM_SIZE;
5649 hd.legalese_size = DEFAULT_LEGALESE_SIZE;
5653 hd.pub.level_unit_types = DEFAULT_LEVEL_UNIT_TYPES;
5654 hd.level_unit_bits = calculate_bits(hd.pub.level_unit_types - 1);
5657 (NV_CHAR **)calloc(hd.pub.level_unit_types,
sizeof(NV_CHAR *));
5658 for (i = 0; i < hd.pub.level_unit_types; ++i) {
5660 (NV_CHAR *)calloc(strlen(level_unit[i]) + 1,
sizeof(NV_CHAR));
5661 strcpy(hd.level_unit[i], level_unit[i]);
5666 hd.pub.dir_unit_types = DEFAULT_DIR_UNIT_TYPES;
5667 hd.dir_unit_bits = calculate_bits(hd.pub.dir_unit_types - 1);
5669 hd.dir_unit = (NV_CHAR **)calloc(hd.pub.dir_unit_types,
sizeof(NV_CHAR *));
5670 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
5672 (NV_CHAR *)calloc(strlen(dir_unit[i]) + 1,
sizeof(NV_CHAR));
5673 strcpy(hd.dir_unit[i], dir_unit[i]);
5678 hd.restriction_bits = DEFAULT_RESTRICTION_BITS;
5679 hd.max_restriction_types = NINT(pow(2.0, (NV_FLOAT64)hd.restriction_bits));
5680 hd.pub.restriction_types = DEFAULT_RESTRICTION_TYPES;
5683 (NV_CHAR **)calloc(hd.max_restriction_types,
sizeof(NV_CHAR *));
5684 for (i = 0; i < hd.max_restriction_types; ++i) {
5685 if (i == hd.pub.restriction_types)
break;
5688 (NV_CHAR *)calloc(strlen(restriction[i]) + 1,
sizeof(NV_CHAR));
5689 strcpy(hd.restriction[i], restriction[i]);
5694 hd.legalese_bits = DEFAULT_LEGALESE_BITS;
5695 hd.max_legaleses = NINT(pow(2.0, (NV_FLOAT64)hd.legalese_bits));
5696 hd.pub.legaleses = DEFAULT_LEGALESES;
5698 hd.legalese = (NV_CHAR **)calloc(hd.max_legaleses,
sizeof(NV_CHAR *));
5699 for (i = 0; i < hd.max_legaleses; ++i) {
5700 if (i == hd.pub.legaleses)
break;
5703 (NV_CHAR *)calloc(strlen(legalese[i]) + 1,
sizeof(NV_CHAR));
5704 strcpy(hd.legalese[i], legalese[i]);
5709 hd.tzfile_bits = DEFAULT_TZFILE_BITS;
5710 hd.max_tzfiles = NINT(pow(2.0, (NV_FLOAT64)hd.tzfile_bits));
5711 hd.pub.tzfiles = DEFAULT_TZFILES;
5713 hd.tzfile = (NV_CHAR **)calloc(hd.max_tzfiles,
sizeof(NV_CHAR *));
5714 for (i = 0; i < hd.max_tzfiles; ++i) {
5715 if (i == hd.pub.tzfiles)
break;
5717 hd.tzfile[i] = (NV_CHAR *)calloc(strlen(tzfile[i]) + 1,
sizeof(NV_CHAR));
5718 strcpy(hd.tzfile[i], tzfile[i]);
5723 hd.country_bits = DEFAULT_COUNTRY_BITS;
5724 hd.max_countries = NINT(pow(2.0, (NV_FLOAT64)hd.country_bits));
5725 hd.pub.countries = DEFAULT_COUNTRIES;
5727 hd.country = (NV_CHAR **)calloc(hd.max_countries,
sizeof(NV_CHAR *));
5728 for (i = 0; i < hd.max_countries; ++i) {
5729 if (i == hd.pub.countries)
break;
5731 hd.country[i] = (NV_CHAR *)calloc(strlen(country[i]) + 1,
sizeof(NV_CHAR));
5732 strcpy(hd.country[i], country[i]);
5737 hd.datum_bits = DEFAULT_DATUM_BITS;
5738 hd.max_datum_types = NINT(pow(2.0, (NV_FLOAT64)hd.datum_bits));
5739 hd.pub.datum_types = DEFAULT_DATUM_TYPES;
5741 hd.datum = (NV_CHAR **)calloc(hd.max_datum_types,
sizeof(NV_CHAR *));
5742 for (i = 0; i < hd.max_datum_types; ++i) {
5743 if (i == hd.pub.datum_types)
break;
5745 hd.datum[i] = (NV_CHAR *)calloc(strlen(datum[i]) + 1,
sizeof(NV_CHAR));
5746 strcpy(hd.datum[i], datum[i]);
5756 i = (open_tide_db(file));
5760 hd.end_of_file = ftell(fp);
5764 write_tide_db_header();
5773static NV_BOOL check_date(NV_U_INT32 date) {
5779 if (m < 1 || m > 12 || d < 1 || d > 31)
return NVFalse;
5793static NV_BOOL check_tide_record(
TIDE_RECORD *rec) {
5795 NV_BOOL ret = NVTrue;
5798 LOG_ERROR(
"libtcd error: null pointer passed to check_tide_record\n");
5804 boundscheck_oneliner(rec->header.name);
5805 boundscheck_oneliner(rec->source);
5806 boundscheck_monologue(rec->comments);
5807 boundscheck_monologue(rec->notes);
5808 boundscheck_oneliner(rec->station_id_context);
5809 boundscheck_oneliner(rec->station_id);
5810 boundscheck_monologue(rec->xfields);
5813 if (rec->header.record_type == REFERENCE_STATION && rec->units > 0)
5814 rec->level_units = rec->units;
5817 if (rec->header.latitude < -90.0 || rec->header.latitude > 90.0 ||
5818 rec->header.longitude < -180.0 || rec->header.longitude > 180.0) {
5819 LOG_ERROR(
"libtcd error: bad coordinates in tide record\n");
5823 if (rec->header.tzfile < 0 ||
5824 rec->header.tzfile >= (NV_INT32)hd.pub.tzfiles) {
5825 LOG_ERROR(
"libtcd error: bad tzfile in tide record\n");
5829 if (rec->header.name[0] ==
'\0') {
5830 LOG_ERROR(
"libtcd error: null name in tide record\n");
5834 if (rec->country < 0 || rec->country >= (NV_INT32)hd.pub.countries) {
5835 LOG_ERROR(
"libtcd error: bad country in tide record\n");
5839 if (rec->restriction >= hd.pub.restriction_types) {
5840 LOG_ERROR(
"libtcd error: bad restriction in tide record\n");
5844 if (rec->legalese >= hd.pub.legaleses) {
5845 LOG_ERROR(
"libtcd error: bad legalese in tide record\n");
5849 if (!check_date(rec->date_imported)) {
5850 LOG_ERROR(
"libtcd error: bad date_imported in tide record\n");
5854 if (rec->direction_units >= hd.pub.dir_unit_types) {
5855 LOG_ERROR(
"libtcd error: bad direction_units in tide record\n");
5859 if (rec->min_direction < 0 || rec->min_direction > 361) {
5860 LOG_ERROR(
"libtcd error: min_direction out of range in tide record\n");
5864 if (rec->max_direction < 0 || rec->max_direction > 361) {
5865 LOG_ERROR(
"libtcd error: max_direction out of range in tide record\n");
5869 if (rec->level_units >= hd.pub.level_unit_types) {
5870 LOG_ERROR(
"libtcd error: bad units in tide record\n");
5874 switch (rec->header.record_type) {
5875 case REFERENCE_STATION:
5876 if (rec->header.reference_station != -1) {
5877 LOG_ERROR(
"libtcd error: type 1 record, reference_station != -1\n");
5881 if (rec->datum_offset < -13421.7728 || rec->datum_offset > 13421.7727) {
5882 LOG_ERROR(
"libtcd error: datum_offset out of range in tide record\n");
5886 if (rec->datum < 0 || rec->datum >= (NV_INT32)hd.pub.datum_types) {
5887 LOG_ERROR(
"libtcd error: bad datum in tide record\n");
5891 if (rec->zone_offset < -4096 || rec->zone_offset > 4095 ||
5892 rec->zone_offset % 100 >= 60) {
5893 LOG_ERROR(
"libtcd error: bad zone_offset in tide record\n");
5897 if (!check_date(rec->expiration_date)) {
5898 LOG_ERROR(
"libtcd error: bad expiration_date in tide record\n");
5902 if (rec->months_on_station > 1023) {
5904 "libtcd error: months_on_station out of range in tide record\n");
5908 if (!check_date(rec->last_date_on_station)) {
5909 LOG_ERROR(
"libtcd error: bad last_date_on_station in tide record\n");
5913 if (rec->confidence > 15) {
5914 LOG_ERROR(
"libtcd error: confidence out of range in tide record\n");
5919 for (i = 0; i < hd.pub.constituents; ++i) {
5920 if (rec->amplitude[i] < 0.0 || rec->amplitude[i] > 52.4287) {
5922 "libtcd error: constituent amplitude out of range in tide "
5928 for (i = 0; i < hd.pub.constituents; ++i) {
5929 if (rec->epoch[i] < 0.0 || rec->epoch[i] > 360.0) {
5931 "libtcd error: constituent epoch out of range in tide record\n");
5939 case SUBORDINATE_STATION:
5940 if (rec->header.reference_station < 0 ||
5941 rec->header.reference_station >= (NV_INT32)hd.pub.number_of_records) {
5942 LOG_ERROR(
"libtcd error: bad reference_station in tide record\n");
5946 if (rec->min_time_add < -4096 || rec->min_time_add > 4095 ||
5947 rec->min_time_add % 100 >= 60) {
5948 LOG_ERROR(
"libtcd error: bad min_time_add in tide record\n");
5952 if (rec->min_level_add < -65.536 || rec->min_level_add > 65.535) {
5953 LOG_ERROR(
"libtcd error: min_level_add out of range in tide record\n");
5957 if (rec->min_level_multiply < 0.0 || rec->min_level_multiply > 65.535) {
5959 "libtcd error: min_level_multiply out of range in tide record\n");
5963 if (rec->max_time_add < -4096 || rec->max_time_add > 4095 ||
5964 rec->max_time_add % 100 >= 60) {
5965 LOG_ERROR(
"libtcd error: bad max_time_add in tide record\n");
5969 if (rec->max_level_add < -65.536 || rec->max_level_add > 65.535) {
5970 LOG_ERROR(
"libtcd error: max_level_add out of range in tide record\n");
5974 if (rec->max_level_multiply < 0.0 || rec->max_level_multiply > 65.535) {
5976 "libtcd error: max_level_multiply out of range in tide record\n");
5980 if (rec->flood_begins != NULLSLACKOFFSET &&
5981 (rec->flood_begins < -4096 || rec->flood_begins > 4095 ||
5982 rec->flood_begins % 100 >= 60)) {
5983 LOG_ERROR(
"libtcd error: bad flood_begins in tide record\n");
5987 if (rec->ebb_begins != NULLSLACKOFFSET &&
5988 (rec->ebb_begins < -4096 || rec->ebb_begins > 4095 ||
5989 rec->ebb_begins % 100 >= 60)) {
5990 LOG_ERROR(
"libtcd error: bad ebb_begins in tide record\n");
5997 LOG_ERROR(
"libtcd error: invalid record_type in tide record\n");
6001 if (ret == NVFalse) dump_tide_record(rec);
6012 NV_U_INT32 i, count = 0, name_size, source_size, comments_size, notes_size,
6013 station_id_context_size, station_id_size, xfields_size;
6019 name_size = strlen(clip_string(rec->header.name)) + 1;
6020 source_size = strlen(clip_string(rec->source)) + 1;
6021 comments_size = strlen(clip_string(rec->comments)) + 1;
6022 notes_size = strlen(clip_string(rec->notes)) + 1;
6023 station_id_context_size = strlen(clip_string(rec->station_id_context)) + 1;
6024 station_id_size = strlen(clip_string(rec->station_id)) + 1;
6026 xfields_size = strlen(rec->xfields) + 1;
6028 rec->header.record_size =
6029 hd.record_size_bits + hd.record_type_bits + hd.latitude_bits +
6030 hd.longitude_bits + hd.station_bits + hd.tzfile_bits + (name_size * 8) +
6032 hd.country_bits + (source_size * 8) + hd.restriction_bits +
6033 (comments_size * 8) + (notes_size * 8) + hd.legalese_bits +
6034 (station_id_context_size * 8) + (station_id_size * 8) + hd.date_bits +
6035 (xfields_size * 8) + hd.dir_unit_bits + hd.direction_bits +
6036 hd.direction_bits + hd.level_unit_bits;
6038 switch (rec->header.record_type) {
6039 case REFERENCE_STATION:
6040 rec->header.record_size += hd.datum_offset_bits + hd.datum_bits +
6041 hd.time_bits + hd.date_bits +
6042 hd.months_on_station_bits + hd.date_bits +
6043 hd.confidence_value_bits + hd.constituent_bits;
6045 for (i = 0; i < hd.pub.constituents; ++i) {
6046 assert(rec->amplitude[i] >= 0.0);
6047 if (rec->amplitude[i] >= AMPLITUDE_EPSILON) ++count;
6050 rec->header.record_size +=
6051 (count * hd.constituent_bits + count * hd.amplitude_bits +
6052 count * hd.epoch_bits);
6056 case SUBORDINATE_STATION:
6057 rec->header.record_size += hd.time_bits + hd.level_add_bits +
6058 hd.level_multiply_bits + hd.time_bits +
6059 hd.level_add_bits + hd.level_multiply_bits +
6060 hd.time_bits + hd.time_bits;
6067 rec->header.record_size = bits2bytes(rec->header.record_size);
6074static void pack_string(NV_U_BYTE *buf, NV_U_INT32 *pos, NV_CHAR *s) {
6075 NV_U_INT32 i, temp_size;
6079 temp_size = strlen(s) + 1;
6080 for (i = 0; i < temp_size; ++i) {
6081 bit_pack(buf, *pos, 8, s[i]);
6106static void pack_tide_record(
TIDE_RECORD *rec, NV_U_BYTE **bufptr,
6107 NV_U_INT32 *bufsize) {
6108 NV_U_INT32 i, pos, constituent_count;
6117 boundscheck_oneliner(rec->header.name);
6118 boundscheck_oneliner(rec->source);
6119 boundscheck_monologue(rec->comments);
6120 boundscheck_monologue(rec->notes);
6121 boundscheck_oneliner(rec->station_id_context);
6122 boundscheck_oneliner(rec->station_id);
6123 boundscheck_monologue(rec->xfields);
6125 constituent_count = figure_size(rec);
6128 (NV_U_BYTE *)calloc(rec->header.record_size,
sizeof(NV_U_BYTE)))) {
6129 perror(
"libtcd can't allocate memory in pack_tide_record");
6139 bit_pack(buf, pos, hd.record_size_bits, rec->header.record_size);
6140 pos += hd.record_size_bits;
6142 bit_pack(buf, pos, hd.record_type_bits, rec->header.record_type);
6143 pos += hd.record_type_bits;
6145 temp_int = NINT(rec->header.latitude * hd.latitude_scale);
6146 bit_pack(buf, pos, hd.latitude_bits, temp_int);
6147 pos += hd.latitude_bits;
6149 temp_int = NINT(rec->header.longitude * hd.longitude_scale);
6150 bit_pack(buf, pos, hd.longitude_bits, temp_int);
6151 pos += hd.longitude_bits;
6157 bit_pack(buf, pos, hd.tzfile_bits, rec->header.tzfile);
6158 pos += hd.tzfile_bits;
6160 pack_string(buf, &pos, clip_string(rec->header.name));
6162 bit_pack(buf, pos, hd.station_bits, rec->header.reference_station);
6163 pos += hd.station_bits;
6165 bit_pack(buf, pos, hd.country_bits, rec->country);
6166 pos += hd.country_bits;
6168 pack_string(buf, &pos, clip_string(rec->source));
6170 bit_pack(buf, pos, hd.restriction_bits, rec->restriction);
6171 pos += hd.restriction_bits;
6173 pack_string(buf, &pos, clip_string(rec->comments));
6174 pack_string(buf, &pos, clip_string(rec->notes));
6176 bit_pack(buf, pos, hd.legalese_bits, rec->legalese);
6177 pos += hd.legalese_bits;
6179 pack_string(buf, &pos, clip_string(rec->station_id_context));
6180 pack_string(buf, &pos, clip_string(rec->station_id));
6182 bit_pack(buf, pos, hd.date_bits, rec->date_imported);
6183 pos += hd.date_bits;
6186 pack_string(buf, &pos, rec->xfields);
6188 bit_pack(buf, pos, hd.dir_unit_bits, rec->direction_units);
6189 pos += hd.dir_unit_bits;
6191 bit_pack(buf, pos, hd.direction_bits, rec->min_direction);
6192 pos += hd.direction_bits;
6194 bit_pack(buf, pos, hd.direction_bits, rec->max_direction);
6195 pos += hd.direction_bits;
6198 bit_pack(buf, pos, hd.level_unit_bits, rec->level_units);
6199 pos += hd.level_unit_bits;
6203 if (rec->header.record_type == REFERENCE_STATION) {
6204 temp_int = NINT(rec->datum_offset * hd.datum_offset_scale);
6205 bit_pack(buf, pos, hd.datum_offset_bits, temp_int);
6206 pos += hd.datum_offset_bits;
6208 bit_pack(buf, pos, hd.datum_bits, rec->datum);
6209 pos += hd.datum_bits;
6211 bit_pack(buf, pos, hd.time_bits, rec->zone_offset);
6212 pos += hd.time_bits;
6214 bit_pack(buf, pos, hd.date_bits, rec->expiration_date);
6215 pos += hd.date_bits;
6217 bit_pack(buf, pos, hd.months_on_station_bits, rec->months_on_station);
6218 pos += hd.months_on_station_bits;
6220 bit_pack(buf, pos, hd.date_bits, rec->last_date_on_station);
6221 pos += hd.date_bits;
6223 bit_pack(buf, pos, hd.confidence_value_bits, rec->confidence);
6224 pos += hd.confidence_value_bits;
6226 bit_pack(buf, pos, hd.constituent_bits, constituent_count);
6227 pos += hd.constituent_bits;
6229 for (i = 0; i < hd.pub.constituents; ++i) {
6230 if (rec->amplitude[i] >= AMPLITUDE_EPSILON) {
6231 bit_pack(buf, pos, hd.constituent_bits, i);
6232 pos += hd.constituent_bits;
6234 temp_int = NINT(rec->amplitude[i] * hd.amplitude_scale);
6236 bit_pack(buf, pos, hd.amplitude_bits, temp_int);
6237 pos += hd.amplitude_bits;
6239 temp_int = NINT(rec->epoch[i] * hd.epoch_scale);
6240 bit_pack(buf, pos, hd.epoch_bits, temp_int);
6241 pos += hd.epoch_bits;
6247 else if (rec->header.record_type == SUBORDINATE_STATION) {
6248 bit_pack(buf, pos, hd.time_bits, rec->min_time_add);
6249 pos += hd.time_bits;
6251 temp_int = NINT(rec->min_level_add * hd.level_add_scale);
6252 bit_pack(buf, pos, hd.level_add_bits, temp_int);
6253 pos += hd.level_add_bits;
6255 temp_int = NINT(rec->min_level_multiply * hd.level_multiply_scale);
6256 bit_pack(buf, pos, hd.level_multiply_bits, temp_int);
6257 pos += hd.level_multiply_bits;
6259 bit_pack(buf, pos, hd.time_bits, rec->max_time_add);
6260 pos += hd.time_bits;
6262 temp_int = NINT(rec->max_level_add * hd.level_add_scale);
6263 bit_pack(buf, pos, hd.level_add_bits, temp_int);
6264 pos += hd.level_add_bits;
6266 temp_int = NINT(rec->max_level_multiply * hd.level_multiply_scale);
6267 bit_pack(buf, pos, hd.level_multiply_bits, temp_int);
6268 pos += hd.level_multiply_bits;
6270 bit_pack(buf, pos, hd.time_bits, rec->flood_begins);
6271 pos += hd.time_bits;
6273 bit_pack(buf, pos, hd.time_bits, rec->ebb_begins);
6274 pos += hd.time_bits;
6278 LOG_ERROR(
"libtcd error: Record type %d is undefined\n",
6279 rec->header.record_type);
6283 *bufsize = rec->header.record_size;
6284 assert(*bufsize == bits2bytes(pos));
6309static NV_BOOL write_tide_record(NV_INT32 num,
TIDE_RECORD *rec) {
6310 NV_U_BYTE *buf = NULL;
6311 NV_U_INT32 bufsize = 0;
6315 "libtcd error: attempt to access database when database not open\n");
6320 pack_tide_record(rec, &buf, &bufsize);
6325 fseek(fp, tindex[num].address, SEEK_SET);
6329 chk_fwrite(buf, bufsize, 1, fp);
6354 return (read_tide_record(current_record + 1, rec));
6378static void unpack_tide_record(NV_U_BYTE *buf, NV_U_INT32 bufsize,
6381 NV_U_INT32 i, j, pos, count;
6388 int r = find_dir_units(
"degrees true");
6390 rec->direction_units = (NV_U_BYTE)r;
6392 rec->min_direction = rec->max_direction = 361;
6393 rec->flood_begins = rec->ebb_begins = NULLSLACKOFFSET;
6394 rec->header.record_number = current_record;
6396 unpack_partial_tide_record(buf, bufsize, rec, &pos);
6398 switch (rec->header.record_type) {
6399 case REFERENCE_STATION:
6400 case SUBORDINATE_STATION:
6403 LOG_ERROR(
"libtcd fatal error: tried to read type %d tide record.\n",
6404 rec->header.record_type);
6406 "This version of libtcd only supports types 1 and 2. Perhaps you "
6407 "should\nupgrade.\n");
6411 switch (hd.pub.major_rev) {
6418 rec->country = bit_unpack(buf, pos, hd.country_bits);
6419 pos += hd.country_bits;
6422 pos += hd.pedigree_bits;
6424 unpack_string(buf, bufsize, &pos, rec->source, ONELINER_LENGTH,
6427 rec->restriction = bit_unpack(buf, pos, hd.restriction_bits);
6428 pos += hd.restriction_bits;
6430 unpack_string(buf, bufsize, &pos, rec->comments, MONOLOGUE_LENGTH,
6433 if (rec->header.record_type == REFERENCE_STATION) {
6434 rec->level_units = bit_unpack(buf, pos, hd.level_unit_bits);
6436 rec->units = rec->level_units;
6438 pos += hd.level_unit_bits;
6440 temp_int = signed_bit_unpack(buf, pos, hd.datum_offset_bits);
6441 rec->datum_offset = (NV_FLOAT32)temp_int / hd.datum_offset_scale;
6442 pos += hd.datum_offset_bits;
6444 rec->datum = bit_unpack(buf, pos, hd.datum_bits);
6445 pos += hd.datum_bits;
6447 rec->zone_offset = signed_bit_unpack(buf, pos, hd.time_bits);
6448 pos += hd.time_bits;
6450 rec->expiration_date = bit_unpack(buf, pos, hd.date_bits);
6451 pos += hd.date_bits;
6453 rec->months_on_station =
6454 bit_unpack(buf, pos, hd.months_on_station_bits);
6455 pos += hd.months_on_station_bits;
6457 rec->last_date_on_station = bit_unpack(buf, pos, hd.date_bits);
6458 pos += hd.date_bits;
6460 rec->confidence = bit_unpack(buf, pos, hd.confidence_value_bits);
6461 pos += hd.confidence_value_bits;
6463 for (i = 0; i < hd.pub.constituents; ++i) {
6464 rec->amplitude[i] = 0.0;
6465 rec->epoch[i] = 0.0;
6468 count = bit_unpack(buf, pos, hd.constituent_bits);
6469 pos += hd.constituent_bits;
6471 for (i = 0; i < count; ++i) {
6472 j = bit_unpack(buf, pos, hd.constituent_bits);
6473 pos += hd.constituent_bits;
6476 (NV_FLOAT32)bit_unpack(buf, pos, hd.amplitude_bits) /
6478 pos += hd.amplitude_bits;
6481 (NV_FLOAT32)bit_unpack(buf, pos, hd.epoch_bits) / hd.epoch_scale;
6482 pos += hd.epoch_bits;
6484 }
else if (rec->header.record_type == SUBORDINATE_STATION) {
6485 rec->level_units = bit_unpack(buf, pos, hd.level_unit_bits);
6486 pos += hd.level_unit_bits;
6488 rec->direction_units = bit_unpack(buf, pos, hd.dir_unit_bits);
6489 pos += hd.dir_unit_bits;
6492 pos += hd.level_unit_bits;
6494 rec->min_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6495 pos += hd.time_bits;
6497 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6498 rec->min_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6499 pos += hd.level_add_bits;
6502 temp_int = signed_bit_unpack(buf, pos, hd.level_multiply_bits);
6503 rec->min_level_multiply =
6504 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6505 pos += hd.level_multiply_bits;
6508 pos += hd.level_add_bits;
6510 rec->min_direction = bit_unpack(buf, pos, hd.direction_bits);
6511 pos += hd.direction_bits;
6513 rec->max_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6514 pos += hd.time_bits;
6516 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6517 rec->max_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6518 pos += hd.level_add_bits;
6521 temp_int = signed_bit_unpack(buf, pos, hd.level_multiply_bits);
6522 rec->max_level_multiply =
6523 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6524 pos += hd.level_multiply_bits;
6527 pos += hd.level_add_bits;
6529 rec->max_direction = bit_unpack(buf, pos, hd.direction_bits);
6530 pos += hd.direction_bits;
6532 rec->flood_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6533 pos += hd.time_bits;
6535 rec->ebb_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6536 pos += hd.time_bits;
6544 rec->country = bit_unpack(buf, pos, hd.country_bits);
6545 pos += hd.country_bits;
6547 unpack_string(buf, bufsize, &pos, rec->source, ONELINER_LENGTH,
6550 rec->restriction = bit_unpack(buf, pos, hd.restriction_bits);
6551 pos += hd.restriction_bits;
6553 unpack_string(buf, bufsize, &pos, rec->comments, MONOLOGUE_LENGTH,
6555 unpack_string(buf, bufsize, &pos, rec->notes, MONOLOGUE_LENGTH,
6558 rec->legalese = bit_unpack(buf, pos, hd.legalese_bits);
6559 pos += hd.legalese_bits;
6561 unpack_string(buf, bufsize, &pos, rec->station_id_context,
6562 ONELINER_LENGTH,
"station_id_context field");
6563 unpack_string(buf, bufsize, &pos, rec->station_id, ONELINER_LENGTH,
6564 "station_id field");
6566 rec->date_imported = bit_unpack(buf, pos, hd.date_bits);
6567 pos += hd.date_bits;
6569 unpack_string(buf, bufsize, &pos, rec->xfields, MONOLOGUE_LENGTH,
6572 rec->direction_units = bit_unpack(buf, pos, hd.dir_unit_bits);
6573 pos += hd.dir_unit_bits;
6575 rec->min_direction = bit_unpack(buf, pos, hd.direction_bits);
6576 pos += hd.direction_bits;
6578 rec->max_direction = bit_unpack(buf, pos, hd.direction_bits);
6579 pos += hd.direction_bits;
6581 rec->level_units = bit_unpack(buf, pos, hd.level_unit_bits);
6583 rec->units = rec->level_units;
6585 pos += hd.level_unit_bits;
6587 if (rec->header.record_type == REFERENCE_STATION) {
6588 temp_int = signed_bit_unpack(buf, pos, hd.datum_offset_bits);
6589 rec->datum_offset = (NV_FLOAT32)temp_int / hd.datum_offset_scale;
6590 pos += hd.datum_offset_bits;
6592 rec->datum = bit_unpack(buf, pos, hd.datum_bits);
6593 pos += hd.datum_bits;
6595 rec->zone_offset = signed_bit_unpack(buf, pos, hd.time_bits);
6596 pos += hd.time_bits;
6598 rec->expiration_date = bit_unpack(buf, pos, hd.date_bits);
6599 pos += hd.date_bits;
6601 rec->months_on_station =
6602 bit_unpack(buf, pos, hd.months_on_station_bits);
6603 pos += hd.months_on_station_bits;
6605 rec->last_date_on_station = bit_unpack(buf, pos, hd.date_bits);
6606 pos += hd.date_bits;
6608 rec->confidence = bit_unpack(buf, pos, hd.confidence_value_bits);
6609 pos += hd.confidence_value_bits;
6611 for (i = 0; i < hd.pub.constituents; ++i) {
6612 rec->amplitude[i] = 0.0;
6613 rec->epoch[i] = 0.0;
6616 count = bit_unpack(buf, pos, hd.constituent_bits);
6617 pos += hd.constituent_bits;
6619 for (i = 0; i < count; ++i) {
6620 j = bit_unpack(buf, pos, hd.constituent_bits);
6621 pos += hd.constituent_bits;
6624 (NV_FLOAT32)bit_unpack(buf, pos, hd.amplitude_bits) /
6626 pos += hd.amplitude_bits;
6629 (NV_FLOAT32)bit_unpack(buf, pos, hd.epoch_bits) / hd.epoch_scale;
6630 pos += hd.epoch_bits;
6632 }
else if (rec->header.record_type == SUBORDINATE_STATION) {
6633 rec->min_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6634 pos += hd.time_bits;
6636 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6637 rec->min_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6638 pos += hd.level_add_bits;
6641 temp_int = bit_unpack(buf, pos, hd.level_multiply_bits);
6642 rec->min_level_multiply =
6643 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6644 pos += hd.level_multiply_bits;
6646 rec->max_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6647 pos += hd.time_bits;
6649 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6650 rec->max_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6651 pos += hd.level_add_bits;
6654 temp_int = bit_unpack(buf, pos, hd.level_multiply_bits);
6655 rec->max_level_multiply =
6656 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6657 pos += hd.level_multiply_bits;
6659 rec->flood_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6660 pos += hd.time_bits;
6662 rec->ebb_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6663 pos += hd.time_bits;
6673 assert(pos <= bufsize * 8);
6697NV_INT32 read_tide_record(NV_INT32 num,
TIDE_RECORD *rec) {
6703 "libtcd error: attempt to access database when database not open\n");
6707 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return -1;
6710 bufsize = tindex[num].record_size;
6711 if ((buf = (NV_U_BYTE *)calloc(bufsize,
sizeof(NV_U_BYTE))) == NULL) {
6712 perror(
"Allocating read_tide_record buffer");
6716 current_record = num;
6717 require(fseek(fp, tindex[num].address, SEEK_SET) == 0);
6718 chk_fread(buf, tindex[num].record_size, 1, fp);
6719 unpack_tide_record(buf, bufsize, rec);
6746 "libtcd error: attempt to access database when database not open\n");
6751 if (!check_tide_record(rec))
return NVFalse;
6753 fseek(fp, hd.end_of_file, SEEK_SET);
6757 rec->header.record_number = hd.pub.number_of_records++;
6759 if (write_tide_record(-1, rec)) {
6761 tindex, hd.pub.number_of_records *
sizeof(
TIDE_INDEX))) == NULL) {
6762 perror(
"Allocating more index records");
6766 tindex[rec->header.record_number].address = pos;
6767 tindex[rec->header.record_number].record_size = rec->header.record_size;
6768 tindex[rec->header.record_number].record_type = rec->header.record_type;
6769 tindex[rec->header.record_number].reference_station =
6770 rec->header.reference_station;
6771 assert(rec->header.tzfile >= 0);
6772 tindex[rec->header.record_number].tzfile = rec->header.tzfile;
6773 tindex[rec->header.record_number].lat =
6774 NINT(rec->header.latitude * hd.latitude_scale);
6775 tindex[rec->header.record_number].lon =
6776 NINT(rec->header.longitude * hd.longitude_scale);
6778 if ((tindex[rec->header.record_number].name = (NV_CHAR *)calloc(
6779 strlen(rec->header.name) + 1,
sizeof(NV_CHAR))) == NULL) {
6780 perror(
"Allocating index name memory");
6784 strcpy(tindex[rec->header.record_number].name, rec->header.name);
6787 hd.end_of_file = pos;
6791 if (db) *db = hd.pub;
6820 NV_INT32 i, newrecnum, *map;
6821 NV_U_BYTE **allrecs_packed;
6824 LOG_ERROR (
"libtcd error: attempt to access database when database not open\n");
6829 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return NVFalse;
6833 if (!(map = (NV_INT32 *) malloc (hd.pub.number_of_records *
sizeof(NV_INT32)))) {
6834 perror (
"libtcd: delete_tide_record: can't malloc");
6837 if (!(allrecs_packed = (NV_U_BYTE **) malloc (hd.pub.number_of_records *
sizeof(NV_U_BYTE*)))) {
6838 perror (
"libtcd: delete_tide_record: can't malloc");
6846 require (fseek (fp, tindex[0].address, SEEK_SET) == 0);
6847 for (newrecnum=0,i=0; i<(NV_INT32)hd.pub.number_of_records; ++i) {
6848 assert (ftell(fp) == tindex[i].address);
6849 if (i == num || (tindex[i].record_type == SUBORDINATE_STATION && tindex[i].reference_station == num)) {
6851 allrecs_packed[i] = NULL;
6852 require (fseek (fp, tindex[i].record_size, SEEK_CUR) == 0);
6854 map[i] = newrecnum++;
6855 if (!(allrecs_packed[i] = (NV_U_BYTE *) malloc (tindex[i].record_size))) {
6856 perror (
"libtcd: delete_tide_record: can't malloc");
6857 for (--i; i>=0; --i)
6858 free (allrecs_packed[i]);
6859 free (allrecs_packed);
6863 chk_fread (allrecs_packed[i], tindex[i].record_size, 1, fp);
6869 require (fseek (fp, tindex[0].address, SEEK_SET) == 0);
6870 require (ftruncate (fileno(fp), tindex[0].address) == 0);
6872 for (i=0; i<(NV_INT32)hd.pub.number_of_records; ++i)
6874 if (tindex[i].record_type == SUBORDINATE_STATION) {
6875 assert (tindex[i].reference_station >= 0);
6876 assert (tindex[i].reference_station <= (NV_INT32)hd.pub.number_of_records);
6877 if (map[tindex[i].reference_station] != tindex[i].reference_station) {
6880 unpack_tide_record (allrecs_packed[i], tindex[i].record_size, &rec);
6881 free (allrecs_packed[i]);
6882 rec.header.reference_station = map[tindex[i].reference_station];
6883 pack_tide_record (&rec, &(allrecs_packed[i]), &(tindex[i].record_size));
6886 chk_fwrite (allrecs_packed[i], tindex[i].record_size, 1, fp);
6887 free (allrecs_packed[i]);
6892 free (allrecs_packed);
6898 hd.end_of_file = ftell(fp);
6899 hd.pub.number_of_records = newrecnum;
6902 open_tide_db (filename);
6931NV_BOOL update_tide_record(NV_INT32 num,
TIDE_RECORD *rec)
6938 NV_U_BYTE *
block = NULL;
6942 "libtcd error: attempt to access database when database not open\n");
6947 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return NVFalse;
6949 if (!check_tide_record(rec))
return NVFalse;
6952 read_tide_record(num, &tmp_rec);
6953 if (rec->header.record_size != tmp_rec.header.record_size) {
6961 size = hd.end_of_file - pos;
6966 if ((
block = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
6967 perror(
"Allocating block");
6970 chk_fread(
block, size, 1, fp);
6974 write_tide_record(num, rec);
6978 chk_fwrite(
block, size, 1, fp);
6982 hd.end_of_file = ftell(fp);
6986 open_tide_db(filename);
6991 write_tide_record(num, rec);
6994 tindex[num].record_size = rec->header.record_size;
6995 tindex[num].record_type = rec->header.record_type;
6996 tindex[num].reference_station = rec->header.reference_station;
6997 tindex[num].tzfile = rec->header.tzfile;
6998 tindex[num].lat = NINT(rec->header.latitude * hd.latitude_scale);
6999 tindex[num].lon = NINT(rec->header.longitude * hd.longitude_scale);
7004 if (strcmp(tindex[num].name, rec->header.name) != 0) {
7005 free(tindex[num].name);
7007 (NV_CHAR *)calloc(strlen(rec->header.name) + 1,
sizeof(NV_CHAR));
7008 strcpy(tindex[num].name, rec->header.name);
7013 if (db) *db = hd.pub;
7050 NV_INT32 m2, s2, k1, o1;
7051 NV_FLOAT32 epoch_m2, epoch_s2, epoch_k1, epoch_o1;
7054 require((m2 = find_constituent(
"M2")) >= 0);
7055 require((s2 = find_constituent(
"S2")) >= 0);
7056 require((k1 = find_constituent(
"K1")) >= 0);
7057 require((o1 = find_constituent(
"O1")) >= 0);
7059 if (rec->amplitude[m2] == 0.0 || rec->amplitude[s2] == 0.0 ||
7060 rec->amplitude[k1] == 0.0 || rec->amplitude[o1] == 0.0)
7063 epoch_m2 = rec->epoch[m2];
7064 epoch_s2 = rec->epoch[s2];
7065 epoch_k1 = rec->epoch[k1];
7066 epoch_o1 = rec->epoch[o1];
7068 for (i = 0; i < hd.pub.constituents; ++i) {
7069 if (rec->amplitude[i] == 0.0 && rec->epoch[i] == 0.0) {
7070 for (j = 0; j < INFERRED_SEMI_DIURNAL_COUNT; ++j) {
7071 if (!strcmp(inferred_semi_diurnal[j], get_constituent(i))) {
7075 (semi_diurnal_coeff[j] / coeff[0]) * rec->amplitude[m2];
7077 if (fabs((NV_FLOAT64)(epoch_s2 - epoch_m2)) > 180.0) {
7078 if (epoch_s2 < epoch_m2) {
7084 rec->epoch[i] = epoch_m2 + ((hd.speed[i] - hd.speed[m2]) /
7085 (hd.speed[s2] - hd.speed[m2])) *
7086 (epoch_s2 - epoch_m2);
7090 for (j = 0; j < INFERRED_DIURNAL_COUNT; ++j) {
7091 if (!strcmp(inferred_diurnal[j], get_constituent(i))) {
7095 (diurnal_coeff[j] / coeff[1]) * rec->amplitude[o1];
7097 if (fabs((NV_FLOAT64)(epoch_k1 - epoch_o1)) > 180.0) {
7098 if (epoch_k1 < epoch_o1) {
7104 rec->epoch[i] = epoch_o1 + ((hd.speed[i] - hd.speed[o1]) /
7105 (hd.speed[k1] - hd.speed[o1])) *
7106 (epoch_k1 - epoch_o1);
7121static NV_U_BYTE mask[8] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe},
7122 notmask[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
7161NV_U_INT32 calculate_bits(NV_U_INT32 value) {
7162 NV_U_INT32 bits = 32;
7163 NV_U_INT32 theBit = 0x80000000;
7165 while (value < theBit) {
7200void bit_pack(NV_U_BYTE buffer[], NV_U_INT32 start, NV_U_INT32 numbits,
7202 NV_INT32 start_byte, end_byte, start_bit, end_bit, i;
7204 i = start + numbits;
7210 start_byte = start >> 3;
7217 start_bit = start & 7;
7222 i = end_byte - start_byte - 1;
7226 if (start_byte == end_byte) {
7231 buffer[start_byte] &= mask[start_bit] | notmask[end_bit];
7237 buffer[start_byte] |=
7238 (value << (8 - end_bit)) & (notmask[start_bit] & mask[end_bit]);
7244#pragma GCC diagnostic push
7245#pragma GCC diagnostic ignored "-Warray-bounds"
7250 buffer[start_byte] &= mask[start_bit];
7258 buffer[start_byte++] |=
7259 (value >> (numbits - (8 - start_bit))) & notmask[start_bit];
7266 buffer[start_byte] &= 0;
7270 buffer[start_byte++] |= (value >> ((i << 3) + end_bit)) & 255;
7275 buffer[start_byte] &= notmask[end_bit];
7281 buffer[start_byte] |= (value << (8 - end_bit));
7282#pragma GCC diagnostic pop
7312NV_U_INT32 bit_unpack(NV_U_BYTE buffer[], NV_U_INT32 start,
7313 NV_U_INT32 numbits) {
7314 NV_INT32 start_byte, end_byte, start_bit, end_bit, i;
7317 i = start + numbits;
7323 start_byte = start >> 3;
7330 start_bit = start & 7;
7335 i = end_byte - start_byte - 1;
7339 if (start_byte == end_byte) {
7343 (NV_U_INT32)buffer[start_byte] & (notmask[start_bit] & mask[end_bit]);
7347 value >>= (8 - end_bit);
7356 value = (NV_U_INT32)(buffer[start_byte++] & notmask[start_bit])
7357 << (numbits - (8 - start_bit));
7364 value += (NV_U_INT32)buffer[start_byte++] << ((i << 3) + end_bit);
7369 if (mask[end_bit]) {
7371 (NV_U_INT32)(buffer[start_byte] & mask[end_bit]) >> (8 - end_bit);
7404NV_INT32 signed_bit_unpack(NV_U_BYTE buffer[], NV_U_INT32 start,
7405 NV_U_INT32 numbits) {
7406 static NV_INT32 extend_mask = 0x7fffffff;
7410 assert(numbits > 0);
7412 value = bit_unpack(buffer, start, numbits);
7414 if (value & (1 << (numbits - 1))) value |= (extend_mask << numbits);
Represents an index entry for tidal and current data.
int have_offsets
Flag indicating presence of time/height offsets.
time_t epoch
Epoch time for the station.
int IDX_time_zone
Station timezone offset from UTC (in minutes)
char IDX_type
Entry type identifier "TCtcIUu".
int num_nodes
Number of nodes in harmonic analysis.
float IDX_lt_off
Low tide height offset.
TCDataSource * pDataSource
Pointer to the associated data source.
float IDX_lt_mpy
Low tide height multiplier.
int Valid15
Validity flag for 15-minute interval data.
time_t recent_high_time
Time of the most recent high tide.
int epoch_year
Year of the epoch.
int IDX_flood_dir
Flood current direction (in degrees)
int IDX_Useable
Flag indicating if the entry is usable.
char IDX_station_name[MAXNAMELEN]
Name of the tidal or current station.
float recent_low_level
Most recently calculated low tide level.
int station_tz_offset
Offset in seconds to convert from harmonic data (epochs) to the station time zone.
double max_amplitude
Maximum tidal amplitude.
int first_year
First year of valid data.
double * m_work_buffer
Work buffer for calculations.
int IDX_ht_time_off
High tide time offset (in minutes)
float Dir15
Direction for 15-minute interval data.
float recent_high_level
Most recently calculated high tide level.
double ** m_cst_nodes
2D array of constituent nodes
int IDX_ebb_dir
Ebb current direction (in degrees)
double ** m_cst_epochs
2D array of constituent epochs
float IDX_ht_mpy
High tide height multiplier.
int current_depth
Depth for current stations.
double IDX_lat
Latitude of the station (in degrees, +North)
double IDX_lon
Longitude of the station (in degrees, +East)
bool Ret15
Return flag for 15-minute interval data.
bool b_skipTooDeep
Flag to skip processing if depth exceeds limit.
int num_epochs
Number of epochs in harmonic data.
double * m_cst_speeds
Array of constituent speeds.
Station_Data * pref_sta_data
Pointer to the reference station data.
int IDX_lt_time_off
Low tide time offset (in minutes)
time_t recent_highlow_calc_time
Timestamp of the most recent high/low calculation.
int num_csts
Number of harmonic constituents.
time_t recent_low_time
Time of the most recent low tide.
float IDX_ht_off
High tide height offset.
int IDX_rec_num
Record number for multiple entries with same name.
float Value15
Value for 15-minute interval data.
General purpose GUI support.
Enhanced logging interface on top of wx/log.h.
std::string tolower(const std::string &input)
Return copy of s with all characters converted to lower case.
Runtime representation of a plugin block.