Revision 3df61d16c51c6cbbe49ca3faabd2215e6061887f authored by Alexander Kruppa on 20 February 2014, 16:47:44 UTC, committed by Alexander Kruppa on 20 February 2014, 16:47:44 UTC
1 parent 744a265
Raw File
typecast.py
import sys

HEAD = """\
#include "macros.h"

/* Typecasting inline functions that assert that cast values are within 
   range of the cast-to type.
   Format is cast_<source type>_<target type>()
   where each of <source type> and <target type> are one of
   ulong	for unsigned long int
   uint		for unsigned int
   long		for long int
   int		for int
   ushort	for unsigned short int
   short	for short int
   uchar	for unsigned char
   char		for char
   size		for size_t
   
   For each function, there is also a
   cast_<source type>_<target type>_fast()
   variant which asserts range validity only if WANT_ASSERT_CONVERSION is
   defined. Thus the non-fast variant should be used in code that is not
   speed critical, and the fast variant in code that is.
*/

#ifdef WANT_ASSERT_CONVERSION
#define ASSERT_CONVERSION(x) assert(x)
#else
#define ASSERT_CONVERSION(x)
#endif

"""

SRC_NAMES = ("srctype", "srctype_c", "srcmin", "srcmax")
DST_NAMES = ("dsttype", "dsttype_c", "dstmin", "dstmax")
TYPES = (
  ("ulong", "unsigned long int", "0", "ULONG_MAX"),
  ("uint", "unsigned int", "0", "UINT_MAX"),
  ("long", "long int", "LONG_MIN", "LONG_MAX"),
  ("int", "int", "INT_MIN", "INT_MAX"),
  ("ushort", "unsigned short int", "0", "USHRT_MAX"), # The 'O' would have made it excessively long?
  ("short", "short int", "SHRT_MIN", "SHRT_MAX"),
  ("uchar", "unsigned char", "0", "UCHAR_MAX"), # The 'O' would have made it excessively long?
  ("char", "char", "CHAR_MIN", "CHAR_MAX"),
  ("size", "size_t", "0", "SIZE_MAX")
)

TEMPLATE1 = """\
static inline {dsttype_c}
cast_{srctype}_{dsttype}{fast}({srctype_c} x)
{{
"""
TEMPLATE2 = """\
#if {srcmin} < {dstmin}
    {assert}(x >= {dstmin});
#endif
"""
TEMPLATE3 = """\
#if {srcmax} > {dstmax}
    {assert}(x <= {dstmax});
#endif
"""
TEMPLATE4 = """\
  return ({dsttype_c}) x;
}}
"""

SLOW = [("assert", "ASSERT"), ("fast", "")]
FAST = [("assert", "ASSERT_CONVERSION"), ("fast", "_fast")]

def print_template(d):
  sys.stdout.write(TEMPLATE1.format(**d))
  if not d["srcmin"] == d["dstmin"]:
    sys.stdout.write(TEMPLATE2.format(**d))
  if not d["srcmax"] == d["dstmax"]:
    sys.stdout.write(TEMPLATE3.format(**d))
  sys.stdout.write(TEMPLATE4.format(**d))
  sys.stdout.write("\n")

print(HEAD)
for srctype in TYPES:
  for dsttype in TYPES:
    if srctype is dsttype:
      continue
    values = list(zip(SRC_NAMES, srctype)) + list(zip(DST_NAMES, dsttype))
    print_template(dict(values + SLOW))
    print_template(dict(values + FAST))
back to top