@@ -156,20 +156,20 @@ putOlsonParts v2 olson1 olson2 posix = do
156156
157157putOlsonPart :: Word8 -> (Integer -> Put) -> OlsonData -> Put
158158putOlsonPart version putTime (OlsonData transs ttinfos leaps _) = do
159− putASCII "TZif"
159+ putASCII "magic number" "TZif"
160160 putWord8 version
161161 putByteString . B.pack $ replicate 15 0 -- padding nulls
162162 replicateM_ 2 $ putCount ttinfosWithTtype
163− -- tzh_ttisgmtcnt
164− -- tzh_ttisstdcnt
165− putCount leaps -- tzh_leapcnt
166− putCount transs -- tzh_timecnt
167− putCount ttinfos -- tzh_typecnt
168− putCount abbrChars -- tzh_charcnt
163+ -- tzh_ttisgmtcnt
164+ -- tzh_ttisstdcnt
165+ putCount leaps -- tzh_leapcnt
166+ putCount transs -- tzh_timecnt
167+ putCount ttinfos -- tzh_typecnt
168+ put32bitIntegral abbrChars -- tzh_charcnt
169169 mapM_ (putTime . transTime ) transs
170170 mapM_ (put8bitIntegral . transIndex) transs
171171 mapM_ putTtInfo ttinfosIndexed
172− putASCII abbrChars
172+ mapM_ putAbbr abbrStrings
173173 mapM_ (putLeapInfo putTime) leaps
174174 mapM_ (putBool . (== Std) . tt_ttype) ttinfosWithTtype -- isstd
175175 mapM_ (putBool . (== UTC) . tt_ttype) ttinfosWithTtype -- isgmt
@@ -177,7 +177,8 @@ putOlsonPart version putTime (OlsonData transs ttinfos leaps _) = do
177177 putCount = put32bitIntegral . length
178178 ttinfosWithTtype = takeWhile ((<= UTC) . tt_ttype) ttinfosIndexed
179179 abbrStrings = uniq . sort $ map tt_abbr ttinfos
180− abbrChars = concatMap (++ "\NUL") abbrStrings
180+ abbrChars = sum (map length abbrStrings) + length abbrStrings
181+ putAbbr abbr = putASCII "time zone abbreviation" abbr >> putWord8 0
181182 abbrAssocs = zip abbrStrings . scanl (+) 0 $
182183 map ((+ 1) . length) abbrStrings
183184 ttinfosIndexed = [TtInfo gmtoff isdst ttype i |
@@ -187,7 +188,7 @@ putOlsonPart version putTime (OlsonData transs ttinfos leaps _) = do
187188putPosixTZ :: Maybe String -> Put
188189putPosixTZ posix = do
189190 putWord8 10
190− putASCII $ fromMaybe "" posix
191+ putASCII "POSIX TZ string"$ fromMaybe "" posix
191192 putWord8 10
192193
193194putTtInfo :: TtInfo Int -> Put
@@ -220,5 +221,11 @@ putBool True = putWord8 1
220221uniq :: Eq a => [a] -> [a]
221222uniq = map head . group
222223
223−putASCII :: String -> Put
224−putASCII = putByteString . B.pack . map (fromIntegral . fromEnum)
224+putASCII :: String -> String -> Put
225+putASCII what =
226+ putByteString . B.pack . map (fromIntegral . verify . fromEnum)
227+ where
228+ verify c
229+ | c >= 32 && c <= 126 = c
230+ | otherwise = error $ "Cannot render TimeZoneSeries: " ++
231+ what ++ " contains non-ASCII characters"