Package: src/packages/memory.fdoc

Memory Operations

key file
memory.flx share/lib/std/scalar/memory.flx
address.flx share/lib/std/scalar/address.flx

Raw Address

//[address.flx]

//$ Core operations on addresses.
open class Address {
  //$ Construct from Felix object pointer.
  ctor[T] address: &T = "(void*)$1";

  //$ Construct from possibly NULL pointer.
  ctor[T] address: cptr[T] = "(void*)$1"; //@

  //$ Construct from possibly array element pointer.
  ctor[T] address: +T = "(void*)$1";

  //$ Construct from C function
  ctor[D,C] address: D --> C = "(void*)$1";


  //$ Check is an address is NULL.
  fun isNULL: address -> bool = "(0==$1)";

  //$ Define NULL address.
  const NULL : address = "NULL";

  instance Eq[address] {
    fun == : address * address -> bool = "$1==$2";
  }
  instance Tord[address] {
    fun < : address * address -> bool = "::std::less<void*>()($1,$2)";
  }

  const addrstrfmt : +char = '"%" PRIxPTR' requires C99_headers::inttypes_h;
  const addrreprfmt : +char = '"0x%" PRIxPTR' requires C99_headers::inttypes_h;

  instance Str[address] {
    fun str (t:address) : string => vsprintf (addrstrfmt, C_hack::cast[uintptr] t);
  }
  instance Repr[address] {
    fun repr (t:address) : string => vsprintf (addrreprfmt, C_hack::cast[uintptr] t);
  }


  instance Str[byte] {
    fun str (t:byte) : string => vsprintf (c"%02x", C_hack::cast[uint] t);
  }

  instance Repr[byte] {
    fun repr (t:byte) : string => vsprintf (c"0x%02x", t);
  }


  fun + : address * !ints -> address = "(void*)((char*)$1+$2)";
  fun - : address * !ints -> address = "(void*)((char*)$1-$2)";
  fun - : address * address -> ptrdiff = "(char*)$1-(char*)$2";
}

open Eq[byte];
open Tord[address];
//[memory.flx]
class Memory
{
  proc memcpy: address * address * !ints =
    "{if($1 && $2 && $3)::std::memcpy($1,$2,$3);}"
    requires Cxx_headers::cstring
  ;

  proc memmove: address * address * !ints =
    "{if($1 && $2 && $3)::std::memmove($1,$2,$3);}"
    requires Cxx_headers::cstring
  ;

  fun memcmp: address * address * !ints -> int =
    "::std::memcmp($1,$2,$3)"
    requires Cxx_headers::cstring
  ;

  fun memchr: address * byte * !ints -> address =
    "::std::memchr($1,$2,$3)"
    requires Cxx_headers::cstring
  ;


  proc memset: address * !ints * byte =
    "::std::memset($1,$2,$3);"
    requires Cxx_headers::cstring
  ;

  //$ Heap operations
  gen calloc: !ints -> address =
    "::std::calloc($1)"
    requires Cxx_headers::cstdlib
  ;

  proc free: address =
    "::std::free($1);"
    requires Cxx_headers::cstdlib
  ;

  gen realloc: address * !ints -> address =
    "::std::realloc($1,$2)"
    requires Cxx_headers::cstdlib
  ;

  //$ Raw unchecked malloc.
  gen raw_malloc: !ints -> address =
    '::std::malloc($1)'
    requires Cxx_headers::cstdlib
  ;

  //$ Malloc with memory check.
  //$ Throws c"out of memory" if out of memory.
  body checked_malloc = """
    void *checked_malloc(size_t n) {
      void *p = ::std::malloc(n);
      if(p) return p;
      else throw "out of memory";
    }
  """;

  gen malloc: !ints -> address = 'checked_malloc($1)'
    requires Cxx_headers::cstdlib, checked_malloc
  ;

  // Standard C++ Search algorithm,
  // returns address of found string
  // or $2 = pointer past end on fail
  fun search: address ^ 4 -> address =
    """
    (void*)::std::search(
      (::std::uint8_t*)$1,
      (::std::uint8_t*)$2,
      (::std::uint8_t*)$3,
      (::std::uint8_t*)$4)
    """
    requires Cxx_headers::algorithm
  ;
}