improved documentation for several modules (#10752)
More detailed documentation for: * md5 * hashes Mostly cosmetic improvements for: * threadpool * typetraits * channels * threads
This commit is contained in:
parent
e9d3c5de19
commit
ca7980f301
6 changed files with 325 additions and 177 deletions
|
|
@ -9,11 +9,11 @@
|
|||
|
||||
## This module implements efficient computations of hash values for diverse
|
||||
## Nim types. All the procs are based on these two building blocks:
|
||||
## - `!& proc <#!&>`_ used to start or mix a hash value, and
|
||||
## - `!$ proc <#!$>`_ used to *finish* the hash value.
|
||||
## If you want to implement hash procs for
|
||||
## your custom types you will end up writing the following kind of skeleton of
|
||||
## code:
|
||||
## - `!& proc <#!&,Hash,int>`_ used to start or mix a hash value, and
|
||||
## - `!$ proc <#!$,Hash>`_ used to *finish* the hash value.
|
||||
##
|
||||
## If you want to implement hash procs for your custom types,
|
||||
## you will end up writing the following kind of skeleton of code:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## proc hash(x: Something): Hash =
|
||||
|
|
@ -37,31 +37,40 @@
|
|||
## h = h !& hash(x.foo)
|
||||
## h = h !& hash(x.bar)
|
||||
## result = !$h
|
||||
##
|
||||
## **See also:**
|
||||
## * `md5 module <md5.html>`_ for MD5 checksum algorithm
|
||||
## * `base64 module <base64.html>`_ for a base64 encoder and decoder
|
||||
## * `std/sha1 module <sha1.html>`_ for a sha1 encoder and decoder
|
||||
## * `tables modlule <tables.html>`_ for hash tables
|
||||
|
||||
|
||||
import
|
||||
strutils
|
||||
|
||||
type
|
||||
Hash* = int ## a hash value; hash tables using these values should
|
||||
Hash* = int ## A hash value. Hash tables using these values should
|
||||
## always have a size of a power of two and can use the ``and``
|
||||
## operator instead of ``mod`` for truncation of the hash value.
|
||||
|
||||
proc `!&`*(h: Hash, val: int): Hash {.inline.} =
|
||||
## mixes a hash value `h` with `val` to produce a new hash value. This is
|
||||
## only needed if you need to implement a hash proc for a new datatype.
|
||||
## Mixes a hash value `h` with `val` to produce a new hash value.
|
||||
##
|
||||
## This is only needed if you need to implement a hash proc for a new datatype.
|
||||
result = h +% val
|
||||
result = result +% result shl 10
|
||||
result = result xor (result shr 6)
|
||||
|
||||
proc `!$`*(h: Hash): Hash {.inline.} =
|
||||
## finishes the computation of the hash value. This is
|
||||
## only needed if you need to implement a hash proc for a new datatype.
|
||||
## Finishes the computation of the hash value.
|
||||
##
|
||||
## This is only needed if you need to implement a hash proc for a new datatype.
|
||||
result = h +% h shl 3
|
||||
result = result xor (result shr 11)
|
||||
result = result +% result shl 15
|
||||
|
||||
proc hashData*(data: pointer, size: int): Hash =
|
||||
## hashes an array of bytes of size `size`
|
||||
## Hashes an array of bytes of size `size`.
|
||||
var h: Hash = 0
|
||||
when defined(js):
|
||||
var p: cstring
|
||||
|
|
@ -80,7 +89,7 @@ when defined(js):
|
|||
var objectID = 0
|
||||
|
||||
proc hash*(x: pointer): Hash {.inline.} =
|
||||
## efficient hashing of pointers
|
||||
## Efficient hashing of pointers.
|
||||
when defined(js):
|
||||
asm """
|
||||
if (typeof `x` == "object") {
|
||||
|
|
@ -97,45 +106,57 @@ proc hash*(x: pointer): Hash {.inline.} =
|
|||
|
||||
when not defined(booting):
|
||||
proc hash*[T: proc](x: T): Hash {.inline.} =
|
||||
## efficient hashing of proc vars; closures are supported too.
|
||||
## Efficient hashing of proc vars. Closures are supported too.
|
||||
when T is "closure":
|
||||
result = hash(rawProc(x)) !& hash(rawEnv(x))
|
||||
else:
|
||||
result = hash(pointer(x))
|
||||
|
||||
proc hash*(x: int): Hash {.inline.} =
|
||||
## efficient hashing of integers
|
||||
## Efficient hashing of integers.
|
||||
result = x
|
||||
|
||||
proc hash*(x: int64): Hash {.inline.} =
|
||||
## efficient hashing of int64 integers
|
||||
## Efficient hashing of `int64` integers.
|
||||
result = toU32(x)
|
||||
|
||||
proc hash*(x: uint): Hash {.inline.} =
|
||||
## efficient hashing of unsigned integers
|
||||
## Efficient hashing of unsigned integers.
|
||||
result = cast[int](x)
|
||||
|
||||
proc hash*(x: uint64): Hash {.inline.} =
|
||||
## efficient hashing of uint64 integers
|
||||
## Efficient hashing of `uint64` integers.
|
||||
result = toU32(cast[int](x))
|
||||
|
||||
proc hash*(x: char): Hash {.inline.} =
|
||||
## efficient hashing of characters
|
||||
## Efficient hashing of characters.
|
||||
result = ord(x)
|
||||
|
||||
proc hash*[T: Ordinal](x: T): Hash {.inline.} =
|
||||
## efficient hashing of other ordinal types (e.g., enums)
|
||||
## Efficient hashing of other ordinal types (e.g. enums).
|
||||
result = ord(x)
|
||||
|
||||
proc hash*(x: string): Hash =
|
||||
## efficient hashing of strings
|
||||
## Efficient hashing of strings.
|
||||
##
|
||||
## See also:
|
||||
## * `hashIgnoreStyle <#hashIgnoreStyle,string>`_
|
||||
## * `hashIgnoreCase <#hashIgnoreCase,string>`_
|
||||
runnableExamples:
|
||||
doAssert hash("abracadabra") == -5600162842546114722
|
||||
doAssert hash("Abracadabra") == 2068684413884279454
|
||||
|
||||
var h: Hash = 0
|
||||
for i in 0..x.len-1:
|
||||
h = h !& ord(x[i])
|
||||
result = !$h
|
||||
|
||||
proc hash*(x: cstring): Hash =
|
||||
## efficient hashing of null-terminated strings
|
||||
## Efficient hashing of null-terminated strings.
|
||||
runnableExamples:
|
||||
doAssert hash(cstring"abracadabra") == -5600162842546114722
|
||||
doAssert hash(cstring"Abracadabra") == 2068684413884279454
|
||||
|
||||
var h: Hash = 0
|
||||
var i = 0
|
||||
when defined(js):
|
||||
|
|
@ -149,17 +170,27 @@ proc hash*(x: cstring): Hash =
|
|||
result = !$h
|
||||
|
||||
proc hash*(sBuf: string, sPos, ePos: int): Hash =
|
||||
## efficient hashing of a string buffer, from starting
|
||||
## position `sPos` to ending position `ePos`
|
||||
## Efficient hashing of a string buffer, from starting
|
||||
## position `sPos` to ending position `ePos` (included).
|
||||
##
|
||||
## ``hash(myStr, 0, myStr.high)`` is equivalent to ``hash(myStr)``
|
||||
## ``hash(myStr, 0, myStr.high)`` is equivalent to ``hash(myStr)``.
|
||||
runnableExamples:
|
||||
var a = "abracadabra"
|
||||
doAssert hash(a, 0, 3) == hash(a, 7, 10)
|
||||
|
||||
var h: Hash = 0
|
||||
for i in sPos..ePos:
|
||||
h = h !& ord(sBuf[i])
|
||||
result = !$h
|
||||
|
||||
proc hashIgnoreStyle*(x: string): Hash =
|
||||
## efficient hashing of strings; style is ignored
|
||||
## Efficient hashing of strings; style is ignored.
|
||||
##
|
||||
## See also:
|
||||
## * `hashIgnoreCase <#hashIgnoreCase,string>`_
|
||||
runnableExamples:
|
||||
doAssert hashIgnoreStyle("aBr_aCa_dAB_ra") == hash("abracadabra")
|
||||
|
||||
var h: Hash = 0
|
||||
var i = 0
|
||||
let xLen = x.len
|
||||
|
|
@ -176,11 +207,15 @@ proc hashIgnoreStyle*(x: string): Hash =
|
|||
result = !$h
|
||||
|
||||
proc hashIgnoreStyle*(sBuf: string, sPos, ePos: int): Hash =
|
||||
## efficient hashing of a string buffer, from starting
|
||||
## position `sPos` to ending position `ePos`; style is ignored
|
||||
## Efficient hashing of a string buffer, from starting
|
||||
## position `sPos` to ending position `ePos` (included); style is ignored.
|
||||
##
|
||||
## ``hashIgnoreStyle(myBuf, 0, myBuf.high)`` is equivalent
|
||||
## to ``hashIgnoreStyle(myBuf)``
|
||||
## to ``hashIgnoreStyle(myBuf)``.
|
||||
runnableExamples:
|
||||
var a = "ABracada_b_r_a"
|
||||
doAssert hashIgnoreStyle(a, 0, 3) == hashIgnoreStyle(a, 7, a.high)
|
||||
|
||||
var h: Hash = 0
|
||||
var i = sPos
|
||||
while i <= ePos:
|
||||
|
|
@ -195,7 +230,13 @@ proc hashIgnoreStyle*(sBuf: string, sPos, ePos: int): Hash =
|
|||
result = !$h
|
||||
|
||||
proc hashIgnoreCase*(x: string): Hash =
|
||||
## efficient hashing of strings; case is ignored
|
||||
## Efficient hashing of strings; case is ignored.
|
||||
##
|
||||
## See also:
|
||||
## * `hashIgnoreStyle <#hashIgnoreStyle,string>`_
|
||||
runnableExamples:
|
||||
doAssert hashIgnoreCase("ABRAcaDABRA") == hashIgnoreCase("abRACAdabra")
|
||||
|
||||
var h: Hash = 0
|
||||
for i in 0..x.len-1:
|
||||
var c = x[i]
|
||||
|
|
@ -205,11 +246,15 @@ proc hashIgnoreCase*(x: string): Hash =
|
|||
result = !$h
|
||||
|
||||
proc hashIgnoreCase*(sBuf: string, sPos, ePos: int): Hash =
|
||||
## efficient hashing of a string buffer, from starting
|
||||
## position `sPos` to ending position `ePos`; case is ignored
|
||||
## Efficient hashing of a string buffer, from starting
|
||||
## position `sPos` to ending position `ePos` (included); case is ignored.
|
||||
##
|
||||
## ``hashIgnoreCase(myBuf, 0, myBuf.high)`` is equivalent
|
||||
## to ``hashIgnoreCase(myBuf)``
|
||||
## to ``hashIgnoreCase(myBuf)``.
|
||||
runnableExamples:
|
||||
var a = "ABracadabRA"
|
||||
doAssert hashIgnoreCase(a, 0, 3) == hashIgnoreCase(a, 7, 10)
|
||||
|
||||
var h: Hash = 0
|
||||
for i in sPos..ePos:
|
||||
var c = sBuf[i]
|
||||
|
|
@ -219,7 +264,7 @@ proc hashIgnoreCase*(sBuf: string, sPos, ePos: int): Hash =
|
|||
result = !$h
|
||||
|
||||
proc hash*(x: float): Hash {.inline.} =
|
||||
## efficient hashing of floats.
|
||||
## Efficient hashing of floats.
|
||||
var y = x + 1.0
|
||||
result = cast[ptr Hash](addr(y))[]
|
||||
|
||||
|
|
@ -231,34 +276,40 @@ proc hash*[A](x: set[A]): Hash
|
|||
|
||||
|
||||
proc hash*[T: tuple](x: T): Hash =
|
||||
## efficient hashing of tuples.
|
||||
## Efficient hashing of tuples.
|
||||
for f in fields(x):
|
||||
result = result !& hash(f)
|
||||
result = !$result
|
||||
|
||||
proc hash*[A](x: openArray[A]): Hash =
|
||||
## efficient hashing of arrays and sequences.
|
||||
## Efficient hashing of arrays and sequences.
|
||||
for it in items(x): result = result !& hash(it)
|
||||
result = !$result
|
||||
|
||||
proc hash*[A](aBuf: openArray[A], sPos, ePos: int): Hash =
|
||||
## efficient hashing of portions of arrays and sequences.
|
||||
## Efficient hashing of portions of arrays and sequences, from starting
|
||||
## position `sPos` to ending position `ePos` (included).
|
||||
##
|
||||
## ``hash(myBuf, 0, myBuf.high)`` is equivalent to ``hash(myBuf)``
|
||||
## ``hash(myBuf, 0, myBuf.high)`` is equivalent to ``hash(myBuf)``.
|
||||
runnableExamples:
|
||||
let a = [1, 2, 5, 1, 2, 6]
|
||||
doAssert hash(a, 0, 1) == hash(a, 3, 4)
|
||||
|
||||
for i in sPos..ePos:
|
||||
result = result !& hash(aBuf[i])
|
||||
result = !$result
|
||||
|
||||
proc hash*[A](x: set[A]): Hash =
|
||||
## efficient hashing of sets.
|
||||
## Efficient hashing of sets.
|
||||
for it in items(x): result = result !& hash(it)
|
||||
result = !$result
|
||||
|
||||
|
||||
when isMainModule:
|
||||
doAssert( hash("aa bb aaaa1234") == hash("aa bb aaaa1234", 0, 13) )
|
||||
doAssert( hash("aa bb aaaa1234") == hash(cstring("aa bb aaaa1234")) )
|
||||
doAssert( hashIgnoreCase("aa bb aaaa1234") == hash("aa bb aaaa1234") )
|
||||
doAssert( hashIgnoreStyle("aa bb aaaa1234") == hashIgnoreCase("aa bb aaaa1234") )
|
||||
doAssert( hashIgnoreCase("aA bb aAAa1234") == hash("aa bb aaaa1234") )
|
||||
doAssert( hashIgnoreStyle("aa_bb_AAaa1234") == hashIgnoreCase("aaBBAAAa1234") )
|
||||
let xx = @['H','e','l','l','o']
|
||||
let ss = "Hello"
|
||||
doAssert( hash(xx) == hash(ss) )
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue