diff options
author | bptato <nincsnevem662@gmail.com> | 2024-08-02 00:29:45 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-08-02 00:44:19 +0200 |
commit | 8f88e5f05b76dd9b16ba91c9e28f07bd1549ae93 (patch) | |
tree | af65e0743bc92a0dd312b0f0f09b36ec8fa14d70 /src/utils/twtstr.nim | |
parent | 22625453ef3275adab3a47990c242dc92397b02b (diff) | |
download | chawan-8f88e5f05b76dd9b16ba91c9e28f07bd1549ae93.tar.gz |
cssvalues, twtstr, mediaquery: refactor & fixes
* cssvalues, twtstr: unify enum parsing code paths, parse enums by bisearch instead of hash tables * mediaquery: refactor (long overdue), fix range comparison syntax parsing, make ident comparisons case-insensitive (as they should be)
Diffstat (limited to 'src/utils/twtstr.nim')
-rw-r--r-- | src/utils/twtstr.nim | 53 |
1 files changed, 25 insertions, 28 deletions
diff --git a/src/utils/twtstr.nim b/src/utils/twtstr.nim index 7cadd41f..a5770042 100644 --- a/src/utils/twtstr.nim +++ b/src/utils/twtstr.nim @@ -537,37 +537,34 @@ proc makeCRLF*(s: string): string = else: result &= s[i] +type IdentMapItem* = tuple[s: string; n: int] + +func getIdentMap*[T: enum](e: typedesc[T]): seq[IdentMapItem] = + result = @[] + for e in T.low .. T.high: + result.add(($e, int(e))) + result.sort(proc(x, y: IdentMapItem): int = cmp(x[0], y[0])) + func strictParseEnum*[T: enum](s: string): Option[T] = - # cmp when len is small enough, otherwise hashmap - when {T.low..T.high}.len <= 4: - for e in T.low .. T.high: - if $e == s: - return some(e) - else: - const tab = (func(): Table[string, T] = - result = initTable[string, T]() - for e in T.low .. T.high: - result[$e] = e - )() - if s in tab: - return some(tab[s]) + const IdentMap = getIdentMap(T) + let i = IdentMap.binarySearch(s, proc(x: IdentMapItem; y: string): int = + return x[0].cmp(y) + ) + if i != -1: + return some(cast[T](IdentMap[i].n)) return none(T) -func parseEnumNoCase*[T: enum](s: string): Option[T] = - # cmp when len is small enough, otherwise hashmap - when {T.low..T.high}.len <= 4: - for e in T.low .. T.high: - if ($e).equalsIgnoreCase(s): - return some(e) - else: - const tab = (func(): Table[string, T] = - result = initTable[string, T]() - for e in T.low .. T.high: - result[$e] = e - )() - if s in tab: - return some(tab[s]) - return none(T) +func parseEnumNoCase0*(map: openArray[IdentMapItem]; s: string): Opt[int] = + let i = map.binarySearch(s, proc(x: IdentMapItem; y: string): int = + return x[0].cmpIgnoreCase(y) + ) + if i != -1: + return ok(map[i].n) + return err() + +func parseEnumNoCase*[T: enum](s: string): Opt[T] = + const IdentMap = getIdentMap(T) + return ok(cast[T](?IdentMap.parseEnumNoCase0(s))) proc getContentTypeAttr*(contentType, attrname: string): string = var i = contentType.find(';') |