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:
Miran 2019-03-01 12:57:55 +01:00 • committed by GitHub
commit ca7980f301
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 325 additions and 177 deletions

View file

@ -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) )