diff options
Diffstat (limited to 'src/third_party/timelib/zones/create-timezonedb.php')
| -rw-r--r-- | src/third_party/timelib/zones/create-timezonedb.php | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/third_party/timelib/zones/create-timezonedb.php b/src/third_party/timelib/zones/create-timezonedb.php new file mode 100644 index 00000000000..679a7c047d7 --- /dev/null +++ b/src/third_party/timelib/zones/create-timezonedb.php @@ -0,0 +1,171 @@ +<?php +function readZoneTab( string $tabFile ) : array +{ + $tab = []; + + // process extra info + $f = file( 'code/zone.tab' ); + + foreach ( $f as $line ) + { + $line = trim( $line ); + $comments = ''; + + if ( strlen( $line ) < 5 || $line[0] == '#' ) + { + continue; + } + $fields = explode( "\t", $line ); + list( $countryCode, $coordinates, $tzid ) = $fields; + if ( sizeof( $fields ) > 3 ) { + $comments = $fields[3]; + } + + // format lang/lat + if ( strlen( $coordinates ) == 11 ) + { + sscanf( $coordinates, '%c%2d%2d%c%3d%2d', $xSign, $xH, $xM, $ySign, $yH, $yM ); + $xS = $yS = 0; + } + else + { + sscanf( $coordinates, '%c%2d%2d%2d%c%3d%2d%2d', $xSign, $xH, $xM, $xS, $ySign, $yH, $yM, $yS ); + } + $lat = $xH + ( $xM / 60 ) + ( $xS / 3600 ); + $long = $yH + ( $yM / 60 ) + ( $yS / 3600 ); + $lat = $xSign == '+' ? $lat : -$lat; + $long = $ySign == '+' ? $long : -$long; + + $tab[$tzid] = [ + 'cc' => $countryCode, + 'lat' => ($lat + 90) * 100000, + 'lng' => ($long + 180) * 100000, + 'desc' => $comments ?: '', + ]; + } + + return $tab; +} + +function readDataFile( string $tzid, array $tab ) : array +{ + $originalHeaderSize = 20; + + // obtain data from tz files + $fatData = file_get_contents( "code/data/{$tzid}", false, NULL, $originalHeaderSize ); + $slimData = file_get_contents( "code/data-slim/{$tzid}", false, NULL, $originalHeaderSize ); + + $tabData = array_key_exists( $tzid, $tab ) ? $tab[$tzid] : null; + + if ( $tabData ) { + $header = pack( 'a4ca2a13', 'PHP2', true, $tabData['cc'], '' ); + $footer = pack( 'NNNa*', $tabData['lat'], $tabData['lng'], strlen( $tabData['desc'] ), $tabData['desc'] ); + } else { + $header = pack( 'a4ca2a13', 'PHP2', $tzid == 'UTC', '??', '' ); + $footer = pack( 'NNNa*', 0, 0, 0, '' ); + } + + $fatData = $header . $fatData . $footer; + $slimData = $header . $slimData . $footer; + + return [ $fatData, $slimData ]; +} + +function createDataAndIndex(array $tab) +{ + $files = array_merge(glob("code/data/*"), glob("code/data/*/*"), glob("code/data/*/*/*")); + usort($files, 'strcasecmp'); + + $fatIndex = []; + $slimIndex = []; + $fatData = $slimData = ''; + + foreach ($files as $fileName) { + if (is_dir($fileName)) { + continue; + } + + $tzid = preg_replace('@code/data/@', '', $fileName); + list($tzFatData, $tzSlimData) = readDataFile($tzid, $tab); + + $fatIndex[$tzid] = strlen($fatData); + $slimIndex[$tzid] = strlen($slimData); + + $fatData .= $tzFatData; + $slimData .= $tzSlimData; + } + + return [$fatIndex, $fatData, $slimIndex, $slimData]; +} + +function getVersion() : string +{ + $version_info = file( 'version-info.txt' ); + $version = trim( $version_info[1] ); + + return $version; +} + +function addData(array $index, string $data) +{ + $elements = count( $index ); + $flipIndex = array_flip( $index ); + $dataSize = strlen( $data ); + + $str = "const timelib_tzdb_index_entry timezonedb_idx_builtin[$elements] = {\n"; + foreach ( $index as $tzid => $start ) + { + $str .= sprintf( "\t{ (char*) %-36s, 0x%06X },\n", "\"{$tzid}\"", $start ); + } + $str .= "};\n"; + + $pos = 0; + + $str .= "\n\nconst unsigned char timelib_timezone_db_data_builtin[{$dataSize}] = {"; + for ( $i = 0; $i < $dataSize; $i++ ) + { + if ( isset( $flipIndex[$i] ) ) + { + $str .= "\n\n/* {$flipIndex[$i] } */\n"; + $pos = 0; + } + $str .= sprintf( "0x%02X,", ord( $data[$i] ) ); + if ( $pos % 16 == 15) { + $str .= "\n"; + } else { + $str .= " "; + } + $pos++; + } + $str .= "\n};\n"; + + return $str; +} + +function writeTimelibH(array $fatIndex, string $fatData, array $slimIndex, string $slimData ) +{ + $elements = count( $fatIndex ); + + $data = "/* This is a generated file, do not modify */\n"; + + /* Error out if TIMELIB_SUPPORTS_V2DATA isn't set */ + $data .= "#ifndef TIMELIB_SUPPORTS_V2DATA\n"; + $data .= "#error Your version of timelib does not understand the timzonedb data format, please upgrade\n"; + $data .= "#endif\n\n"; + + $data .= "#ifdef TIMELIB_SUPPORT_SLIM_FILE\n"; + $data .= addData( $slimIndex, $slimData ); + $data .= "#else\n"; + $data .= addData( $fatIndex, $fatData ); + $data .= "#endif\n\n"; + + $version = getVersion(); + $data .= "const timelib_tzdb timezonedb_builtin = { \"{$version}\", {$elements}, timezonedb_idx_builtin, timelib_timezone_db_data_builtin };\n"; + + file_put_contents( 'timezonedb.h', $data ); +} + +$tab = readZoneTab( 'code/zone.tab' ); +list( $fatIndex, $fatData, $slimIndex, $slimData ) = createDataAndIndex( $tab ); +writeTimelibH( $fatIndex, $fatData, $slimIndex, $slimData ); +?> |
