Skip to content

Instantly share code, notes, and snippets.

@rbehrends
Created May 6, 2014 18:48
Show Gist options
  • Save rbehrends/087c1edcf90cb590b660 to your computer and use it in GitHub Desktop.
Save rbehrends/087c1edcf90cb590b660 to your computer and use it in GitHub Desktop.
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