30#include <wx/hashmap.h>
40#include "model/georef.h"
51time_t s_next_epoch = TIDE_BAD_TIME;
52time_t s_this_epoch = TIDE_BAD_TIME;
55double time2dt_tide(time_t t,
int deriv,
IDX_entry *pIDX);
56int yearoftimet(time_t t);
57void happy_new_year(
IDX_entry *pIDX,
int new_year);
60double time2tide(time_t t,
IDX_entry *pIDX) {
return time2dt_tide(t, 0, pIDX); }
66double BOGUS_amplitude(
double mpy,
IDX_entry *pIDX) {
69 if (!pmsd->have_BOGUS)
80double time2atide(time_t t,
IDX_entry *pIDX) {
81 return BOGUS_amplitude(time2tide(t, pIDX), pIDX) + pIDX->
pref_sta_data->DATUM;
92int next_big_event(time_t *tm,
IDX_entry *pIDX) {
94 int flags = 0, slope = 0;
95 p = time2atide(*tm, pIDX);
97 q = time2atide(*tm, pIDX);
101 if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
103 flags |= (1 << slope);
117 if ((p > marklev && q <= marklev) || (p < marklev && q >= marklev)) {
133 q = time2atide(*tm, pIDX);
134 if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
136 flags |= (1 << slope);
148 if (flags < 4) *tm -= 60;
152 q = time2atide(*tm, pIDX);
161double time2mean(time_t t,
IDX_entry *pIDX) {
164 int new_year = yearoftimet(t);
165 if (pIDX->
epoch_year != new_year) happy_new_year(pIDX, new_year);
167 for (a = 0; a < pIDX->
num_csts; a++) {
184double time2asecondary(time_t t,
IDX_entry *pIDX) {
188 if (!(pIDX->
have_offsets))
return time2atide(tadj, pIDX);
195#define intervalwidth 15
196#define stretchfactor 3
198 static time_t lowtime = 0, hightime = 0;
199 static double lowlvl, highlvl;
201 double S, Z, HI, HS, magicnum;
202 time_t interval = 3600 * intervalwidth;
203 long difflow, diffhigh;
204 int badlowflag = 0, badhighflag = 0;
219 Z = time2mean(T, pIDX);
220 S = time2tide(T, pIDX) - Z;
242 difflow = T - lowtime;
244 difflow = lowtime - T;
246 diffhigh = T - hightime;
248 diffhigh = hightime - T;
251 if (difflow > interval * stretchfactor) badlowflag = 1;
252 if (badlowflag || (difflow > interval && S > 0)) {
256 next_big_event(&tt, pIDX);
257 lowlvl = time2tide(tt, pIDX);
259 while (tt < T + interval) {
260 next_big_event(&tt, pIDX);
261 tl = time2tide(tt, pIDX);
262 if (tl < lowlvl && tt < T + interval) {
269 if (diffhigh > interval * stretchfactor) badhighflag = 1;
270 if (badhighflag || (diffhigh > interval && S < 0)) {
274 next_big_event(&tt, pIDX);
275 highlvl = time2tide(tt, pIDX);
277 while (tt < T + interval) {
278 next_big_event(&tt, pIDX);
279 tl = time2tide(tt, pIDX);
280 if (tl > highlvl && tt < T + interval) {
300 magicnum = 0.5 * S / fabs(highlvl - Z);
302 magicnum = 0.5 * S / fabs(lowlvl - Z);
306 HI = time2tide(T, pIDX);
309 double ht_off, lt_off;
322 double RH = 1.0, RL = 1.0, HH = 0.0, HL = 0.0;
331 HS = HI * ((RH + RL) / 2 + (RH - RL) * magicnum) + (HH + HL) / 2 +
332 (HH - HL) * magicnum;
386double _time2dt_tide(time_t t,
int deriv,
IDX_entry *pIDX) {
387 double dt_tide = 0.0;
391 tempd = M_PI / 2.0 * deriv;
392 for (a = 0; a < pIDX->
num_csts; a++) {
399 for (b = deriv; b > 0; b--) term *= pIDX->
m_cst_speeds[a];
422static double blend_weight(
double x,
int deriv) {
425 if (x2 >= 1.0)
return deriv == 0 && x > 0.0 ? 1.0 : 0.0;
429 return ((3.0 * x2 - 10.0) * x2 + 15.0) * x / 16.0 + 0.5;
431 return ((x2 - 2.0) * x2 + 1.0) * (15.0 / 16.0);
433 return (x2 - 1.0) * x * (15.0 / 4.0);
442double blend_tide(time_t t,
unsigned int deriv,
int first_year,
double blend,
444 double fl[TIDE_MAX_DERIV + 1];
445 double fr[TIDE_MAX_DERIV + 1];
447 double w[TIDE_MAX_DERIV + 1];
456 int year = yearoftimet(t);
457 if (year == first_year + 1)
459 else if (year != first_year)
460 happy_new_year(pIDX, first_year);
461 for (n = 0; n <= deriv; n++) fp[n] = _time2dt_tide(t, n, pIDX);
468 happy_new_year(pIDX, first_year + 1);
471 happy_new_year(pIDX, first_year);
474 for (n = 0; n <= deriv; n++) {
475 fp[n] = _time2dt_tide(t, n, pIDX);
476 w[n] = blend_weight(blend, n);
484 for (n = 0; n <= deriv; n++) {
485 f += fact * w[n] * (fr[deriv - n] - fl[deriv - n]);
486 fact *= (double)(deriv - n) / (n + 1) * (1.0 / TIDE_BLEND_TIME);
488 printf(
" %ld %g %g %g %g\n", (
long)t, blend, fr[0], fl[0], f);
492double time2dt_tide(time_t t,
int deriv,
IDX_entry *pIDX) {
494 int yott = yearoftimet(t);
498 if (new_year != s_this_year) {
500 set_epoch(pIDX, new_year + 1);
501 s_next_epoch = pIDX->
epoch;
503 s_next_epoch = TIDE_BAD_TIME;
505 happy_new_year(pIDX, s_this_year = new_year);
506 s_this_epoch = pIDX->
epoch;
513 if (t - s_this_epoch <= TIDE_BLEND_TIME && s_this_year > pIDX->
first_year)
514 return blend_tide(t, deriv, s_this_year - 1,
515 (
double)(t - s_this_epoch) / TIDE_BLEND_TIME, pIDX);
516 else if (s_next_epoch - t <= TIDE_BLEND_TIME &&
518 return blend_tide(t, deriv, s_this_year,
519 -(
double)(s_next_epoch - t) / TIDE_BLEND_TIME, pIDX);
524 if (pIDX->
epoch_year != new_year) happy_new_year(pIDX, new_year);
526 return _time2dt_tide(t, deriv, pIDX);
531void figure_max_amplitude(
IDX_entry *pIDX) {
536 double year_amp = 0.0;
538 for (a = 0; a < pIDX->
num_csts; a++)
546void figure_multipliers(
IDX_entry *pIDX,
int year) {
549 figure_max_amplitude(pIDX);
550 for (a = 0; a < pIDX->
num_csts; a++) {
558#define compare_int(a, b) (((int)(a)) - ((int)(b)))
559int compare_tm(
struct tm *a,
struct tm *b) {
567 temp = compare_int(a->tm_year, b->tm_year);
568 if (temp)
return temp;
569 temp = compare_int(a->tm_mon, b->tm_mon);
570 if (temp)
return temp;
571 temp = compare_int(a->tm_mday, b->tm_mday);
572 if (temp)
return temp;
573 temp = compare_int(a->tm_hour, b->tm_hour);
574 if (temp)
return temp;
575 temp = compare_int(a->tm_min, b->tm_min);
576 if (temp)
return temp;
577 return compare_int(a->tm_sec, b->tm_sec);
583time_t tm2gmt(
struct tm *ht) {
584 time_t guess, newguess, thebit;
585 int loopcounter, compare;
589 loopcounter = (
sizeof(time_t) * 8) - 1;
590 thebit = ((time_t)1) << (loopcounter - 1);
595 if ((
signed long)thebit < (time_t)(0)) {
598 thebit = ((time_t)1) << (loopcounter - 1);
601 for (; loopcounter; loopcounter--) {
602 newguess = guess | thebit;
603 gt = gmtime(&newguess);
605 compare = compare_tm(gt, ht);
606 if (compare <= 0) guess = newguess;
614int yearoftimet(time_t t) {
return ((gmtime(&t))->tm_year) + 1900; }
617void set_epoch(
IDX_entry *pIDX,
int year) {
620 ht.tm_year = year - 1900;
621 ht.tm_sec = ht.tm_min = ht.tm_hour = ht.tm_mon = 0;
623 pIDX->
epoch = tm2gmt(&ht);
627void happy_new_year(
IDX_entry *pIDX,
int new_year) {
629 figure_multipliers(pIDX, new_year);
630 set_epoch(pIDX, new_year);
636TCMgr::~TCMgr() { PurgeData(); }
638void TCMgr::PurgeData() {
639 m_Combined_IDX_array.clear();
642 m_source_array.Clear();
645TC_Error_Code TCMgr::LoadDataSources(std::vector<std::string> &sources) {
649 m_sourcefile_array.clear();
650 m_sourcefile_array = sources;
654 for (
auto src : sources) {
656 TC_Error_Code r = s->LoadData(src);
657 if (r != TC_NO_ERROR) {
659 msg.Printf(
" Error loading Tide/Currect data source %s ", src.c_str());
660 if (r == TC_FILE_NOT_FOUND)
661 msg +=
"Error Code: TC_FILE_NOT_FOUND";
664 msg1.Printf(
"Error code: %d", r);
670 m_source_array.Add(s);
672 for (
int k = 0; k < s->GetMaxIndex(); k++) {
676 m_Combined_IDX_array.push_back(pIDX);
683 if (m_Combined_IDX_array.empty())
685 NULL, _(
"It seems you have no tide/current harmonic data installed."),
686 _(
"OpenCPN Info"), wxOK | wxCENTER);
688 ScrubCurrentDepths();
692void TCMgr::ScrubCurrentDepths() {
697 WX_DECLARE_STRING_HASH_MAP(
int, currentDepth_index_hash);
699 currentDepth_index_hash hash1;
701 for (
int i = 1; i < Get_max_IDX() + 1; i++) {
716 currentDepth_index_hash::iterator it = hash1.find(key1);
717 if (it == hash1.end()) {
726 if (depth_a < depth_b) {
738const IDX_entry *TCMgr::GetIDX_entry(
int index)
const {
739 if ((
unsigned int)index < m_Combined_IDX_array.size())
740 return m_Combined_IDX_array[index];
745bool TCMgr::GetTideOrCurrent(time_t t,
int idx,
float &tcvalue,
float &dir) {
751 IDX_entry *pIDX = m_Combined_IDX_array[idx];
766 if (pIDX->
pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
return false;
770 int yott = yearoftimet(t);
772 happy_new_year(pIDX, yott);
776 double level = time2asecondary(t + (00 * 60), pIDX);
787extern wxDateTime gTimeSource;
789bool TCMgr::GetTideOrCurrent15(time_t t_d,
int idx,
float &tcvalue,
float &dir,
792 IDX_entry *pIDX = m_Combined_IDX_array[idx];
801 wxDateTime this_now = gTimeSource;
802 if (this_now.IsValid() ==
false) this_now = wxDateTime::Now();
803 wxDateTime this_gmt = this_now.ToGMT();
804 wxTimeSpan diff = this_gmt.Subtract(this_now);
805 int diff_mins = diff.GetMinutes();
808 if (this_now.IsDST()) station_offset += 60;
809 int corr_mins = station_offset - diff_mins;
811 wxDateTime today_00 = this_now;
812 today_00.ResetTime();
813 int t_today_00 = today_00.GetTicks();
814 int t_today_00_at_station = t_today_00 - (corr_mins * 60);
817 this_gmt.GetTicks() - (station_offset * 60) + (corr_mins * 60);
819 int t_mins = (t_at_station - t_today_00_at_station) / 60;
820 int t_15s = t_mins / 15;
824 int tref1 = t_today_00_at_station + t_15s * 15 * 60;
831 int tref = t_today_00_at_station + t_15s * 15 * 60;
832 ret = GetTideOrCurrent(tref, idx, tcvalue, dir);
837 pIDX->
Ret15 = !(ret == 0);
845 int tref = t_today_00_at_station + t_15s * 15 * 60;
846 ret = GetTideOrCurrent(tref, idx, tcvalue, dir);
851 pIDX->
Ret15 = !(ret == 0);
858bool TCMgr::GetTideFlowSens(time_t t,
int sch_step,
int idx,
float &tcvalue_now,
859 float &tcvalue_prev,
bool &w_t) {
866 IDX_entry *pIDX = m_Combined_IDX_array[idx];
868 if (!pIDX)
return false;
873 if (pIDX->
pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
return false;
877 int yott = yearoftimet(t);
878 happy_new_year(pIDX, yott);
882 tcvalue_now = time2asecondary(t, pIDX);
883 tcvalue_prev = time2asecondary(t + sch_step, pIDX);
886 tcvalue_now > tcvalue_prev;
891void TCMgr::GetHightOrLowTide(time_t t,
int sch_step_1,
int sch_step_2,
892 float tide_val,
bool w_t,
int idx,
float &tcvalue,
899 IDX_entry *pIDX = m_Combined_IDX_array[idx];
906 if (pIDX->
pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
return;
922 int yott = yearoftimet(t);
923 happy_new_year(pIDX, yott);
926 double newval = tide_val;
927 double oldval = (w_t) ? newval - 1 : newval + 1;
931 while ((newval > oldval) == w_t)
935 ttt = t + (sch_step_1 * j);
936 newval = time2asecondary(ttt, pIDX);
938 oldval = (w_t) ? newval - 1 : newval + 1;
939 while ((newval > oldval) == w_t)
943 ttt = t + (sch_step_1 * j) - (sch_step_2 * k);
944 newval = time2asecondary(ttt, pIDX);
947 tctime = ttt + sch_step_2;
966int TCMgr::GetNextBigEvent(time_t *tm,
int idx) {
971 int flags = 0, slope = 0;
972 ret = GetTideOrCurrent(*tm, idx, tcvalue[0], dir);
975 ret = GetTideOrCurrent(*tm, idx, tcvalue[0], dir);
978 if (p < q) slope = 1;
980 if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
982 flags |= (1 << slope);
986 if (flags < 4) *tm -= 60;
990 ret = GetTideOrCurrent(*tm, idx, tcvalue[0], dir);
997std::wstring TCMgr::GetTidalEventStr(
int station_id, wxDateTime ref_dt,
998 double lat,
double lon,
int dt_type) {
1000 time_t dtmtt = ref_dt.FromUTC().GetTicks();
1001 int event = GetNextBigEvent(&dtmtt, station_id);
1002 wxDateTime event_dt = wxDateTime(dtmtt).MakeUTC();
1004 std::wstring event_str;
1006 event_str = _(
"LW").ToStdWstring();
1007 }
else if (event == 2) {
1008 event_str = _(
"HW").ToStdWstring();
1010 event_str = _(
"Unavailable").ToStdWstring();
1014 event_str.append(L
": ");
1016 toUsrDateTime(event_dt, dt_type, lon).FormatISOCombined(
' '));
1022std::map<double, const IDX_entry *> TCMgr::GetStationsForLL(
double xlat,
1023 double xlon)
const {
1024 std::map<double, const IDX_entry *> x;
1027 for (
int j = 1; j < Get_max_IDX() + 1; j++) {
1028 lpIDX = GetIDX_entry(j);
1032 if (type ==
't' || type ==
'T') {
1034 DistanceBearingMercator(xlat, xlon, lpIDX->
IDX_lat, lpIDX->
IDX_lon, &brg,
1036 x.emplace(std::make_pair(dist, lpIDX));
1043int TCMgr::GetStationIDXbyName(
const wxString &prefix,
double xlat,
1044 double xlon)
const {
1048 double distx = 100000.;
1050 int jmax = Get_max_IDX();
1052 for (
int j = 1; j < Get_max_IDX() + 1; j++) {
1053 lpIDX = GetIDX_entry(j);
1057 if (((type ==
't') || (type ==
'T'))
1058 && (locnx.StartsWith(prefix))) {
1060 DistanceBearingMercator(xlat, xlon, lpIDX->
IDX_lat, lpIDX->
IDX_lon, &brg,
1072int TCMgr::GetStationIDXbyNameType(
const wxString &prefix,
double xlat,
1073 double xlon,
char type)
const {
1077 double distx = 100000.;
1081 int jmax = Get_max_IDX();
1083 for (
int j = 1; j < Get_max_IDX() + 1; j++) {
1084 lpIDX = GetIDX_entry(j);
1088 if ((type == typep) && (locnx.StartsWith(prefix))) {
1090 DistanceBearingMercator(xlat, xlon, lpIDX->
IDX_lat, lpIDX->
IDX_lon, &brg,
1116#define DEFAULT_HEADER_SIZE 4096
1117#define DEFAULT_NUMBER_OF_RECORDS 0
1118#define DEFAULT_LEVEL_UNIT_TYPES 5
1119#define DEFAULT_DIR_UNIT_TYPES 3
1120#define DEFAULT_RESTRICTION_TYPES 2
1121#define DEFAULT_RESTRICTION_BITS 4
1122#define DEFAULT_TZFILES 406
1123#define DEFAULT_TZFILE_BITS 10
1124#define DEFAULT_COUNTRIES 240
1125#define DEFAULT_COUNTRY_BITS 9
1126#define DEFAULT_DATUM_TYPES 61
1127#define DEFAULT_DATUM_BITS 7
1128#define DEFAULT_LEGALESES 1
1129#define DEFAULT_LEGALESE_BITS 4
1130#define DEFAULT_SPEED_SCALE 10000000
1131#define DEFAULT_EQUILIBRIUM_SCALE 100
1132#define DEFAULT_NODE_SCALE 10000
1133#define DEFAULT_AMPLITUDE_BITS 19
1134#define DEFAULT_AMPLITUDE_SCALE 10000
1135#define DEFAULT_EPOCH_BITS 16
1136#define DEFAULT_EPOCH_SCALE 100
1137#define DEFAULT_RECORD_TYPE_BITS 4
1138#define DEFAULT_LATITUDE_BITS 25
1139#define DEFAULT_LATITUDE_SCALE 100000
1140#define DEFAULT_LONGITUDE_BITS 26
1141#define DEFAULT_LONGITUDE_SCALE 100000
1142#define DEFAULT_RECORD_SIZE_BITS 16
1143#define DEFAULT_STATION_BITS 18
1144#define DEFAULT_DATUM_OFFSET_BITS 28
1145#define DEFAULT_DATUM_OFFSET_SCALE 10000
1146#define DEFAULT_DATE_BITS 27
1147#define DEFAULT_MONTHS_ON_STATION_BITS 10
1148#define DEFAULT_CONFIDENCE_VALUE_BITS 4
1149#define DEFAULT_NUMBER_OF_CONSTITUENTS_BITS 8
1150#define DEFAULT_TIME_BITS 13
1151#define DEFAULT_LEVEL_ADD_BITS 17
1152#define DEFAULT_LEVEL_ADD_SCALE 1000
1153#define DEFAULT_LEVEL_MULTIPLY_BITS 16
1154#define DEFAULT_LEVEL_MULTIPLY_SCALE 1000
1155#define DEFAULT_DIRECTION_BITS 9
1156#define DEFAULT_CONSTITUENT_SIZE 10
1157#define DEFAULT_LEVEL_UNIT_SIZE 15
1158#define DEFAULT_DIR_UNIT_SIZE 15
1159#define DEFAULT_RESTRICTION_SIZE 30
1160#define DEFAULT_DATUM_SIZE 70
1161#define DEFAULT_LEGALESE_SIZE 70
1162#define DEFAULT_TZFILE_SIZE 30
1163#define DEFAULT_COUNTRY_SIZE 50
1167#define INFERRED_SEMI_DIURNAL_COUNT 10
1168#define INFERRED_DIURNAL_COUNT 10
1171#pragma warning(disable : 4305)
1174const NV_CHAR *inferred_semi_diurnal[INFERRED_SEMI_DIURNAL_COUNT] = {
1175 "N2",
"NU2",
"MU2",
"2N2",
"LDA2",
"T2",
"R2",
"L2",
"K2",
"KJ2"};
1176const NV_CHAR *inferred_diurnal[INFERRED_DIURNAL_COUNT] = {
1177 "OO1",
"M1",
"J1",
"RHO1",
"Q1",
"2Q1",
"P1",
"PI1",
"PHI1",
"PSI1"};
1178NV_FLOAT32 semi_diurnal_coeff[INFERRED_SEMI_DIURNAL_COUNT] = {
1179 .1759, .0341, .0219, .0235, .0066, .0248, .0035, .0251, .1151, .0064};
1180NV_FLOAT32 diurnal_coeff[INFERRED_DIURNAL_COUNT] = {
1181 .0163, .0209, .0297, .0142, .0730, .0097, .1755, .0103, .0076, .0042};
1185NV_FLOAT32 coeff[2] = {.9085, .3771};
1195NV_CHAR level_unit[DEFAULT_LEVEL_UNIT_TYPES][DEFAULT_LEVEL_UNIT_SIZE] = {
1196 "Unknown",
"feet",
"meters",
"knots",
"knots^2"};
1200NV_CHAR dir_unit[DEFAULT_DIR_UNIT_TYPES][DEFAULT_DIR_UNIT_SIZE] = {
1201 "Unknown",
"degrees true",
"degrees"};
1205NV_CHAR restriction[DEFAULT_RESTRICTION_TYPES][DEFAULT_RESTRICTION_SIZE] = {
1206 "Public Domain",
"DoD/DoD Contractors Only"};
1210NV_CHAR legalese[DEFAULT_LEGALESES][DEFAULT_LEGALESE_SIZE] = {
"NULL"};
1214NV_CHAR datum[DEFAULT_DATUM_TYPES][DEFAULT_DATUM_SIZE] = {
1218 "Mean Lower Low Water",
1220 "Mean Higher High Water",
1221 "Mean Lower High Water",
1222 "Mean Higher Low Water",
1223 "Mean Low Water Springs",
1224 "Mean Lower Low Water Springs",
1225 "Mean Low Water Neaps",
1226 "Mean High Water Neaps",
1227 "Mean High Water Springs",
1228 "Mean Higher High Water Springs",
1229 "Indian Spring Low Water",
1230 "Equatorial Spring Low Water",
1231 "Lowest Normal Low Water",
1233 "Lowest Possible Low Water",
1234 "Lowest Astronomical Tide",
1235 "International Great Lakes Datum(1955)",
1236 "Lower Low Water, Large Tide",
1237 "Lowest Normal Tide",
1238 "Higher High Water, Large Tide",
1240 "Higher High Water, Mean Tide",
1241 "Lower Low Water, Mean Tide",
1243 "World Geodetic System (1984)",
1244 "National Geodetic Vertical Datum",
1245 "Gulf Coast Low Water Datum",
1246 "Approximate Level of Mean Sea Level",
1247 "Approximate Level of Mean Low Water",
1248 "Approximate Level of Mean Lower Low Water",
1249 "Approximate Level of Mean High Water",
1250 "Approximate Level of Mean Higher High Water",
1251 "Approximate Level of Mean Lower High Water",
1252 "Approximate Level of Mean Higher Low Water",
1253 "Approximate Level of Mean Low Water Springs",
1254 "Approximate Level of Mean Lower Low Water Springs",
1255 "Approximate Level of Mean Low Water Neaps",
1256 "Approximate Level of Mean High Water Neaps",
1257 "Approximate Level of Mean High Water Springs",
1258 "Approximate Level of Mean Higher High Water Springs",
1259 "Approximate Level of Indian Spring Low Water",
1260 "Approximate Level of Equatorial Spring Low Water",
1261 "Approximate Level of Lowest Normal Low Water",
1262 "Approximate Level of Lowest Low Water",
1263 "Approximate Level of Lowest Possible Low Water",
1264 "Approximate Level of Lowest Astronomical Tide",
1265 "Approximate Level of International Great Lakes Datum (1955)",
1266 "Approximate Level of Lower Low Water, Large Tide",
1267 "Approximate Level of Lowest Normal Tide",
1268 "Approximate Level of Higher High Water, Large Tide",
1269 "Approximate Level of Mean Water Level",
1270 "Approximate Level of Higher High Water, Mean Tide",
1271 "Approximate Level of Lower Low Water, Mean Tide",
1272 "Approximate Level of Mean Tide Level",
1273 "Approximate Level of World Geodetic System (1984)",
1274 "Approximate Level of National Geodetic Vertical Datum",
1275 "Approximate Level of Gulf Coast Low Water Datum"};
1279NV_CHAR country[DEFAULT_COUNTRIES][DEFAULT_COUNTRY_SIZE] = {
1288 "Antigua & Barbuda",
1306 "Bosnia & Herzegovina",
1311 "British Indian Ocean Territory",
1321 "Central African Rep.",
1326 "Cocos (Keeling) Islands",
1329 "Congo (Dem. Rep.)",
1341 "Dominican Republic",
1346 "Equatorial Guinea",
1357 "French Southern & Antarctic Lands",
1374 "Heard Island & McDonald Islands",
1431 "Netherlands Antilles",
1439 "Northern Mariana Islands",
1462 "Sao Tome & Principe",
1473 "South Georgia & the South Sandwich Islands",
1479 "St Pierre & Miquelon",
1483 "Svalbard & Jan Mayen",
1495 "Trinidad & Tobago",
1499 "Turks & Caicos Is",
1503 "United Arab Emirates",
1506 "US minor outlying islands",
1512 "Virgin Islands (UK)",
1513 "Virgin Islands (US)",
1523NV_CHAR tzfile[DEFAULT_TZFILES][DEFAULT_TZFILE_SIZE] = {
1527 ":Africa/Addis_Ababa",
1535 ":Africa/Brazzaville",
1536 ":Africa/Bujumbura",
1538 ":Africa/Casablanca",
1542 ":Africa/Dar_es_Salaam",
1549 ":Africa/Johannesburg",
1555 ":Africa/Libreville",
1558 ":Africa/Lubumbashi",
1564 ":Africa/Mogadishu",
1569 ":Africa/Nouakchott",
1570 ":Africa/Ouagadougou",
1571 ":Africa/Porto-Novo",
1578 ":America/Anchorage",
1579 ":America/Anguilla",
1581 ":America/Araguaina",
1583 ":America/Asuncion",
1585 ":America/Barbados",
1588 ":America/Boa_Vista",
1591 ":America/Buenos_Aires",
1592 ":America/Cambridge_Bay",
1595 ":America/Catamarca",
1599 ":America/Chihuahua",
1601 ":America/Costa_Rica",
1604 ":America/Danmarkshavn",
1606 ":America/Dawson_Creek",
1609 ":America/Dominica",
1610 ":America/Edmonton",
1611 ":America/Eirunepe",
1612 ":America/El_Salvador",
1613 ":America/Ensenada",
1614 ":America/Fortaleza",
1615 ":America/Glace_Bay",
1617 ":America/Goose_Bay",
1618 ":America/Grand_Turk",
1620 ":America/Guadeloupe",
1621 ":America/Guatemala",
1622 ":America/Guayaquil",
1626 ":America/Hermosillo",
1627 ":America/Indiana/Knox",
1628 ":America/Indiana/Marengo",
1629 ":America/Indianapolis",
1630 ":America/Indiana/Vevay",
1636 ":America/Kentucky/Monticello",
1639 ":America/Los_Angeles",
1640 ":America/Louisville",
1644 ":America/Martinique",
1645 ":America/Mazatlan",
1647 ":America/Menominee",
1649 ":America/Mexico_City",
1650 ":America/Miquelon",
1651 ":America/Monterrey",
1652 ":America/Montevideo",
1653 ":America/Montreal",
1654 ":America/Montserrat",
1656 ":America/New_York",
1660 ":America/North_Dakota/Center",
1662 ":America/Pangnirtung",
1663 ":America/Paramaribo",
1665 ":America/Port-au-Prince",
1666 ":America/Port_of_Spain",
1667 ":America/Porto_Velho",
1668 ":America/Puerto_Rico",
1669 ":America/Rainy_River",
1670 ":America/Rankin_Inlet",
1673 ":America/Rio_Branco",
1674 ":America/Santiago",
1675 ":America/Santo_Domingo",
1676 ":America/Sao_Paulo",
1677 ":America/Scoresbysund",
1678 ":America/Shiprock",
1679 ":America/St_Johns",
1680 ":America/St_Kitts",
1681 ":America/St_Lucia",
1682 ":America/St_Thomas",
1683 ":America/St_Vincent",
1684 ":America/Swift_Current",
1685 ":America/Tegucigalpa",
1687 ":America/Thunder_Bay",
1690 ":America/Vancouver",
1691 ":America/Whitehorse",
1692 ":America/Winnipeg",
1694 ":America/Yellowknife",
1695 ":Antarctica/Casey",
1696 ":Antarctica/Davis",
1697 ":Antarctica/DumontDUrville",
1698 ":Antarctica/Mawson",
1699 ":Antarctica/McMurdo",
1700 ":Antarctica/Palmer",
1701 ":Antarctica/South_Pole",
1702 ":Antarctica/Syowa",
1703 ":Antarctica/Vostok",
1704 ":Arctic/Longyearbyen",
1741 ":Asia/Krasnoyarsk",
1742 ":Asia/Kuala_Lumpur",
1751 ":Asia/Novosibirsk",
1773 ":Asia/Ulaanbaatar",
1776 ":Asia/Vladivostok",
1778 ":Asia/Yekaterinburg",
1781 ":Atlantic/Bermuda",
1783 ":Atlantic/Cape_Verde",
1785 ":Atlantic/Jan_Mayen",
1786 ":Atlantic/Madeira",
1787 ":Atlantic/Reykjavik",
1788 ":Atlantic/South_Georgia",
1789 ":Atlantic/Stanley",
1790 ":Atlantic/St_Helena",
1791 ":Australia/Adelaide",
1792 ":Australia/Brisbane",
1793 ":Australia/Broken_Hill",
1794 ":Australia/Darwin",
1795 ":Australia/Hobart",
1796 ":Australia/Lindeman",
1797 ":Australia/Lord_Howe",
1798 ":Australia/Melbourne",
1800 ":Australia/Sydney",
1830 ":Europe/Amsterdam",
1836 ":Europe/Bratislava",
1838 ":Europe/Bucharest",
1841 ":Europe/Copenhagen",
1843 ":Europe/Gibraltar",
1846 ":Europe/Kaliningrad",
1849 ":Europe/Ljubljana",
1851 ":Europe/Luxembourg",
1863 ":Europe/San_Marino",
1865 ":Europe/Simferopol",
1868 ":Europe/Stockholm",
1878 ":Europe/Zaporozhye",
1880 ":Indian/Antananarivo",
1882 ":Indian/Christmas",
1885 ":Indian/Kerguelen",
1888 ":Indian/Mauritius",
1892 ":Pacific/Auckland",
1896 ":Pacific/Enderbury",
1899 ":Pacific/Funafuti",
1900 ":Pacific/Galapagos",
1902 ":Pacific/Guadalcanal",
1904 ":Pacific/Honolulu",
1905 ":Pacific/Johnston",
1906 ":Pacific/Kiritimati",
1908 ":Pacific/Kwajalein",
1910 ":Pacific/Marquesas",
1916 ":Pacific/Pago_Pago",
1918 ":Pacific/Pitcairn",
1920 ":Pacific/Port_Moresby",
1921 ":Pacific/Rarotonga",
1925 ":Pacific/Tongatapu",
1940#define require(expr) \
1943 require_expr = (int)(expr); \
1944 assert(require_expr); \
2264NV_U_INT32 calculate_bits(NV_U_INT32 value);
2265void bit_pack(NV_U_BYTE *, NV_U_INT32, NV_U_INT32, NV_INT32);
2266NV_U_INT32 bit_unpack(NV_U_BYTE *, NV_U_INT32, NV_U_INT32);
2267NV_INT32 signed_bit_unpack(NV_U_BYTE buffer[], NV_U_INT32 start,
2268 NV_U_INT32 numbits);
2274 NV_U_INT32 record_size;
2276 NV_INT32 reference_station;
2279 NV_U_BYTE record_type;
2283static FILE *fp = NULL;
2285static NV_BOOL modified = NVFalse;
2286static NV_INT32 current_record, current_index;
2287static NV_CHAR filename[MONOLOGUE_LENGTH];
2297static void chk_fread(
void *ptr,
size_t size,
size_t nmemb, FILE *stream) {
2299 ret = fread(ptr, size, nmemb, stream);
2303 throw std::runtime_error(
"tcmgr file read exception");
2307static void chk_fwrite(
const void *ptr,
size_t size,
size_t nmemb,
2310 ret = fwrite(ptr, size, nmemb, stream);
2315 throw std::runtime_error(
"tcmgr file read exception");
2342 LOG_ERROR(
"\n\nRecord number = %d\n", rec->header.record_number);
2343 LOG_ERROR(
"Record size = %u\n", rec->header.record_size);
2344 LOG_ERROR(
"Record type = %u\n", rec->header.record_type);
2345 LOG_ERROR(
"Latitude = %f\n", rec->header.latitude);
2346 LOG_ERROR(
"Longitude = %f\n", rec->header.longitude);
2347 LOG_ERROR(
"Reference station = %d\n", rec->header.reference_station);
2348 LOG_ERROR(
"Tzfile = %s\n", get_tzfile(rec->header.tzfile));
2349 LOG_ERROR(
"Name = %s\n", rec->header.name);
2351 LOG_ERROR(
"Country = %s\n", get_country(rec->country));
2352 LOG_ERROR(
"Source = %s\n", rec->source);
2353 LOG_ERROR(
"Restriction = %s\n", get_restriction(rec->restriction));
2354 LOG_ERROR(
"Comments = %s\n", rec->comments);
2355 LOG_ERROR(
"Notes = %s\n", rec->notes);
2356 LOG_ERROR(
"Legalese = %s\n", get_legalese(rec->legalese));
2357 LOG_ERROR(
"Station ID context = %s\n", rec->station_id_context);
2358 LOG_ERROR(
"Station ID = %s\n", rec->station_id);
2359 LOG_ERROR(
"Date imported = %d\n", rec->date_imported);
2360 LOG_ERROR(
"Xfields = %s\n", rec->xfields);
2362 LOG_ERROR(
"Direction units = %s\n", get_dir_units(rec->direction_units));
2363 LOG_ERROR(
"Min direction = %d\n", rec->min_direction);
2364 LOG_ERROR(
"Max direction = %d\n", rec->max_direction);
2365 LOG_ERROR(
"Level units = %s\n", get_level_units(rec->level_units));
2367 if (rec->header.record_type == REFERENCE_STATION) {
2368 LOG_ERROR(
"Datum offset = %f\n", rec->datum_offset);
2369 LOG_ERROR(
"Datum = %s\n", get_datum(rec->datum));
2370 LOG_ERROR(
"Zone offset = %d\n", rec->zone_offset);
2371 LOG_ERROR(
"Expiration date = %d\n", rec->expiration_date);
2372 LOG_ERROR(
"Months on station = %d\n", rec->months_on_station);
2373 LOG_ERROR(
"Last date on station = %d\n", rec->last_date_on_station);
2374 LOG_ERROR(
"Confidence = %d\n", rec->confidence);
2375 for (i = 0; i < hd.pub.constituents; ++i) {
2376 if (rec->amplitude[i] != 0.0 || rec->epoch[i] != 0.0) {
2377 LOG_ERROR(
"Amplitude[%d] = %f\n", i, rec->amplitude[i]);
2378 LOG_ERROR(
"Epoch[%d] = %f\n", i, rec->epoch[i]);
2383 else if (rec->header.record_type == SUBORDINATE_STATION) {
2384 LOG_ERROR(
"Min time add = %d\n", rec->min_time_add);
2385 LOG_ERROR(
"Min level add = %f\n", rec->min_level_add);
2386 LOG_ERROR(
"Min level multiply = %f\n", rec->min_level_multiply);
2387 LOG_ERROR(
"Max time add = %d\n", rec->max_time_add);
2388 LOG_ERROR(
"Max level add = %f\n", rec->max_level_add);
2389 LOG_ERROR(
"Max level multiply = %f\n", rec->max_level_multiply);
2390 LOG_ERROR(
"Flood begins = %d\n", rec->flood_begins);
2391 LOG_ERROR(
"Ebb begins = %d\n", rec->ebb_begins);
2404static void write_protect() {
2405 if (hd.pub.major_rev < LIBTCD_MAJOR_REV) {
2407 "libtcd error: can't modify TCD files created by earlier version. "
2408 "Use\nrewrite_tide_db to upgrade the TCD file.\n");
2432const NV_CHAR *get_country(NV_INT32 num) {
2435 "libtcd error: attempt to access database when database not open\n");
2438 if (num >= 0 && num < (NV_INT32)hd.pub.countries)
return (hd.country[num]);
2459const NV_CHAR *get_tzfile(NV_INT32 num) {
2462 "libtcd error: attempt to access database when database not open\n");
2465 if (num >= 0 && num < (NV_INT32)hd.pub.tzfiles)
return (hd.tzfile[num]);
2486const NV_CHAR *get_station(NV_INT32 num) {
2489 "libtcd error: attempt to access database when database not open\n");
2492 if (num >= 0 && num < (NV_INT32)hd.pub.number_of_records)
2493 return (tindex[num].name);
2515const NV_CHAR *get_constituent(NV_INT32 num) {
2518 "libtcd error: attempt to access database when database not open\n");
2521 if (num >= 0 && num < (NV_INT32)hd.pub.constituents)
2522 return (hd.constituent[num]);
2544const NV_CHAR *get_level_units(NV_INT32 num) {
2547 "libtcd error: attempt to access database when database not open\n");
2550 if (num >= 0 && num < (NV_INT32)hd.pub.level_unit_types)
2551 return (hd.level_unit[num]);
2573const NV_CHAR *get_dir_units(NV_INT32 num) {
2576 "libtcd error: attempt to access database when database not open\n");
2579 if (num >= 0 && num < (NV_INT32)hd.pub.dir_unit_types)
2580 return (hd.dir_unit[num]);
2602const NV_CHAR *get_restriction(NV_INT32 num) {
2605 "libtcd error: attempt to access database when database not open\n");
2608 if (num >= 0 && num < (NV_INT32)hd.pub.restriction_types)
2609 return (hd.restriction[num]);
2632NV_CHAR *get_pedigree(NV_INT32 num) {
return "Unknown"; }
2652const NV_CHAR *get_datum(NV_INT32 num) {
2655 "libtcd error: attempt to access database when database not open\n");
2658 if (num >= 0 && num < (NV_INT32)hd.pub.datum_types)
return (hd.datum[num]);
2665const NV_CHAR *get_legalese(NV_INT32 num) {
2668 "libtcd error: attempt to access database when database not open\n");
2671 if (num >= 0 && num < (NV_INT32)hd.pub.legaleses)
return (hd.legalese[num]);
2693NV_FLOAT64 get_speed(NV_INT32 num) {
2696 "libtcd error: attempt to access database when database not open\n");
2699 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
2700 return hd.speed[num];
2722NV_FLOAT32 get_equilibrium(NV_INT32 num, NV_INT32 year) {
2725 "libtcd error: attempt to access database when database not open\n");
2728 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
2729 year < (NV_INT32)hd.pub.number_of_years);
2730 return hd.equilibrium[num][year];
2736NV_FLOAT32 *get_equilibriums(NV_INT32 num) {
2739 "libtcd error: attempt to access database when database not open\n");
2742 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
2743 return hd.equilibrium[num];
2765NV_FLOAT32 get_node_factor(NV_INT32 num, NV_INT32 year) {
2768 "libtcd error: attempt to access database when database not open\n");
2771 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
2772 year < (NV_INT32)hd.pub.number_of_years);
2773 return hd.node_factor[num][year];
2779NV_FLOAT32 *get_node_factors(NV_INT32 num) {
2782 "libtcd error: attempt to access database when database not open\n");
2785 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
2786 return hd.node_factor[num];
2815 "libtcd error: attempt to access database when database not open\n");
2819 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return (NVFalse);
2823 rec->record_number = num;
2824 rec->record_size = tindex[num].record_size;
2825 rec->record_type = tindex[num].record_type;
2826 rec->latitude = (NV_FLOAT64)tindex[num].lat / hd.latitude_scale;
2827 rec->longitude = (NV_FLOAT64)tindex[num].lon / hd.longitude_scale;
2828 rec->reference_station = tindex[num].reference_station;
2829 rec->tzfile = tindex[num].tzfile;
2830 strcpy(rec->name, tindex[num].name);
2832 current_index = num;
2856 if (!get_partial_tide_record(current_index + 1, rec))
return (-1);
2858 return (current_index);
2881NV_INT32 get_nearest_partial_tide_record(NV_FLOAT64 lat, NV_FLOAT64 lon,
2883 NV_FLOAT64 diff, min_diff, lt, ln;
2884 NV_U_INT32 i, shortest = 0;
2886 min_diff = 999999999.9;
2887 for (i = 0; i < hd.pub.number_of_records; ++i) {
2888 lt = (NV_FLOAT64)tindex[i].lat / hd.latitude_scale;
2889 ln = (NV_FLOAT64)tindex[i].lon / hd.longitude_scale;
2891 diff = sqrt((lat - lt) * (lat - lt) + (lon - ln) * (lon - ln));
2893 if (diff < min_diff) {
2899 if (!get_partial_tide_record(shortest, rec))
return (-1);
2921NV_INT32 get_time(
const NV_CHAR *
string) {
2922 NV_INT32 hour, minute, hhmm;
2925 sscanf(
string,
"%d:%d", &hour, &minute);
2929 if (
string[0] ==
'-') {
2930 if (hour < 0) hour = -hour;
2932 hhmm = -(hour * 100 + minute);
2934 hhmm = hour * 100 + minute;
2958NV_CHAR *ret_time(NV_INT32 time) {
2959 NV_INT32 hour, minute;
2960 static NV_CHAR tname[16];
2962 hour = abs(time) / 100;
2963 assert(hour <= 99999 && hour >= -99999);
2964 minute = abs(time) % 100;
2967 sprintf(tname,
"-%02d:%02d", hour, minute);
2969 sprintf(tname,
"+%02d:%02d", hour, minute);
2978NV_CHAR *ret_time_neat(NV_INT32 time) {
2979 NV_INT32 hour, minute;
2980 static NV_CHAR tname[16];
2982 hour = abs(time) / 100;
2983 assert(hour <= 99999 && hour >= -99999);
2984 minute = abs(time) % 100;
2987 sprintf(tname,
"-%d:%02d", hour, minute);
2989 sprintf(tname,
"+%d:%02d", hour, minute);
2991 strcpy(tname,
"0:00");
2999NV_CHAR *ret_date(NV_U_INT32 date) {
3000 static NV_CHAR tname[30];
3002 strcpy(tname,
"NULL");
3009 sprintf(tname,
"%4u-%02u-%02u", y, m, d);
3033 "libtcd error: attempt to access database when database not open\n");
3043static void boundscheck_monologue(
const NV_CHAR *
string) {
3045 if (strlen(
string) >= MONOLOGUE_LENGTH) {
3059static void boundscheck_oneliner(
const NV_CHAR *
string) {
3061 if (strlen(
string) >= ONELINER_LENGTH) {
3089static NV_CHAR *clip_string(
const NV_CHAR *
string) {
3090 static NV_CHAR new_string[MONOLOGUE_LENGTH];
3091 NV_INT32 i, l, start = -1, end = -1;
3093 boundscheck_monologue(
string);
3094 new_string[0] =
'\0';
3096 l = (int)strlen(
string);
3098 for (i = 0; i < l; ++i) {
3099 if (
string[i] !=
' ') {
3104 for (i = l - 1; i >= start; --i) {
3105 if (
string[i] !=
' ' &&
string[i] != 10 &&
string[i] != 13) {
3110 if (start > -1 && end > -1 && end >= start) {
3111 strncpy(new_string,
string + start, end - start + 1);
3112 new_string[end - start + 1] =
'\0';
3139NV_INT32 search_station(
const NV_CHAR *
string) {
3140 static NV_CHAR last_search[ONELINER_LENGTH];
3141 static NV_U_INT32 j = 0;
3143 NV_CHAR name[ONELINER_LENGTH], search[ONELINER_LENGTH];
3147 "libtcd error: attempt to access database when database not open\n");
3151 boundscheck_oneliner(
string);
3153 for (i = 0; i < strlen(
string) + 1; ++i) search[i] =
tolower(
string[i]);
3155 if (strcmp(search, last_search)) j = 0;
3157 strcpy(last_search, search);
3159 while (j < hd.pub.number_of_records) {
3160 for (i = 0; i < strlen(tindex[j].name) + 1; ++i)
3161 name[i] =
tolower(tindex[j].name[i]);
3164 if (strstr(name, search))
return (j - 1);
3189NV_INT32 find_station(
const NV_CHAR *name) {
3194 "libtcd error: attempt to access database when database not open\n");
3199 for (i = 0; i < hd.pub.number_of_records; ++i) {
3200 if (!strcmp(name, tindex[i].name))
return (i);
3224NV_INT32 find_tzfile(
const NV_CHAR *name) {
3231 "libtcd error: attempt to access database when database not open\n");
3235 temp = clip_string(name);
3238 for (i = 0; i < hd.pub.tzfiles; ++i) {
3239 if (!strcmp(temp, get_tzfile(i))) {
3266NV_INT32 find_country(
const NV_CHAR *name) {
3273 "libtcd error: attempt to access database when database not open\n");
3277 temp = clip_string(name);
3280 for (i = 0; i < hd.pub.countries; ++i) {
3281 if (!strcmp(temp, get_country(i))) {
3308NV_INT32 find_level_units(
const NV_CHAR *name) {
3315 "libtcd error: attempt to access database when database not open\n");
3319 temp = clip_string(name);
3322 for (i = 0; i < hd.pub.level_unit_types; ++i) {
3323 if (!strcmp(get_level_units(i), temp)) {
3350NV_INT32 find_dir_units(
const NV_CHAR *name) {
3357 "libtcd error: attempt to access database when database not open\n");
3361 temp = clip_string(name);
3364 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
3365 if (!strcmp(get_dir_units(i), temp)) {
3393NV_INT32 find_pedigree(
const NV_CHAR *name) {
return 0; }
3414NV_INT32 find_datum(
const NV_CHAR *name) {
3421 "libtcd error: attempt to access database when database not open\n");
3425 temp = clip_string(name);
3428 for (i = 0; i < hd.pub.datum_types; ++i) {
3429 if (!strcmp(get_datum(i), temp)) {
3441NV_INT32 find_legalese(
const NV_CHAR *name) {
3448 "libtcd error: attempt to access database when database not open\n");
3452 temp = clip_string(name);
3455 for (i = 0; i < hd.pub.legaleses; ++i) {
3456 if (!strcmp(get_legalese(i), temp)) {
3484NV_INT32 find_constituent(
const NV_CHAR *name) {
3490 "libtcd error: attempt to access database when database not open\n");
3494 temp = clip_string(name);
3496 for (i = 0; i < hd.pub.constituents; ++i) {
3497 if (!strcmp(get_constituent(i), temp))
return (i);
3521NV_INT32 find_restriction(
const NV_CHAR *name) {
3528 "libtcd error: attempt to access database when database not open\n");
3532 temp = clip_string(name);
3535 for (i = 0; i < hd.pub.restriction_types; ++i) {
3536 if (!strcmp(get_restriction(i), temp)) {
3562void set_speed(NV_INT32 num, NV_FLOAT64 value) {
3565 "libtcd error: attempt to access database when database not open\n");
3569 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
3571 LOG_ERROR(
"libtcd set_speed: somebody tried to set a negative speed (%f)\n",
3575 hd.speed[num] = value;
3599void set_equilibrium(NV_INT32 num, NV_INT32 year, NV_FLOAT32 value) {
3602 "libtcd error: attempt to access database when database not open\n");
3606 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
3607 year < (NV_INT32)hd.pub.number_of_years);
3608 hd.equilibrium[num][year] = value;
3632void set_node_factor(NV_INT32 num, NV_INT32 year, NV_FLOAT32 value) {
3635 "libtcd error: attempt to access database when database not open\n");
3639 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
3640 year < (NV_INT32)hd.pub.number_of_years);
3643 "libtcd set_node_factor: somebody tried to set a negative or zero node "
3648 hd.node_factor[num][year] = value;
3699 "libtcd error: attempt to access database when database not open\n");
3705 if (strlen(name) + 1 > hd.tzfile_size) {
3706 LOG_ERROR(
"libtcd error: tzfile exceeds size limit (%u).\n",
3708 LOG_ERROR(
"The offending input is: %s\n", name);
3712 if (hd.pub.tzfiles == hd.max_tzfiles) {
3713 LOG_ERROR(
"You have exceeded the maximum number of tzfile types!\n");
3714 LOG_ERROR(
"You cannot add any new tzfile types.\n");
3715 LOG_ERROR(
"Modify the DEFAULT_TZFILE_BITS and rebuild the database.\n");
3719 c_name = clip_string(name);
3721 hd.tzfile[hd.pub.tzfiles] =
3722 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3724 if (hd.tzfile[hd.pub.tzfiles] == NULL) {
3725 perror(
"Allocating new tzfile string");
3729 strcpy(hd.tzfile[hd.pub.tzfiles++], c_name);
3730 if (db) *db = hd.pub;
3732 return (hd.pub.tzfiles - 1);
3758 "libtcd error: attempt to access database when database not open\n");
3764 if (strlen(name) + 1 > hd.country_size) {
3765 LOG_ERROR(
"libtcd error: country exceeds size limit (%u).\n",
3767 LOG_ERROR(
"The offending input is: %s\n", name);
3771 if (hd.pub.countries == hd.max_countries) {
3772 LOG_ERROR(
"You have exceeded the maximum number of country names!\n");
3773 LOG_ERROR(
"You cannot add any new country names.\n");
3774 LOG_ERROR(
"Modify the DEFAULT_COUNTRY_BITS and rebuild the database.\n");
3778 c_name = clip_string(name);
3780 hd.country[hd.pub.countries] =
3781 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3783 if (hd.country[hd.pub.countries] == NULL) {
3784 perror(
"Allocating new country string");
3788 strcpy(hd.country[hd.pub.countries++], c_name);
3789 if (db) *db = hd.pub;
3791 return (hd.pub.countries - 1);
3817 "libtcd error: attempt to access database when database not open\n");
3823 if (strlen(name) + 1 > hd.datum_size) {
3824 LOG_ERROR(
"libtcd error: datum exceeds size limit (%u).\n", hd.datum_size);
3825 LOG_ERROR(
"The offending input is: %s\n", name);
3829 if (hd.pub.datum_types == hd.max_datum_types) {
3830 LOG_ERROR(
"You have exceeded the maximum number of datum types!\n");
3831 LOG_ERROR(
"You cannot add any new datum types.\n");
3832 LOG_ERROR(
"Modify the DEFAULT_DATUM_BITS and rebuild the database.\n");
3836 c_name = clip_string(name);
3838 hd.datum[hd.pub.datum_types] =
3839 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3841 if (hd.datum[hd.pub.datum_types] == NULL) {
3842 perror(
"Allocating new datum string");
3846 strcpy(hd.datum[hd.pub.datum_types++], c_name);
3847 if (db) *db = hd.pub;
3849 return (hd.pub.datum_types - 1);
3860 "libtcd error: attempt to access database when database not open\n");
3866 if (strlen(name) + 1 > hd.legalese_size) {
3867 LOG_ERROR(
"libtcd error: legalese exceeds size limit (%u).\n",
3869 LOG_ERROR(
"The offending input is: %s\n", name);
3873 if (hd.pub.legaleses == hd.max_legaleses) {
3874 LOG_ERROR(
"You have exceeded the maximum number of legaleses!\n");
3875 LOG_ERROR(
"You cannot add any new legaleses.\n");
3876 LOG_ERROR(
"Modify the DEFAULT_LEGALESE_BITS and rebuild the database.\n");
3880 c_name = clip_string(name);
3882 hd.legalese[hd.pub.legaleses] =
3883 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3885 if (hd.legalese[hd.pub.legaleses] == NULL) {
3886 perror(
"Allocating new legalese string");
3890 strcpy(hd.legalese[hd.pub.legaleses++], c_name);
3891 if (db) *db = hd.pub;
3893 return (hd.pub.legaleses - 1);
3919 "libtcd error: attempt to access database when database not open\n");
3925 if (strlen(name) + 1 > hd.restriction_size) {
3926 LOG_ERROR(
"libtcd error: restriction exceeds size limit (%u).\n",
3927 hd.restriction_size);
3928 LOG_ERROR(
"The offending input is: %s\n", name);
3932 if (hd.pub.restriction_types == hd.max_restriction_types) {
3933 LOG_ERROR(
"You have exceeded the maximum number of restriction types!\n");
3934 LOG_ERROR(
"You cannot add any new restriction types.\n");
3936 "Modify the DEFAULT_RESTRICTION_BITS and rebuild the database.\n");
3940 c_name = clip_string(name);
3942 hd.restriction[hd.pub.restriction_types] =
3943 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3945 if (hd.restriction[hd.pub.restriction_types] == NULL) {
3946 perror(
"Allocating new restriction string");
3950 strcpy(hd.restriction[hd.pub.restriction_types++], c_name);
3951 if (db) *db = hd.pub;
3953 return (hd.pub.restriction_types - 1);
3959NV_INT32 find_or_add_restriction(
const NV_CHAR *name,
DB_HEADER_PUBLIC *db) {
3961 ret = find_restriction(name);
3962 if (ret < 0) ret = add_restriction(name, db);
3972 ret = find_tzfile(name);
3973 if (ret < 0) ret = add_tzfile(name, db);
3983 ret = find_country(name);
3984 if (ret < 0) ret = add_country(name, db);
3994 ret = find_datum(name);
3995 if (ret < 0) ret = add_datum(name, db);
4005 ret = find_legalese(name);
4006 if (ret < 0) ret = add_legalese(name, db);
4037 if (rec.max_time_add == rec.min_time_add &&
4038 rec.max_level_add == rec.min_level_add &&
4039 rec.max_level_multiply == rec.min_level_multiply &&
4040 rec.max_avg_level == 0 && rec.min_avg_level == 0 &&
4041 rec.max_direction == 361 && rec.min_direction == 361 &&
4042 rec.flood_begins == NULLSLACKOFFSET && rec.ebb_begins == NULLSLACKOFFSET)
4065static NV_U_INT32 header_checksum() {
4066 NV_U_INT32 checksum, i, save_pos;
4068 NV_U_INT32 crc_table[256] = {
4069 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
4070 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
4071 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
4072 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
4073 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
4074 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
4075 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
4076 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
4077 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
4078 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
4079 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
4080 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
4081 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
4082 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
4083 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
4084 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
4085 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
4086 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
4087 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
4088 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
4089 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
4090 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
4091 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
4092 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
4093 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
4094 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
4095 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
4096 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
4097 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
4098 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
4099 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
4100 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
4101 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
4102 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
4103 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
4104 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
4105 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
4106 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
4107 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
4108 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
4109 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
4110 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
4111 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D};
4115 "libtcd error: attempt to access database when database not open\n");
4119 save_pos = ftell(fp);
4121 fseek(fp, 0, SEEK_SET);
4123 if ((buf = (NV_U_BYTE *)calloc(hd.header_size,
sizeof(NV_U_BYTE))) == NULL) {
4124 perror(
"Allocating checksum buffer");
4130 assert(hd.header_size > 0);
4131 chk_fread(buf, hd.header_size, 1, fp);
4132 for (i = 0; i < (NV_U_INT32)hd.header_size; ++i) {
4133 checksum = crc_table[(checksum ^ buf[i]) & 0xff] ^ (checksum >> 8);
4139 fseek(fp, save_pos, SEEK_SET);
4160static NV_U_INT32 old_header_checksum() {
4161 NV_U_INT32 checksum, i, save_pos;
4166 "libtcd error: attempt to access database when database not open\n");
4170 save_pos = ftell(fp);
4174 fseek(fp, 0, SEEK_SET);
4176 if ((buf = (NV_U_BYTE *)calloc(hd.header_size,
sizeof(NV_U_BYTE))) == NULL) {
4177 perror(
"Allocating checksum buffer");
4181 chk_fread(buf, hd.header_size, 1, fp);
4183 for (i = 0; i < hd.header_size; ++i) checksum += buf[i];
4187 fseek(fp, save_pos, SEEK_SET);
4197static NV_CHAR *curtime() {
4198 static NV_CHAR buf[ONELINER_LENGTH];
4199 time_t t = time(NULL);
4200 require(strftime(buf, ONELINER_LENGTH,
"%Y-%m-%d %H:%M %Z", localtime(&t)) >
4209static NV_U_INT32 bits2bytes(NV_U_INT32 nbits) {
4210 if (nbits % 8)
return nbits / 8 + 1;
4230static void write_tide_db_header() {
4231 NV_U_INT32 i, size, pos;
4232 NV_INT32 start, temp_int;
4233 static NV_CHAR zero = 0;
4234 NV_U_BYTE *buf, checksum_c[4];
4238 "libtcd error: attempt to access database when database not open\n");
4243 fseek(fp, 0, SEEK_SET);
4245 fprintf(fp,
"[VERSION] = %s\n", LIBTCD_VERSION);
4246 fprintf(fp,
"[MAJOR REV] = %u\n", LIBTCD_MAJOR_REV);
4247 fprintf(fp,
"[MINOR REV] = %u\n", LIBTCD_MINOR_REV);
4249 fprintf(fp,
"[LAST MODIFIED] = %s\n", curtime());
4251 fprintf(fp,
"[HEADER SIZE] = %u\n", hd.header_size);
4252 fprintf(fp,
"[NUMBER OF RECORDS] = %u\n", hd.pub.number_of_records);
4254 fprintf(fp,
"[START YEAR] = %d\n", hd.pub.start_year);
4255 fprintf(fp,
"[NUMBER OF YEARS] = %u\n", hd.pub.number_of_years);
4257 fprintf(fp,
"[SPEED BITS] = %u\n", hd.speed_bits);
4258 fprintf(fp,
"[SPEED SCALE] = %u\n", hd.speed_scale);
4259 fprintf(fp,
"[SPEED OFFSET] = %d\n", hd.speed_offset);
4260 fprintf(fp,
"[EQUILIBRIUM BITS] = %u\n", hd.equilibrium_bits);
4261 fprintf(fp,
"[EQUILIBRIUM SCALE] = %u\n", hd.equilibrium_scale);
4262 fprintf(fp,
"[EQUILIBRIUM OFFSET] = %d\n", hd.equilibrium_offset);
4263 fprintf(fp,
"[NODE BITS] = %u\n", hd.node_bits);
4264 fprintf(fp,
"[NODE SCALE] = %u\n", hd.node_scale);
4265 fprintf(fp,
"[NODE OFFSET] = %d\n", hd.node_offset);
4266 fprintf(fp,
"[AMPLITUDE BITS] = %u\n", hd.amplitude_bits);
4267 fprintf(fp,
"[AMPLITUDE SCALE] = %u\n", hd.amplitude_scale);
4268 fprintf(fp,
"[EPOCH BITS] = %u\n", hd.epoch_bits);
4269 fprintf(fp,
"[EPOCH SCALE] = %u\n", hd.epoch_scale);
4271 fprintf(fp,
"[RECORD TYPE BITS] = %u\n", hd.record_type_bits);
4272 fprintf(fp,
"[LATITUDE BITS] = %u\n", hd.latitude_bits);
4273 fprintf(fp,
"[LATITUDE SCALE] = %u\n", hd.latitude_scale);
4274 fprintf(fp,
"[LONGITUDE BITS] = %u\n", hd.longitude_bits);
4275 fprintf(fp,
"[LONGITUDE SCALE] = %u\n", hd.longitude_scale);
4276 fprintf(fp,
"[RECORD SIZE BITS] = %u\n", hd.record_size_bits);
4278 fprintf(fp,
"[STATION BITS] = %u\n", hd.station_bits);
4280 fprintf(fp,
"[DATUM OFFSET BITS] = %u\n", hd.datum_offset_bits);
4281 fprintf(fp,
"[DATUM OFFSET SCALE] = %u\n", hd.datum_offset_scale);
4282 fprintf(fp,
"[DATE BITS] = %u\n", hd.date_bits);
4283 fprintf(fp,
"[MONTHS ON STATION BITS] = %u\n", hd.months_on_station_bits);
4284 fprintf(fp,
"[CONFIDENCE VALUE BITS] = %u\n", hd.confidence_value_bits);
4286 fprintf(fp,
"[TIME BITS] = %u\n", hd.time_bits);
4287 fprintf(fp,
"[LEVEL ADD BITS] = %u\n", hd.level_add_bits);
4288 fprintf(fp,
"[LEVEL ADD SCALE] = %u\n", hd.level_add_scale);
4289 fprintf(fp,
"[LEVEL MULTIPLY BITS] = %u\n", hd.level_multiply_bits);
4290 fprintf(fp,
"[LEVEL MULTIPLY SCALE] = %u\n", hd.level_multiply_scale);
4291 fprintf(fp,
"[DIRECTION BITS] = %u\n", hd.direction_bits);
4293 fprintf(fp,
"[LEVEL UNIT BITS] = %u\n", hd.level_unit_bits);
4294 fprintf(fp,
"[LEVEL UNIT TYPES] = %u\n", hd.pub.level_unit_types);
4295 fprintf(fp,
"[LEVEL UNIT SIZE] = %u\n", hd.level_unit_size);
4297 fprintf(fp,
"[DIRECTION UNIT BITS] = %u\n", hd.dir_unit_bits);
4298 fprintf(fp,
"[DIRECTION UNIT TYPES] = %u\n", hd.pub.dir_unit_types);
4299 fprintf(fp,
"[DIRECTION UNIT SIZE] = %u\n", hd.dir_unit_size);
4301 fprintf(fp,
"[RESTRICTION BITS] = %u\n", hd.restriction_bits);
4302 fprintf(fp,
"[RESTRICTION TYPES] = %u\n", hd.pub.restriction_types);
4303 fprintf(fp,
"[RESTRICTION SIZE] = %u\n", hd.restriction_size);
4305 fprintf(fp,
"[DATUM BITS] = %u\n", hd.datum_bits);
4306 fprintf(fp,
"[DATUM TYPES] = %u\n", hd.pub.datum_types);
4307 fprintf(fp,
"[DATUM SIZE] = %u\n", hd.datum_size);
4309 fprintf(fp,
"[LEGALESE BITS] = %u\n", hd.legalese_bits);
4310 fprintf(fp,
"[LEGALESE TYPES] = %u\n", hd.pub.legaleses);
4311 fprintf(fp,
"[LEGALESE SIZE] = %u\n", hd.legalese_size);
4313 fprintf(fp,
"[CONSTITUENT BITS] = %u\n", hd.constituent_bits);
4314 fprintf(fp,
"[CONSTITUENTS] = %u\n", hd.pub.constituents);
4315 fprintf(fp,
"[CONSTITUENT SIZE] = %u\n", hd.constituent_size);
4317 fprintf(fp,
"[TZFILE BITS] = %u\n", hd.tzfile_bits);
4318 fprintf(fp,
"[TZFILES] = %u\n", hd.pub.tzfiles);
4319 fprintf(fp,
"[TZFILE SIZE] = %u\n", hd.tzfile_size);
4321 fprintf(fp,
"[COUNTRY BITS] = %u\n", hd.country_bits);
4322 fprintf(fp,
"[COUNTRIES] = %u\n", hd.pub.countries);
4323 fprintf(fp,
"[COUNTRY SIZE] = %u\n", hd.country_size);
4325 fprintf(fp,
"[END OF FILE] = %u\n", hd.end_of_file);
4326 fprintf(fp,
"[END OF ASCII HEADER DATA]\n");
4332 for (i = start; i < hd.header_size; ++i) chk_fwrite(&zero, 1, 1, fp);
4337 bit_pack(checksum_c, 0, 32, header_checksum());
4338 chk_fwrite(checksum_c, 4, 1, fp);
4345 size = hd.pub.level_unit_types * hd.level_unit_size;
4347 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4348 perror(
"Allocating unit write buffer");
4351 memset(buf, 0, size);
4353 for (i = 0; i < hd.pub.level_unit_types; ++i) {
4354 assert(strlen(hd.level_unit[i]) + 1 <= hd.level_unit_size);
4355 strcpy((NV_CHAR *)&buf[pos], hd.level_unit[i]);
4356 pos += hd.level_unit_size;
4359 chk_fwrite(buf, pos, 1, fp);
4365 size = hd.pub.dir_unit_types * hd.dir_unit_size;
4367 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4368 perror(
"Allocating unit write buffer");
4371 memset(buf, 0, size);
4373 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
4374 assert(strlen(hd.dir_unit[i]) + 1 <= hd.dir_unit_size);
4375 strcpy((NV_CHAR *)&buf[pos], hd.dir_unit[i]);
4376 pos += hd.dir_unit_size;
4379 chk_fwrite(buf, pos, 1, fp);
4385 size = hd.max_restriction_types * hd.restriction_size;
4387 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4388 perror(
"Allocating restriction write buffer");
4391 memset(buf, 0, size);
4393 for (i = 0; i < hd.max_restriction_types; ++i) {
4394 if (i == hd.pub.restriction_types)
break;
4395 assert(strlen(hd.restriction[i]) + 1 <= hd.restriction_size);
4396 strcpy((NV_CHAR *)&buf[pos], hd.restriction[i]);
4397 pos += hd.restriction_size;
4399 memcpy(&buf[pos],
"__END__", 7);
4401 chk_fwrite(buf, size, 1, fp);
4407 size = hd.max_tzfiles * hd.tzfile_size;
4409 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4410 perror(
"Allocating tzfile write buffer");
4413 memset(buf, 0, size);
4415 for (i = 0; i < hd.max_tzfiles; ++i) {
4416 if (i == hd.pub.tzfiles)
break;
4417 assert(strlen(hd.tzfile[i]) + 1 <= hd.tzfile_size);
4418 strcpy((NV_CHAR *)&buf[pos], hd.tzfile[i]);
4419 pos += hd.tzfile_size;
4421 memcpy(&buf[pos],
"__END__", 7);
4423 chk_fwrite(buf, size, 1, fp);
4429 size = hd.max_countries * hd.country_size;
4431 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4432 perror(
"Allocating country write buffer");
4435 memset(buf, 0, size);
4437 for (i = 0; i < hd.max_countries; ++i) {
4438 if (i == hd.pub.countries)
break;
4439 assert(strlen(hd.country[i]) + 1 <= hd.country_size);
4440 strcpy((NV_CHAR *)&buf[pos], hd.country[i]);
4441 pos += hd.country_size;
4443 memcpy(&buf[pos],
"__END__", 7);
4445 chk_fwrite(buf, size, 1, fp);
4451 size = hd.max_datum_types * hd.datum_size;
4453 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4454 perror(
"Allocating datum write buffer");
4457 memset(buf, 0, size);
4459 for (i = 0; i < hd.max_datum_types; ++i) {
4460 if (i == hd.pub.datum_types)
break;
4461 assert(strlen(hd.datum[i]) + 1 <= hd.datum_size);
4462 strcpy((NV_CHAR *)&buf[pos], hd.datum[i]);
4463 pos += hd.datum_size;
4465 memcpy(&buf[pos],
"__END__", 7);
4467 chk_fwrite(buf, size, 1, fp);
4473 size = hd.max_legaleses * hd.legalese_size;
4475 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4476 perror(
"Allocating legalese write buffer");
4479 memset(buf, 0, size);
4481 for (i = 0; i < hd.max_legaleses; ++i) {
4482 if (i == hd.pub.legaleses)
break;
4483 assert(strlen(hd.legalese[i]) + 1 <= hd.legalese_size);
4484 strcpy((NV_CHAR *)&buf[pos], hd.legalese[i]);
4485 pos += hd.legalese_size;
4487 memcpy(&buf[pos],
"__END__", 7);
4489 chk_fwrite(buf, size, 1, fp);
4495 size = hd.pub.constituents * hd.constituent_size;
4497 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4498 perror(
"Allocating constituent write buffer");
4501 memset(buf, 0, size);
4503 for (i = 0; i < hd.pub.constituents; ++i) {
4504 assert(strlen(hd.constituent[i]) + 1 <= hd.constituent_size);
4505 strcpy((NV_CHAR *)&buf[pos], hd.constituent[i]);
4506 pos += hd.constituent_size;
4509 chk_fwrite(buf, pos, 1, fp);
4517 size = bits2bytes(hd.pub.constituents * hd.speed_bits);
4519 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4520 perror(
"Allocating speed write buffer");
4523 memset(buf, 0, size);
4525 for (i = 0; i < hd.pub.constituents; ++i) {
4526 temp_int = NINT(hd.speed[i] * hd.speed_scale) - hd.speed_offset;
4527 assert(temp_int >= 0);
4528 bit_pack(buf, pos, hd.speed_bits, temp_int);
4529 pos += hd.speed_bits;
4532 chk_fwrite(buf, size, 1, fp);
4538 size = bits2bytes(hd.pub.constituents * hd.pub.number_of_years *
4539 hd.equilibrium_bits);
4541 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4542 perror(
"Allocating equilibrium write buffer");
4545 memset(buf, 0, size);
4547 for (i = 0; i < hd.pub.constituents; ++i) {
4549 for (j = 0; j < hd.pub.number_of_years; ++j) {
4550 temp_int = NINT(hd.equilibrium[i][j] * hd.equilibrium_scale) -
4551 hd.equilibrium_offset;
4552 assert(temp_int >= 0);
4553 bit_pack(buf, pos, hd.equilibrium_bits, temp_int);
4554 pos += hd.equilibrium_bits;
4558 chk_fwrite(buf, size, 1, fp);
4565 bits2bytes(hd.pub.constituents * hd.pub.number_of_years * hd.node_bits);
4567 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4568 perror(
"Allocating node write buffer");
4571 memset(buf, 0, size);
4573 for (i = 0; i < hd.pub.constituents; ++i) {
4575 for (j = 0; j < hd.pub.number_of_years; ++j) {
4576 temp_int = NINT(hd.node_factor[i][j] * hd.node_scale) - hd.node_offset;
4577 assert(temp_int >= 0);
4578 bit_pack(buf, pos, hd.node_bits, temp_int);
4579 pos += hd.node_bits;
4583 chk_fwrite(buf, size, 1, fp);
4614static void unpack_string(NV_U_BYTE *buf, NV_U_INT32 bufsize, NV_U_INT32 *pos,
4615 NV_CHAR *outbuf, NV_U_INT32 outbuflen,
4616 const NV_CHAR *desc) {
4626 for (i = 0; c; ++i) {
4627 assert(*pos < bufsize);
4628 c = bit_unpack(buf, *pos, 8);
4630 if (i < outbuflen) {
4632 }
else if (i == outbuflen) {
4635 LOG_ERROR(
"libtcd warning: truncating overlong %s\n", desc);
4636 LOG_ERROR(
"The offending string starts with:\n%s\n", outbuf);
4664static void unpack_partial_tide_record(NV_U_BYTE *buf, NV_U_INT32 bufsize,
4674 rec->header.record_size = bit_unpack(buf, *pos, hd.record_size_bits);
4675 *pos += hd.record_size_bits;
4677 rec->header.record_type = bit_unpack(buf, *pos, hd.record_type_bits);
4678 *pos += hd.record_type_bits;
4680 temp_int = signed_bit_unpack(buf, *pos, hd.latitude_bits);
4681 rec->header.latitude = (NV_FLOAT64)temp_int / hd.latitude_scale;
4682 *pos += hd.latitude_bits;
4684 temp_int = signed_bit_unpack(buf, *pos, hd.longitude_bits);
4685 rec->header.longitude = (NV_FLOAT64)temp_int / hd.longitude_scale;
4686 *pos += hd.longitude_bits;
4691 rec->header.tzfile = bit_unpack(buf, *pos, hd.tzfile_bits);
4692 *pos += hd.tzfile_bits;
4694 unpack_string(buf, bufsize, pos, rec->header.name, ONELINER_LENGTH,
4697 rec->header.reference_station = signed_bit_unpack(buf, *pos, hd.station_bits);
4698 *pos += hd.station_bits;
4700 assert(*pos <= bufsize * 8);
4723static NV_INT32 read_partial_tide_record(NV_INT32 num,
TIDE_RECORD *rec) {
4725 NV_U_INT32 maximum_possible_size, pos;
4729 "libtcd error: attempt to access database when database not open\n");
4738 maximum_possible_size = hd.record_size_bits + hd.record_type_bits +
4739 hd.latitude_bits + hd.longitude_bits +
4740 hd.tzfile_bits + (ONELINER_LENGTH * 8) +
4742 maximum_possible_size = bits2bytes(maximum_possible_size);
4744 if ((buf = (NV_U_BYTE *)calloc(maximum_possible_size,
sizeof(NV_U_BYTE))) ==
4746 perror(
"Allocating partial tide record buffer");
4750 current_record = num;
4751 fseek(fp, tindex[num].address, SEEK_SET);
4756 size_t size = fread(buf, 1, maximum_possible_size, fp);
4757 unpack_partial_tide_record(buf, size, rec, &pos);
4777static NV_BOOL read_tide_db_header() {
4779 NV_CHAR varin[ONELINER_LENGTH], *info;
4780 NV_U_INT32 utemp, i, j, pos, size, key_count;
4781 NV_U_BYTE *buf, checksum_c[5];
4786 "libtcd error: attempt to access database when database not open\n");
4790 strcpy(hd.pub.version,
"NO VERSION");
4793 key_count =
sizeof(keys) /
sizeof(
KEY);
4796 memset(&hd, 0,
sizeof(hd));
4799 while (fgets(varin,
sizeof(varin), fp) != NULL) {
4800 if (strlen(varin) == ONELINER_LENGTH - 1) {
4801 if (varin[ONELINER_LENGTH - 2] !=
'\n') {
4802 LOG_ERROR(
"libtcd error: header line too long, begins with:\n");
4803 LOG_ERROR(
"%s\n", varin);
4804 LOG_ERROR(
"in file %s\n", filename);
4805 LOG_ERROR(
"Configured limit is %u\n", ONELINER_LENGTH - 1);
4811 if (strstr(varin,
"[END OF ASCII HEADER DATA]"))
break;
4814 info = strchr(varin,
'=');
4816 LOG_ERROR(
"libtcd error: invalid tide db header line:\n");
4817 LOG_ERROR(
"%s", varin);
4818 LOG_ERROR(
"in file %s\n", filename);
4825 for (i = 0; i < key_count; ++i) {
4826 if (strstr(varin, keys[i].keyphrase)) {
4827 if (!strcmp(keys[i].datatype,
"cstr"))
4828 strcpy((
char *)keys[i].address.cstr, clip_string(info));
4829 else if (!strcmp(keys[i].datatype,
"i32")) {
4830 if (sscanf(info,
"%d", keys[i].address.i32) != 1) {
4831 LOG_ERROR(
"libtcd error: invalid tide db header line:\n");
4832 LOG_ERROR(
"%s", varin);
4833 LOG_ERROR(
"in file %s\n", filename);
4837 }
else if (!strcmp(keys[i].datatype,
"ui32")) {
4838 if (sscanf(info,
"%u", keys[i].address.ui32) != 1) {
4839 LOG_ERROR(
"libtcd error: invalid tide db header line:\n");
4840 LOG_ERROR(
"%s", varin);
4841 LOG_ERROR(
"in file %s\n", filename);
4853 if (!strcmp(hd.pub.version,
"NO VERSION")) {
4854 LOG_ERROR(
"libtcd error: no version found in tide db header\n");
4855 LOG_ERROR(
"in file %s\n", filename);
4861 if (hd.pub.major_rev > LIBTCD_MAJOR_REV) {
4863 "libtcd error: major revision in TCD file (%u) exceeds major revision "
4866 LOG_ERROR(
"libtcd (%u). You must upgrade libtcd to read this file.\n",
4873 fseek(fp, hd.header_size, SEEK_SET);
4877 chk_fread(checksum_c, 4, 1, fp);
4878 utemp = bit_unpack(checksum_c, 0, 32);
4880 if (utemp != header_checksum()) {
4882 if (utemp != old_header_checksum()) {
4883 LOG_ERROR(
"libtcd error: header checksum error in file %s\n", filename);
4885 "Someone may have modified the ASCII portion of the header (don't do that),\n\
4886or it may just be corrupt.\n");
4891 LOG_ERROR(
"libtcd error: header checksum error in file %s\n", filename);
4893 "Someone may have modified the ASCII portion of the header (don't do that),\n\
4894or it may be an ancient pre-version-1.02 TCD file, or it may just be corrupt.\n\
4895Pre-version-1.02 TCD files can be read by building libtcd with COMPAT114\n\
4901 fseek(fp, hd.header_size + 4, SEEK_SET);
4906 hd.max_restriction_types = NINT(pow(2.0, (NV_FLOAT64)hd.restriction_bits));
4910 hd.max_tzfiles = NINT(pow(2.0, (NV_FLOAT64)hd.tzfile_bits));
4914 hd.max_countries = NINT(pow(2.0, (NV_FLOAT64)hd.country_bits));
4919 hd.max_datum_types = NINT(pow(2.0, (NV_FLOAT64)hd.datum_bits));
4924 if (hd.pub.major_rev < 2)
4925 hd.max_legaleses = 1;
4927 hd.max_legaleses = NINT(pow(2.0, (NV_FLOAT64)hd.legalese_bits));
4934 (NV_CHAR **)calloc(hd.pub.level_unit_types,
sizeof(NV_CHAR *));
4936 if ((buf = (NV_U_BYTE *)calloc(hd.level_unit_size,
sizeof(NV_U_BYTE))) ==
4938 perror(
"Allocating level unit read buffer");
4942 for (i = 0; i < hd.pub.level_unit_types; ++i) {
4943 chk_fread(buf, hd.level_unit_size, 1, fp);
4945 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
4946 strcpy(hd.level_unit[i], (NV_CHAR *)buf);
4952 hd.dir_unit = (NV_CHAR **)calloc(hd.pub.dir_unit_types,
sizeof(NV_CHAR *));
4954 if ((buf = (NV_U_BYTE *)calloc(hd.dir_unit_size,
sizeof(NV_U_BYTE))) ==
4956 perror(
"Allocating dir unit read buffer");
4960 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
4961 chk_fread(buf, hd.dir_unit_size, 1, fp);
4963 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
4964 strcpy(hd.dir_unit[i], (NV_CHAR *)buf);
4972 (NV_CHAR **)calloc(hd.max_restriction_types,
sizeof(NV_CHAR *));
4974 if ((buf = (NV_U_BYTE *)calloc(hd.restriction_size,
sizeof(NV_U_BYTE))) ==
4976 perror(
"Allocating restriction read buffer");
4980 hd.pub.restriction_types = 0;
4981 for (i = 0; i < hd.max_restriction_types; ++i) {
4982 chk_fread(buf, hd.restriction_size, 1, fp);
4983 if (!strcmp((
char *)buf,
"__END__")) {
4984 hd.pub.restriction_types = i;
4988 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
4989 strcpy(hd.restriction[i], (NV_CHAR *)buf);
4992 fseek(fp, utemp + hd.max_restriction_types * hd.restriction_size, SEEK_SET);
4995 if (hd.pub.major_rev < 2)
4996 fseek(fp, hd.pedigree_size * NINT(pow(2.0, (NV_FLOAT64)hd.pedigree_bits)),
4998 hd.pub.pedigree_types = 1;
5003 hd.tzfile = (NV_CHAR **)calloc(hd.max_tzfiles,
sizeof(NV_CHAR *));
5005 if ((buf = (NV_U_BYTE *)calloc(hd.tzfile_size,
sizeof(NV_U_BYTE))) == NULL) {
5006 perror(
"Allocating tzfile read buffer");
5011 for (i = 0; i < hd.max_tzfiles; ++i) {
5012 chk_fread(buf, hd.tzfile_size, 1, fp);
5013 if (!strcmp((
char *)buf,
"__END__")) {
5017 hd.tzfile[i] = (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5018 strcpy(hd.tzfile[i], (NV_CHAR *)buf);
5021 fseek(fp, utemp + hd.max_tzfiles * hd.tzfile_size, SEEK_SET);
5026 hd.country = (NV_CHAR **)calloc(hd.max_countries,
sizeof(NV_CHAR *));
5028 if ((buf = (NV_U_BYTE *)calloc(hd.country_size,
sizeof(NV_U_BYTE))) == NULL) {
5029 perror(
"Allocating country read buffer");
5033 hd.pub.countries = 0;
5034 for (i = 0; i < hd.max_countries; ++i) {
5035 chk_fread(buf, hd.country_size, 1, fp);
5036 if (!strcmp((
char *)buf,
"__END__")) {
5037 hd.pub.countries = i;
5040 hd.country[i] = (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5041 strcpy(hd.country[i], (NV_CHAR *)buf);
5044 fseek(fp, utemp + hd.max_countries * hd.country_size, SEEK_SET);
5049 hd.datum = (NV_CHAR **)calloc(hd.max_datum_types,
sizeof(NV_CHAR *));
5051 if ((buf = (NV_U_BYTE *)calloc(hd.datum_size,
sizeof(NV_U_BYTE))) == NULL) {
5052 perror(
"Allocating datum read buffer");
5056 hd.pub.datum_types = 0;
5057 for (i = 0; i < hd.max_datum_types; ++i) {
5058 chk_fread(buf, hd.datum_size, 1, fp);
5059 if (!strcmp((
char *)buf,
"__END__")) {
5060 hd.pub.datum_types = i;
5063 hd.datum[i] = (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5064 strcpy(hd.datum[i], (NV_CHAR *)buf);
5067 fseek(fp, utemp + hd.max_datum_types * hd.datum_size, SEEK_SET);
5071 if (hd.pub.major_rev < 2) {
5072 hd.legalese = (NV_CHAR **)malloc(
sizeof(NV_CHAR *));
5073 assert(hd.legalese != NULL);
5074 hd.legalese[0] = (NV_CHAR *)malloc(5 *
sizeof(NV_CHAR));
5075 assert(hd.legalese[0] != NULL);
5076 strcpy(hd.legalese[0],
"NULL");
5077 hd.pub.legaleses = 1;
5080 hd.legalese = (NV_CHAR **)calloc(hd.max_legaleses,
sizeof(NV_CHAR *));
5082 if ((buf = (NV_U_BYTE *)calloc(hd.legalese_size,
sizeof(NV_U_BYTE))) ==
5084 perror(
"Allocating legalese read buffer");
5088 hd.pub.legaleses = 0;
5089 for (i = 0; i < hd.max_legaleses; ++i) {
5090 chk_fread(buf, hd.legalese_size, 1, fp);
5091 if (!strcmp((
char *)buf,
"__END__")) {
5092 hd.pub.legaleses = i;
5096 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5097 strcpy(hd.legalese[i], (NV_CHAR *)buf);
5100 fseek(fp, utemp + hd.max_legaleses * hd.legalese_size, SEEK_SET);
5105 hd.constituent = (NV_CHAR **)calloc(hd.pub.constituents,
sizeof(NV_CHAR *));
5107 if ((buf = (NV_U_BYTE *)calloc(hd.constituent_size,
sizeof(NV_U_BYTE))) ==
5109 perror(
"Allocating constituent read buffer");
5113 for (i = 0; i < hd.pub.constituents; ++i) {
5114 chk_fread(buf, hd.constituent_size, 1, fp);
5116 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5117 strcpy(hd.constituent[i], (NV_CHAR *)buf);
5121 if (hd.speed_offset < 0 || hd.equilibrium_offset < 0 || hd.node_offset < 0) {
5122 LOG_ERROR(
"libtcd WARNING: File: %s\n", filename);
5124 "WARNING: This TCD file was created by a pre-version-1.11 libtcd.\n\
5125Versions of libtcd prior to 1.11 contained a serious bug that can result\n\
5126in overflows in the speeds, equilibrium arguments, or node factors. This\n\
5127database should be rebuilt from the original data if possible.\n");
5134 hd.speed = (NV_FLOAT64 *)calloc(hd.pub.constituents,
sizeof(NV_FLOAT64));
5138 if (hd.pub.major_rev < 2)
5139 size = ((hd.pub.constituents * hd.speed_bits) / 8) + 1;
5141 size = bits2bytes(hd.pub.constituents * hd.speed_bits);
5143 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
5144 perror(
"Allocating speed read buffer");
5148 chk_fread(buf, size, 1, fp);
5150 for (i = 0; i < hd.pub.constituents; ++i) {
5151 temp_int = bit_unpack(buf, pos, hd.speed_bits);
5152 hd.speed[i] = (NV_FLOAT64)(temp_int + hd.speed_offset) / hd.speed_scale;
5153 pos += hd.speed_bits;
5154 assert(hd.speed[i] >= 0.0);
5161 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5163 for (i = 0; i < hd.pub.constituents; ++i) {
5165 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5170 if (hd.pub.major_rev < 2)
5172 ((hd.pub.constituents * hd.pub.number_of_years * hd.equilibrium_bits) /
5176 size = bits2bytes(hd.pub.constituents * hd.pub.number_of_years *
5177 hd.equilibrium_bits);
5179 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
5180 perror(
"Allocating equilibrium read buffer");
5184 chk_fread(buf, size, 1, fp);
5186 for (i = 0; i < hd.pub.constituents; ++i) {
5187 for (j = 0; j < hd.pub.number_of_years; ++j) {
5188 temp_int = bit_unpack(buf, pos, hd.equilibrium_bits);
5189 hd.equilibrium[i][j] =
5190 (NV_FLOAT32)(temp_int + hd.equilibrium_offset) / hd.equilibrium_scale;
5191 pos += hd.equilibrium_bits;
5199 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5201 for (i = 0; i < hd.pub.constituents; ++i) {
5203 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5208 if (hd.pub.major_rev < 2)
5210 ((hd.pub.constituents * hd.pub.number_of_years * hd.node_bits) / 8) + 1;
5213 bits2bytes(hd.pub.constituents * hd.pub.number_of_years * hd.node_bits);
5215 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
5216 perror(
"Allocating node read buffer");
5220 chk_fread(buf, size, 1, fp);
5222 for (i = 0; i < hd.pub.constituents; ++i) {
5223 for (j = 0; j < hd.pub.number_of_years; ++j) {
5224 temp_int = bit_unpack(buf, pos, hd.node_bits);
5225 hd.node_factor[i][j] =
5226 (NV_FLOAT32)(temp_int + hd.node_offset) / hd.node_scale;
5227 pos += hd.node_bits;
5228 assert(hd.node_factor[i][j] > 0.0);
5237 if (hd.pub.number_of_records) {
5238 if ((tindex = (
TIDE_INDEX *)calloc(hd.pub.number_of_records,
5240 perror(
"Allocating tide index");
5244 tindex[0].address = ftell(fp);
5248 for (i = 0; i < hd.pub.number_of_records; ++i) {
5252 if (i) tindex[i].address = tindex[i - 1].address + rec.header.record_size;
5254 read_partial_tide_record(i, &rec);
5258 tindex[i].record_size = rec.header.record_size;
5259 tindex[i].record_type = rec.header.record_type;
5260 tindex[i].reference_station = rec.header.reference_station;
5261 assert(rec.header.tzfile >= 0);
5262 tindex[i].tzfile = rec.header.tzfile;
5263 tindex[i].lat = NINT(rec.header.latitude * hd.latitude_scale);
5264 tindex[i].lon = NINT(rec.header.longitude * hd.longitude_scale);
5266 if ((tindex[i].name = (NV_CHAR *)calloc(strlen(rec.header.name) + 1,
5267 sizeof(NV_CHAR))) == NULL) {
5268 perror(
"Allocating index name memory");
5272 strcpy(tindex[i].name, rec.header.name);
5275 current_record = -1;
5298NV_BOOL open_tide_db(
const NV_CHAR *file) {
5300 current_record = -1;
5303 if (!strcmp(file, filename) && !modified)
5308 if ((fp = fopen(file,
"rb+")) == NULL) {
5309 if ((fp = fopen(file,
"rb")) == NULL)
return (NVFalse);
5311 boundscheck_monologue(file);
5312 strcpy(filename, file);
5313 return (read_tide_db_header());
5334void close_tide_db() {
5338 LOG_ERROR(
"libtcd warning: close_tide_db called when no database open\n");
5345 if (modified) write_tide_db_header();
5349 assert(hd.constituent);
5350 for (i = 0; i < hd.pub.constituents; ++i) {
5351 if (hd.constituent[i] != NULL) free(hd.constituent[i]);
5353 free(hd.constituent);
5354 hd.constituent = NULL;
5356 if (hd.speed != NULL) free(hd.speed);
5358 assert(hd.equilibrium);
5359 for (i = 0; i < hd.pub.constituents; ++i) {
5360 if (hd.equilibrium[i] != NULL) free(hd.equilibrium[i]);
5362 free(hd.equilibrium);
5363 hd.equilibrium = NULL;
5365 assert(hd.node_factor);
5366 for (i = 0; i < hd.pub.constituents; ++i) {
5367 if (hd.node_factor[i] != NULL) free(hd.node_factor[i]);
5369 free(hd.node_factor);
5370 hd.node_factor = NULL;
5372 assert(hd.level_unit);
5373 for (i = 0; i < hd.pub.level_unit_types; ++i) {
5374 if (hd.level_unit[i] != NULL) free(hd.level_unit[i]);
5376 free(hd.level_unit);
5377 hd.level_unit = NULL;
5379 assert(hd.dir_unit);
5380 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
5381 if (hd.dir_unit[i] != NULL) free(hd.dir_unit[i]);
5386 assert(hd.restriction);
5387 for (i = 0; i < hd.max_restriction_types; ++i) {
5388 if (hd.restriction[i] != NULL) free(hd.restriction[i]);
5390 free(hd.restriction);
5391 hd.restriction = NULL;
5393 assert(hd.legalese);
5394 for (i = 0; i < hd.max_legaleses; ++i) {
5395 if (hd.legalese[i] != NULL) free(hd.legalese[i]);
5401 for (i = 0; i < hd.max_tzfiles; ++i) {
5402 if (hd.tzfile[i] != NULL) free(hd.tzfile[i]);
5408 for (i = 0; i < hd.max_countries; ++i) {
5409 if (hd.country[i] != NULL) free(hd.country[i]);
5415 for (i = 0; i < hd.max_datum_types; ++i) {
5416 if (hd.datum[i] != NULL) free(hd.datum[i]);
5423 for (i = 0; i < hd.pub.number_of_records; ++i) {
5424 if (tindex[i].name) free(tindex[i].name);
5465NV_BOOL create_tide_db(
const NV_CHAR *file, NV_U_INT32 constituents,
5466 NV_CHAR
const *
const constituent[],
5467 const NV_FLOAT64 *speed, NV_INT32 start_year,
5468 NV_U_INT32 num_years,
5469 NV_FLOAT32
const *
const equilibrium[],
5470 NV_FLOAT32
const *
const node_factor[]) {
5472 NV_FLOAT64 min_value, max_value;
5477 assert(constituent);
5479 assert(equilibrium);
5480 assert(node_factor);
5481 for (i = 0; i < constituents; ++i) {
5482 if (speed[i] < 0.0) {
5484 "libtcd create_tide_db: somebody tried to set a negative speed "
5489 for (j = 0; j < num_years; ++j) {
5490 if (node_factor[i][j] <= 0.0) {
5492 "libtcd create_tide_db: somebody tried to set a negative or zero "
5493 "node factor (%f)\n",
5500 if (fp) close_tide_db();
5502 if ((fp = fopen(file,
"wb+")) == NULL) {
5509 memset(&hd, 0,
sizeof(hd));
5511 hd.pub.major_rev = LIBTCD_MAJOR_REV;
5512 hd.pub.minor_rev = LIBTCD_MINOR_REV;
5514 hd.header_size = DEFAULT_HEADER_SIZE;
5515 hd.pub.number_of_records = DEFAULT_NUMBER_OF_RECORDS;
5517 hd.pub.start_year = start_year;
5518 hd.pub.number_of_years = num_years;
5520 hd.pub.constituents = constituents;
5524 hd.constituent = (NV_CHAR **)calloc(hd.pub.constituents,
sizeof(NV_CHAR *));
5525 for (i = 0; i < hd.pub.constituents; ++i) {
5527 (NV_CHAR *)calloc(strlen(constituent[i]) + 1,
sizeof(NV_CHAR));
5528 strcpy(hd.constituent[i], constituent[i]);
5534 hd.constituent_bits = calculate_bits(hd.pub.constituents);
5538 hd.speed = (NV_FLOAT64 *)calloc(hd.pub.constituents,
sizeof(NV_FLOAT64));
5540 hd.speed_scale = DEFAULT_SPEED_SCALE;
5541 min_value = 99999999.0;
5542 max_value = -99999999.0;
5543 for (i = 0; i < hd.pub.constituents; ++i) {
5544 if (speed[i] < min_value) min_value = speed[i];
5545 if (speed[i] > max_value) max_value = speed[i];
5547 hd.speed[i] = speed[i];
5553 hd.speed_offset = (NINT(min_value * hd.speed_scale));
5554 temp_int = NINT(max_value * hd.speed_scale) - hd.speed_offset;
5555 assert(temp_int >= 0);
5556 hd.speed_bits = calculate_bits((NV_U_INT32)temp_int);
5558 assert(hd.speed_bits < 32);
5563 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5565 hd.equilibrium_scale = DEFAULT_EQUILIBRIUM_SCALE;
5566 min_value = 99999999.0;
5567 max_value = -99999999.0;
5568 for (i = 0; i < hd.pub.constituents; ++i) {
5570 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5571 for (j = 0; j < hd.pub.number_of_years; ++j) {
5572 if (equilibrium[i][j] < min_value) min_value = equilibrium[i][j];
5573 if (equilibrium[i][j] > max_value) max_value = equilibrium[i][j];
5575 hd.equilibrium[i][j] = equilibrium[i][j];
5582 hd.equilibrium_offset = (NINT(min_value * hd.equilibrium_scale));
5583 temp_int = NINT(max_value * hd.equilibrium_scale) - hd.equilibrium_offset;
5584 assert(temp_int >= 0);
5585 hd.equilibrium_bits = calculate_bits((NV_U_INT32)temp_int);
5590 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5592 hd.node_scale = DEFAULT_NODE_SCALE;
5593 min_value = 99999999.0;
5594 max_value = -99999999.0;
5595 for (i = 0; i < hd.pub.constituents; ++i) {
5597 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5598 for (j = 0; j < hd.pub.number_of_years; ++j) {
5599 if (node_factor[i][j] < min_value) min_value = node_factor[i][j];
5600 if (node_factor[i][j] > max_value) max_value = node_factor[i][j];
5602 hd.node_factor[i][j] = node_factor[i][j];
5609 hd.node_offset = (NINT(min_value * hd.node_scale));
5610 temp_int = NINT(max_value * hd.node_scale) - hd.node_offset;
5611 assert(temp_int >= 0);
5612 hd.node_bits = calculate_bits((NV_U_INT32)temp_int);
5616 hd.amplitude_bits = DEFAULT_AMPLITUDE_BITS;
5617 hd.amplitude_scale = DEFAULT_AMPLITUDE_SCALE;
5618 hd.epoch_bits = DEFAULT_EPOCH_BITS;
5619 hd.epoch_scale = DEFAULT_EPOCH_SCALE;
5621 hd.record_type_bits = DEFAULT_RECORD_TYPE_BITS;
5622 hd.latitude_bits = DEFAULT_LATITUDE_BITS;
5623 hd.latitude_scale = DEFAULT_LATITUDE_SCALE;
5624 hd.longitude_bits = DEFAULT_LONGITUDE_BITS;
5625 hd.longitude_scale = DEFAULT_LONGITUDE_SCALE;
5626 hd.record_size_bits = DEFAULT_RECORD_SIZE_BITS;
5628 hd.station_bits = DEFAULT_STATION_BITS;
5630 hd.datum_offset_bits = DEFAULT_DATUM_OFFSET_BITS;
5631 hd.datum_offset_scale = DEFAULT_DATUM_OFFSET_SCALE;
5632 hd.date_bits = DEFAULT_DATE_BITS;
5633 hd.months_on_station_bits = DEFAULT_MONTHS_ON_STATION_BITS;
5634 hd.confidence_value_bits = DEFAULT_CONFIDENCE_VALUE_BITS;
5636 hd.time_bits = DEFAULT_TIME_BITS;
5637 hd.level_add_bits = DEFAULT_LEVEL_ADD_BITS;
5638 hd.level_add_scale = DEFAULT_LEVEL_ADD_SCALE;
5639 hd.level_multiply_bits = DEFAULT_LEVEL_MULTIPLY_BITS;
5640 hd.level_multiply_scale = DEFAULT_LEVEL_MULTIPLY_SCALE;
5641 hd.direction_bits = DEFAULT_DIRECTION_BITS;
5643 hd.constituent_size = DEFAULT_CONSTITUENT_SIZE;
5644 hd.level_unit_size = DEFAULT_LEVEL_UNIT_SIZE;
5645 hd.dir_unit_size = DEFAULT_DIR_UNIT_SIZE;
5646 hd.restriction_size = DEFAULT_RESTRICTION_SIZE;
5647 hd.tzfile_size = DEFAULT_TZFILE_SIZE;
5648 hd.country_size = DEFAULT_COUNTRY_SIZE;
5649 hd.datum_size = DEFAULT_DATUM_SIZE;
5650 hd.legalese_size = DEFAULT_LEGALESE_SIZE;
5654 hd.pub.level_unit_types = DEFAULT_LEVEL_UNIT_TYPES;
5655 hd.level_unit_bits = calculate_bits(hd.pub.level_unit_types - 1);
5658 (NV_CHAR **)calloc(hd.pub.level_unit_types,
sizeof(NV_CHAR *));
5659 for (i = 0; i < hd.pub.level_unit_types; ++i) {
5661 (NV_CHAR *)calloc(strlen(level_unit[i]) + 1,
sizeof(NV_CHAR));
5662 strcpy(hd.level_unit[i], level_unit[i]);
5667 hd.pub.dir_unit_types = DEFAULT_DIR_UNIT_TYPES;
5668 hd.dir_unit_bits = calculate_bits(hd.pub.dir_unit_types - 1);
5670 hd.dir_unit = (NV_CHAR **)calloc(hd.pub.dir_unit_types,
sizeof(NV_CHAR *));
5671 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
5673 (NV_CHAR *)calloc(strlen(dir_unit[i]) + 1,
sizeof(NV_CHAR));
5674 strcpy(hd.dir_unit[i], dir_unit[i]);
5679 hd.restriction_bits = DEFAULT_RESTRICTION_BITS;
5680 hd.max_restriction_types = NINT(pow(2.0, (NV_FLOAT64)hd.restriction_bits));
5681 hd.pub.restriction_types = DEFAULT_RESTRICTION_TYPES;
5684 (NV_CHAR **)calloc(hd.max_restriction_types,
sizeof(NV_CHAR *));
5685 for (i = 0; i < hd.max_restriction_types; ++i) {
5686 if (i == hd.pub.restriction_types)
break;
5689 (NV_CHAR *)calloc(strlen(restriction[i]) + 1,
sizeof(NV_CHAR));
5690 strcpy(hd.restriction[i], restriction[i]);
5695 hd.legalese_bits = DEFAULT_LEGALESE_BITS;
5696 hd.max_legaleses = NINT(pow(2.0, (NV_FLOAT64)hd.legalese_bits));
5697 hd.pub.legaleses = DEFAULT_LEGALESES;
5699 hd.legalese = (NV_CHAR **)calloc(hd.max_legaleses,
sizeof(NV_CHAR *));
5700 for (i = 0; i < hd.max_legaleses; ++i) {
5701 if (i == hd.pub.legaleses)
break;
5704 (NV_CHAR *)calloc(strlen(legalese[i]) + 1,
sizeof(NV_CHAR));
5705 strcpy(hd.legalese[i], legalese[i]);
5710 hd.tzfile_bits = DEFAULT_TZFILE_BITS;
5711 hd.max_tzfiles = NINT(pow(2.0, (NV_FLOAT64)hd.tzfile_bits));
5712 hd.pub.tzfiles = DEFAULT_TZFILES;
5714 hd.tzfile = (NV_CHAR **)calloc(hd.max_tzfiles,
sizeof(NV_CHAR *));
5715 for (i = 0; i < hd.max_tzfiles; ++i) {
5716 if (i == hd.pub.tzfiles)
break;
5718 hd.tzfile[i] = (NV_CHAR *)calloc(strlen(tzfile[i]) + 1,
sizeof(NV_CHAR));
5719 strcpy(hd.tzfile[i], tzfile[i]);
5724 hd.country_bits = DEFAULT_COUNTRY_BITS;
5725 hd.max_countries = NINT(pow(2.0, (NV_FLOAT64)hd.country_bits));
5726 hd.pub.countries = DEFAULT_COUNTRIES;
5728 hd.country = (NV_CHAR **)calloc(hd.max_countries,
sizeof(NV_CHAR *));
5729 for (i = 0; i < hd.max_countries; ++i) {
5730 if (i == hd.pub.countries)
break;
5732 hd.country[i] = (NV_CHAR *)calloc(strlen(country[i]) + 1,
sizeof(NV_CHAR));
5733 strcpy(hd.country[i], country[i]);
5738 hd.datum_bits = DEFAULT_DATUM_BITS;
5739 hd.max_datum_types = NINT(pow(2.0, (NV_FLOAT64)hd.datum_bits));
5740 hd.pub.datum_types = DEFAULT_DATUM_TYPES;
5742 hd.datum = (NV_CHAR **)calloc(hd.max_datum_types,
sizeof(NV_CHAR *));
5743 for (i = 0; i < hd.max_datum_types; ++i) {
5744 if (i == hd.pub.datum_types)
break;
5746 hd.datum[i] = (NV_CHAR *)calloc(strlen(datum[i]) + 1,
sizeof(NV_CHAR));
5747 strcpy(hd.datum[i], datum[i]);
5757 i = (open_tide_db(file));
5761 hd.end_of_file = ftell(fp);
5765 write_tide_db_header();
5774static NV_BOOL check_date(NV_U_INT32 date) {
5780 if (m < 1 || m > 12 || d < 1 || d > 31)
return NVFalse;
5794static NV_BOOL check_tide_record(
TIDE_RECORD *rec) {
5796 NV_BOOL ret = NVTrue;
5799 LOG_ERROR(
"libtcd error: null pointer passed to check_tide_record\n");
5805 boundscheck_oneliner(rec->header.name);
5806 boundscheck_oneliner(rec->source);
5807 boundscheck_monologue(rec->comments);
5808 boundscheck_monologue(rec->notes);
5809 boundscheck_oneliner(rec->station_id_context);
5810 boundscheck_oneliner(rec->station_id);
5811 boundscheck_monologue(rec->xfields);
5814 if (rec->header.record_type == REFERENCE_STATION && rec->units > 0)
5815 rec->level_units = rec->units;
5818 if (rec->header.latitude < -90.0 || rec->header.latitude > 90.0 ||
5819 rec->header.longitude < -180.0 || rec->header.longitude > 180.0) {
5820 LOG_ERROR(
"libtcd error: bad coordinates in tide record\n");
5824 if (rec->header.tzfile < 0 ||
5825 rec->header.tzfile >= (NV_INT32)hd.pub.tzfiles) {
5826 LOG_ERROR(
"libtcd error: bad tzfile in tide record\n");
5830 if (rec->header.name[0] ==
'\0') {
5831 LOG_ERROR(
"libtcd error: null name in tide record\n");
5835 if (rec->country < 0 || rec->country >= (NV_INT32)hd.pub.countries) {
5836 LOG_ERROR(
"libtcd error: bad country in tide record\n");
5840 if (rec->restriction >= hd.pub.restriction_types) {
5841 LOG_ERROR(
"libtcd error: bad restriction in tide record\n");
5845 if (rec->legalese >= hd.pub.legaleses) {
5846 LOG_ERROR(
"libtcd error: bad legalese in tide record\n");
5850 if (!check_date(rec->date_imported)) {
5851 LOG_ERROR(
"libtcd error: bad date_imported in tide record\n");
5855 if (rec->direction_units >= hd.pub.dir_unit_types) {
5856 LOG_ERROR(
"libtcd error: bad direction_units in tide record\n");
5860 if (rec->min_direction < 0 || rec->min_direction > 361) {
5861 LOG_ERROR(
"libtcd error: min_direction out of range in tide record\n");
5865 if (rec->max_direction < 0 || rec->max_direction > 361) {
5866 LOG_ERROR(
"libtcd error: max_direction out of range in tide record\n");
5870 if (rec->level_units >= hd.pub.level_unit_types) {
5871 LOG_ERROR(
"libtcd error: bad units in tide record\n");
5875 switch (rec->header.record_type) {
5876 case REFERENCE_STATION:
5877 if (rec->header.reference_station != -1) {
5878 LOG_ERROR(
"libtcd error: type 1 record, reference_station != -1\n");
5882 if (rec->datum_offset < -13421.7728 || rec->datum_offset > 13421.7727) {
5883 LOG_ERROR(
"libtcd error: datum_offset out of range in tide record\n");
5887 if (rec->datum < 0 || rec->datum >= (NV_INT32)hd.pub.datum_types) {
5888 LOG_ERROR(
"libtcd error: bad datum in tide record\n");
5892 if (rec->zone_offset < -4096 || rec->zone_offset > 4095 ||
5893 rec->zone_offset % 100 >= 60) {
5894 LOG_ERROR(
"libtcd error: bad zone_offset in tide record\n");
5898 if (!check_date(rec->expiration_date)) {
5899 LOG_ERROR(
"libtcd error: bad expiration_date in tide record\n");
5903 if (rec->months_on_station > 1023) {
5905 "libtcd error: months_on_station out of range in tide record\n");
5909 if (!check_date(rec->last_date_on_station)) {
5910 LOG_ERROR(
"libtcd error: bad last_date_on_station in tide record\n");
5914 if (rec->confidence > 15) {
5915 LOG_ERROR(
"libtcd error: confidence out of range in tide record\n");
5920 for (i = 0; i < hd.pub.constituents; ++i) {
5921 if (rec->amplitude[i] < 0.0 || rec->amplitude[i] > 52.4287) {
5923 "libtcd error: constituent amplitude out of range in tide "
5929 for (i = 0; i < hd.pub.constituents; ++i) {
5930 if (rec->epoch[i] < 0.0 || rec->epoch[i] > 360.0) {
5932 "libtcd error: constituent epoch out of range in tide record\n");
5940 case SUBORDINATE_STATION:
5941 if (rec->header.reference_station < 0 ||
5942 rec->header.reference_station >= (NV_INT32)hd.pub.number_of_records) {
5943 LOG_ERROR(
"libtcd error: bad reference_station in tide record\n");
5947 if (rec->min_time_add < -4096 || rec->min_time_add > 4095 ||
5948 rec->min_time_add % 100 >= 60) {
5949 LOG_ERROR(
"libtcd error: bad min_time_add in tide record\n");
5953 if (rec->min_level_add < -65.536 || rec->min_level_add > 65.535) {
5954 LOG_ERROR(
"libtcd error: min_level_add out of range in tide record\n");
5958 if (rec->min_level_multiply < 0.0 || rec->min_level_multiply > 65.535) {
5960 "libtcd error: min_level_multiply out of range in tide record\n");
5964 if (rec->max_time_add < -4096 || rec->max_time_add > 4095 ||
5965 rec->max_time_add % 100 >= 60) {
5966 LOG_ERROR(
"libtcd error: bad max_time_add in tide record\n");
5970 if (rec->max_level_add < -65.536 || rec->max_level_add > 65.535) {
5971 LOG_ERROR(
"libtcd error: max_level_add out of range in tide record\n");
5975 if (rec->max_level_multiply < 0.0 || rec->max_level_multiply > 65.535) {
5977 "libtcd error: max_level_multiply out of range in tide record\n");
5981 if (rec->flood_begins != NULLSLACKOFFSET &&
5982 (rec->flood_begins < -4096 || rec->flood_begins > 4095 ||
5983 rec->flood_begins % 100 >= 60)) {
5984 LOG_ERROR(
"libtcd error: bad flood_begins in tide record\n");
5988 if (rec->ebb_begins != NULLSLACKOFFSET &&
5989 (rec->ebb_begins < -4096 || rec->ebb_begins > 4095 ||
5990 rec->ebb_begins % 100 >= 60)) {
5991 LOG_ERROR(
"libtcd error: bad ebb_begins in tide record\n");
5998 LOG_ERROR(
"libtcd error: invalid record_type in tide record\n");
6002 if (ret == NVFalse) dump_tide_record(rec);
6013 NV_U_INT32 i, count = 0, name_size, source_size, comments_size, notes_size,
6014 station_id_context_size, station_id_size, xfields_size;
6020 name_size = strlen(clip_string(rec->header.name)) + 1;
6021 source_size = strlen(clip_string(rec->source)) + 1;
6022 comments_size = strlen(clip_string(rec->comments)) + 1;
6023 notes_size = strlen(clip_string(rec->notes)) + 1;
6024 station_id_context_size = strlen(clip_string(rec->station_id_context)) + 1;
6025 station_id_size = strlen(clip_string(rec->station_id)) + 1;
6027 xfields_size = strlen(rec->xfields) + 1;
6029 rec->header.record_size =
6030 hd.record_size_bits + hd.record_type_bits + hd.latitude_bits +
6031 hd.longitude_bits + hd.station_bits + hd.tzfile_bits + (name_size * 8) +
6033 hd.country_bits + (source_size * 8) + hd.restriction_bits +
6034 (comments_size * 8) + (notes_size * 8) + hd.legalese_bits +
6035 (station_id_context_size * 8) + (station_id_size * 8) + hd.date_bits +
6036 (xfields_size * 8) + hd.dir_unit_bits + hd.direction_bits +
6037 hd.direction_bits + hd.level_unit_bits;
6039 switch (rec->header.record_type) {
6040 case REFERENCE_STATION:
6041 rec->header.record_size += hd.datum_offset_bits + hd.datum_bits +
6042 hd.time_bits + hd.date_bits +
6043 hd.months_on_station_bits + hd.date_bits +
6044 hd.confidence_value_bits + hd.constituent_bits;
6046 for (i = 0; i < hd.pub.constituents; ++i) {
6047 assert(rec->amplitude[i] >= 0.0);
6048 if (rec->amplitude[i] >= AMPLITUDE_EPSILON) ++count;
6051 rec->header.record_size +=
6052 (count * hd.constituent_bits + count * hd.amplitude_bits +
6053 count * hd.epoch_bits);
6057 case SUBORDINATE_STATION:
6058 rec->header.record_size += hd.time_bits + hd.level_add_bits +
6059 hd.level_multiply_bits + hd.time_bits +
6060 hd.level_add_bits + hd.level_multiply_bits +
6061 hd.time_bits + hd.time_bits;
6068 rec->header.record_size = bits2bytes(rec->header.record_size);
6075static void pack_string(NV_U_BYTE *buf, NV_U_INT32 *pos, NV_CHAR *s) {
6076 NV_U_INT32 i, temp_size;
6080 temp_size = strlen(s) + 1;
6081 for (i = 0; i < temp_size; ++i) {
6082 bit_pack(buf, *pos, 8, s[i]);
6107static void pack_tide_record(
TIDE_RECORD *rec, NV_U_BYTE **bufptr,
6108 NV_U_INT32 *bufsize) {
6109 NV_U_INT32 i, pos, constituent_count;
6118 boundscheck_oneliner(rec->header.name);
6119 boundscheck_oneliner(rec->source);
6120 boundscheck_monologue(rec->comments);
6121 boundscheck_monologue(rec->notes);
6122 boundscheck_oneliner(rec->station_id_context);
6123 boundscheck_oneliner(rec->station_id);
6124 boundscheck_monologue(rec->xfields);
6126 constituent_count = figure_size(rec);
6129 (NV_U_BYTE *)calloc(rec->header.record_size,
sizeof(NV_U_BYTE)))) {
6130 perror(
"libtcd can't allocate memory in pack_tide_record");
6140 bit_pack(buf, pos, hd.record_size_bits, rec->header.record_size);
6141 pos += hd.record_size_bits;
6143 bit_pack(buf, pos, hd.record_type_bits, rec->header.record_type);
6144 pos += hd.record_type_bits;
6146 temp_int = NINT(rec->header.latitude * hd.latitude_scale);
6147 bit_pack(buf, pos, hd.latitude_bits, temp_int);
6148 pos += hd.latitude_bits;
6150 temp_int = NINT(rec->header.longitude * hd.longitude_scale);
6151 bit_pack(buf, pos, hd.longitude_bits, temp_int);
6152 pos += hd.longitude_bits;
6158 bit_pack(buf, pos, hd.tzfile_bits, rec->header.tzfile);
6159 pos += hd.tzfile_bits;
6161 pack_string(buf, &pos, clip_string(rec->header.name));
6163 bit_pack(buf, pos, hd.station_bits, rec->header.reference_station);
6164 pos += hd.station_bits;
6166 bit_pack(buf, pos, hd.country_bits, rec->country);
6167 pos += hd.country_bits;
6169 pack_string(buf, &pos, clip_string(rec->source));
6171 bit_pack(buf, pos, hd.restriction_bits, rec->restriction);
6172 pos += hd.restriction_bits;
6174 pack_string(buf, &pos, clip_string(rec->comments));
6175 pack_string(buf, &pos, clip_string(rec->notes));
6177 bit_pack(buf, pos, hd.legalese_bits, rec->legalese);
6178 pos += hd.legalese_bits;
6180 pack_string(buf, &pos, clip_string(rec->station_id_context));
6181 pack_string(buf, &pos, clip_string(rec->station_id));
6183 bit_pack(buf, pos, hd.date_bits, rec->date_imported);
6184 pos += hd.date_bits;
6187 pack_string(buf, &pos, rec->xfields);
6189 bit_pack(buf, pos, hd.dir_unit_bits, rec->direction_units);
6190 pos += hd.dir_unit_bits;
6192 bit_pack(buf, pos, hd.direction_bits, rec->min_direction);
6193 pos += hd.direction_bits;
6195 bit_pack(buf, pos, hd.direction_bits, rec->max_direction);
6196 pos += hd.direction_bits;
6199 bit_pack(buf, pos, hd.level_unit_bits, rec->level_units);
6200 pos += hd.level_unit_bits;
6204 if (rec->header.record_type == REFERENCE_STATION) {
6205 temp_int = NINT(rec->datum_offset * hd.datum_offset_scale);
6206 bit_pack(buf, pos, hd.datum_offset_bits, temp_int);
6207 pos += hd.datum_offset_bits;
6209 bit_pack(buf, pos, hd.datum_bits, rec->datum);
6210 pos += hd.datum_bits;
6212 bit_pack(buf, pos, hd.time_bits, rec->zone_offset);
6213 pos += hd.time_bits;
6215 bit_pack(buf, pos, hd.date_bits, rec->expiration_date);
6216 pos += hd.date_bits;
6218 bit_pack(buf, pos, hd.months_on_station_bits, rec->months_on_station);
6219 pos += hd.months_on_station_bits;
6221 bit_pack(buf, pos, hd.date_bits, rec->last_date_on_station);
6222 pos += hd.date_bits;
6224 bit_pack(buf, pos, hd.confidence_value_bits, rec->confidence);
6225 pos += hd.confidence_value_bits;
6227 bit_pack(buf, pos, hd.constituent_bits, constituent_count);
6228 pos += hd.constituent_bits;
6230 for (i = 0; i < hd.pub.constituents; ++i) {
6231 if (rec->amplitude[i] >= AMPLITUDE_EPSILON) {
6232 bit_pack(buf, pos, hd.constituent_bits, i);
6233 pos += hd.constituent_bits;
6235 temp_int = NINT(rec->amplitude[i] * hd.amplitude_scale);
6237 bit_pack(buf, pos, hd.amplitude_bits, temp_int);
6238 pos += hd.amplitude_bits;
6240 temp_int = NINT(rec->epoch[i] * hd.epoch_scale);
6241 bit_pack(buf, pos, hd.epoch_bits, temp_int);
6242 pos += hd.epoch_bits;
6248 else if (rec->header.record_type == SUBORDINATE_STATION) {
6249 bit_pack(buf, pos, hd.time_bits, rec->min_time_add);
6250 pos += hd.time_bits;
6252 temp_int = NINT(rec->min_level_add * hd.level_add_scale);
6253 bit_pack(buf, pos, hd.level_add_bits, temp_int);
6254 pos += hd.level_add_bits;
6256 temp_int = NINT(rec->min_level_multiply * hd.level_multiply_scale);
6257 bit_pack(buf, pos, hd.level_multiply_bits, temp_int);
6258 pos += hd.level_multiply_bits;
6260 bit_pack(buf, pos, hd.time_bits, rec->max_time_add);
6261 pos += hd.time_bits;
6263 temp_int = NINT(rec->max_level_add * hd.level_add_scale);
6264 bit_pack(buf, pos, hd.level_add_bits, temp_int);
6265 pos += hd.level_add_bits;
6267 temp_int = NINT(rec->max_level_multiply * hd.level_multiply_scale);
6268 bit_pack(buf, pos, hd.level_multiply_bits, temp_int);
6269 pos += hd.level_multiply_bits;
6271 bit_pack(buf, pos, hd.time_bits, rec->flood_begins);
6272 pos += hd.time_bits;
6274 bit_pack(buf, pos, hd.time_bits, rec->ebb_begins);
6275 pos += hd.time_bits;
6279 LOG_ERROR(
"libtcd error: Record type %d is undefined\n",
6280 rec->header.record_type);
6284 *bufsize = rec->header.record_size;
6285 assert(*bufsize == bits2bytes(pos));
6310static NV_BOOL write_tide_record(NV_INT32 num,
TIDE_RECORD *rec) {
6311 NV_U_BYTE *buf = NULL;
6312 NV_U_INT32 bufsize = 0;
6316 "libtcd error: attempt to access database when database not open\n");
6321 pack_tide_record(rec, &buf, &bufsize);
6326 fseek(fp, tindex[num].address, SEEK_SET);
6330 chk_fwrite(buf, bufsize, 1, fp);
6355 return (read_tide_record(current_record + 1, rec));
6379static void unpack_tide_record(NV_U_BYTE *buf, NV_U_INT32 bufsize,
6382 NV_U_INT32 i, j, pos, count;
6389 int r = find_dir_units(
"degrees true");
6391 rec->direction_units = (NV_U_BYTE)r;
6393 rec->min_direction = rec->max_direction = 361;
6394 rec->flood_begins = rec->ebb_begins = NULLSLACKOFFSET;
6395 rec->header.record_number = current_record;
6397 unpack_partial_tide_record(buf, bufsize, rec, &pos);
6399 switch (rec->header.record_type) {
6400 case REFERENCE_STATION:
6401 case SUBORDINATE_STATION:
6404 LOG_ERROR(
"libtcd fatal error: tried to read type %d tide record.\n",
6405 rec->header.record_type);
6407 "This version of libtcd only supports types 1 and 2. Perhaps you "
6408 "should\nupgrade.\n");
6412 switch (hd.pub.major_rev) {
6419 rec->country = bit_unpack(buf, pos, hd.country_bits);
6420 pos += hd.country_bits;
6423 pos += hd.pedigree_bits;
6425 unpack_string(buf, bufsize, &pos, rec->source, ONELINER_LENGTH,
6428 rec->restriction = bit_unpack(buf, pos, hd.restriction_bits);
6429 pos += hd.restriction_bits;
6431 unpack_string(buf, bufsize, &pos, rec->comments, MONOLOGUE_LENGTH,
6434 if (rec->header.record_type == REFERENCE_STATION) {
6435 rec->level_units = bit_unpack(buf, pos, hd.level_unit_bits);
6437 rec->units = rec->level_units;
6439 pos += hd.level_unit_bits;
6441 temp_int = signed_bit_unpack(buf, pos, hd.datum_offset_bits);
6442 rec->datum_offset = (NV_FLOAT32)temp_int / hd.datum_offset_scale;
6443 pos += hd.datum_offset_bits;
6445 rec->datum = bit_unpack(buf, pos, hd.datum_bits);
6446 pos += hd.datum_bits;
6448 rec->zone_offset = signed_bit_unpack(buf, pos, hd.time_bits);
6449 pos += hd.time_bits;
6451 rec->expiration_date = bit_unpack(buf, pos, hd.date_bits);
6452 pos += hd.date_bits;
6454 rec->months_on_station =
6455 bit_unpack(buf, pos, hd.months_on_station_bits);
6456 pos += hd.months_on_station_bits;
6458 rec->last_date_on_station = bit_unpack(buf, pos, hd.date_bits);
6459 pos += hd.date_bits;
6461 rec->confidence = bit_unpack(buf, pos, hd.confidence_value_bits);
6462 pos += hd.confidence_value_bits;
6464 for (i = 0; i < hd.pub.constituents; ++i) {
6465 rec->amplitude[i] = 0.0;
6466 rec->epoch[i] = 0.0;
6469 count = bit_unpack(buf, pos, hd.constituent_bits);
6470 pos += hd.constituent_bits;
6472 for (i = 0; i < count; ++i) {
6473 j = bit_unpack(buf, pos, hd.constituent_bits);
6474 pos += hd.constituent_bits;
6477 (NV_FLOAT32)bit_unpack(buf, pos, hd.amplitude_bits) /
6479 pos += hd.amplitude_bits;
6482 (NV_FLOAT32)bit_unpack(buf, pos, hd.epoch_bits) / hd.epoch_scale;
6483 pos += hd.epoch_bits;
6485 }
else if (rec->header.record_type == SUBORDINATE_STATION) {
6486 rec->level_units = bit_unpack(buf, pos, hd.level_unit_bits);
6487 pos += hd.level_unit_bits;
6489 rec->direction_units = bit_unpack(buf, pos, hd.dir_unit_bits);
6490 pos += hd.dir_unit_bits;
6493 pos += hd.level_unit_bits;
6495 rec->min_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6496 pos += hd.time_bits;
6498 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6499 rec->min_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6500 pos += hd.level_add_bits;
6503 temp_int = signed_bit_unpack(buf, pos, hd.level_multiply_bits);
6504 rec->min_level_multiply =
6505 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6506 pos += hd.level_multiply_bits;
6509 pos += hd.level_add_bits;
6511 rec->min_direction = bit_unpack(buf, pos, hd.direction_bits);
6512 pos += hd.direction_bits;
6514 rec->max_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6515 pos += hd.time_bits;
6517 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6518 rec->max_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6519 pos += hd.level_add_bits;
6522 temp_int = signed_bit_unpack(buf, pos, hd.level_multiply_bits);
6523 rec->max_level_multiply =
6524 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6525 pos += hd.level_multiply_bits;
6528 pos += hd.level_add_bits;
6530 rec->max_direction = bit_unpack(buf, pos, hd.direction_bits);
6531 pos += hd.direction_bits;
6533 rec->flood_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6534 pos += hd.time_bits;
6536 rec->ebb_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6537 pos += hd.time_bits;
6545 rec->country = bit_unpack(buf, pos, hd.country_bits);
6546 pos += hd.country_bits;
6548 unpack_string(buf, bufsize, &pos, rec->source, ONELINER_LENGTH,
6551 rec->restriction = bit_unpack(buf, pos, hd.restriction_bits);
6552 pos += hd.restriction_bits;
6554 unpack_string(buf, bufsize, &pos, rec->comments, MONOLOGUE_LENGTH,
6556 unpack_string(buf, bufsize, &pos, rec->notes, MONOLOGUE_LENGTH,
6559 rec->legalese = bit_unpack(buf, pos, hd.legalese_bits);
6560 pos += hd.legalese_bits;
6562 unpack_string(buf, bufsize, &pos, rec->station_id_context,
6563 ONELINER_LENGTH,
"station_id_context field");
6564 unpack_string(buf, bufsize, &pos, rec->station_id, ONELINER_LENGTH,
6565 "station_id field");
6567 rec->date_imported = bit_unpack(buf, pos, hd.date_bits);
6568 pos += hd.date_bits;
6570 unpack_string(buf, bufsize, &pos, rec->xfields, MONOLOGUE_LENGTH,
6573 rec->direction_units = bit_unpack(buf, pos, hd.dir_unit_bits);
6574 pos += hd.dir_unit_bits;
6576 rec->min_direction = bit_unpack(buf, pos, hd.direction_bits);
6577 pos += hd.direction_bits;
6579 rec->max_direction = bit_unpack(buf, pos, hd.direction_bits);
6580 pos += hd.direction_bits;
6582 rec->level_units = bit_unpack(buf, pos, hd.level_unit_bits);
6584 rec->units = rec->level_units;
6586 pos += hd.level_unit_bits;
6588 if (rec->header.record_type == REFERENCE_STATION) {
6589 temp_int = signed_bit_unpack(buf, pos, hd.datum_offset_bits);
6590 rec->datum_offset = (NV_FLOAT32)temp_int / hd.datum_offset_scale;
6591 pos += hd.datum_offset_bits;
6593 rec->datum = bit_unpack(buf, pos, hd.datum_bits);
6594 pos += hd.datum_bits;
6596 rec->zone_offset = signed_bit_unpack(buf, pos, hd.time_bits);
6597 pos += hd.time_bits;
6599 rec->expiration_date = bit_unpack(buf, pos, hd.date_bits);
6600 pos += hd.date_bits;
6602 rec->months_on_station =
6603 bit_unpack(buf, pos, hd.months_on_station_bits);
6604 pos += hd.months_on_station_bits;
6606 rec->last_date_on_station = bit_unpack(buf, pos, hd.date_bits);
6607 pos += hd.date_bits;
6609 rec->confidence = bit_unpack(buf, pos, hd.confidence_value_bits);
6610 pos += hd.confidence_value_bits;
6612 for (i = 0; i < hd.pub.constituents; ++i) {
6613 rec->amplitude[i] = 0.0;
6614 rec->epoch[i] = 0.0;
6617 count = bit_unpack(buf, pos, hd.constituent_bits);
6618 pos += hd.constituent_bits;
6620 for (i = 0; i < count; ++i) {
6621 j = bit_unpack(buf, pos, hd.constituent_bits);
6622 pos += hd.constituent_bits;
6625 (NV_FLOAT32)bit_unpack(buf, pos, hd.amplitude_bits) /
6627 pos += hd.amplitude_bits;
6630 (NV_FLOAT32)bit_unpack(buf, pos, hd.epoch_bits) / hd.epoch_scale;
6631 pos += hd.epoch_bits;
6633 }
else if (rec->header.record_type == SUBORDINATE_STATION) {
6634 rec->min_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6635 pos += hd.time_bits;
6637 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6638 rec->min_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6639 pos += hd.level_add_bits;
6642 temp_int = bit_unpack(buf, pos, hd.level_multiply_bits);
6643 rec->min_level_multiply =
6644 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6645 pos += hd.level_multiply_bits;
6647 rec->max_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6648 pos += hd.time_bits;
6650 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6651 rec->max_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6652 pos += hd.level_add_bits;
6655 temp_int = bit_unpack(buf, pos, hd.level_multiply_bits);
6656 rec->max_level_multiply =
6657 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6658 pos += hd.level_multiply_bits;
6660 rec->flood_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6661 pos += hd.time_bits;
6663 rec->ebb_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6664 pos += hd.time_bits;
6674 assert(pos <= bufsize * 8);
6698NV_INT32 read_tide_record(NV_INT32 num,
TIDE_RECORD *rec) {
6704 "libtcd error: attempt to access database when database not open\n");
6708 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return -1;
6711 bufsize = tindex[num].record_size;
6712 if ((buf = (NV_U_BYTE *)calloc(bufsize,
sizeof(NV_U_BYTE))) == NULL) {
6713 perror(
"Allocating read_tide_record buffer");
6717 current_record = num;
6718 require(fseek(fp, tindex[num].address, SEEK_SET) == 0);
6719 chk_fread(buf, tindex[num].record_size, 1, fp);
6720 unpack_tide_record(buf, bufsize, rec);
6747 "libtcd error: attempt to access database when database not open\n");
6752 if (!check_tide_record(rec))
return NVFalse;
6754 fseek(fp, hd.end_of_file, SEEK_SET);
6758 rec->header.record_number = hd.pub.number_of_records++;
6760 if (write_tide_record(-1, rec)) {
6762 tindex, hd.pub.number_of_records *
sizeof(
TIDE_INDEX))) == NULL) {
6763 perror(
"Allocating more index records");
6767 tindex[rec->header.record_number].address = pos;
6768 tindex[rec->header.record_number].record_size = rec->header.record_size;
6769 tindex[rec->header.record_number].record_type = rec->header.record_type;
6770 tindex[rec->header.record_number].reference_station =
6771 rec->header.reference_station;
6772 assert(rec->header.tzfile >= 0);
6773 tindex[rec->header.record_number].tzfile = rec->header.tzfile;
6774 tindex[rec->header.record_number].lat =
6775 NINT(rec->header.latitude * hd.latitude_scale);
6776 tindex[rec->header.record_number].lon =
6777 NINT(rec->header.longitude * hd.longitude_scale);
6779 if ((tindex[rec->header.record_number].name = (NV_CHAR *)calloc(
6780 strlen(rec->header.name) + 1,
sizeof(NV_CHAR))) == NULL) {
6781 perror(
"Allocating index name memory");
6785 strcpy(tindex[rec->header.record_number].name, rec->header.name);
6788 hd.end_of_file = pos;
6792 if (db) *db = hd.pub;
6821 NV_INT32 i, newrecnum, *map;
6822 NV_U_BYTE **allrecs_packed;
6825 LOG_ERROR (
"libtcd error: attempt to access database when database not open\n");
6830 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return NVFalse;
6834 if (!(map = (NV_INT32 *) malloc (hd.pub.number_of_records *
sizeof(NV_INT32)))) {
6835 perror (
"libtcd: delete_tide_record: can't malloc");
6838 if (!(allrecs_packed = (NV_U_BYTE **) malloc (hd.pub.number_of_records *
sizeof(NV_U_BYTE*)))) {
6839 perror (
"libtcd: delete_tide_record: can't malloc");
6847 require (fseek (fp, tindex[0].address, SEEK_SET) == 0);
6848 for (newrecnum=0,i=0; i<(NV_INT32)hd.pub.number_of_records; ++i) {
6849 assert (ftell(fp) == tindex[i].address);
6850 if (i == num || (tindex[i].record_type == SUBORDINATE_STATION && tindex[i].reference_station == num)) {
6852 allrecs_packed[i] = NULL;
6853 require (fseek (fp, tindex[i].record_size, SEEK_CUR) == 0);
6855 map[i] = newrecnum++;
6856 if (!(allrecs_packed[i] = (NV_U_BYTE *) malloc (tindex[i].record_size))) {
6857 perror (
"libtcd: delete_tide_record: can't malloc");
6858 for (--i; i>=0; --i)
6859 free (allrecs_packed[i]);
6860 free (allrecs_packed);
6864 chk_fread (allrecs_packed[i], tindex[i].record_size, 1, fp);
6870 require (fseek (fp, tindex[0].address, SEEK_SET) == 0);
6871 require (ftruncate (fileno(fp), tindex[0].address) == 0);
6873 for (i=0; i<(NV_INT32)hd.pub.number_of_records; ++i)
6875 if (tindex[i].record_type == SUBORDINATE_STATION) {
6876 assert (tindex[i].reference_station >= 0);
6877 assert (tindex[i].reference_station <= (NV_INT32)hd.pub.number_of_records);
6878 if (map[tindex[i].reference_station] != tindex[i].reference_station) {
6881 unpack_tide_record (allrecs_packed[i], tindex[i].record_size, &rec);
6882 free (allrecs_packed[i]);
6883 rec.header.reference_station = map[tindex[i].reference_station];
6884 pack_tide_record (&rec, &(allrecs_packed[i]), &(tindex[i].record_size));
6887 chk_fwrite (allrecs_packed[i], tindex[i].record_size, 1, fp);
6888 free (allrecs_packed[i]);
6893 free (allrecs_packed);
6899 hd.end_of_file = ftell(fp);
6900 hd.pub.number_of_records = newrecnum;
6903 open_tide_db (filename);
6932NV_BOOL update_tide_record(NV_INT32 num,
TIDE_RECORD *rec)
6939 NV_U_BYTE *
block = NULL;
6943 "libtcd error: attempt to access database when database not open\n");
6948 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return NVFalse;
6950 if (!check_tide_record(rec))
return NVFalse;
6953 read_tide_record(num, &tmp_rec);
6954 if (rec->header.record_size != tmp_rec.header.record_size) {
6962 size = hd.end_of_file - pos;
6967 if ((
block = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
6968 perror(
"Allocating block");
6971 chk_fread(
block, size, 1, fp);
6975 write_tide_record(num, rec);
6979 chk_fwrite(
block, size, 1, fp);
6983 hd.end_of_file = ftell(fp);
6987 open_tide_db(filename);
6992 write_tide_record(num, rec);
6995 tindex[num].record_size = rec->header.record_size;
6996 tindex[num].record_type = rec->header.record_type;
6997 tindex[num].reference_station = rec->header.reference_station;
6998 tindex[num].tzfile = rec->header.tzfile;
6999 tindex[num].lat = NINT(rec->header.latitude * hd.latitude_scale);
7000 tindex[num].lon = NINT(rec->header.longitude * hd.longitude_scale);
7005 if (strcmp(tindex[num].name, rec->header.name) != 0) {
7006 free(tindex[num].name);
7008 (NV_CHAR *)calloc(strlen(rec->header.name) + 1,
sizeof(NV_CHAR));
7009 strcpy(tindex[num].name, rec->header.name);
7014 if (db) *db = hd.pub;
7051 NV_INT32 m2, s2, k1, o1;
7052 NV_FLOAT32 epoch_m2, epoch_s2, epoch_k1, epoch_o1;
7055 require((m2 = find_constituent(
"M2")) >= 0);
7056 require((s2 = find_constituent(
"S2")) >= 0);
7057 require((k1 = find_constituent(
"K1")) >= 0);
7058 require((o1 = find_constituent(
"O1")) >= 0);
7060 if (rec->amplitude[m2] == 0.0 || rec->amplitude[s2] == 0.0 ||
7061 rec->amplitude[k1] == 0.0 || rec->amplitude[o1] == 0.0)
7064 epoch_m2 = rec->epoch[m2];
7065 epoch_s2 = rec->epoch[s2];
7066 epoch_k1 = rec->epoch[k1];
7067 epoch_o1 = rec->epoch[o1];
7069 for (i = 0; i < hd.pub.constituents; ++i) {
7070 if (rec->amplitude[i] == 0.0 && rec->epoch[i] == 0.0) {
7071 for (j = 0; j < INFERRED_SEMI_DIURNAL_COUNT; ++j) {
7072 if (!strcmp(inferred_semi_diurnal[j], get_constituent(i))) {
7076 (semi_diurnal_coeff[j] / coeff[0]) * rec->amplitude[m2];
7078 if (fabs((NV_FLOAT64)(epoch_s2 - epoch_m2)) > 180.0) {
7079 if (epoch_s2 < epoch_m2) {
7085 rec->epoch[i] = epoch_m2 + ((hd.speed[i] - hd.speed[m2]) /
7086 (hd.speed[s2] - hd.speed[m2])) *
7087 (epoch_s2 - epoch_m2);
7091 for (j = 0; j < INFERRED_DIURNAL_COUNT; ++j) {
7092 if (!strcmp(inferred_diurnal[j], get_constituent(i))) {
7096 (diurnal_coeff[j] / coeff[1]) * rec->amplitude[o1];
7098 if (fabs((NV_FLOAT64)(epoch_k1 - epoch_o1)) > 180.0) {
7099 if (epoch_k1 < epoch_o1) {
7105 rec->epoch[i] = epoch_o1 + ((hd.speed[i] - hd.speed[o1]) /
7106 (hd.speed[k1] - hd.speed[o1])) *
7107 (epoch_k1 - epoch_o1);
7122static NV_U_BYTE mask[8] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe},
7123 notmask[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
7162NV_U_INT32 calculate_bits(NV_U_INT32 value) {
7163 NV_U_INT32 bits = 32;
7164 NV_U_INT32 theBit = 0x80000000;
7166 while (value < theBit) {
7201void bit_pack(NV_U_BYTE buffer[], NV_U_INT32 start, NV_U_INT32 numbits,
7203 NV_INT32 start_byte, end_byte, start_bit, end_bit, i;
7205 i = start + numbits;
7211 start_byte = start >> 3;
7218 start_bit = start & 7;
7223 i = end_byte - start_byte - 1;
7227 if (start_byte == end_byte) {
7232 buffer[start_byte] &= mask[start_bit] | notmask[end_bit];
7238 buffer[start_byte] |=
7239 (value << (8 - end_bit)) & (notmask[start_bit] & mask[end_bit]);
7245#pragma GCC diagnostic push
7246#pragma GCC diagnostic ignored "-Warray-bounds"
7251 buffer[start_byte] &= mask[start_bit];
7259 buffer[start_byte++] |=
7260 (value >> (numbits - (8 - start_bit))) & notmask[start_bit];
7267 buffer[start_byte] &= 0;
7271 buffer[start_byte++] |= (value >> ((i << 3) + end_bit)) & 255;
7276 buffer[start_byte] &= notmask[end_bit];
7282 buffer[start_byte] |= (value << (8 - end_bit));
7283#pragma GCC diagnostic pop
7313NV_U_INT32 bit_unpack(NV_U_BYTE buffer[], NV_U_INT32 start,
7314 NV_U_INT32 numbits) {
7315 NV_INT32 start_byte, end_byte, start_bit, end_bit, i;
7318 i = start + numbits;
7324 start_byte = start >> 3;
7331 start_bit = start & 7;
7336 i = end_byte - start_byte - 1;
7340 if (start_byte == end_byte) {
7344 (NV_U_INT32)buffer[start_byte] & (notmask[start_bit] & mask[end_bit]);
7348 value >>= (8 - end_bit);
7357 value = (NV_U_INT32)(buffer[start_byte++] & notmask[start_bit])
7358 << (numbits - (8 - start_bit));
7365 value += (NV_U_INT32)buffer[start_byte++] << ((i << 3) + end_bit);
7370 if (mask[end_bit]) {
7372 (NV_U_INT32)(buffer[start_byte] & mask[end_bit]) >> (8 - end_bit);
7405NV_INT32 signed_bit_unpack(NV_U_BYTE buffer[], NV_U_INT32 start,
7406 NV_U_INT32 numbits) {
7407 static NV_INT32 extend_mask = 0x7fffffff;
7411 assert(numbits > 0);
7413 value = bit_unpack(buffer, start, numbits);
7415 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.