-
-
Save rbehrends/087c1edcf90cb590b660 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from os import nil | |
| from strutils import `%`, formatFloat, ffDecimal, toBin | |
| import unsigned | |
| from math import random, randomize | |
| from times import nil | |
| # Type declarations | |
| type | |
| TBitScalar = int | |
| type | |
| EBitarray = object of EBase | |
| TBitarrayKind = enum inmem, mmap | |
| PBitarray = ref TBitarray | |
| TFlexArray {.unchecked.} = array[0..0, TBitScalar] | |
| TBitarray = ref object | |
| size_elements: int | |
| size_bits: int | |
| size_specified: int | |
| bitarray: ptr TFlexArray | |
| case in_memory: bool | |
| of true: | |
| nil | |
| of false: | |
| mm_filehandle: TMemFile | |
| const ONE = TBitScalar(1) | |
| proc finalize_bitarray(a: TBitarray) = | |
| if not a.bitarray.isNil: | |
| case a.in_memory | |
| of true: | |
| dealloc(a.bitarray) | |
| a.bitarray = nil | |
| of false: | |
| # close mm_filehandle if still open | |
| proc create_bitarray*(size: int): TBitarray = | |
| ## Creates an in-memory bitarray using a specified input size. | |
| ## Note that this will round up to the nearest byte. | |
| let n_elements = size div (sizeof(TBitScalar) * 8) | |
| let n_bits = n_elements * (sizeof(TBitScalar) * 8) | |
| new(result, finalize_bitarray) | |
| result.in_memory = true | |
| result.bitarray = cast[ptr TFlexArray](n_elements) | |
| result.size_elements = n_elements | |
| result.size_bits = n_bits | |
| result.size_specified = size | |
| proc create_bitarray*(file: string, size: int = -1): TBitarray = | |
| ## Creates an mmap-backed bitarray. If the specified file exists | |
| ## it will be opened, but an exception will be raised if the size | |
| ## is specified and does not match. If the file does not exist | |
| ## it will be created. | |
| let n_elements = size div (sizeof(char) * 8) | |
| let n_bits = n_elements * (sizeof(char) * 8) | |
| var mm_file: TMemFile | |
| if os.existsFile(file): | |
| mm_file = open(file, mode = fmReadWrite, mappedSize = -1) | |
| if size != -1 and mm_file.size != n_elements: | |
| raise newException(EBitarray, "Existing mmap file does not have the specified size $1" % $size) | |
| else: | |
| if size == -1: | |
| raise newException(EBitarray, "No existing mmap file. Must specify size to create one.") | |
| mm_file = open(file, mode = fmReadWrite, newFileSize = n_elements) | |
| new(result, finalize_bitarray) | |
| result.in_memory = false | |
| result.bitarray = cast[ptr TFlexArray](mm_file.mem) | |
| result.size_elements = n_elements | |
| result.size_bits = n_bits | |
| result.size_specified = size | |
| result.mm_filehandle = mm_file |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment