shithub: mc

Download patch

ref: 2da5de43f610bfd33116a06631a4eaa85deb811d
parent: f637a3c144fe69410d7134cfe57b95258bfabe1f
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Nov 19 14:13:00 EST 2017

Cache timezone info.

	Loading and parsing zoneinfo files every time we print
	a date? eugh.

--- a/lib/date/zoneinfo+posixy.myr
+++ b/lib/date/zoneinfo+posixy.myr
@@ -32,6 +32,11 @@
 	"/etc/zoneinfo"
 ]
 
+var zonecache	: std.htab(byte[:], zifile#)#
+const __init__ = {
+	zonecache = std.mkht()
+}
+
 const findtzoff = {tz, tm -> std.option(date.duration)
 	var path
 	var zone
@@ -40,26 +45,32 @@
 	var ds
 	var i
 
-	/* load zone */
-	if std.sleq(tz, "") || std.sleq(tz, "UTC")
-		-> `std.Some 0
-	elif std.sleq(tz, "local")
-		path = std.sldup("/etc/localtime")
-	else
-		path = ""
-		for z : zonepath
-			path = std.pathcat(z, tz)
-			if sys.stat(path, &sb) == 0
-				goto found
+	match std.htget(zonecache, tz)
+	| `std.Some z:
+		zone = z
+	| `std.None:
+		/* load zone */
+		if std.sleq(tz, "") || std.sleq(tz, "UTC")
+			-> `std.Some 0
+		elif std.sleq(tz, "local")
+			path = std.sldup("/etc/localtime")
+		else
+			path = ""
+			for z : zonepath
+				path = std.pathcat(z, tz)
+				if sys.stat(path, &sb) == 0
+					goto found
+				;;
+				std.slfree(path)
 			;;
 			std.slfree(path)
+			-> `std.None
 		;;
+	:found
+		zone = load(path)
 		std.slfree(path)
-		-> `std.None
+		std.htput(zonecache, std.sldup(tz), zone)
 	;;
-:found
-	zone = load(path)
-	std.slfree(path)
 
 	/* find applicable gmt offset */
 	cur = (tm / 1_000_000 : int32)
@@ -70,28 +81,26 @@
 		/* nothing */
 	;;
 	ds = zone.ttinfo[zone.timetype[i]].gmtoff
-	free(zone)
 	->  `std.Some ((ds : date.duration) * 1_000_000)
 }
 
 const load = {file
 	var nisgmt, nisstd, nleap, ntime, ntype, nchar
-	var i, f, p
+	var i, f, p, data
 
 	/* check magic */
 	match std.slurp(file)
-	| `std.Ok d:	p = d
-	| `std.Err m:	
-		-> std.zalloc()
+	| `std.Ok d:	data = d
+	| `std.Err m:	-> std.zalloc()
 	;;
 
-	if !std.sleq(p[:4], "TZif")
+	if !std.eq(data[:4], "TZif")
 		std.put("{} is not a zone info file\n", file)
 		-> std.zalloc()
 	;;
 
 	/* skip to data */
-	p = p[20:]
+	p = data[20:]
 	(nisgmt, p) = fetchbe32(p)
 	(nisstd, p) = fetchbe32(p)
 	(nleap, p) = fetchbe32(p)
@@ -136,6 +145,7 @@
 	for i = 0; i < nisgmt; i++
 		(f.isgmt[i], p) = fetchbe8(p)
 	;;
+	std.slfree(data)
 
 	-> f
 }