1 // $Id: ZoneIndex.cc 5749 2014-10-11 19:42:10Z flaterco $
2 
3 /*  ZoneIndex  Index stations by zone for xttpd.
4 
5     Copyright (C) 1998  David Flater.
6 
7     This program is free software: you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation, either version 3 of the License, or
10     (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include "libxtide/libxtide.hh"
22 using namespace libxtide;
23 #include "ZoneIndex.hh"
24 
25 
lookup(const Dstr & zone)26 ZoneIndex::ZInode * const ZoneIndex::ZImap::lookup (const Dstr &zone) {
27   assert (zone.length());
28 
29   ZImap::iterator xactmatch = find (zone);
30   if (xactmatch != end())
31     return &(xactmatch->second);
32 
33   for (ZImap::iterator it = begin(); it != end(); ++it)
34     // ":America/New_York" %= ":America/"
35     if ((zone %= it->first) && (it->first.back() == '/'))
36       return it->second.subzones.lookup (zone);
37 
38   return NULL;
39 }
40 
41 
operator [](const Dstr & zone)42 ZoneIndex::ZInode * const ZoneIndex::operator[] (const Dstr &zone) {
43   if (zone.length())
44     return top.subzones.lookup (zone);
45   return &top;
46 }
47 
48 
makezone(const Dstr & zone)49 ZoneIndex::ZInode &ZoneIndex::makezone (const Dstr &zone) {
50   assert (zone.length());
51   assert (zone.back() != '/');
52   ZInode *tryit = operator[](zone);
53   if (tryit)
54     return *tryit;
55   else {
56     Dstr smallzone (zone), addzone (zone);
57     int i;
58     // Find the level that already exists.
59     while ((i = smallzone.strrchr ('/')) != -1) {
60       if (i == (int)smallzone.length() - 1) {
61         addzone = smallzone;
62         smallzone -= i;
63       } else {
64         smallzone -= i+1;
65         if ((tryit = operator[](smallzone)))
66           break;
67       }
68     }
69     // Add one more level.
70     if (tryit)
71       (void) tryit->subzones[addzone];
72     else
73       (void) top.subzones[addzone];
74     // Repeat till done.
75     return makezone (zone);
76   }
77 }
78 
79 
add(StationRef * sr)80 void ZoneIndex::add (StationRef *sr) {
81   assert (sr);
82   const Dstr &zone = sr->timezone;
83   assert (!zone.isNull());
84   makezone(zone).stationIndex.push_back (sr);
85 }
86 
87 
add(const StationIndex & stationIndex)88 void ZoneIndex::add (const StationIndex &stationIndex) {
89   Global::log ("Building zone index...", LOG_NOTICE);
90   for (unsigned long i=0; i<stationIndex.size(); ++i)
91     add (stationIndex[i]);
92 }
93 
94 // Cleanup2006 Cruft CloseEnough
95