28#include <wx/hashmap.h>
50static time_t s_next_epoch = TIDE_BAD_TIME;
51static time_t s_this_epoch = TIDE_BAD_TIME;
52static int s_this_year = -1;
54static double time2dt_tide(time_t t,
int deriv,
IDX_entry *pIDX);
55static int yearoftimet(time_t t);
56static void happy_new_year(
IDX_entry *pIDX,
int new_year);
57static void set_epoch(
IDX_entry *pIDX,
int year);
59static double time2tide(time_t t,
IDX_entry *pIDX) {
60 return time2dt_tide(t, 0, pIDX);
70 if (!pmsd->have_BOGUS)
81double time2atide(time_t t,
IDX_entry *pIDX) {
93int next_big_event(time_t *tm,
IDX_entry *pIDX) {
95 int flags = 0, slope = 0;
96 p = time2atide(*tm, pIDX);
98 q = time2atide(*tm, pIDX);
100 if (p < q) slope = 1;
102 if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
104 flags |= (1 << slope);
118 if ((p > marklev && q <= marklev) || (p < marklev && q >= marklev)) {
134 q = time2atide(*tm, pIDX);
135 if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
137 flags |= (1 << slope);
149 if (flags < 4) *tm -= 60;
153 q = time2atide(*tm, pIDX);
162double time2mean(time_t t,
IDX_entry *pIDX) {
165 int new_year = yearoftimet(t);
166 if (pIDX->
epoch_year != new_year) happy_new_year(pIDX, new_year);
168 for (a = 0; a < pIDX->
num_csts; a++) {
185double time2asecondary(time_t t,
IDX_entry *pIDX) {
189 if (!(pIDX->
have_offsets))
return time2atide(tadj, pIDX);
196#define intervalwidth 15
197#define stretchfactor 3
199 static time_t lowtime = 0, hightime = 0;
200 static double lowlvl, highlvl;
202 double S, Z, HI, HS, magicnum;
203 time_t interval = 3600 * intervalwidth;
204 long difflow, diffhigh;
205 int badlowflag = 0, badhighflag = 0;
220 Z = time2mean(T, pIDX);
221 S = time2tide(T, pIDX) - Z;
243 difflow = T - lowtime;
245 difflow = lowtime - T;
247 diffhigh = T - hightime;
249 diffhigh = hightime - T;
252 if (difflow > interval * stretchfactor) badlowflag = 1;
253 if (badlowflag || (difflow > interval && S > 0)) {
257 next_big_event(&tt, pIDX);
258 lowlvl = time2tide(tt, pIDX);
260 while (tt < T + interval) {
261 next_big_event(&tt, pIDX);
262 tl = time2tide(tt, pIDX);
263 if (tl < lowlvl && tt < T + interval) {
270 if (diffhigh > interval * stretchfactor) badhighflag = 1;
271 if (badhighflag || (diffhigh > interval && S < 0)) {
275 next_big_event(&tt, pIDX);
276 highlvl = time2tide(tt, pIDX);
278 while (tt < T + interval) {
279 next_big_event(&tt, pIDX);
280 tl = time2tide(tt, pIDX);
281 if (tl > highlvl && tt < T + interval) {
301 magicnum = 0.5 * S / fabs(highlvl - Z);
303 magicnum = 0.5 * S / fabs(lowlvl - Z);
307 HI = time2tide(T, pIDX);
310 double ht_off, lt_off;
323 double RH = 1.0, RL = 1.0, HH = 0.0, HL = 0.0;
332 HS = HI * ((RH + RL) / 2 + (RH - RL) * magicnum) + (HH + HL) / 2 +
333 (HH - HL) * magicnum;
387double _time2dt_tide(time_t t,
int deriv,
IDX_entry *pIDX) {
388 double dt_tide = 0.0;
392 tempd = M_PI / 2.0 * deriv;
393 for (a = 0; a < pIDX->
num_csts; a++) {
400 for (b = deriv; b > 0; b--) term *= pIDX->
m_cst_speeds[a];
423static double blend_weight(
double x,
int deriv) {
426 if (x2 >= 1.0)
return deriv == 0 && x > 0.0 ? 1.0 : 0.0;
430 return ((3.0 * x2 - 10.0) * x2 + 15.0) * x / 16.0 + 0.5;
432 return ((x2 - 2.0) * x2 + 1.0) * (15.0 / 16.0);
434 return (x2 - 1.0) * x * (15.0 / 4.0);
443double blend_tide(time_t t,
unsigned int deriv,
int first_year,
double blend,
445 double fl[TIDE_MAX_DERIV + 1];
446 double fr[TIDE_MAX_DERIV + 1];
448 double w[TIDE_MAX_DERIV + 1];
457 int year = yearoftimet(t);
458 if (year == first_year + 1)
460 else if (year != first_year)
461 happy_new_year(pIDX, first_year);
462 for (n = 0; n <= deriv; n++) fp[n] = _time2dt_tide(t, n, pIDX);
469 happy_new_year(pIDX, first_year + 1);
472 happy_new_year(pIDX, first_year);
475 for (n = 0; n <= deriv; n++) {
476 fp[n] = _time2dt_tide(t, n, pIDX);
477 w[n] = blend_weight(blend, n);
485 for (n = 0; n <= deriv; n++) {
486 f += fact * w[n] * (fr[deriv - n] - fl[deriv - n]);
487 fact *= (double)(deriv - n) / (n + 1) * (1.0 / TIDE_BLEND_TIME);
489 printf(
" %ld %g %g %g %g\n", (
long)t, blend, fr[0], fl[0], f);
493static double time2dt_tide(time_t t,
int deriv,
IDX_entry *pIDX) {
495 int yott = yearoftimet(t);
499 if (new_year != s_this_year) {
501 set_epoch(pIDX, new_year + 1);
502 s_next_epoch = pIDX->
epoch;
504 s_next_epoch = TIDE_BAD_TIME;
506 happy_new_year(pIDX, s_this_year = new_year);
507 s_this_epoch = pIDX->
epoch;
514 if (t - s_this_epoch <= TIDE_BLEND_TIME && s_this_year > pIDX->
first_year)
515 return blend_tide(t, deriv, s_this_year - 1,
516 (
double)(t - s_this_epoch) / TIDE_BLEND_TIME, pIDX);
517 else if (s_next_epoch - t <= TIDE_BLEND_TIME &&
519 return blend_tide(t, deriv, s_this_year,
520 -(
double)(s_next_epoch - t) / TIDE_BLEND_TIME, pIDX);
525 if (pIDX->
epoch_year != new_year) happy_new_year(pIDX, new_year);
527 return _time2dt_tide(t, deriv, pIDX);
532void figure_max_amplitude(
IDX_entry *pIDX) {
537 double year_amp = 0.0;
539 for (a = 0; a < pIDX->
num_csts; a++)
547void figure_multipliers(
IDX_entry *pIDX,
int year) {
550 figure_max_amplitude(pIDX);
551 for (a = 0; a < pIDX->
num_csts; a++) {
559#define compare_int(a, b) (((int)(a)) - ((int)(b)))
560int compare_tm(
struct tm *a,
struct tm *b) {
568 temp = compare_int(a->tm_year, b->tm_year);
569 if (temp)
return temp;
570 temp = compare_int(a->tm_mon, b->tm_mon);
571 if (temp)
return temp;
572 temp = compare_int(a->tm_mday, b->tm_mday);
573 if (temp)
return temp;
574 temp = compare_int(a->tm_hour, b->tm_hour);
575 if (temp)
return temp;
576 temp = compare_int(a->tm_min, b->tm_min);
577 if (temp)
return temp;
578 return compare_int(a->tm_sec, b->tm_sec);
584time_t tm2gmt(
struct tm *ht) {
585 time_t guess, newguess, thebit;
586 int loopcounter, compare;
590 loopcounter = (
sizeof(time_t) * 8) - 1;
591 thebit = ((time_t)1) << (loopcounter - 1);
596 if ((
signed long)thebit < (time_t)(0)) {
599 thebit = ((time_t)1) << (loopcounter - 1);
602 for (; loopcounter; loopcounter--) {
603 newguess = guess | thebit;
604 gt = gmtime(&newguess);
606 compare = compare_tm(gt, ht);
607 if (compare <= 0) guess = newguess;
615static int yearoftimet(time_t t) {
return ((gmtime(&t))->tm_year) + 1900; }
618static void set_epoch(
IDX_entry *pIDX,
int year) {
621 ht.tm_year = year - 1900;
622 ht.tm_sec = ht.tm_min = ht.tm_hour = ht.tm_mon = 0;
624 pIDX->
epoch = tm2gmt(&ht);
628static void happy_new_year(
IDX_entry *pIDX,
int new_year) {
630 figure_multipliers(pIDX, new_year);
631 set_epoch(pIDX, new_year);
637TCMgr::~TCMgr() { PurgeData(); }
639void TCMgr::PurgeData() {
640 m_Combined_IDX_array.clear();
643 m_source_array.Clear();
646TC_Error_Code TCMgr::LoadDataSources(std::vector<std::string> &sources) {
650 m_sourcefile_array.clear();
651 m_sourcefile_array = sources;
655 for (
auto src : sources) {
657 TC_Error_Code r = s->LoadData(src);
658 if (r != TC_NO_ERROR) {
660 msg.Printf(
" Error loading Tide/Currect data source %s ", src.c_str());
661 if (r == TC_FILE_NOT_FOUND)
662 msg +=
"Error Code: TC_FILE_NOT_FOUND";
665 msg1.Printf(
"Error code: %d", r);
671 m_source_array.Add(s);
673 for (
int k = 0; k < s->GetMaxIndex(); k++) {
677 m_Combined_IDX_array.push_back(pIDX);
684 if (m_Combined_IDX_array.empty())
686 NULL, _(
"It seems you have no tide/current harmonic data installed."),
687 _(
"OpenCPN Info"), wxOK | wxCENTER);
689 ScrubCurrentDepths();
693void TCMgr::ScrubCurrentDepths() {
698 WX_DECLARE_STRING_HASH_MAP(
int, currentDepth_index_hash);
700 currentDepth_index_hash hash1;
702 for (
int i = 1; i < Get_max_IDX() + 1; i++) {
717 currentDepth_index_hash::iterator it = hash1.find(key1);
718 if (it == hash1.end()) {
727 if (depth_a < depth_b) {
739const IDX_entry *TCMgr::GetIDX_entry(
int index)
const {
740 if ((
unsigned int)index < m_Combined_IDX_array.size())
741 return m_Combined_IDX_array[index];
746bool TCMgr::GetTideOrCurrent(time_t t,
int idx,
float &tcvalue,
float &dir) {
752 IDX_entry *pIDX = m_Combined_IDX_array[idx];
767 if (pIDX->
pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
return false;
771 int yott = yearoftimet(t);
773 happy_new_year(pIDX, yott);
777 double level = time2asecondary(t + (00 * 60), pIDX);
788extern wxDateTime gTimeSource;
790bool TCMgr::GetTideOrCurrent15(time_t t_d,
int idx,
float &tcvalue,
float &dir,
793 IDX_entry *pIDX = m_Combined_IDX_array[idx];
802 wxDateTime this_now = gTimeSource;
803 if (this_now.IsValid() ==
false) this_now = wxDateTime::Now();
804 wxDateTime this_gmt = this_now.ToGMT();
805 wxTimeSpan diff = this_gmt.Subtract(this_now);
806 int diff_mins = diff.GetMinutes();
809 if (this_now.IsDST()) station_offset += 60;
810 int corr_mins = station_offset - diff_mins;
812 wxDateTime today_00 = this_now;
813 today_00.ResetTime();
814 int t_today_00 = today_00.GetTicks();
815 int t_today_00_at_station = t_today_00 - (corr_mins * 60);
818 this_gmt.GetTicks() - (station_offset * 60) + (corr_mins * 60);
820 int t_mins = (t_at_station - t_today_00_at_station) / 60;
821 int t_15s = t_mins / 15;
825 int tref1 = t_today_00_at_station + t_15s * 15 * 60;
832 int tref = t_today_00_at_station + t_15s * 15 * 60;
833 ret = GetTideOrCurrent(tref, idx, tcvalue, dir);
838 pIDX->
Ret15 = !(ret == 0);
846 int tref = t_today_00_at_station + t_15s * 15 * 60;
847 ret = GetTideOrCurrent(tref, idx, tcvalue, dir);
852 pIDX->
Ret15 = !(ret == 0);
859bool TCMgr::GetTideFlowSens(time_t t,
int sch_step,
int idx,
float &tcvalue_now,
860 float &tcvalue_prev,
bool &w_t) {
867 IDX_entry *pIDX = m_Combined_IDX_array[idx];
869 if (!pIDX)
return false;
874 if (pIDX->
pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
return false;
878 int yott = yearoftimet(t);
879 happy_new_year(pIDX, yott);
883 tcvalue_now = time2asecondary(t, pIDX);
884 tcvalue_prev = time2asecondary(t + sch_step, pIDX);
887 tcvalue_now > tcvalue_prev;
892void TCMgr::GetHightOrLowTide(time_t t,
int sch_step_1,
int sch_step_2,
893 float tide_val,
bool w_t,
int idx,
float &tcvalue,
900 IDX_entry *pIDX = m_Combined_IDX_array[idx];
907 if (pIDX->
pDataSource->LoadHarmonicData(pIDX) != TC_NO_ERROR)
return;
923 int yott = yearoftimet(t);
924 happy_new_year(pIDX, yott);
927 double newval = tide_val;
928 double oldval = (w_t) ? newval - 1 : newval + 1;
932 while ((newval > oldval) == w_t)
936 ttt = t + (sch_step_1 * j);
937 newval = time2asecondary(ttt, pIDX);
939 oldval = (w_t) ? newval - 1 : newval + 1;
940 while ((newval > oldval) == w_t)
944 ttt = t + (sch_step_1 * j) - (sch_step_2 * k);
945 newval = time2asecondary(ttt, pIDX);
948 tctime = ttt + sch_step_2;
967int TCMgr::GetNextBigEvent(time_t *tm,
int idx) {
972 int flags = 0, slope = 0;
973 ret = GetTideOrCurrent(*tm, idx, tcvalue[0], dir);
976 ret = GetTideOrCurrent(*tm, idx, tcvalue[0], dir);
979 if (p < q) slope = 1;
981 if ((slope == 1 && q < p) || (slope == 0 && p < q)) {
983 flags |= (1 << slope);
987 if (flags < 4) *tm -= 60;
991 ret = GetTideOrCurrent(*tm, idx, tcvalue[0], dir);
998std::wstring TCMgr::GetTidalEventStr(
int station_id, wxDateTime ref_dt,
999 double lat,
double lon,
int dt_type) {
1001 time_t dtmtt = ref_dt.FromUTC().GetTicks();
1002 int event = GetNextBigEvent(&dtmtt, station_id);
1003 wxDateTime event_dt = wxDateTime(dtmtt).MakeUTC();
1005 std::wstring event_str;
1007 event_str = _(
"LW").ToStdWstring();
1008 }
else if (event == 2) {
1009 event_str = _(
"HW").ToStdWstring();
1011 event_str = _(
"Unavailable").ToStdWstring();
1015 event_str.append(L
": ");
1017 toUsrDateTime(event_dt, dt_type, lon).FormatISOCombined(
' '));
1023std::map<double, const IDX_entry *> TCMgr::GetStationsForLL(
double xlat,
1024 double xlon)
const {
1025 std::map<double, const IDX_entry *> x;
1028 for (
int j = 1; j < Get_max_IDX() + 1; j++) {
1029 lpIDX = GetIDX_entry(j);
1033 if (type ==
't' || type ==
'T') {
1035 DistanceBearingMercator(xlat, xlon, lpIDX->
IDX_lat, lpIDX->
IDX_lon, &brg,
1037 x.emplace(std::make_pair(dist, lpIDX));
1044int TCMgr::GetStationIDXbyName(
const wxString &prefix,
double xlat,
1045 double xlon)
const {
1049 double distx = 100000.;
1051 int jmax = Get_max_IDX();
1053 for (
int j = 1; j < Get_max_IDX() + 1; j++) {
1054 lpIDX = GetIDX_entry(j);
1058 if (((type ==
't') || (type ==
'T'))
1059 && (locnx.StartsWith(prefix))) {
1061 DistanceBearingMercator(xlat, xlon, lpIDX->
IDX_lat, lpIDX->
IDX_lon, &brg,
1073int TCMgr::GetStationIDXbyNameType(
const wxString &prefix,
double xlat,
1074 double xlon,
char type)
const {
1078 double distx = 100000.;
1082 int jmax = Get_max_IDX();
1084 for (
int j = 1; j < Get_max_IDX() + 1; j++) {
1085 lpIDX = GetIDX_entry(j);
1089 if ((type == typep) && (locnx.StartsWith(prefix))) {
1091 DistanceBearingMercator(xlat, xlon, lpIDX->
IDX_lat, lpIDX->
IDX_lon, &brg,
1117#define DEFAULT_HEADER_SIZE 4096
1118#define DEFAULT_NUMBER_OF_RECORDS 0
1119#define DEFAULT_LEVEL_UNIT_TYPES 5
1120#define DEFAULT_DIR_UNIT_TYPES 3
1121#define DEFAULT_RESTRICTION_TYPES 2
1122#define DEFAULT_RESTRICTION_BITS 4
1123#define DEFAULT_TZFILES 406
1124#define DEFAULT_TZFILE_BITS 10
1125#define DEFAULT_COUNTRIES 240
1126#define DEFAULT_COUNTRY_BITS 9
1127#define DEFAULT_DATUM_TYPES 61
1128#define DEFAULT_DATUM_BITS 7
1129#define DEFAULT_LEGALESES 1
1130#define DEFAULT_LEGALESE_BITS 4
1131#define DEFAULT_SPEED_SCALE 10000000
1132#define DEFAULT_EQUILIBRIUM_SCALE 100
1133#define DEFAULT_NODE_SCALE 10000
1134#define DEFAULT_AMPLITUDE_BITS 19
1135#define DEFAULT_AMPLITUDE_SCALE 10000
1136#define DEFAULT_EPOCH_BITS 16
1137#define DEFAULT_EPOCH_SCALE 100
1138#define DEFAULT_RECORD_TYPE_BITS 4
1139#define DEFAULT_LATITUDE_BITS 25
1140#define DEFAULT_LATITUDE_SCALE 100000
1141#define DEFAULT_LONGITUDE_BITS 26
1142#define DEFAULT_LONGITUDE_SCALE 100000
1143#define DEFAULT_RECORD_SIZE_BITS 16
1144#define DEFAULT_STATION_BITS 18
1145#define DEFAULT_DATUM_OFFSET_BITS 28
1146#define DEFAULT_DATUM_OFFSET_SCALE 10000
1147#define DEFAULT_DATE_BITS 27
1148#define DEFAULT_MONTHS_ON_STATION_BITS 10
1149#define DEFAULT_CONFIDENCE_VALUE_BITS 4
1150#define DEFAULT_NUMBER_OF_CONSTITUENTS_BITS 8
1151#define DEFAULT_TIME_BITS 13
1152#define DEFAULT_LEVEL_ADD_BITS 17
1153#define DEFAULT_LEVEL_ADD_SCALE 1000
1154#define DEFAULT_LEVEL_MULTIPLY_BITS 16
1155#define DEFAULT_LEVEL_MULTIPLY_SCALE 1000
1156#define DEFAULT_DIRECTION_BITS 9
1157#define DEFAULT_CONSTITUENT_SIZE 10
1158#define DEFAULT_LEVEL_UNIT_SIZE 15
1159#define DEFAULT_DIR_UNIT_SIZE 15
1160#define DEFAULT_RESTRICTION_SIZE 30
1161#define DEFAULT_DATUM_SIZE 70
1162#define DEFAULT_LEGALESE_SIZE 70
1163#define DEFAULT_TZFILE_SIZE 30
1164#define DEFAULT_COUNTRY_SIZE 50
1168#define INFERRED_SEMI_DIURNAL_COUNT 10
1169#define INFERRED_DIURNAL_COUNT 10
1172#pragma warning(disable : 4305)
1175const NV_CHAR *inferred_semi_diurnal[INFERRED_SEMI_DIURNAL_COUNT] = {
1176 "N2",
"NU2",
"MU2",
"2N2",
"LDA2",
"T2",
"R2",
"L2",
"K2",
"KJ2"};
1177const NV_CHAR *inferred_diurnal[INFERRED_DIURNAL_COUNT] = {
1178 "OO1",
"M1",
"J1",
"RHO1",
"Q1",
"2Q1",
"P1",
"PI1",
"PHI1",
"PSI1"};
1179NV_FLOAT32 semi_diurnal_coeff[INFERRED_SEMI_DIURNAL_COUNT] = {
1180 .1759, .0341, .0219, .0235, .0066, .0248, .0035, .0251, .1151, .0064};
1181NV_FLOAT32 diurnal_coeff[INFERRED_DIURNAL_COUNT] = {
1182 .0163, .0209, .0297, .0142, .0730, .0097, .1755, .0103, .0076, .0042};
1186NV_FLOAT32 coeff[2] = {.9085, .3771};
1196NV_CHAR level_unit[DEFAULT_LEVEL_UNIT_TYPES][DEFAULT_LEVEL_UNIT_SIZE] = {
1197 "Unknown",
"feet",
"meters",
"knots",
"knots^2"};
1201NV_CHAR dir_unit[DEFAULT_DIR_UNIT_TYPES][DEFAULT_DIR_UNIT_SIZE] = {
1202 "Unknown",
"degrees true",
"degrees"};
1206NV_CHAR restriction[DEFAULT_RESTRICTION_TYPES][DEFAULT_RESTRICTION_SIZE] = {
1207 "Public Domain",
"DoD/DoD Contractors Only"};
1211NV_CHAR legalese[DEFAULT_LEGALESES][DEFAULT_LEGALESE_SIZE] = {
"NULL"};
1215NV_CHAR datum[DEFAULT_DATUM_TYPES][DEFAULT_DATUM_SIZE] = {
1219 "Mean Lower Low Water",
1221 "Mean Higher High Water",
1222 "Mean Lower High Water",
1223 "Mean Higher Low Water",
1224 "Mean Low Water Springs",
1225 "Mean Lower Low Water Springs",
1226 "Mean Low Water Neaps",
1227 "Mean High Water Neaps",
1228 "Mean High Water Springs",
1229 "Mean Higher High Water Springs",
1230 "Indian Spring Low Water",
1231 "Equatorial Spring Low Water",
1232 "Lowest Normal Low Water",
1234 "Lowest Possible Low Water",
1235 "Lowest Astronomical Tide",
1236 "International Great Lakes Datum(1955)",
1237 "Lower Low Water, Large Tide",
1238 "Lowest Normal Tide",
1239 "Higher High Water, Large Tide",
1241 "Higher High Water, Mean Tide",
1242 "Lower Low Water, Mean Tide",
1244 "World Geodetic System (1984)",
1245 "National Geodetic Vertical Datum",
1246 "Gulf Coast Low Water Datum",
1247 "Approximate Level of Mean Sea Level",
1248 "Approximate Level of Mean Low Water",
1249 "Approximate Level of Mean Lower Low Water",
1250 "Approximate Level of Mean High Water",
1251 "Approximate Level of Mean Higher High Water",
1252 "Approximate Level of Mean Lower High Water",
1253 "Approximate Level of Mean Higher Low Water",
1254 "Approximate Level of Mean Low Water Springs",
1255 "Approximate Level of Mean Lower Low Water Springs",
1256 "Approximate Level of Mean Low Water Neaps",
1257 "Approximate Level of Mean High Water Neaps",
1258 "Approximate Level of Mean High Water Springs",
1259 "Approximate Level of Mean Higher High Water Springs",
1260 "Approximate Level of Indian Spring Low Water",
1261 "Approximate Level of Equatorial Spring Low Water",
1262 "Approximate Level of Lowest Normal Low Water",
1263 "Approximate Level of Lowest Low Water",
1264 "Approximate Level of Lowest Possible Low Water",
1265 "Approximate Level of Lowest Astronomical Tide",
1266 "Approximate Level of International Great Lakes Datum (1955)",
1267 "Approximate Level of Lower Low Water, Large Tide",
1268 "Approximate Level of Lowest Normal Tide",
1269 "Approximate Level of Higher High Water, Large Tide",
1270 "Approximate Level of Mean Water Level",
1271 "Approximate Level of Higher High Water, Mean Tide",
1272 "Approximate Level of Lower Low Water, Mean Tide",
1273 "Approximate Level of Mean Tide Level",
1274 "Approximate Level of World Geodetic System (1984)",
1275 "Approximate Level of National Geodetic Vertical Datum",
1276 "Approximate Level of Gulf Coast Low Water Datum"};
1280NV_CHAR country[DEFAULT_COUNTRIES][DEFAULT_COUNTRY_SIZE] = {
1289 "Antigua & Barbuda",
1307 "Bosnia & Herzegovina",
1312 "British Indian Ocean Territory",
1322 "Central African Rep.",
1327 "Cocos (Keeling) Islands",
1330 "Congo (Dem. Rep.)",
1342 "Dominican Republic",
1347 "Equatorial Guinea",
1358 "French Southern & Antarctic Lands",
1375 "Heard Island & McDonald Islands",
1432 "Netherlands Antilles",
1440 "Northern Mariana Islands",
1463 "Sao Tome & Principe",
1474 "South Georgia & the South Sandwich Islands",
1480 "St Pierre & Miquelon",
1484 "Svalbard & Jan Mayen",
1496 "Trinidad & Tobago",
1500 "Turks & Caicos Is",
1504 "United Arab Emirates",
1507 "US minor outlying islands",
1513 "Virgin Islands (UK)",
1514 "Virgin Islands (US)",
1524NV_CHAR tzfile[DEFAULT_TZFILES][DEFAULT_TZFILE_SIZE] = {
1528 ":Africa/Addis_Ababa",
1536 ":Africa/Brazzaville",
1537 ":Africa/Bujumbura",
1539 ":Africa/Casablanca",
1543 ":Africa/Dar_es_Salaam",
1550 ":Africa/Johannesburg",
1556 ":Africa/Libreville",
1559 ":Africa/Lubumbashi",
1565 ":Africa/Mogadishu",
1570 ":Africa/Nouakchott",
1571 ":Africa/Ouagadougou",
1572 ":Africa/Porto-Novo",
1579 ":America/Anchorage",
1580 ":America/Anguilla",
1582 ":America/Araguaina",
1584 ":America/Asuncion",
1586 ":America/Barbados",
1589 ":America/Boa_Vista",
1592 ":America/Buenos_Aires",
1593 ":America/Cambridge_Bay",
1596 ":America/Catamarca",
1600 ":America/Chihuahua",
1602 ":America/Costa_Rica",
1605 ":America/Danmarkshavn",
1607 ":America/Dawson_Creek",
1610 ":America/Dominica",
1611 ":America/Edmonton",
1612 ":America/Eirunepe",
1613 ":America/El_Salvador",
1614 ":America/Ensenada",
1615 ":America/Fortaleza",
1616 ":America/Glace_Bay",
1618 ":America/Goose_Bay",
1619 ":America/Grand_Turk",
1621 ":America/Guadeloupe",
1622 ":America/Guatemala",
1623 ":America/Guayaquil",
1627 ":America/Hermosillo",
1628 ":America/Indiana/Knox",
1629 ":America/Indiana/Marengo",
1630 ":America/Indianapolis",
1631 ":America/Indiana/Vevay",
1637 ":America/Kentucky/Monticello",
1640 ":America/Los_Angeles",
1641 ":America/Louisville",
1645 ":America/Martinique",
1646 ":America/Mazatlan",
1648 ":America/Menominee",
1650 ":America/Mexico_City",
1651 ":America/Miquelon",
1652 ":America/Monterrey",
1653 ":America/Montevideo",
1654 ":America/Montreal",
1655 ":America/Montserrat",
1657 ":America/New_York",
1661 ":America/North_Dakota/Center",
1663 ":America/Pangnirtung",
1664 ":America/Paramaribo",
1666 ":America/Port-au-Prince",
1667 ":America/Port_of_Spain",
1668 ":America/Porto_Velho",
1669 ":America/Puerto_Rico",
1670 ":America/Rainy_River",
1671 ":America/Rankin_Inlet",
1674 ":America/Rio_Branco",
1675 ":America/Santiago",
1676 ":America/Santo_Domingo",
1677 ":America/Sao_Paulo",
1678 ":America/Scoresbysund",
1679 ":America/Shiprock",
1680 ":America/St_Johns",
1681 ":America/St_Kitts",
1682 ":America/St_Lucia",
1683 ":America/St_Thomas",
1684 ":America/St_Vincent",
1685 ":America/Swift_Current",
1686 ":America/Tegucigalpa",
1688 ":America/Thunder_Bay",
1691 ":America/Vancouver",
1692 ":America/Whitehorse",
1693 ":America/Winnipeg",
1695 ":America/Yellowknife",
1696 ":Antarctica/Casey",
1697 ":Antarctica/Davis",
1698 ":Antarctica/DumontDUrville",
1699 ":Antarctica/Mawson",
1700 ":Antarctica/McMurdo",
1701 ":Antarctica/Palmer",
1702 ":Antarctica/South_Pole",
1703 ":Antarctica/Syowa",
1704 ":Antarctica/Vostok",
1705 ":Arctic/Longyearbyen",
1742 ":Asia/Krasnoyarsk",
1743 ":Asia/Kuala_Lumpur",
1752 ":Asia/Novosibirsk",
1774 ":Asia/Ulaanbaatar",
1777 ":Asia/Vladivostok",
1779 ":Asia/Yekaterinburg",
1782 ":Atlantic/Bermuda",
1784 ":Atlantic/Cape_Verde",
1786 ":Atlantic/Jan_Mayen",
1787 ":Atlantic/Madeira",
1788 ":Atlantic/Reykjavik",
1789 ":Atlantic/South_Georgia",
1790 ":Atlantic/Stanley",
1791 ":Atlantic/St_Helena",
1792 ":Australia/Adelaide",
1793 ":Australia/Brisbane",
1794 ":Australia/Broken_Hill",
1795 ":Australia/Darwin",
1796 ":Australia/Hobart",
1797 ":Australia/Lindeman",
1798 ":Australia/Lord_Howe",
1799 ":Australia/Melbourne",
1801 ":Australia/Sydney",
1831 ":Europe/Amsterdam",
1837 ":Europe/Bratislava",
1839 ":Europe/Bucharest",
1842 ":Europe/Copenhagen",
1844 ":Europe/Gibraltar",
1847 ":Europe/Kaliningrad",
1850 ":Europe/Ljubljana",
1852 ":Europe/Luxembourg",
1864 ":Europe/San_Marino",
1866 ":Europe/Simferopol",
1869 ":Europe/Stockholm",
1879 ":Europe/Zaporozhye",
1881 ":Indian/Antananarivo",
1883 ":Indian/Christmas",
1886 ":Indian/Kerguelen",
1889 ":Indian/Mauritius",
1893 ":Pacific/Auckland",
1897 ":Pacific/Enderbury",
1900 ":Pacific/Funafuti",
1901 ":Pacific/Galapagos",
1903 ":Pacific/Guadalcanal",
1905 ":Pacific/Honolulu",
1906 ":Pacific/Johnston",
1907 ":Pacific/Kiritimati",
1909 ":Pacific/Kwajalein",
1911 ":Pacific/Marquesas",
1917 ":Pacific/Pago_Pago",
1919 ":Pacific/Pitcairn",
1921 ":Pacific/Port_Moresby",
1922 ":Pacific/Rarotonga",
1926 ":Pacific/Tongatapu",
1941#define require(expr) \
1944 require_expr = (int)(expr); \
1945 assert(require_expr); \
2265NV_U_INT32 calculate_bits(NV_U_INT32 value);
2266void bit_pack(NV_U_BYTE *, NV_U_INT32, NV_U_INT32, NV_INT32);
2267NV_U_INT32 bit_unpack(NV_U_BYTE *, NV_U_INT32, NV_U_INT32);
2268NV_INT32 signed_bit_unpack(NV_U_BYTE buffer[], NV_U_INT32 start,
2269 NV_U_INT32 numbits);
2275 NV_U_INT32 record_size;
2277 NV_INT32 reference_station;
2280 NV_U_BYTE record_type;
2284static FILE *fp = NULL;
2286static NV_BOOL modified = NVFalse;
2287static NV_INT32 current_record, current_index;
2288static NV_CHAR filename[MONOLOGUE_LENGTH];
2298static void chk_fread(
void *ptr,
size_t size,
size_t nmemb, FILE *stream) {
2300 ret = fread(ptr, size, nmemb, stream);
2304 throw std::runtime_error(
"tcmgr file read exception");
2308static void chk_fwrite(
const void *ptr,
size_t size,
size_t nmemb,
2311 ret = fwrite(ptr, size, nmemb, stream);
2316 throw std::runtime_error(
"tcmgr file read exception");
2343 LOG_ERROR(
"\n\nRecord number = %d\n", rec->header.record_number);
2344 LOG_ERROR(
"Record size = %u\n", rec->header.record_size);
2345 LOG_ERROR(
"Record type = %u\n", rec->header.record_type);
2346 LOG_ERROR(
"Latitude = %f\n", rec->header.latitude);
2347 LOG_ERROR(
"Longitude = %f\n", rec->header.longitude);
2348 LOG_ERROR(
"Reference station = %d\n", rec->header.reference_station);
2349 LOG_ERROR(
"Tzfile = %s\n", get_tzfile(rec->header.tzfile));
2350 LOG_ERROR(
"Name = %s\n", rec->header.name);
2352 LOG_ERROR(
"Country = %s\n", get_country(rec->country));
2353 LOG_ERROR(
"Source = %s\n", rec->source);
2354 LOG_ERROR(
"Restriction = %s\n", get_restriction(rec->restriction));
2355 LOG_ERROR(
"Comments = %s\n", rec->comments);
2356 LOG_ERROR(
"Notes = %s\n", rec->notes);
2357 LOG_ERROR(
"Legalese = %s\n", get_legalese(rec->legalese));
2358 LOG_ERROR(
"Station ID context = %s\n", rec->station_id_context);
2359 LOG_ERROR(
"Station ID = %s\n", rec->station_id);
2360 LOG_ERROR(
"Date imported = %d\n", rec->date_imported);
2361 LOG_ERROR(
"Xfields = %s\n", rec->xfields);
2363 LOG_ERROR(
"Direction units = %s\n", get_dir_units(rec->direction_units));
2364 LOG_ERROR(
"Min direction = %d\n", rec->min_direction);
2365 LOG_ERROR(
"Max direction = %d\n", rec->max_direction);
2366 LOG_ERROR(
"Level units = %s\n", get_level_units(rec->level_units));
2368 if (rec->header.record_type == REFERENCE_STATION) {
2369 LOG_ERROR(
"Datum offset = %f\n", rec->datum_offset);
2370 LOG_ERROR(
"Datum = %s\n", get_datum(rec->datum));
2371 LOG_ERROR(
"Zone offset = %d\n", rec->zone_offset);
2372 LOG_ERROR(
"Expiration date = %d\n", rec->expiration_date);
2373 LOG_ERROR(
"Months on station = %d\n", rec->months_on_station);
2374 LOG_ERROR(
"Last date on station = %d\n", rec->last_date_on_station);
2375 LOG_ERROR(
"Confidence = %d\n", rec->confidence);
2376 for (i = 0; i < hd.pub.constituents; ++i) {
2377 if (rec->amplitude[i] != 0.0 || rec->epoch[i] != 0.0) {
2378 LOG_ERROR(
"Amplitude[%d] = %f\n", i, rec->amplitude[i]);
2379 LOG_ERROR(
"Epoch[%d] = %f\n", i, rec->epoch[i]);
2384 else if (rec->header.record_type == SUBORDINATE_STATION) {
2385 LOG_ERROR(
"Min time add = %d\n", rec->min_time_add);
2386 LOG_ERROR(
"Min level add = %f\n", rec->min_level_add);
2387 LOG_ERROR(
"Min level multiply = %f\n", rec->min_level_multiply);
2388 LOG_ERROR(
"Max time add = %d\n", rec->max_time_add);
2389 LOG_ERROR(
"Max level add = %f\n", rec->max_level_add);
2390 LOG_ERROR(
"Max level multiply = %f\n", rec->max_level_multiply);
2391 LOG_ERROR(
"Flood begins = %d\n", rec->flood_begins);
2392 LOG_ERROR(
"Ebb begins = %d\n", rec->ebb_begins);
2405static void write_protect() {
2406 if (hd.pub.major_rev < LIBTCD_MAJOR_REV) {
2408 "libtcd error: can't modify TCD files created by earlier version. "
2409 "Use\nrewrite_tide_db to upgrade the TCD file.\n");
2433const NV_CHAR *get_country(NV_INT32 num) {
2436 "libtcd error: attempt to access database when database not open\n");
2439 if (num >= 0 && num < (NV_INT32)hd.pub.countries)
return (hd.country[num]);
2460const NV_CHAR *get_tzfile(NV_INT32 num) {
2463 "libtcd error: attempt to access database when database not open\n");
2466 if (num >= 0 && num < (NV_INT32)hd.pub.tzfiles)
return (hd.tzfile[num]);
2487const NV_CHAR *get_station(NV_INT32 num) {
2490 "libtcd error: attempt to access database when database not open\n");
2493 if (num >= 0 && num < (NV_INT32)hd.pub.number_of_records)
2494 return (tindex[num].name);
2516const NV_CHAR *get_constituent(NV_INT32 num) {
2519 "libtcd error: attempt to access database when database not open\n");
2522 if (num >= 0 && num < (NV_INT32)hd.pub.constituents)
2523 return (hd.constituent[num]);
2545const NV_CHAR *get_level_units(NV_INT32 num) {
2548 "libtcd error: attempt to access database when database not open\n");
2551 if (num >= 0 && num < (NV_INT32)hd.pub.level_unit_types)
2552 return (hd.level_unit[num]);
2574const NV_CHAR *get_dir_units(NV_INT32 num) {
2577 "libtcd error: attempt to access database when database not open\n");
2580 if (num >= 0 && num < (NV_INT32)hd.pub.dir_unit_types)
2581 return (hd.dir_unit[num]);
2603const NV_CHAR *get_restriction(NV_INT32 num) {
2606 "libtcd error: attempt to access database when database not open\n");
2609 if (num >= 0 && num < (NV_INT32)hd.pub.restriction_types)
2610 return (hd.restriction[num]);
2633NV_CHAR *get_pedigree(NV_INT32 num) {
return "Unknown"; }
2653const NV_CHAR *get_datum(NV_INT32 num) {
2656 "libtcd error: attempt to access database when database not open\n");
2659 if (num >= 0 && num < (NV_INT32)hd.pub.datum_types)
return (hd.datum[num]);
2666const NV_CHAR *get_legalese(NV_INT32 num) {
2669 "libtcd error: attempt to access database when database not open\n");
2672 if (num >= 0 && num < (NV_INT32)hd.pub.legaleses)
return (hd.legalese[num]);
2694NV_FLOAT64 get_speed(NV_INT32 num) {
2697 "libtcd error: attempt to access database when database not open\n");
2700 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
2701 return hd.speed[num];
2723NV_FLOAT32 get_equilibrium(NV_INT32 num, NV_INT32 year) {
2726 "libtcd error: attempt to access database when database not open\n");
2729 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
2730 year < (NV_INT32)hd.pub.number_of_years);
2731 return hd.equilibrium[num][year];
2737NV_FLOAT32 *get_equilibriums(NV_INT32 num) {
2740 "libtcd error: attempt to access database when database not open\n");
2743 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
2744 return hd.equilibrium[num];
2766NV_FLOAT32 get_node_factor(NV_INT32 num, NV_INT32 year) {
2769 "libtcd error: attempt to access database when database not open\n");
2772 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
2773 year < (NV_INT32)hd.pub.number_of_years);
2774 return hd.node_factor[num][year];
2780NV_FLOAT32 *get_node_factors(NV_INT32 num) {
2783 "libtcd error: attempt to access database when database not open\n");
2786 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
2787 return hd.node_factor[num];
2816 "libtcd error: attempt to access database when database not open\n");
2820 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return (NVFalse);
2824 rec->record_number = num;
2825 rec->record_size = tindex[num].record_size;
2826 rec->record_type = tindex[num].record_type;
2827 rec->latitude = (NV_FLOAT64)tindex[num].lat / hd.latitude_scale;
2828 rec->longitude = (NV_FLOAT64)tindex[num].lon / hd.longitude_scale;
2829 rec->reference_station = tindex[num].reference_station;
2830 rec->tzfile = tindex[num].tzfile;
2831 strcpy(rec->name, tindex[num].name);
2833 current_index = num;
2857 if (!get_partial_tide_record(current_index + 1, rec))
return (-1);
2859 return (current_index);
2882NV_INT32 get_nearest_partial_tide_record(NV_FLOAT64 lat, NV_FLOAT64 lon,
2884 NV_FLOAT64 diff, min_diff, lt, ln;
2885 NV_U_INT32 i, shortest = 0;
2887 min_diff = 999999999.9;
2888 for (i = 0; i < hd.pub.number_of_records; ++i) {
2889 lt = (NV_FLOAT64)tindex[i].lat / hd.latitude_scale;
2890 ln = (NV_FLOAT64)tindex[i].lon / hd.longitude_scale;
2892 diff = sqrt((lat - lt) * (lat - lt) + (lon - ln) * (lon - ln));
2894 if (diff < min_diff) {
2900 if (!get_partial_tide_record(shortest, rec))
return (-1);
2922NV_INT32 get_time(
const NV_CHAR *
string) {
2923 NV_INT32 hour, minute, hhmm;
2926 sscanf(
string,
"%d:%d", &hour, &minute);
2930 if (
string[0] ==
'-') {
2931 if (hour < 0) hour = -hour;
2933 hhmm = -(hour * 100 + minute);
2935 hhmm = hour * 100 + minute;
2959NV_CHAR *ret_time(NV_INT32 time) {
2960 NV_INT32 hour, minute;
2961 static NV_CHAR tname[16];
2963 hour = abs(time) / 100;
2964 assert(hour <= 99999 && hour >= -99999);
2965 minute = abs(time) % 100;
2968 sprintf(tname,
"-%02d:%02d", hour, minute);
2970 sprintf(tname,
"+%02d:%02d", hour, minute);
2979NV_CHAR *ret_time_neat(NV_INT32 time) {
2980 NV_INT32 hour, minute;
2981 static NV_CHAR tname[16];
2983 hour = abs(time) / 100;
2984 assert(hour <= 99999 && hour >= -99999);
2985 minute = abs(time) % 100;
2988 sprintf(tname,
"-%d:%02d", hour, minute);
2990 sprintf(tname,
"+%d:%02d", hour, minute);
2992 strcpy(tname,
"0:00");
3000NV_CHAR *ret_date(NV_U_INT32 date) {
3001 static NV_CHAR tname[30];
3003 strcpy(tname,
"NULL");
3010 sprintf(tname,
"%4u-%02u-%02u", y, m, d);
3034 "libtcd error: attempt to access database when database not open\n");
3044static void boundscheck_monologue(
const NV_CHAR *
string) {
3046 if (strlen(
string) >= MONOLOGUE_LENGTH) {
3060static void boundscheck_oneliner(
const NV_CHAR *
string) {
3062 if (strlen(
string) >= ONELINER_LENGTH) {
3090static NV_CHAR *clip_string(
const NV_CHAR *
string) {
3091 static NV_CHAR new_string[MONOLOGUE_LENGTH];
3092 NV_INT32 i, l, start = -1, end = -1;
3094 boundscheck_monologue(
string);
3095 new_string[0] =
'\0';
3097 l = (int)strlen(
string);
3099 for (i = 0; i < l; ++i) {
3100 if (
string[i] !=
' ') {
3105 for (i = l - 1; i >= start; --i) {
3106 if (
string[i] !=
' ' &&
string[i] != 10 &&
string[i] != 13) {
3111 if (start > -1 && end > -1 && end >= start) {
3112 strncpy(new_string,
string + start, end - start + 1);
3113 new_string[end - start + 1] =
'\0';
3140NV_INT32 search_station(
const NV_CHAR *
string) {
3141 static NV_CHAR last_search[ONELINER_LENGTH];
3142 static NV_U_INT32 j = 0;
3144 NV_CHAR name[ONELINER_LENGTH], search[ONELINER_LENGTH];
3148 "libtcd error: attempt to access database when database not open\n");
3152 boundscheck_oneliner(
string);
3154 for (i = 0; i < strlen(
string) + 1; ++i) search[i] =
tolower(
string[i]);
3156 if (strcmp(search, last_search)) j = 0;
3158 strcpy(last_search, search);
3160 while (j < hd.pub.number_of_records) {
3161 for (i = 0; i < strlen(tindex[j].name) + 1; ++i)
3162 name[i] =
tolower(tindex[j].name[i]);
3165 if (strstr(name, search))
return (j - 1);
3190NV_INT32 find_station(
const NV_CHAR *name) {
3195 "libtcd error: attempt to access database when database not open\n");
3200 for (i = 0; i < hd.pub.number_of_records; ++i) {
3201 if (!strcmp(name, tindex[i].name))
return (i);
3225NV_INT32 find_tzfile(
const NV_CHAR *name) {
3232 "libtcd error: attempt to access database when database not open\n");
3236 temp = clip_string(name);
3239 for (i = 0; i < hd.pub.tzfiles; ++i) {
3240 if (!strcmp(temp, get_tzfile(i))) {
3267NV_INT32 find_country(
const NV_CHAR *name) {
3274 "libtcd error: attempt to access database when database not open\n");
3278 temp = clip_string(name);
3281 for (i = 0; i < hd.pub.countries; ++i) {
3282 if (!strcmp(temp, get_country(i))) {
3309NV_INT32 find_level_units(
const NV_CHAR *name) {
3316 "libtcd error: attempt to access database when database not open\n");
3320 temp = clip_string(name);
3323 for (i = 0; i < hd.pub.level_unit_types; ++i) {
3324 if (!strcmp(get_level_units(i), temp)) {
3351NV_INT32 find_dir_units(
const NV_CHAR *name) {
3358 "libtcd error: attempt to access database when database not open\n");
3362 temp = clip_string(name);
3365 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
3366 if (!strcmp(get_dir_units(i), temp)) {
3394NV_INT32 find_pedigree(
const NV_CHAR *name) {
return 0; }
3415NV_INT32 find_datum(
const NV_CHAR *name) {
3422 "libtcd error: attempt to access database when database not open\n");
3426 temp = clip_string(name);
3429 for (i = 0; i < hd.pub.datum_types; ++i) {
3430 if (!strcmp(get_datum(i), temp)) {
3442NV_INT32 find_legalese(
const NV_CHAR *name) {
3449 "libtcd error: attempt to access database when database not open\n");
3453 temp = clip_string(name);
3456 for (i = 0; i < hd.pub.legaleses; ++i) {
3457 if (!strcmp(get_legalese(i), temp)) {
3485NV_INT32 find_constituent(
const NV_CHAR *name) {
3491 "libtcd error: attempt to access database when database not open\n");
3495 temp = clip_string(name);
3497 for (i = 0; i < hd.pub.constituents; ++i) {
3498 if (!strcmp(get_constituent(i), temp))
return (i);
3522NV_INT32 find_restriction(
const NV_CHAR *name) {
3529 "libtcd error: attempt to access database when database not open\n");
3533 temp = clip_string(name);
3536 for (i = 0; i < hd.pub.restriction_types; ++i) {
3537 if (!strcmp(get_restriction(i), temp)) {
3563void set_speed(NV_INT32 num, NV_FLOAT64 value) {
3566 "libtcd error: attempt to access database when database not open\n");
3570 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents);
3572 LOG_ERROR(
"libtcd set_speed: somebody tried to set a negative speed (%f)\n",
3576 hd.speed[num] = value;
3600void set_equilibrium(NV_INT32 num, NV_INT32 year, NV_FLOAT32 value) {
3603 "libtcd error: attempt to access database when database not open\n");
3607 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
3608 year < (NV_INT32)hd.pub.number_of_years);
3609 hd.equilibrium[num][year] = value;
3633void set_node_factor(NV_INT32 num, NV_INT32 year, NV_FLOAT32 value) {
3636 "libtcd error: attempt to access database when database not open\n");
3640 assert(num >= 0 && num < (NV_INT32)hd.pub.constituents && year >= 0 &&
3641 year < (NV_INT32)hd.pub.number_of_years);
3644 "libtcd set_node_factor: somebody tried to set a negative or zero node "
3649 hd.node_factor[num][year] = value;
3700 "libtcd error: attempt to access database when database not open\n");
3706 if (strlen(name) + 1 > hd.tzfile_size) {
3707 LOG_ERROR(
"libtcd error: tzfile exceeds size limit (%u).\n",
3709 LOG_ERROR(
"The offending input is: %s\n", name);
3713 if (hd.pub.tzfiles == hd.max_tzfiles) {
3714 LOG_ERROR(
"You have exceeded the maximum number of tzfile types!\n");
3715 LOG_ERROR(
"You cannot add any new tzfile types.\n");
3716 LOG_ERROR(
"Modify the DEFAULT_TZFILE_BITS and rebuild the database.\n");
3720 c_name = clip_string(name);
3722 hd.tzfile[hd.pub.tzfiles] =
3723 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3725 if (hd.tzfile[hd.pub.tzfiles] == NULL) {
3726 perror(
"Allocating new tzfile string");
3730 strcpy(hd.tzfile[hd.pub.tzfiles++], c_name);
3731 if (db) *db = hd.pub;
3733 return (hd.pub.tzfiles - 1);
3759 "libtcd error: attempt to access database when database not open\n");
3765 if (strlen(name) + 1 > hd.country_size) {
3766 LOG_ERROR(
"libtcd error: country exceeds size limit (%u).\n",
3768 LOG_ERROR(
"The offending input is: %s\n", name);
3772 if (hd.pub.countries == hd.max_countries) {
3773 LOG_ERROR(
"You have exceeded the maximum number of country names!\n");
3774 LOG_ERROR(
"You cannot add any new country names.\n");
3775 LOG_ERROR(
"Modify the DEFAULT_COUNTRY_BITS and rebuild the database.\n");
3779 c_name = clip_string(name);
3781 hd.country[hd.pub.countries] =
3782 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3784 if (hd.country[hd.pub.countries] == NULL) {
3785 perror(
"Allocating new country string");
3789 strcpy(hd.country[hd.pub.countries++], c_name);
3790 if (db) *db = hd.pub;
3792 return (hd.pub.countries - 1);
3818 "libtcd error: attempt to access database when database not open\n");
3824 if (strlen(name) + 1 > hd.datum_size) {
3825 LOG_ERROR(
"libtcd error: datum exceeds size limit (%u).\n", hd.datum_size);
3826 LOG_ERROR(
"The offending input is: %s\n", name);
3830 if (hd.pub.datum_types == hd.max_datum_types) {
3831 LOG_ERROR(
"You have exceeded the maximum number of datum types!\n");
3832 LOG_ERROR(
"You cannot add any new datum types.\n");
3833 LOG_ERROR(
"Modify the DEFAULT_DATUM_BITS and rebuild the database.\n");
3837 c_name = clip_string(name);
3839 hd.datum[hd.pub.datum_types] =
3840 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3842 if (hd.datum[hd.pub.datum_types] == NULL) {
3843 perror(
"Allocating new datum string");
3847 strcpy(hd.datum[hd.pub.datum_types++], c_name);
3848 if (db) *db = hd.pub;
3850 return (hd.pub.datum_types - 1);
3861 "libtcd error: attempt to access database when database not open\n");
3867 if (strlen(name) + 1 > hd.legalese_size) {
3868 LOG_ERROR(
"libtcd error: legalese exceeds size limit (%u).\n",
3870 LOG_ERROR(
"The offending input is: %s\n", name);
3874 if (hd.pub.legaleses == hd.max_legaleses) {
3875 LOG_ERROR(
"You have exceeded the maximum number of legaleses!\n");
3876 LOG_ERROR(
"You cannot add any new legaleses.\n");
3877 LOG_ERROR(
"Modify the DEFAULT_LEGALESE_BITS and rebuild the database.\n");
3881 c_name = clip_string(name);
3883 hd.legalese[hd.pub.legaleses] =
3884 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3886 if (hd.legalese[hd.pub.legaleses] == NULL) {
3887 perror(
"Allocating new legalese string");
3891 strcpy(hd.legalese[hd.pub.legaleses++], c_name);
3892 if (db) *db = hd.pub;
3894 return (hd.pub.legaleses - 1);
3920 "libtcd error: attempt to access database when database not open\n");
3926 if (strlen(name) + 1 > hd.restriction_size) {
3927 LOG_ERROR(
"libtcd error: restriction exceeds size limit (%u).\n",
3928 hd.restriction_size);
3929 LOG_ERROR(
"The offending input is: %s\n", name);
3933 if (hd.pub.restriction_types == hd.max_restriction_types) {
3934 LOG_ERROR(
"You have exceeded the maximum number of restriction types!\n");
3935 LOG_ERROR(
"You cannot add any new restriction types.\n");
3937 "Modify the DEFAULT_RESTRICTION_BITS and rebuild the database.\n");
3941 c_name = clip_string(name);
3943 hd.restriction[hd.pub.restriction_types] =
3944 (NV_CHAR *)calloc(strlen(c_name) + 1,
sizeof(NV_CHAR));
3946 if (hd.restriction[hd.pub.restriction_types] == NULL) {
3947 perror(
"Allocating new restriction string");
3951 strcpy(hd.restriction[hd.pub.restriction_types++], c_name);
3952 if (db) *db = hd.pub;
3954 return (hd.pub.restriction_types - 1);
3960NV_INT32 find_or_add_restriction(
const NV_CHAR *name,
DB_HEADER_PUBLIC *db) {
3962 ret = find_restriction(name);
3963 if (ret < 0) ret = add_restriction(name, db);
3973 ret = find_tzfile(name);
3974 if (ret < 0) ret = add_tzfile(name, db);
3984 ret = find_country(name);
3985 if (ret < 0) ret = add_country(name, db);
3995 ret = find_datum(name);
3996 if (ret < 0) ret = add_datum(name, db);
4006 ret = find_legalese(name);
4007 if (ret < 0) ret = add_legalese(name, db);
4038 if (rec.max_time_add == rec.min_time_add &&
4039 rec.max_level_add == rec.min_level_add &&
4040 rec.max_level_multiply == rec.min_level_multiply &&
4041 rec.max_avg_level == 0 && rec.min_avg_level == 0 &&
4042 rec.max_direction == 361 && rec.min_direction == 361 &&
4043 rec.flood_begins == NULLSLACKOFFSET && rec.ebb_begins == NULLSLACKOFFSET)
4066static NV_U_INT32 header_checksum() {
4067 NV_U_INT32 checksum, i, save_pos;
4069 NV_U_INT32 crc_table[256] = {
4070 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
4071 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
4072 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
4073 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
4074 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
4075 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
4076 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
4077 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
4078 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
4079 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
4080 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
4081 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
4082 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
4083 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
4084 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
4085 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
4086 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
4087 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
4088 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
4089 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
4090 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
4091 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
4092 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
4093 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
4094 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
4095 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
4096 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
4097 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
4098 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
4099 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
4100 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
4101 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
4102 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
4103 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
4104 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
4105 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
4106 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
4107 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
4108 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
4109 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
4110 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
4111 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
4112 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D};
4116 "libtcd error: attempt to access database when database not open\n");
4120 save_pos = ftell(fp);
4122 fseek(fp, 0, SEEK_SET);
4124 if ((buf = (NV_U_BYTE *)calloc(hd.header_size,
sizeof(NV_U_BYTE))) == NULL) {
4125 perror(
"Allocating checksum buffer");
4131 assert(hd.header_size > 0);
4132 chk_fread(buf, hd.header_size, 1, fp);
4133 for (i = 0; i < (NV_U_INT32)hd.header_size; ++i) {
4134 checksum = crc_table[(checksum ^ buf[i]) & 0xff] ^ (checksum >> 8);
4140 fseek(fp, save_pos, SEEK_SET);
4161static NV_U_INT32 old_header_checksum() {
4162 NV_U_INT32 checksum, i, save_pos;
4167 "libtcd error: attempt to access database when database not open\n");
4171 save_pos = ftell(fp);
4175 fseek(fp, 0, SEEK_SET);
4177 if ((buf = (NV_U_BYTE *)calloc(hd.header_size,
sizeof(NV_U_BYTE))) == NULL) {
4178 perror(
"Allocating checksum buffer");
4182 chk_fread(buf, hd.header_size, 1, fp);
4184 for (i = 0; i < hd.header_size; ++i) checksum += buf[i];
4188 fseek(fp, save_pos, SEEK_SET);
4198static NV_CHAR *curtime() {
4199 static NV_CHAR buf[ONELINER_LENGTH];
4200 time_t t = time(NULL);
4201 require(strftime(buf, ONELINER_LENGTH,
"%Y-%m-%d %H:%M %Z", localtime(&t)) >
4210static NV_U_INT32 bits2bytes(NV_U_INT32 nbits) {
4211 if (nbits % 8)
return nbits / 8 + 1;
4231static void write_tide_db_header() {
4232 NV_U_INT32 i, size, pos;
4233 NV_INT32 start, temp_int;
4234 static NV_CHAR zero = 0;
4235 NV_U_BYTE *buf, checksum_c[4];
4239 "libtcd error: attempt to access database when database not open\n");
4244 fseek(fp, 0, SEEK_SET);
4246 fprintf(fp,
"[VERSION] = %s\n", LIBTCD_VERSION);
4247 fprintf(fp,
"[MAJOR REV] = %u\n", LIBTCD_MAJOR_REV);
4248 fprintf(fp,
"[MINOR REV] = %u\n", LIBTCD_MINOR_REV);
4250 fprintf(fp,
"[LAST MODIFIED] = %s\n", curtime());
4252 fprintf(fp,
"[HEADER SIZE] = %u\n", hd.header_size);
4253 fprintf(fp,
"[NUMBER OF RECORDS] = %u\n", hd.pub.number_of_records);
4255 fprintf(fp,
"[START YEAR] = %d\n", hd.pub.start_year);
4256 fprintf(fp,
"[NUMBER OF YEARS] = %u\n", hd.pub.number_of_years);
4258 fprintf(fp,
"[SPEED BITS] = %u\n", hd.speed_bits);
4259 fprintf(fp,
"[SPEED SCALE] = %u\n", hd.speed_scale);
4260 fprintf(fp,
"[SPEED OFFSET] = %d\n", hd.speed_offset);
4261 fprintf(fp,
"[EQUILIBRIUM BITS] = %u\n", hd.equilibrium_bits);
4262 fprintf(fp,
"[EQUILIBRIUM SCALE] = %u\n", hd.equilibrium_scale);
4263 fprintf(fp,
"[EQUILIBRIUM OFFSET] = %d\n", hd.equilibrium_offset);
4264 fprintf(fp,
"[NODE BITS] = %u\n", hd.node_bits);
4265 fprintf(fp,
"[NODE SCALE] = %u\n", hd.node_scale);
4266 fprintf(fp,
"[NODE OFFSET] = %d\n", hd.node_offset);
4267 fprintf(fp,
"[AMPLITUDE BITS] = %u\n", hd.amplitude_bits);
4268 fprintf(fp,
"[AMPLITUDE SCALE] = %u\n", hd.amplitude_scale);
4269 fprintf(fp,
"[EPOCH BITS] = %u\n", hd.epoch_bits);
4270 fprintf(fp,
"[EPOCH SCALE] = %u\n", hd.epoch_scale);
4272 fprintf(fp,
"[RECORD TYPE BITS] = %u\n", hd.record_type_bits);
4273 fprintf(fp,
"[LATITUDE BITS] = %u\n", hd.latitude_bits);
4274 fprintf(fp,
"[LATITUDE SCALE] = %u\n", hd.latitude_scale);
4275 fprintf(fp,
"[LONGITUDE BITS] = %u\n", hd.longitude_bits);
4276 fprintf(fp,
"[LONGITUDE SCALE] = %u\n", hd.longitude_scale);
4277 fprintf(fp,
"[RECORD SIZE BITS] = %u\n", hd.record_size_bits);
4279 fprintf(fp,
"[STATION BITS] = %u\n", hd.station_bits);
4281 fprintf(fp,
"[DATUM OFFSET BITS] = %u\n", hd.datum_offset_bits);
4282 fprintf(fp,
"[DATUM OFFSET SCALE] = %u\n", hd.datum_offset_scale);
4283 fprintf(fp,
"[DATE BITS] = %u\n", hd.date_bits);
4284 fprintf(fp,
"[MONTHS ON STATION BITS] = %u\n", hd.months_on_station_bits);
4285 fprintf(fp,
"[CONFIDENCE VALUE BITS] = %u\n", hd.confidence_value_bits);
4287 fprintf(fp,
"[TIME BITS] = %u\n", hd.time_bits);
4288 fprintf(fp,
"[LEVEL ADD BITS] = %u\n", hd.level_add_bits);
4289 fprintf(fp,
"[LEVEL ADD SCALE] = %u\n", hd.level_add_scale);
4290 fprintf(fp,
"[LEVEL MULTIPLY BITS] = %u\n", hd.level_multiply_bits);
4291 fprintf(fp,
"[LEVEL MULTIPLY SCALE] = %u\n", hd.level_multiply_scale);
4292 fprintf(fp,
"[DIRECTION BITS] = %u\n", hd.direction_bits);
4294 fprintf(fp,
"[LEVEL UNIT BITS] = %u\n", hd.level_unit_bits);
4295 fprintf(fp,
"[LEVEL UNIT TYPES] = %u\n", hd.pub.level_unit_types);
4296 fprintf(fp,
"[LEVEL UNIT SIZE] = %u\n", hd.level_unit_size);
4298 fprintf(fp,
"[DIRECTION UNIT BITS] = %u\n", hd.dir_unit_bits);
4299 fprintf(fp,
"[DIRECTION UNIT TYPES] = %u\n", hd.pub.dir_unit_types);
4300 fprintf(fp,
"[DIRECTION UNIT SIZE] = %u\n", hd.dir_unit_size);
4302 fprintf(fp,
"[RESTRICTION BITS] = %u\n", hd.restriction_bits);
4303 fprintf(fp,
"[RESTRICTION TYPES] = %u\n", hd.pub.restriction_types);
4304 fprintf(fp,
"[RESTRICTION SIZE] = %u\n", hd.restriction_size);
4306 fprintf(fp,
"[DATUM BITS] = %u\n", hd.datum_bits);
4307 fprintf(fp,
"[DATUM TYPES] = %u\n", hd.pub.datum_types);
4308 fprintf(fp,
"[DATUM SIZE] = %u\n", hd.datum_size);
4310 fprintf(fp,
"[LEGALESE BITS] = %u\n", hd.legalese_bits);
4311 fprintf(fp,
"[LEGALESE TYPES] = %u\n", hd.pub.legaleses);
4312 fprintf(fp,
"[LEGALESE SIZE] = %u\n", hd.legalese_size);
4314 fprintf(fp,
"[CONSTITUENT BITS] = %u\n", hd.constituent_bits);
4315 fprintf(fp,
"[CONSTITUENTS] = %u\n", hd.pub.constituents);
4316 fprintf(fp,
"[CONSTITUENT SIZE] = %u\n", hd.constituent_size);
4318 fprintf(fp,
"[TZFILE BITS] = %u\n", hd.tzfile_bits);
4319 fprintf(fp,
"[TZFILES] = %u\n", hd.pub.tzfiles);
4320 fprintf(fp,
"[TZFILE SIZE] = %u\n", hd.tzfile_size);
4322 fprintf(fp,
"[COUNTRY BITS] = %u\n", hd.country_bits);
4323 fprintf(fp,
"[COUNTRIES] = %u\n", hd.pub.countries);
4324 fprintf(fp,
"[COUNTRY SIZE] = %u\n", hd.country_size);
4326 fprintf(fp,
"[END OF FILE] = %u\n", hd.end_of_file);
4327 fprintf(fp,
"[END OF ASCII HEADER DATA]\n");
4333 for (i = start; i < hd.header_size; ++i) chk_fwrite(&zero, 1, 1, fp);
4338 bit_pack(checksum_c, 0, 32, header_checksum());
4339 chk_fwrite(checksum_c, 4, 1, fp);
4346 size = hd.pub.level_unit_types * hd.level_unit_size;
4348 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4349 perror(
"Allocating unit write buffer");
4352 memset(buf, 0, size);
4354 for (i = 0; i < hd.pub.level_unit_types; ++i) {
4355 assert(strlen(hd.level_unit[i]) + 1 <= hd.level_unit_size);
4356 strcpy((NV_CHAR *)&buf[pos], hd.level_unit[i]);
4357 pos += hd.level_unit_size;
4360 chk_fwrite(buf, pos, 1, fp);
4366 size = hd.pub.dir_unit_types * hd.dir_unit_size;
4368 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4369 perror(
"Allocating unit write buffer");
4372 memset(buf, 0, size);
4374 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
4375 assert(strlen(hd.dir_unit[i]) + 1 <= hd.dir_unit_size);
4376 strcpy((NV_CHAR *)&buf[pos], hd.dir_unit[i]);
4377 pos += hd.dir_unit_size;
4380 chk_fwrite(buf, pos, 1, fp);
4386 size = hd.max_restriction_types * hd.restriction_size;
4388 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4389 perror(
"Allocating restriction write buffer");
4392 memset(buf, 0, size);
4394 for (i = 0; i < hd.max_restriction_types; ++i) {
4395 if (i == hd.pub.restriction_types)
break;
4396 assert(strlen(hd.restriction[i]) + 1 <= hd.restriction_size);
4397 strcpy((NV_CHAR *)&buf[pos], hd.restriction[i]);
4398 pos += hd.restriction_size;
4400 memcpy(&buf[pos],
"__END__", 7);
4402 chk_fwrite(buf, size, 1, fp);
4408 size = hd.max_tzfiles * hd.tzfile_size;
4410 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4411 perror(
"Allocating tzfile write buffer");
4414 memset(buf, 0, size);
4416 for (i = 0; i < hd.max_tzfiles; ++i) {
4417 if (i == hd.pub.tzfiles)
break;
4418 assert(strlen(hd.tzfile[i]) + 1 <= hd.tzfile_size);
4419 strcpy((NV_CHAR *)&buf[pos], hd.tzfile[i]);
4420 pos += hd.tzfile_size;
4422 memcpy(&buf[pos],
"__END__", 7);
4424 chk_fwrite(buf, size, 1, fp);
4430 size = hd.max_countries * hd.country_size;
4432 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4433 perror(
"Allocating country write buffer");
4436 memset(buf, 0, size);
4438 for (i = 0; i < hd.max_countries; ++i) {
4439 if (i == hd.pub.countries)
break;
4440 assert(strlen(hd.country[i]) + 1 <= hd.country_size);
4441 strcpy((NV_CHAR *)&buf[pos], hd.country[i]);
4442 pos += hd.country_size;
4444 memcpy(&buf[pos],
"__END__", 7);
4446 chk_fwrite(buf, size, 1, fp);
4452 size = hd.max_datum_types * hd.datum_size;
4454 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4455 perror(
"Allocating datum write buffer");
4458 memset(buf, 0, size);
4460 for (i = 0; i < hd.max_datum_types; ++i) {
4461 if (i == hd.pub.datum_types)
break;
4462 assert(strlen(hd.datum[i]) + 1 <= hd.datum_size);
4463 strcpy((NV_CHAR *)&buf[pos], hd.datum[i]);
4464 pos += hd.datum_size;
4466 memcpy(&buf[pos],
"__END__", 7);
4468 chk_fwrite(buf, size, 1, fp);
4474 size = hd.max_legaleses * hd.legalese_size;
4476 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4477 perror(
"Allocating legalese write buffer");
4480 memset(buf, 0, size);
4482 for (i = 0; i < hd.max_legaleses; ++i) {
4483 if (i == hd.pub.legaleses)
break;
4484 assert(strlen(hd.legalese[i]) + 1 <= hd.legalese_size);
4485 strcpy((NV_CHAR *)&buf[pos], hd.legalese[i]);
4486 pos += hd.legalese_size;
4488 memcpy(&buf[pos],
"__END__", 7);
4490 chk_fwrite(buf, size, 1, fp);
4496 size = hd.pub.constituents * hd.constituent_size;
4498 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4499 perror(
"Allocating constituent write buffer");
4502 memset(buf, 0, size);
4504 for (i = 0; i < hd.pub.constituents; ++i) {
4505 assert(strlen(hd.constituent[i]) + 1 <= hd.constituent_size);
4506 strcpy((NV_CHAR *)&buf[pos], hd.constituent[i]);
4507 pos += hd.constituent_size;
4510 chk_fwrite(buf, pos, 1, fp);
4518 size = bits2bytes(hd.pub.constituents * hd.speed_bits);
4520 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4521 perror(
"Allocating speed write buffer");
4524 memset(buf, 0, size);
4526 for (i = 0; i < hd.pub.constituents; ++i) {
4527 temp_int = NINT(hd.speed[i] * hd.speed_scale) - hd.speed_offset;
4528 assert(temp_int >= 0);
4529 bit_pack(buf, pos, hd.speed_bits, temp_int);
4530 pos += hd.speed_bits;
4533 chk_fwrite(buf, size, 1, fp);
4539 size = bits2bytes(hd.pub.constituents * hd.pub.number_of_years *
4540 hd.equilibrium_bits);
4542 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4543 perror(
"Allocating equilibrium write buffer");
4546 memset(buf, 0, size);
4548 for (i = 0; i < hd.pub.constituents; ++i) {
4550 for (j = 0; j < hd.pub.number_of_years; ++j) {
4551 temp_int = NINT(hd.equilibrium[i][j] * hd.equilibrium_scale) -
4552 hd.equilibrium_offset;
4553 assert(temp_int >= 0);
4554 bit_pack(buf, pos, hd.equilibrium_bits, temp_int);
4555 pos += hd.equilibrium_bits;
4559 chk_fwrite(buf, size, 1, fp);
4566 bits2bytes(hd.pub.constituents * hd.pub.number_of_years * hd.node_bits);
4568 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
4569 perror(
"Allocating node write buffer");
4572 memset(buf, 0, size);
4574 for (i = 0; i < hd.pub.constituents; ++i) {
4576 for (j = 0; j < hd.pub.number_of_years; ++j) {
4577 temp_int = NINT(hd.node_factor[i][j] * hd.node_scale) - hd.node_offset;
4578 assert(temp_int >= 0);
4579 bit_pack(buf, pos, hd.node_bits, temp_int);
4580 pos += hd.node_bits;
4584 chk_fwrite(buf, size, 1, fp);
4615static void unpack_string(NV_U_BYTE *buf, NV_U_INT32 bufsize, NV_U_INT32 *pos,
4616 NV_CHAR *outbuf, NV_U_INT32 outbuflen,
4617 const NV_CHAR *desc) {
4627 for (i = 0; c; ++i) {
4628 assert(*pos < bufsize);
4629 c = bit_unpack(buf, *pos, 8);
4631 if (i < outbuflen) {
4633 }
else if (i == outbuflen) {
4636 LOG_ERROR(
"libtcd warning: truncating overlong %s\n", desc);
4637 LOG_ERROR(
"The offending string starts with:\n%s\n", outbuf);
4665static void unpack_partial_tide_record(NV_U_BYTE *buf, NV_U_INT32 bufsize,
4675 rec->header.record_size = bit_unpack(buf, *pos, hd.record_size_bits);
4676 *pos += hd.record_size_bits;
4678 rec->header.record_type = bit_unpack(buf, *pos, hd.record_type_bits);
4679 *pos += hd.record_type_bits;
4681 temp_int = signed_bit_unpack(buf, *pos, hd.latitude_bits);
4682 rec->header.latitude = (NV_FLOAT64)temp_int / hd.latitude_scale;
4683 *pos += hd.latitude_bits;
4685 temp_int = signed_bit_unpack(buf, *pos, hd.longitude_bits);
4686 rec->header.longitude = (NV_FLOAT64)temp_int / hd.longitude_scale;
4687 *pos += hd.longitude_bits;
4692 rec->header.tzfile = bit_unpack(buf, *pos, hd.tzfile_bits);
4693 *pos += hd.tzfile_bits;
4695 unpack_string(buf, bufsize, pos, rec->header.name, ONELINER_LENGTH,
4698 rec->header.reference_station = signed_bit_unpack(buf, *pos, hd.station_bits);
4699 *pos += hd.station_bits;
4701 assert(*pos <= bufsize * 8);
4724static NV_INT32 read_partial_tide_record(NV_INT32 num,
TIDE_RECORD *rec) {
4726 NV_U_INT32 maximum_possible_size, pos;
4730 "libtcd error: attempt to access database when database not open\n");
4739 maximum_possible_size = hd.record_size_bits + hd.record_type_bits +
4740 hd.latitude_bits + hd.longitude_bits +
4741 hd.tzfile_bits + (ONELINER_LENGTH * 8) +
4743 maximum_possible_size = bits2bytes(maximum_possible_size);
4745 if ((buf = (NV_U_BYTE *)calloc(maximum_possible_size,
sizeof(NV_U_BYTE))) ==
4747 perror(
"Allocating partial tide record buffer");
4751 current_record = num;
4752 fseek(fp, tindex[num].address, SEEK_SET);
4757 size_t size = fread(buf, 1, maximum_possible_size, fp);
4758 unpack_partial_tide_record(buf, size, rec, &pos);
4778static NV_BOOL read_tide_db_header() {
4780 NV_CHAR varin[ONELINER_LENGTH], *info;
4781 NV_U_INT32 utemp, i, j, pos, size, key_count;
4782 NV_U_BYTE *buf, checksum_c[5];
4787 "libtcd error: attempt to access database when database not open\n");
4791 strcpy(hd.pub.version,
"NO VERSION");
4794 key_count =
sizeof(keys) /
sizeof(
KEY);
4797 memset(&hd, 0,
sizeof(hd));
4800 while (fgets(varin,
sizeof(varin), fp) != NULL) {
4801 if (strlen(varin) == ONELINER_LENGTH - 1) {
4802 if (varin[ONELINER_LENGTH - 2] !=
'\n') {
4803 LOG_ERROR(
"libtcd error: header line too long, begins with:\n");
4804 LOG_ERROR(
"%s\n", varin);
4805 LOG_ERROR(
"in file %s\n", filename);
4806 LOG_ERROR(
"Configured limit is %u\n", ONELINER_LENGTH - 1);
4812 if (strstr(varin,
"[END OF ASCII HEADER DATA]"))
break;
4815 info = strchr(varin,
'=');
4817 LOG_ERROR(
"libtcd error: invalid tide db header line:\n");
4818 LOG_ERROR(
"%s", varin);
4819 LOG_ERROR(
"in file %s\n", filename);
4826 for (i = 0; i < key_count; ++i) {
4827 if (strstr(varin, keys[i].keyphrase)) {
4828 if (!strcmp(keys[i].datatype,
"cstr"))
4829 strcpy((
char *)keys[i].address.cstr, clip_string(info));
4830 else if (!strcmp(keys[i].datatype,
"i32")) {
4831 if (sscanf(info,
"%d", keys[i].address.i32) != 1) {
4832 LOG_ERROR(
"libtcd error: invalid tide db header line:\n");
4833 LOG_ERROR(
"%s", varin);
4834 LOG_ERROR(
"in file %s\n", filename);
4838 }
else if (!strcmp(keys[i].datatype,
"ui32")) {
4839 if (sscanf(info,
"%u", keys[i].address.ui32) != 1) {
4840 LOG_ERROR(
"libtcd error: invalid tide db header line:\n");
4841 LOG_ERROR(
"%s", varin);
4842 LOG_ERROR(
"in file %s\n", filename);
4854 if (!strcmp(hd.pub.version,
"NO VERSION")) {
4855 LOG_ERROR(
"libtcd error: no version found in tide db header\n");
4856 LOG_ERROR(
"in file %s\n", filename);
4862 if (hd.pub.major_rev > LIBTCD_MAJOR_REV) {
4864 "libtcd error: major revision in TCD file (%u) exceeds major revision "
4867 LOG_ERROR(
"libtcd (%u). You must upgrade libtcd to read this file.\n",
4874 fseek(fp, hd.header_size, SEEK_SET);
4878 chk_fread(checksum_c, 4, 1, fp);
4879 utemp = bit_unpack(checksum_c, 0, 32);
4881 if (utemp != header_checksum()) {
4883 if (utemp != old_header_checksum()) {
4884 LOG_ERROR(
"libtcd error: header checksum error in file %s\n", filename);
4886 "Someone may have modified the ASCII portion of the header (don't do that),\n\
4887or it may just be corrupt.\n");
4892 LOG_ERROR(
"libtcd error: header checksum error in file %s\n", filename);
4894 "Someone may have modified the ASCII portion of the header (don't do that),\n\
4895or it may be an ancient pre-version-1.02 TCD file, or it may just be corrupt.\n\
4896Pre-version-1.02 TCD files can be read by building libtcd with COMPAT114\n\
4902 fseek(fp, hd.header_size + 4, SEEK_SET);
4907 hd.max_restriction_types = NINT(pow(2.0, (NV_FLOAT64)hd.restriction_bits));
4911 hd.max_tzfiles = NINT(pow(2.0, (NV_FLOAT64)hd.tzfile_bits));
4915 hd.max_countries = NINT(pow(2.0, (NV_FLOAT64)hd.country_bits));
4920 hd.max_datum_types = NINT(pow(2.0, (NV_FLOAT64)hd.datum_bits));
4925 if (hd.pub.major_rev < 2)
4926 hd.max_legaleses = 1;
4928 hd.max_legaleses = NINT(pow(2.0, (NV_FLOAT64)hd.legalese_bits));
4935 (NV_CHAR **)calloc(hd.pub.level_unit_types,
sizeof(NV_CHAR *));
4937 if ((buf = (NV_U_BYTE *)calloc(hd.level_unit_size,
sizeof(NV_U_BYTE))) ==
4939 perror(
"Allocating level unit read buffer");
4943 for (i = 0; i < hd.pub.level_unit_types; ++i) {
4944 chk_fread(buf, hd.level_unit_size, 1, fp);
4946 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
4947 strcpy(hd.level_unit[i], (NV_CHAR *)buf);
4953 hd.dir_unit = (NV_CHAR **)calloc(hd.pub.dir_unit_types,
sizeof(NV_CHAR *));
4955 if ((buf = (NV_U_BYTE *)calloc(hd.dir_unit_size,
sizeof(NV_U_BYTE))) ==
4957 perror(
"Allocating dir unit read buffer");
4961 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
4962 chk_fread(buf, hd.dir_unit_size, 1, fp);
4964 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
4965 strcpy(hd.dir_unit[i], (NV_CHAR *)buf);
4973 (NV_CHAR **)calloc(hd.max_restriction_types,
sizeof(NV_CHAR *));
4975 if ((buf = (NV_U_BYTE *)calloc(hd.restriction_size,
sizeof(NV_U_BYTE))) ==
4977 perror(
"Allocating restriction read buffer");
4981 hd.pub.restriction_types = 0;
4982 for (i = 0; i < hd.max_restriction_types; ++i) {
4983 chk_fread(buf, hd.restriction_size, 1, fp);
4984 if (!strcmp((
char *)buf,
"__END__")) {
4985 hd.pub.restriction_types = i;
4989 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
4990 strcpy(hd.restriction[i], (NV_CHAR *)buf);
4993 fseek(fp, utemp + hd.max_restriction_types * hd.restriction_size, SEEK_SET);
4996 if (hd.pub.major_rev < 2)
4997 fseek(fp, hd.pedigree_size * NINT(pow(2.0, (NV_FLOAT64)hd.pedigree_bits)),
4999 hd.pub.pedigree_types = 1;
5004 hd.tzfile = (NV_CHAR **)calloc(hd.max_tzfiles,
sizeof(NV_CHAR *));
5006 if ((buf = (NV_U_BYTE *)calloc(hd.tzfile_size,
sizeof(NV_U_BYTE))) == NULL) {
5007 perror(
"Allocating tzfile read buffer");
5012 for (i = 0; i < hd.max_tzfiles; ++i) {
5013 chk_fread(buf, hd.tzfile_size, 1, fp);
5014 if (!strcmp((
char *)buf,
"__END__")) {
5018 hd.tzfile[i] = (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5019 strcpy(hd.tzfile[i], (NV_CHAR *)buf);
5022 fseek(fp, utemp + hd.max_tzfiles * hd.tzfile_size, SEEK_SET);
5027 hd.country = (NV_CHAR **)calloc(hd.max_countries,
sizeof(NV_CHAR *));
5029 if ((buf = (NV_U_BYTE *)calloc(hd.country_size,
sizeof(NV_U_BYTE))) == NULL) {
5030 perror(
"Allocating country read buffer");
5034 hd.pub.countries = 0;
5035 for (i = 0; i < hd.max_countries; ++i) {
5036 chk_fread(buf, hd.country_size, 1, fp);
5037 if (!strcmp((
char *)buf,
"__END__")) {
5038 hd.pub.countries = i;
5041 hd.country[i] = (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5042 strcpy(hd.country[i], (NV_CHAR *)buf);
5045 fseek(fp, utemp + hd.max_countries * hd.country_size, SEEK_SET);
5050 hd.datum = (NV_CHAR **)calloc(hd.max_datum_types,
sizeof(NV_CHAR *));
5052 if ((buf = (NV_U_BYTE *)calloc(hd.datum_size,
sizeof(NV_U_BYTE))) == NULL) {
5053 perror(
"Allocating datum read buffer");
5057 hd.pub.datum_types = 0;
5058 for (i = 0; i < hd.max_datum_types; ++i) {
5059 chk_fread(buf, hd.datum_size, 1, fp);
5060 if (!strcmp((
char *)buf,
"__END__")) {
5061 hd.pub.datum_types = i;
5064 hd.datum[i] = (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5065 strcpy(hd.datum[i], (NV_CHAR *)buf);
5068 fseek(fp, utemp + hd.max_datum_types * hd.datum_size, SEEK_SET);
5072 if (hd.pub.major_rev < 2) {
5073 hd.legalese = (NV_CHAR **)malloc(
sizeof(NV_CHAR *));
5074 assert(hd.legalese != NULL);
5075 hd.legalese[0] = (NV_CHAR *)malloc(5 *
sizeof(NV_CHAR));
5076 assert(hd.legalese[0] != NULL);
5077 strcpy(hd.legalese[0],
"NULL");
5078 hd.pub.legaleses = 1;
5081 hd.legalese = (NV_CHAR **)calloc(hd.max_legaleses,
sizeof(NV_CHAR *));
5083 if ((buf = (NV_U_BYTE *)calloc(hd.legalese_size,
sizeof(NV_U_BYTE))) ==
5085 perror(
"Allocating legalese read buffer");
5089 hd.pub.legaleses = 0;
5090 for (i = 0; i < hd.max_legaleses; ++i) {
5091 chk_fread(buf, hd.legalese_size, 1, fp);
5092 if (!strcmp((
char *)buf,
"__END__")) {
5093 hd.pub.legaleses = i;
5097 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5098 strcpy(hd.legalese[i], (NV_CHAR *)buf);
5101 fseek(fp, utemp + hd.max_legaleses * hd.legalese_size, SEEK_SET);
5106 hd.constituent = (NV_CHAR **)calloc(hd.pub.constituents,
sizeof(NV_CHAR *));
5108 if ((buf = (NV_U_BYTE *)calloc(hd.constituent_size,
sizeof(NV_U_BYTE))) ==
5110 perror(
"Allocating constituent read buffer");
5114 for (i = 0; i < hd.pub.constituents; ++i) {
5115 chk_fread(buf, hd.constituent_size, 1, fp);
5117 (NV_CHAR *)calloc(strlen((
char *)buf) + 1,
sizeof(NV_CHAR));
5118 strcpy(hd.constituent[i], (NV_CHAR *)buf);
5122 if (hd.speed_offset < 0 || hd.equilibrium_offset < 0 || hd.node_offset < 0) {
5123 LOG_ERROR(
"libtcd WARNING: File: %s\n", filename);
5125 "WARNING: This TCD file was created by a pre-version-1.11 libtcd.\n\
5126Versions of libtcd prior to 1.11 contained a serious bug that can result\n\
5127in overflows in the speeds, equilibrium arguments, or node factors. This\n\
5128database should be rebuilt from the original data if possible.\n");
5135 hd.speed = (NV_FLOAT64 *)calloc(hd.pub.constituents,
sizeof(NV_FLOAT64));
5139 if (hd.pub.major_rev < 2)
5140 size = ((hd.pub.constituents * hd.speed_bits) / 8) + 1;
5142 size = bits2bytes(hd.pub.constituents * hd.speed_bits);
5144 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
5145 perror(
"Allocating speed read buffer");
5149 chk_fread(buf, size, 1, fp);
5151 for (i = 0; i < hd.pub.constituents; ++i) {
5152 temp_int = bit_unpack(buf, pos, hd.speed_bits);
5153 hd.speed[i] = (NV_FLOAT64)(temp_int + hd.speed_offset) / hd.speed_scale;
5154 pos += hd.speed_bits;
5155 assert(hd.speed[i] >= 0.0);
5162 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5164 for (i = 0; i < hd.pub.constituents; ++i) {
5166 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5171 if (hd.pub.major_rev < 2)
5173 ((hd.pub.constituents * hd.pub.number_of_years * hd.equilibrium_bits) /
5177 size = bits2bytes(hd.pub.constituents * hd.pub.number_of_years *
5178 hd.equilibrium_bits);
5180 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
5181 perror(
"Allocating equilibrium read buffer");
5185 chk_fread(buf, size, 1, fp);
5187 for (i = 0; i < hd.pub.constituents; ++i) {
5188 for (j = 0; j < hd.pub.number_of_years; ++j) {
5189 temp_int = bit_unpack(buf, pos, hd.equilibrium_bits);
5190 hd.equilibrium[i][j] =
5191 (NV_FLOAT32)(temp_int + hd.equilibrium_offset) / hd.equilibrium_scale;
5192 pos += hd.equilibrium_bits;
5200 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5202 for (i = 0; i < hd.pub.constituents; ++i) {
5204 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5209 if (hd.pub.major_rev < 2)
5211 ((hd.pub.constituents * hd.pub.number_of_years * hd.node_bits) / 8) + 1;
5214 bits2bytes(hd.pub.constituents * hd.pub.number_of_years * hd.node_bits);
5216 if ((buf = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
5217 perror(
"Allocating node read buffer");
5221 chk_fread(buf, size, 1, fp);
5223 for (i = 0; i < hd.pub.constituents; ++i) {
5224 for (j = 0; j < hd.pub.number_of_years; ++j) {
5225 temp_int = bit_unpack(buf, pos, hd.node_bits);
5226 hd.node_factor[i][j] =
5227 (NV_FLOAT32)(temp_int + hd.node_offset) / hd.node_scale;
5228 pos += hd.node_bits;
5229 assert(hd.node_factor[i][j] > 0.0);
5238 if (hd.pub.number_of_records) {
5239 if ((tindex = (
TIDE_INDEX *)calloc(hd.pub.number_of_records,
5241 perror(
"Allocating tide index");
5245 tindex[0].address = ftell(fp);
5249 for (i = 0; i < hd.pub.number_of_records; ++i) {
5253 if (i) tindex[i].address = tindex[i - 1].address + rec.header.record_size;
5255 read_partial_tide_record(i, &rec);
5259 tindex[i].record_size = rec.header.record_size;
5260 tindex[i].record_type = rec.header.record_type;
5261 tindex[i].reference_station = rec.header.reference_station;
5262 assert(rec.header.tzfile >= 0);
5263 tindex[i].tzfile = rec.header.tzfile;
5264 tindex[i].lat = NINT(rec.header.latitude * hd.latitude_scale);
5265 tindex[i].lon = NINT(rec.header.longitude * hd.longitude_scale);
5267 if ((tindex[i].name = (NV_CHAR *)calloc(strlen(rec.header.name) + 1,
5268 sizeof(NV_CHAR))) == NULL) {
5269 perror(
"Allocating index name memory");
5273 strcpy(tindex[i].name, rec.header.name);
5276 current_record = -1;
5299NV_BOOL open_tide_db(
const NV_CHAR *file) {
5301 current_record = -1;
5304 if (!strcmp(file, filename) && !modified)
5309 if ((fp = fopen(file,
"rb+")) == NULL) {
5310 if ((fp = fopen(file,
"rb")) == NULL)
return (NVFalse);
5312 boundscheck_monologue(file);
5313 strcpy(filename, file);
5314 return (read_tide_db_header());
5335void close_tide_db() {
5339 LOG_ERROR(
"libtcd warning: close_tide_db called when no database open\n");
5346 if (modified) write_tide_db_header();
5350 assert(hd.constituent);
5351 for (i = 0; i < hd.pub.constituents; ++i) {
5352 if (hd.constituent[i] != NULL) free(hd.constituent[i]);
5354 free(hd.constituent);
5355 hd.constituent = NULL;
5357 if (hd.speed != NULL) free(hd.speed);
5359 assert(hd.equilibrium);
5360 for (i = 0; i < hd.pub.constituents; ++i) {
5361 if (hd.equilibrium[i] != NULL) free(hd.equilibrium[i]);
5363 free(hd.equilibrium);
5364 hd.equilibrium = NULL;
5366 assert(hd.node_factor);
5367 for (i = 0; i < hd.pub.constituents; ++i) {
5368 if (hd.node_factor[i] != NULL) free(hd.node_factor[i]);
5370 free(hd.node_factor);
5371 hd.node_factor = NULL;
5373 assert(hd.level_unit);
5374 for (i = 0; i < hd.pub.level_unit_types; ++i) {
5375 if (hd.level_unit[i] != NULL) free(hd.level_unit[i]);
5377 free(hd.level_unit);
5378 hd.level_unit = NULL;
5380 assert(hd.dir_unit);
5381 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
5382 if (hd.dir_unit[i] != NULL) free(hd.dir_unit[i]);
5387 assert(hd.restriction);
5388 for (i = 0; i < hd.max_restriction_types; ++i) {
5389 if (hd.restriction[i] != NULL) free(hd.restriction[i]);
5391 free(hd.restriction);
5392 hd.restriction = NULL;
5394 assert(hd.legalese);
5395 for (i = 0; i < hd.max_legaleses; ++i) {
5396 if (hd.legalese[i] != NULL) free(hd.legalese[i]);
5402 for (i = 0; i < hd.max_tzfiles; ++i) {
5403 if (hd.tzfile[i] != NULL) free(hd.tzfile[i]);
5409 for (i = 0; i < hd.max_countries; ++i) {
5410 if (hd.country[i] != NULL) free(hd.country[i]);
5416 for (i = 0; i < hd.max_datum_types; ++i) {
5417 if (hd.datum[i] != NULL) free(hd.datum[i]);
5424 for (i = 0; i < hd.pub.number_of_records; ++i) {
5425 if (tindex[i].name) free(tindex[i].name);
5466NV_BOOL create_tide_db(
const NV_CHAR *file, NV_U_INT32 constituents,
5467 NV_CHAR
const *
const constituent[],
5468 const NV_FLOAT64 *speed, NV_INT32 start_year,
5469 NV_U_INT32 num_years,
5470 NV_FLOAT32
const *
const equilibrium[],
5471 NV_FLOAT32
const *
const node_factor[]) {
5473 NV_FLOAT64 min_value, max_value;
5478 assert(constituent);
5480 assert(equilibrium);
5481 assert(node_factor);
5482 for (i = 0; i < constituents; ++i) {
5483 if (speed[i] < 0.0) {
5485 "libtcd create_tide_db: somebody tried to set a negative speed "
5490 for (j = 0; j < num_years; ++j) {
5491 if (node_factor[i][j] <= 0.0) {
5493 "libtcd create_tide_db: somebody tried to set a negative or zero "
5494 "node factor (%f)\n",
5501 if (fp) close_tide_db();
5503 if ((fp = fopen(file,
"wb+")) == NULL) {
5510 memset(&hd, 0,
sizeof(hd));
5512 hd.pub.major_rev = LIBTCD_MAJOR_REV;
5513 hd.pub.minor_rev = LIBTCD_MINOR_REV;
5515 hd.header_size = DEFAULT_HEADER_SIZE;
5516 hd.pub.number_of_records = DEFAULT_NUMBER_OF_RECORDS;
5518 hd.pub.start_year = start_year;
5519 hd.pub.number_of_years = num_years;
5521 hd.pub.constituents = constituents;
5525 hd.constituent = (NV_CHAR **)calloc(hd.pub.constituents,
sizeof(NV_CHAR *));
5526 for (i = 0; i < hd.pub.constituents; ++i) {
5528 (NV_CHAR *)calloc(strlen(constituent[i]) + 1,
sizeof(NV_CHAR));
5529 strcpy(hd.constituent[i], constituent[i]);
5535 hd.constituent_bits = calculate_bits(hd.pub.constituents);
5539 hd.speed = (NV_FLOAT64 *)calloc(hd.pub.constituents,
sizeof(NV_FLOAT64));
5541 hd.speed_scale = DEFAULT_SPEED_SCALE;
5542 min_value = 99999999.0;
5543 max_value = -99999999.0;
5544 for (i = 0; i < hd.pub.constituents; ++i) {
5545 if (speed[i] < min_value) min_value = speed[i];
5546 if (speed[i] > max_value) max_value = speed[i];
5548 hd.speed[i] = speed[i];
5554 hd.speed_offset = (NINT(min_value * hd.speed_scale));
5555 temp_int = NINT(max_value * hd.speed_scale) - hd.speed_offset;
5556 assert(temp_int >= 0);
5557 hd.speed_bits = calculate_bits((NV_U_INT32)temp_int);
5559 assert(hd.speed_bits < 32);
5564 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5566 hd.equilibrium_scale = DEFAULT_EQUILIBRIUM_SCALE;
5567 min_value = 99999999.0;
5568 max_value = -99999999.0;
5569 for (i = 0; i < hd.pub.constituents; ++i) {
5571 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5572 for (j = 0; j < hd.pub.number_of_years; ++j) {
5573 if (equilibrium[i][j] < min_value) min_value = equilibrium[i][j];
5574 if (equilibrium[i][j] > max_value) max_value = equilibrium[i][j];
5576 hd.equilibrium[i][j] = equilibrium[i][j];
5583 hd.equilibrium_offset = (NINT(min_value * hd.equilibrium_scale));
5584 temp_int = NINT(max_value * hd.equilibrium_scale) - hd.equilibrium_offset;
5585 assert(temp_int >= 0);
5586 hd.equilibrium_bits = calculate_bits((NV_U_INT32)temp_int);
5591 (NV_FLOAT32 **)calloc(hd.pub.constituents,
sizeof(NV_FLOAT32 *));
5593 hd.node_scale = DEFAULT_NODE_SCALE;
5594 min_value = 99999999.0;
5595 max_value = -99999999.0;
5596 for (i = 0; i < hd.pub.constituents; ++i) {
5598 (NV_FLOAT32 *)calloc(hd.pub.number_of_years,
sizeof(NV_FLOAT32));
5599 for (j = 0; j < hd.pub.number_of_years; ++j) {
5600 if (node_factor[i][j] < min_value) min_value = node_factor[i][j];
5601 if (node_factor[i][j] > max_value) max_value = node_factor[i][j];
5603 hd.node_factor[i][j] = node_factor[i][j];
5610 hd.node_offset = (NINT(min_value * hd.node_scale));
5611 temp_int = NINT(max_value * hd.node_scale) - hd.node_offset;
5612 assert(temp_int >= 0);
5613 hd.node_bits = calculate_bits((NV_U_INT32)temp_int);
5617 hd.amplitude_bits = DEFAULT_AMPLITUDE_BITS;
5618 hd.amplitude_scale = DEFAULT_AMPLITUDE_SCALE;
5619 hd.epoch_bits = DEFAULT_EPOCH_BITS;
5620 hd.epoch_scale = DEFAULT_EPOCH_SCALE;
5622 hd.record_type_bits = DEFAULT_RECORD_TYPE_BITS;
5623 hd.latitude_bits = DEFAULT_LATITUDE_BITS;
5624 hd.latitude_scale = DEFAULT_LATITUDE_SCALE;
5625 hd.longitude_bits = DEFAULT_LONGITUDE_BITS;
5626 hd.longitude_scale = DEFAULT_LONGITUDE_SCALE;
5627 hd.record_size_bits = DEFAULT_RECORD_SIZE_BITS;
5629 hd.station_bits = DEFAULT_STATION_BITS;
5631 hd.datum_offset_bits = DEFAULT_DATUM_OFFSET_BITS;
5632 hd.datum_offset_scale = DEFAULT_DATUM_OFFSET_SCALE;
5633 hd.date_bits = DEFAULT_DATE_BITS;
5634 hd.months_on_station_bits = DEFAULT_MONTHS_ON_STATION_BITS;
5635 hd.confidence_value_bits = DEFAULT_CONFIDENCE_VALUE_BITS;
5637 hd.time_bits = DEFAULT_TIME_BITS;
5638 hd.level_add_bits = DEFAULT_LEVEL_ADD_BITS;
5639 hd.level_add_scale = DEFAULT_LEVEL_ADD_SCALE;
5640 hd.level_multiply_bits = DEFAULT_LEVEL_MULTIPLY_BITS;
5641 hd.level_multiply_scale = DEFAULT_LEVEL_MULTIPLY_SCALE;
5642 hd.direction_bits = DEFAULT_DIRECTION_BITS;
5644 hd.constituent_size = DEFAULT_CONSTITUENT_SIZE;
5645 hd.level_unit_size = DEFAULT_LEVEL_UNIT_SIZE;
5646 hd.dir_unit_size = DEFAULT_DIR_UNIT_SIZE;
5647 hd.restriction_size = DEFAULT_RESTRICTION_SIZE;
5648 hd.tzfile_size = DEFAULT_TZFILE_SIZE;
5649 hd.country_size = DEFAULT_COUNTRY_SIZE;
5650 hd.datum_size = DEFAULT_DATUM_SIZE;
5651 hd.legalese_size = DEFAULT_LEGALESE_SIZE;
5655 hd.pub.level_unit_types = DEFAULT_LEVEL_UNIT_TYPES;
5656 hd.level_unit_bits = calculate_bits(hd.pub.level_unit_types - 1);
5659 (NV_CHAR **)calloc(hd.pub.level_unit_types,
sizeof(NV_CHAR *));
5660 for (i = 0; i < hd.pub.level_unit_types; ++i) {
5662 (NV_CHAR *)calloc(strlen(level_unit[i]) + 1,
sizeof(NV_CHAR));
5663 strcpy(hd.level_unit[i], level_unit[i]);
5668 hd.pub.dir_unit_types = DEFAULT_DIR_UNIT_TYPES;
5669 hd.dir_unit_bits = calculate_bits(hd.pub.dir_unit_types - 1);
5671 hd.dir_unit = (NV_CHAR **)calloc(hd.pub.dir_unit_types,
sizeof(NV_CHAR *));
5672 for (i = 0; i < hd.pub.dir_unit_types; ++i) {
5674 (NV_CHAR *)calloc(strlen(dir_unit[i]) + 1,
sizeof(NV_CHAR));
5675 strcpy(hd.dir_unit[i], dir_unit[i]);
5680 hd.restriction_bits = DEFAULT_RESTRICTION_BITS;
5681 hd.max_restriction_types = NINT(pow(2.0, (NV_FLOAT64)hd.restriction_bits));
5682 hd.pub.restriction_types = DEFAULT_RESTRICTION_TYPES;
5685 (NV_CHAR **)calloc(hd.max_restriction_types,
sizeof(NV_CHAR *));
5686 for (i = 0; i < hd.max_restriction_types; ++i) {
5687 if (i == hd.pub.restriction_types)
break;
5690 (NV_CHAR *)calloc(strlen(restriction[i]) + 1,
sizeof(NV_CHAR));
5691 strcpy(hd.restriction[i], restriction[i]);
5696 hd.legalese_bits = DEFAULT_LEGALESE_BITS;
5697 hd.max_legaleses = NINT(pow(2.0, (NV_FLOAT64)hd.legalese_bits));
5698 hd.pub.legaleses = DEFAULT_LEGALESES;
5700 hd.legalese = (NV_CHAR **)calloc(hd.max_legaleses,
sizeof(NV_CHAR *));
5701 for (i = 0; i < hd.max_legaleses; ++i) {
5702 if (i == hd.pub.legaleses)
break;
5705 (NV_CHAR *)calloc(strlen(legalese[i]) + 1,
sizeof(NV_CHAR));
5706 strcpy(hd.legalese[i], legalese[i]);
5711 hd.tzfile_bits = DEFAULT_TZFILE_BITS;
5712 hd.max_tzfiles = NINT(pow(2.0, (NV_FLOAT64)hd.tzfile_bits));
5713 hd.pub.tzfiles = DEFAULT_TZFILES;
5715 hd.tzfile = (NV_CHAR **)calloc(hd.max_tzfiles,
sizeof(NV_CHAR *));
5716 for (i = 0; i < hd.max_tzfiles; ++i) {
5717 if (i == hd.pub.tzfiles)
break;
5719 hd.tzfile[i] = (NV_CHAR *)calloc(strlen(tzfile[i]) + 1,
sizeof(NV_CHAR));
5720 strcpy(hd.tzfile[i], tzfile[i]);
5725 hd.country_bits = DEFAULT_COUNTRY_BITS;
5726 hd.max_countries = NINT(pow(2.0, (NV_FLOAT64)hd.country_bits));
5727 hd.pub.countries = DEFAULT_COUNTRIES;
5729 hd.country = (NV_CHAR **)calloc(hd.max_countries,
sizeof(NV_CHAR *));
5730 for (i = 0; i < hd.max_countries; ++i) {
5731 if (i == hd.pub.countries)
break;
5733 hd.country[i] = (NV_CHAR *)calloc(strlen(country[i]) + 1,
sizeof(NV_CHAR));
5734 strcpy(hd.country[i], country[i]);
5739 hd.datum_bits = DEFAULT_DATUM_BITS;
5740 hd.max_datum_types = NINT(pow(2.0, (NV_FLOAT64)hd.datum_bits));
5741 hd.pub.datum_types = DEFAULT_DATUM_TYPES;
5743 hd.datum = (NV_CHAR **)calloc(hd.max_datum_types,
sizeof(NV_CHAR *));
5744 for (i = 0; i < hd.max_datum_types; ++i) {
5745 if (i == hd.pub.datum_types)
break;
5747 hd.datum[i] = (NV_CHAR *)calloc(strlen(datum[i]) + 1,
sizeof(NV_CHAR));
5748 strcpy(hd.datum[i], datum[i]);
5758 i = (open_tide_db(file));
5762 hd.end_of_file = ftell(fp);
5766 write_tide_db_header();
5775static NV_BOOL check_date(NV_U_INT32 date) {
5781 if (m < 1 || m > 12 || d < 1 || d > 31)
return NVFalse;
5795static NV_BOOL check_tide_record(
TIDE_RECORD *rec) {
5797 NV_BOOL ret = NVTrue;
5800 LOG_ERROR(
"libtcd error: null pointer passed to check_tide_record\n");
5806 boundscheck_oneliner(rec->header.name);
5807 boundscheck_oneliner(rec->source);
5808 boundscheck_monologue(rec->comments);
5809 boundscheck_monologue(rec->notes);
5810 boundscheck_oneliner(rec->station_id_context);
5811 boundscheck_oneliner(rec->station_id);
5812 boundscheck_monologue(rec->xfields);
5815 if (rec->header.record_type == REFERENCE_STATION && rec->units > 0)
5816 rec->level_units = rec->units;
5819 if (rec->header.latitude < -90.0 || rec->header.latitude > 90.0 ||
5820 rec->header.longitude < -180.0 || rec->header.longitude > 180.0) {
5821 LOG_ERROR(
"libtcd error: bad coordinates in tide record\n");
5825 if (rec->header.tzfile < 0 ||
5826 rec->header.tzfile >= (NV_INT32)hd.pub.tzfiles) {
5827 LOG_ERROR(
"libtcd error: bad tzfile in tide record\n");
5831 if (rec->header.name[0] ==
'\0') {
5832 LOG_ERROR(
"libtcd error: null name in tide record\n");
5836 if (rec->country < 0 || rec->country >= (NV_INT32)hd.pub.countries) {
5837 LOG_ERROR(
"libtcd error: bad country in tide record\n");
5841 if (rec->restriction >= hd.pub.restriction_types) {
5842 LOG_ERROR(
"libtcd error: bad restriction in tide record\n");
5846 if (rec->legalese >= hd.pub.legaleses) {
5847 LOG_ERROR(
"libtcd error: bad legalese in tide record\n");
5851 if (!check_date(rec->date_imported)) {
5852 LOG_ERROR(
"libtcd error: bad date_imported in tide record\n");
5856 if (rec->direction_units >= hd.pub.dir_unit_types) {
5857 LOG_ERROR(
"libtcd error: bad direction_units in tide record\n");
5861 if (rec->min_direction < 0 || rec->min_direction > 361) {
5862 LOG_ERROR(
"libtcd error: min_direction out of range in tide record\n");
5866 if (rec->max_direction < 0 || rec->max_direction > 361) {
5867 LOG_ERROR(
"libtcd error: max_direction out of range in tide record\n");
5871 if (rec->level_units >= hd.pub.level_unit_types) {
5872 LOG_ERROR(
"libtcd error: bad units in tide record\n");
5876 switch (rec->header.record_type) {
5877 case REFERENCE_STATION:
5878 if (rec->header.reference_station != -1) {
5879 LOG_ERROR(
"libtcd error: type 1 record, reference_station != -1\n");
5883 if (rec->datum_offset < -13421.7728 || rec->datum_offset > 13421.7727) {
5884 LOG_ERROR(
"libtcd error: datum_offset out of range in tide record\n");
5888 if (rec->datum < 0 || rec->datum >= (NV_INT32)hd.pub.datum_types) {
5889 LOG_ERROR(
"libtcd error: bad datum in tide record\n");
5893 if (rec->zone_offset < -4096 || rec->zone_offset > 4095 ||
5894 rec->zone_offset % 100 >= 60) {
5895 LOG_ERROR(
"libtcd error: bad zone_offset in tide record\n");
5899 if (!check_date(rec->expiration_date)) {
5900 LOG_ERROR(
"libtcd error: bad expiration_date in tide record\n");
5904 if (rec->months_on_station > 1023) {
5906 "libtcd error: months_on_station out of range in tide record\n");
5910 if (!check_date(rec->last_date_on_station)) {
5911 LOG_ERROR(
"libtcd error: bad last_date_on_station in tide record\n");
5915 if (rec->confidence > 15) {
5916 LOG_ERROR(
"libtcd error: confidence out of range in tide record\n");
5921 for (i = 0; i < hd.pub.constituents; ++i) {
5922 if (rec->amplitude[i] < 0.0 || rec->amplitude[i] > 52.4287) {
5924 "libtcd error: constituent amplitude out of range in tide "
5930 for (i = 0; i < hd.pub.constituents; ++i) {
5931 if (rec->epoch[i] < 0.0 || rec->epoch[i] > 360.0) {
5933 "libtcd error: constituent epoch out of range in tide record\n");
5941 case SUBORDINATE_STATION:
5942 if (rec->header.reference_station < 0 ||
5943 rec->header.reference_station >= (NV_INT32)hd.pub.number_of_records) {
5944 LOG_ERROR(
"libtcd error: bad reference_station in tide record\n");
5948 if (rec->min_time_add < -4096 || rec->min_time_add > 4095 ||
5949 rec->min_time_add % 100 >= 60) {
5950 LOG_ERROR(
"libtcd error: bad min_time_add in tide record\n");
5954 if (rec->min_level_add < -65.536 || rec->min_level_add > 65.535) {
5955 LOG_ERROR(
"libtcd error: min_level_add out of range in tide record\n");
5959 if (rec->min_level_multiply < 0.0 || rec->min_level_multiply > 65.535) {
5961 "libtcd error: min_level_multiply out of range in tide record\n");
5965 if (rec->max_time_add < -4096 || rec->max_time_add > 4095 ||
5966 rec->max_time_add % 100 >= 60) {
5967 LOG_ERROR(
"libtcd error: bad max_time_add in tide record\n");
5971 if (rec->max_level_add < -65.536 || rec->max_level_add > 65.535) {
5972 LOG_ERROR(
"libtcd error: max_level_add out of range in tide record\n");
5976 if (rec->max_level_multiply < 0.0 || rec->max_level_multiply > 65.535) {
5978 "libtcd error: max_level_multiply out of range in tide record\n");
5982 if (rec->flood_begins != NULLSLACKOFFSET &&
5983 (rec->flood_begins < -4096 || rec->flood_begins > 4095 ||
5984 rec->flood_begins % 100 >= 60)) {
5985 LOG_ERROR(
"libtcd error: bad flood_begins in tide record\n");
5989 if (rec->ebb_begins != NULLSLACKOFFSET &&
5990 (rec->ebb_begins < -4096 || rec->ebb_begins > 4095 ||
5991 rec->ebb_begins % 100 >= 60)) {
5992 LOG_ERROR(
"libtcd error: bad ebb_begins in tide record\n");
5999 LOG_ERROR(
"libtcd error: invalid record_type in tide record\n");
6003 if (ret == NVFalse) dump_tide_record(rec);
6014 NV_U_INT32 i, count = 0, name_size, source_size, comments_size, notes_size,
6015 station_id_context_size, station_id_size, xfields_size;
6021 name_size = strlen(clip_string(rec->header.name)) + 1;
6022 source_size = strlen(clip_string(rec->source)) + 1;
6023 comments_size = strlen(clip_string(rec->comments)) + 1;
6024 notes_size = strlen(clip_string(rec->notes)) + 1;
6025 station_id_context_size = strlen(clip_string(rec->station_id_context)) + 1;
6026 station_id_size = strlen(clip_string(rec->station_id)) + 1;
6028 xfields_size = strlen(rec->xfields) + 1;
6030 rec->header.record_size =
6031 hd.record_size_bits + hd.record_type_bits + hd.latitude_bits +
6032 hd.longitude_bits + hd.station_bits + hd.tzfile_bits + (name_size * 8) +
6034 hd.country_bits + (source_size * 8) + hd.restriction_bits +
6035 (comments_size * 8) + (notes_size * 8) + hd.legalese_bits +
6036 (station_id_context_size * 8) + (station_id_size * 8) + hd.date_bits +
6037 (xfields_size * 8) + hd.dir_unit_bits + hd.direction_bits +
6038 hd.direction_bits + hd.level_unit_bits;
6040 switch (rec->header.record_type) {
6041 case REFERENCE_STATION:
6042 rec->header.record_size += hd.datum_offset_bits + hd.datum_bits +
6043 hd.time_bits + hd.date_bits +
6044 hd.months_on_station_bits + hd.date_bits +
6045 hd.confidence_value_bits + hd.constituent_bits;
6047 for (i = 0; i < hd.pub.constituents; ++i) {
6048 assert(rec->amplitude[i] >= 0.0);
6049 if (rec->amplitude[i] >= AMPLITUDE_EPSILON) ++count;
6052 rec->header.record_size +=
6053 (count * hd.constituent_bits + count * hd.amplitude_bits +
6054 count * hd.epoch_bits);
6058 case SUBORDINATE_STATION:
6059 rec->header.record_size += hd.time_bits + hd.level_add_bits +
6060 hd.level_multiply_bits + hd.time_bits +
6061 hd.level_add_bits + hd.level_multiply_bits +
6062 hd.time_bits + hd.time_bits;
6069 rec->header.record_size = bits2bytes(rec->header.record_size);
6076static void pack_string(NV_U_BYTE *buf, NV_U_INT32 *pos, NV_CHAR *s) {
6077 NV_U_INT32 i, temp_size;
6081 temp_size = strlen(s) + 1;
6082 for (i = 0; i < temp_size; ++i) {
6083 bit_pack(buf, *pos, 8, s[i]);
6108static void pack_tide_record(
TIDE_RECORD *rec, NV_U_BYTE **bufptr,
6109 NV_U_INT32 *bufsize) {
6110 NV_U_INT32 i, pos, constituent_count;
6119 boundscheck_oneliner(rec->header.name);
6120 boundscheck_oneliner(rec->source);
6121 boundscheck_monologue(rec->comments);
6122 boundscheck_monologue(rec->notes);
6123 boundscheck_oneliner(rec->station_id_context);
6124 boundscheck_oneliner(rec->station_id);
6125 boundscheck_monologue(rec->xfields);
6127 constituent_count = figure_size(rec);
6130 (NV_U_BYTE *)calloc(rec->header.record_size,
sizeof(NV_U_BYTE)))) {
6131 perror(
"libtcd can't allocate memory in pack_tide_record");
6141 bit_pack(buf, pos, hd.record_size_bits, rec->header.record_size);
6142 pos += hd.record_size_bits;
6144 bit_pack(buf, pos, hd.record_type_bits, rec->header.record_type);
6145 pos += hd.record_type_bits;
6147 temp_int = NINT(rec->header.latitude * hd.latitude_scale);
6148 bit_pack(buf, pos, hd.latitude_bits, temp_int);
6149 pos += hd.latitude_bits;
6151 temp_int = NINT(rec->header.longitude * hd.longitude_scale);
6152 bit_pack(buf, pos, hd.longitude_bits, temp_int);
6153 pos += hd.longitude_bits;
6159 bit_pack(buf, pos, hd.tzfile_bits, rec->header.tzfile);
6160 pos += hd.tzfile_bits;
6162 pack_string(buf, &pos, clip_string(rec->header.name));
6164 bit_pack(buf, pos, hd.station_bits, rec->header.reference_station);
6165 pos += hd.station_bits;
6167 bit_pack(buf, pos, hd.country_bits, rec->country);
6168 pos += hd.country_bits;
6170 pack_string(buf, &pos, clip_string(rec->source));
6172 bit_pack(buf, pos, hd.restriction_bits, rec->restriction);
6173 pos += hd.restriction_bits;
6175 pack_string(buf, &pos, clip_string(rec->comments));
6176 pack_string(buf, &pos, clip_string(rec->notes));
6178 bit_pack(buf, pos, hd.legalese_bits, rec->legalese);
6179 pos += hd.legalese_bits;
6181 pack_string(buf, &pos, clip_string(rec->station_id_context));
6182 pack_string(buf, &pos, clip_string(rec->station_id));
6184 bit_pack(buf, pos, hd.date_bits, rec->date_imported);
6185 pos += hd.date_bits;
6188 pack_string(buf, &pos, rec->xfields);
6190 bit_pack(buf, pos, hd.dir_unit_bits, rec->direction_units);
6191 pos += hd.dir_unit_bits;
6193 bit_pack(buf, pos, hd.direction_bits, rec->min_direction);
6194 pos += hd.direction_bits;
6196 bit_pack(buf, pos, hd.direction_bits, rec->max_direction);
6197 pos += hd.direction_bits;
6200 bit_pack(buf, pos, hd.level_unit_bits, rec->level_units);
6201 pos += hd.level_unit_bits;
6205 if (rec->header.record_type == REFERENCE_STATION) {
6206 temp_int = NINT(rec->datum_offset * hd.datum_offset_scale);
6207 bit_pack(buf, pos, hd.datum_offset_bits, temp_int);
6208 pos += hd.datum_offset_bits;
6210 bit_pack(buf, pos, hd.datum_bits, rec->datum);
6211 pos += hd.datum_bits;
6213 bit_pack(buf, pos, hd.time_bits, rec->zone_offset);
6214 pos += hd.time_bits;
6216 bit_pack(buf, pos, hd.date_bits, rec->expiration_date);
6217 pos += hd.date_bits;
6219 bit_pack(buf, pos, hd.months_on_station_bits, rec->months_on_station);
6220 pos += hd.months_on_station_bits;
6222 bit_pack(buf, pos, hd.date_bits, rec->last_date_on_station);
6223 pos += hd.date_bits;
6225 bit_pack(buf, pos, hd.confidence_value_bits, rec->confidence);
6226 pos += hd.confidence_value_bits;
6228 bit_pack(buf, pos, hd.constituent_bits, constituent_count);
6229 pos += hd.constituent_bits;
6231 for (i = 0; i < hd.pub.constituents; ++i) {
6232 if (rec->amplitude[i] >= AMPLITUDE_EPSILON) {
6233 bit_pack(buf, pos, hd.constituent_bits, i);
6234 pos += hd.constituent_bits;
6236 temp_int = NINT(rec->amplitude[i] * hd.amplitude_scale);
6238 bit_pack(buf, pos, hd.amplitude_bits, temp_int);
6239 pos += hd.amplitude_bits;
6241 temp_int = NINT(rec->epoch[i] * hd.epoch_scale);
6242 bit_pack(buf, pos, hd.epoch_bits, temp_int);
6243 pos += hd.epoch_bits;
6249 else if (rec->header.record_type == SUBORDINATE_STATION) {
6250 bit_pack(buf, pos, hd.time_bits, rec->min_time_add);
6251 pos += hd.time_bits;
6253 temp_int = NINT(rec->min_level_add * hd.level_add_scale);
6254 bit_pack(buf, pos, hd.level_add_bits, temp_int);
6255 pos += hd.level_add_bits;
6257 temp_int = NINT(rec->min_level_multiply * hd.level_multiply_scale);
6258 bit_pack(buf, pos, hd.level_multiply_bits, temp_int);
6259 pos += hd.level_multiply_bits;
6261 bit_pack(buf, pos, hd.time_bits, rec->max_time_add);
6262 pos += hd.time_bits;
6264 temp_int = NINT(rec->max_level_add * hd.level_add_scale);
6265 bit_pack(buf, pos, hd.level_add_bits, temp_int);
6266 pos += hd.level_add_bits;
6268 temp_int = NINT(rec->max_level_multiply * hd.level_multiply_scale);
6269 bit_pack(buf, pos, hd.level_multiply_bits, temp_int);
6270 pos += hd.level_multiply_bits;
6272 bit_pack(buf, pos, hd.time_bits, rec->flood_begins);
6273 pos += hd.time_bits;
6275 bit_pack(buf, pos, hd.time_bits, rec->ebb_begins);
6276 pos += hd.time_bits;
6280 LOG_ERROR(
"libtcd error: Record type %d is undefined\n",
6281 rec->header.record_type);
6285 *bufsize = rec->header.record_size;
6286 assert(*bufsize == bits2bytes(pos));
6311static NV_BOOL write_tide_record(NV_INT32 num,
TIDE_RECORD *rec) {
6312 NV_U_BYTE *buf = NULL;
6313 NV_U_INT32 bufsize = 0;
6317 "libtcd error: attempt to access database when database not open\n");
6322 pack_tide_record(rec, &buf, &bufsize);
6327 fseek(fp, tindex[num].address, SEEK_SET);
6331 chk_fwrite(buf, bufsize, 1, fp);
6356 return (read_tide_record(current_record + 1, rec));
6380static void unpack_tide_record(NV_U_BYTE *buf, NV_U_INT32 bufsize,
6383 NV_U_INT32 i, j, pos, count;
6390 int r = find_dir_units(
"degrees true");
6392 rec->direction_units = (NV_U_BYTE)r;
6394 rec->min_direction = rec->max_direction = 361;
6395 rec->flood_begins = rec->ebb_begins = NULLSLACKOFFSET;
6396 rec->header.record_number = current_record;
6398 unpack_partial_tide_record(buf, bufsize, rec, &pos);
6400 switch (rec->header.record_type) {
6401 case REFERENCE_STATION:
6402 case SUBORDINATE_STATION:
6405 LOG_ERROR(
"libtcd fatal error: tried to read type %d tide record.\n",
6406 rec->header.record_type);
6408 "This version of libtcd only supports types 1 and 2. Perhaps you "
6409 "should\nupgrade.\n");
6413 switch (hd.pub.major_rev) {
6420 rec->country = bit_unpack(buf, pos, hd.country_bits);
6421 pos += hd.country_bits;
6424 pos += hd.pedigree_bits;
6426 unpack_string(buf, bufsize, &pos, rec->source, ONELINER_LENGTH,
6429 rec->restriction = bit_unpack(buf, pos, hd.restriction_bits);
6430 pos += hd.restriction_bits;
6432 unpack_string(buf, bufsize, &pos, rec->comments, MONOLOGUE_LENGTH,
6435 if (rec->header.record_type == REFERENCE_STATION) {
6436 rec->level_units = bit_unpack(buf, pos, hd.level_unit_bits);
6438 rec->units = rec->level_units;
6440 pos += hd.level_unit_bits;
6442 temp_int = signed_bit_unpack(buf, pos, hd.datum_offset_bits);
6443 rec->datum_offset = (NV_FLOAT32)temp_int / hd.datum_offset_scale;
6444 pos += hd.datum_offset_bits;
6446 rec->datum = bit_unpack(buf, pos, hd.datum_bits);
6447 pos += hd.datum_bits;
6449 rec->zone_offset = signed_bit_unpack(buf, pos, hd.time_bits);
6450 pos += hd.time_bits;
6452 rec->expiration_date = bit_unpack(buf, pos, hd.date_bits);
6453 pos += hd.date_bits;
6455 rec->months_on_station =
6456 bit_unpack(buf, pos, hd.months_on_station_bits);
6457 pos += hd.months_on_station_bits;
6459 rec->last_date_on_station = bit_unpack(buf, pos, hd.date_bits);
6460 pos += hd.date_bits;
6462 rec->confidence = bit_unpack(buf, pos, hd.confidence_value_bits);
6463 pos += hd.confidence_value_bits;
6465 for (i = 0; i < hd.pub.constituents; ++i) {
6466 rec->amplitude[i] = 0.0;
6467 rec->epoch[i] = 0.0;
6470 count = bit_unpack(buf, pos, hd.constituent_bits);
6471 pos += hd.constituent_bits;
6473 for (i = 0; i < count; ++i) {
6474 j = bit_unpack(buf, pos, hd.constituent_bits);
6475 pos += hd.constituent_bits;
6478 (NV_FLOAT32)bit_unpack(buf, pos, hd.amplitude_bits) /
6480 pos += hd.amplitude_bits;
6483 (NV_FLOAT32)bit_unpack(buf, pos, hd.epoch_bits) / hd.epoch_scale;
6484 pos += hd.epoch_bits;
6486 }
else if (rec->header.record_type == SUBORDINATE_STATION) {
6487 rec->level_units = bit_unpack(buf, pos, hd.level_unit_bits);
6488 pos += hd.level_unit_bits;
6490 rec->direction_units = bit_unpack(buf, pos, hd.dir_unit_bits);
6491 pos += hd.dir_unit_bits;
6494 pos += hd.level_unit_bits;
6496 rec->min_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6497 pos += hd.time_bits;
6499 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6500 rec->min_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6501 pos += hd.level_add_bits;
6504 temp_int = signed_bit_unpack(buf, pos, hd.level_multiply_bits);
6505 rec->min_level_multiply =
6506 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6507 pos += hd.level_multiply_bits;
6510 pos += hd.level_add_bits;
6512 rec->min_direction = bit_unpack(buf, pos, hd.direction_bits);
6513 pos += hd.direction_bits;
6515 rec->max_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6516 pos += hd.time_bits;
6518 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6519 rec->max_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6520 pos += hd.level_add_bits;
6523 temp_int = signed_bit_unpack(buf, pos, hd.level_multiply_bits);
6524 rec->max_level_multiply =
6525 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6526 pos += hd.level_multiply_bits;
6529 pos += hd.level_add_bits;
6531 rec->max_direction = bit_unpack(buf, pos, hd.direction_bits);
6532 pos += hd.direction_bits;
6534 rec->flood_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6535 pos += hd.time_bits;
6537 rec->ebb_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6538 pos += hd.time_bits;
6546 rec->country = bit_unpack(buf, pos, hd.country_bits);
6547 pos += hd.country_bits;
6549 unpack_string(buf, bufsize, &pos, rec->source, ONELINER_LENGTH,
6552 rec->restriction = bit_unpack(buf, pos, hd.restriction_bits);
6553 pos += hd.restriction_bits;
6555 unpack_string(buf, bufsize, &pos, rec->comments, MONOLOGUE_LENGTH,
6557 unpack_string(buf, bufsize, &pos, rec->notes, MONOLOGUE_LENGTH,
6560 rec->legalese = bit_unpack(buf, pos, hd.legalese_bits);
6561 pos += hd.legalese_bits;
6563 unpack_string(buf, bufsize, &pos, rec->station_id_context,
6564 ONELINER_LENGTH,
"station_id_context field");
6565 unpack_string(buf, bufsize, &pos, rec->station_id, ONELINER_LENGTH,
6566 "station_id field");
6568 rec->date_imported = bit_unpack(buf, pos, hd.date_bits);
6569 pos += hd.date_bits;
6571 unpack_string(buf, bufsize, &pos, rec->xfields, MONOLOGUE_LENGTH,
6574 rec->direction_units = bit_unpack(buf, pos, hd.dir_unit_bits);
6575 pos += hd.dir_unit_bits;
6577 rec->min_direction = bit_unpack(buf, pos, hd.direction_bits);
6578 pos += hd.direction_bits;
6580 rec->max_direction = bit_unpack(buf, pos, hd.direction_bits);
6581 pos += hd.direction_bits;
6583 rec->level_units = bit_unpack(buf, pos, hd.level_unit_bits);
6585 rec->units = rec->level_units;
6587 pos += hd.level_unit_bits;
6589 if (rec->header.record_type == REFERENCE_STATION) {
6590 temp_int = signed_bit_unpack(buf, pos, hd.datum_offset_bits);
6591 rec->datum_offset = (NV_FLOAT32)temp_int / hd.datum_offset_scale;
6592 pos += hd.datum_offset_bits;
6594 rec->datum = bit_unpack(buf, pos, hd.datum_bits);
6595 pos += hd.datum_bits;
6597 rec->zone_offset = signed_bit_unpack(buf, pos, hd.time_bits);
6598 pos += hd.time_bits;
6600 rec->expiration_date = bit_unpack(buf, pos, hd.date_bits);
6601 pos += hd.date_bits;
6603 rec->months_on_station =
6604 bit_unpack(buf, pos, hd.months_on_station_bits);
6605 pos += hd.months_on_station_bits;
6607 rec->last_date_on_station = bit_unpack(buf, pos, hd.date_bits);
6608 pos += hd.date_bits;
6610 rec->confidence = bit_unpack(buf, pos, hd.confidence_value_bits);
6611 pos += hd.confidence_value_bits;
6613 for (i = 0; i < hd.pub.constituents; ++i) {
6614 rec->amplitude[i] = 0.0;
6615 rec->epoch[i] = 0.0;
6618 count = bit_unpack(buf, pos, hd.constituent_bits);
6619 pos += hd.constituent_bits;
6621 for (i = 0; i < count; ++i) {
6622 j = bit_unpack(buf, pos, hd.constituent_bits);
6623 pos += hd.constituent_bits;
6626 (NV_FLOAT32)bit_unpack(buf, pos, hd.amplitude_bits) /
6628 pos += hd.amplitude_bits;
6631 (NV_FLOAT32)bit_unpack(buf, pos, hd.epoch_bits) / hd.epoch_scale;
6632 pos += hd.epoch_bits;
6634 }
else if (rec->header.record_type == SUBORDINATE_STATION) {
6635 rec->min_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6636 pos += hd.time_bits;
6638 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6639 rec->min_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6640 pos += hd.level_add_bits;
6643 temp_int = bit_unpack(buf, pos, hd.level_multiply_bits);
6644 rec->min_level_multiply =
6645 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6646 pos += hd.level_multiply_bits;
6648 rec->max_time_add = signed_bit_unpack(buf, pos, hd.time_bits);
6649 pos += hd.time_bits;
6651 temp_int = signed_bit_unpack(buf, pos, hd.level_add_bits);
6652 rec->max_level_add = (NV_FLOAT32)temp_int / hd.level_add_scale;
6653 pos += hd.level_add_bits;
6656 temp_int = bit_unpack(buf, pos, hd.level_multiply_bits);
6657 rec->max_level_multiply =
6658 (NV_FLOAT32)temp_int / hd.level_multiply_scale;
6659 pos += hd.level_multiply_bits;
6661 rec->flood_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6662 pos += hd.time_bits;
6664 rec->ebb_begins = signed_bit_unpack(buf, pos, hd.time_bits);
6665 pos += hd.time_bits;
6675 assert(pos <= bufsize * 8);
6699NV_INT32 read_tide_record(NV_INT32 num,
TIDE_RECORD *rec) {
6705 "libtcd error: attempt to access database when database not open\n");
6709 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return -1;
6712 bufsize = tindex[num].record_size;
6713 if ((buf = (NV_U_BYTE *)calloc(bufsize,
sizeof(NV_U_BYTE))) == NULL) {
6714 perror(
"Allocating read_tide_record buffer");
6718 current_record = num;
6719 require(fseek(fp, tindex[num].address, SEEK_SET) == 0);
6720 chk_fread(buf, tindex[num].record_size, 1, fp);
6721 unpack_tide_record(buf, bufsize, rec);
6748 "libtcd error: attempt to access database when database not open\n");
6753 if (!check_tide_record(rec))
return NVFalse;
6755 fseek(fp, hd.end_of_file, SEEK_SET);
6759 rec->header.record_number = hd.pub.number_of_records++;
6761 if (write_tide_record(-1, rec)) {
6763 tindex, hd.pub.number_of_records *
sizeof(
TIDE_INDEX))) == NULL) {
6764 perror(
"Allocating more index records");
6768 tindex[rec->header.record_number].address = pos;
6769 tindex[rec->header.record_number].record_size = rec->header.record_size;
6770 tindex[rec->header.record_number].record_type = rec->header.record_type;
6771 tindex[rec->header.record_number].reference_station =
6772 rec->header.reference_station;
6773 assert(rec->header.tzfile >= 0);
6774 tindex[rec->header.record_number].tzfile = rec->header.tzfile;
6775 tindex[rec->header.record_number].lat =
6776 NINT(rec->header.latitude * hd.latitude_scale);
6777 tindex[rec->header.record_number].lon =
6778 NINT(rec->header.longitude * hd.longitude_scale);
6780 if ((tindex[rec->header.record_number].name = (NV_CHAR *)calloc(
6781 strlen(rec->header.name) + 1,
sizeof(NV_CHAR))) == NULL) {
6782 perror(
"Allocating index name memory");
6786 strcpy(tindex[rec->header.record_number].name, rec->header.name);
6789 hd.end_of_file = pos;
6793 if (db) *db = hd.pub;
6822 NV_INT32 i, newrecnum, *map;
6823 NV_U_BYTE **allrecs_packed;
6826 LOG_ERROR (
"libtcd error: attempt to access database when database not open\n");
6831 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return NVFalse;
6835 if (!(map = (NV_INT32 *) malloc (hd.pub.number_of_records *
sizeof(NV_INT32)))) {
6836 perror (
"libtcd: delete_tide_record: can't malloc");
6839 if (!(allrecs_packed = (NV_U_BYTE **) malloc (hd.pub.number_of_records *
sizeof(NV_U_BYTE*)))) {
6840 perror (
"libtcd: delete_tide_record: can't malloc");
6848 require (fseek (fp, tindex[0].address, SEEK_SET) == 0);
6849 for (newrecnum=0,i=0; i<(NV_INT32)hd.pub.number_of_records; ++i) {
6850 assert (ftell(fp) == tindex[i].address);
6851 if (i == num || (tindex[i].record_type == SUBORDINATE_STATION && tindex[i].reference_station == num)) {
6853 allrecs_packed[i] = NULL;
6854 require (fseek (fp, tindex[i].record_size, SEEK_CUR) == 0);
6856 map[i] = newrecnum++;
6857 if (!(allrecs_packed[i] = (NV_U_BYTE *) malloc (tindex[i].record_size))) {
6858 perror (
"libtcd: delete_tide_record: can't malloc");
6859 for (--i; i>=0; --i)
6860 free (allrecs_packed[i]);
6861 free (allrecs_packed);
6865 chk_fread (allrecs_packed[i], tindex[i].record_size, 1, fp);
6871 require (fseek (fp, tindex[0].address, SEEK_SET) == 0);
6872 require (ftruncate (fileno(fp), tindex[0].address) == 0);
6874 for (i=0; i<(NV_INT32)hd.pub.number_of_records; ++i)
6876 if (tindex[i].record_type == SUBORDINATE_STATION) {
6877 assert (tindex[i].reference_station >= 0);
6878 assert (tindex[i].reference_station <= (NV_INT32)hd.pub.number_of_records);
6879 if (map[tindex[i].reference_station] != tindex[i].reference_station) {
6882 unpack_tide_record (allrecs_packed[i], tindex[i].record_size, &rec);
6883 free (allrecs_packed[i]);
6884 rec.header.reference_station = map[tindex[i].reference_station];
6885 pack_tide_record (&rec, &(allrecs_packed[i]), &(tindex[i].record_size));
6888 chk_fwrite (allrecs_packed[i], tindex[i].record_size, 1, fp);
6889 free (allrecs_packed[i]);
6894 free (allrecs_packed);
6900 hd.end_of_file = ftell(fp);
6901 hd.pub.number_of_records = newrecnum;
6904 open_tide_db (filename);
6933NV_BOOL update_tide_record(NV_INT32 num,
TIDE_RECORD *rec)
6940 NV_U_BYTE *
block = NULL;
6944 "libtcd error: attempt to access database when database not open\n");
6949 if (num < 0 || num >= (NV_INT32)hd.pub.number_of_records)
return NVFalse;
6951 if (!check_tide_record(rec))
return NVFalse;
6954 read_tide_record(num, &tmp_rec);
6955 if (rec->header.record_size != tmp_rec.header.record_size) {
6963 size = hd.end_of_file - pos;
6968 if ((
block = (NV_U_BYTE *)calloc(size,
sizeof(NV_U_BYTE))) == NULL) {
6969 perror(
"Allocating block");
6972 chk_fread(
block, size, 1, fp);
6976 write_tide_record(num, rec);
6980 chk_fwrite(
block, size, 1, fp);
6984 hd.end_of_file = ftell(fp);
6988 open_tide_db(filename);
6993 write_tide_record(num, rec);
6996 tindex[num].record_size = rec->header.record_size;
6997 tindex[num].record_type = rec->header.record_type;
6998 tindex[num].reference_station = rec->header.reference_station;
6999 tindex[num].tzfile = rec->header.tzfile;
7000 tindex[num].lat = NINT(rec->header.latitude * hd.latitude_scale);
7001 tindex[num].lon = NINT(rec->header.longitude * hd.longitude_scale);
7006 if (strcmp(tindex[num].name, rec->header.name) != 0) {
7007 free(tindex[num].name);
7009 (NV_CHAR *)calloc(strlen(rec->header.name) + 1,
sizeof(NV_CHAR));
7010 strcpy(tindex[num].name, rec->header.name);
7015 if (db) *db = hd.pub;
7052 NV_INT32 m2, s2, k1, o1;
7053 NV_FLOAT32 epoch_m2, epoch_s2, epoch_k1, epoch_o1;
7056 require((m2 = find_constituent(
"M2")) >= 0);
7057 require((s2 = find_constituent(
"S2")) >= 0);
7058 require((k1 = find_constituent(
"K1")) >= 0);
7059 require((o1 = find_constituent(
"O1")) >= 0);
7061 if (rec->amplitude[m2] == 0.0 || rec->amplitude[s2] == 0.0 ||
7062 rec->amplitude[k1] == 0.0 || rec->amplitude[o1] == 0.0)
7065 epoch_m2 = rec->epoch[m2];
7066 epoch_s2 = rec->epoch[s2];
7067 epoch_k1 = rec->epoch[k1];
7068 epoch_o1 = rec->epoch[o1];
7070 for (i = 0; i < hd.pub.constituents; ++i) {
7071 if (rec->amplitude[i] == 0.0 && rec->epoch[i] == 0.0) {
7072 for (j = 0; j < INFERRED_SEMI_DIURNAL_COUNT; ++j) {
7073 if (!strcmp(inferred_semi_diurnal[j], get_constituent(i))) {
7077 (semi_diurnal_coeff[j] / coeff[0]) * rec->amplitude[m2];
7079 if (fabs((NV_FLOAT64)(epoch_s2 - epoch_m2)) > 180.0) {
7080 if (epoch_s2 < epoch_m2) {
7086 rec->epoch[i] = epoch_m2 + ((hd.speed[i] - hd.speed[m2]) /
7087 (hd.speed[s2] - hd.speed[m2])) *
7088 (epoch_s2 - epoch_m2);
7092 for (j = 0; j < INFERRED_DIURNAL_COUNT; ++j) {
7093 if (!strcmp(inferred_diurnal[j], get_constituent(i))) {
7097 (diurnal_coeff[j] / coeff[1]) * rec->amplitude[o1];
7099 if (fabs((NV_FLOAT64)(epoch_k1 - epoch_o1)) > 180.0) {
7100 if (epoch_k1 < epoch_o1) {
7106 rec->epoch[i] = epoch_o1 + ((hd.speed[i] - hd.speed[o1]) /
7107 (hd.speed[k1] - hd.speed[o1])) *
7108 (epoch_k1 - epoch_o1);
7123static NV_U_BYTE mask[8] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe},
7124 notmask[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
7163NV_U_INT32 calculate_bits(NV_U_INT32 value) {
7164 NV_U_INT32 bits = 32;
7165 NV_U_INT32 theBit = 0x80000000;
7167 while (value < theBit) {
7202void bit_pack(NV_U_BYTE buffer[], NV_U_INT32 start, NV_U_INT32 numbits,
7204 NV_INT32 start_byte, end_byte, start_bit, end_bit, i;
7206 i = start + numbits;
7212 start_byte = start >> 3;
7219 start_bit = start & 7;
7224 i = end_byte - start_byte - 1;
7228 if (start_byte == end_byte) {
7233 buffer[start_byte] &= mask[start_bit] | notmask[end_bit];
7239 buffer[start_byte] |=
7240 (value << (8 - end_bit)) & (notmask[start_bit] & mask[end_bit]);
7246#pragma GCC diagnostic push
7247#pragma GCC diagnostic ignored "-Warray-bounds"
7252 buffer[start_byte] &= mask[start_bit];
7260 buffer[start_byte++] |=
7261 (value >> (numbits - (8 - start_bit))) & notmask[start_bit];
7268 buffer[start_byte] &= 0;
7272 buffer[start_byte++] |= (value >> ((i << 3) + end_bit)) & 255;
7277 buffer[start_byte] &= notmask[end_bit];
7283 buffer[start_byte] |= (value << (8 - end_bit));
7284#pragma GCC diagnostic pop
7314NV_U_INT32 bit_unpack(NV_U_BYTE buffer[], NV_U_INT32 start,
7315 NV_U_INT32 numbits) {
7316 NV_INT32 start_byte, end_byte, start_bit, end_bit, i;
7319 i = start + numbits;
7325 start_byte = start >> 3;
7332 start_bit = start & 7;
7337 i = end_byte - start_byte - 1;
7341 if (start_byte == end_byte) {
7345 (NV_U_INT32)buffer[start_byte] & (notmask[start_bit] & mask[end_bit]);
7349 value >>= (8 - end_bit);
7358 value = (NV_U_INT32)(buffer[start_byte++] & notmask[start_bit])
7359 << (numbits - (8 - start_bit));
7366 value += (NV_U_INT32)buffer[start_byte++] << ((i << 3) + end_bit);
7371 if (mask[end_bit]) {
7373 (NV_U_INT32)(buffer[start_byte] & mask[end_bit]) >> (8 - end_bit);
7406NV_INT32 signed_bit_unpack(NV_U_BYTE buffer[], NV_U_INT32 start,
7407 NV_U_INT32 numbits) {
7408 static NV_INT32 extend_mask = 0x7fffffff;
7412 assert(numbits > 0);
7414 value = bit_unpack(buffer, start, numbits);
7416 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.
wxDateTime toUsrDateTime(const wxDateTime ts, const int format, const double lon)
Converts a timestamp from UTC to the user's preferred time format.
Runtime representation of a plugin block.
TCMgr * ptcmgr
Global instance.
double BOGUS_amplitude(double mpy, IDX_entry *pIDX)
BOGUS amplitude stuff - Added mgh For knots^2 current stations, returns square root of (value * ampli...
Tide and Current Manager @TODO Add original author copyright.