text:
import os
import struct
import logging
import gzip
import tempfile

log = logging.getLogger("blendfile")
log.setLevel(logging.ERROR)

FILE_BUFFER_SIZE = 1024 * 1024

# -----------------------------------------------------------------------------
# module global routines
#
# read routines
# open a filename
# determine if the file is compressed
# and returns a handle
def open_blend(filename, access="rb"):
    """Opens a blend file for reading or writing pending on the access
    supports 2 kind of blend files. Uncompressed and compressed.
    Known issue: does not support packaged blend files
    """
    handle = open(filename, access)
    magic_test = b"BLENDER"
    magic = handle.read(len(magic_test))
    if magic == magic_test:
        log.debug("normal blendfile detected")
        handle.seek(0, os.SEEK_SET)
        bfile = BlendFile(handle)
        bfile.is_compressed = False
        bfile.filepath_orig = filename
        return bfile
    elif magic[:2] == b'\x1f\x8b':
        log.debug("gzip blendfile detected")
        handle.close()
        log.debug("decompressing started")
        fs = gzip.open(filename, "rb")
        data = fs.read(FILE_BUFFER_SIZE)
        magic = data[:len(magic_test)]
        if magic == magic_test:
            handle = tempfile.TemporaryFile()
            while data:
                handle.write(data)
                data = fs.read(FILE_BUFFER_SIZE)
            log.debug("decompressing finished")
            fs.close()
            log.debug("resetting decompressed file")
            handle.seek(os.SEEK_SET, 0)
            bfile = BlendFile(handle)
            bfile.is_compressed = True
            bfile.filepath_orig = filename
            return bfile
        else:
            raise Exception("filetype inside gzip not a blend")
    else:
        raise Exception("filetype not a blend or a gzip blend")

def align(offset, by):
    n = by - 1
    return (offset + n) & ~n

# -----------------------------------------------------------------------------
# module classes

class BlendFile:
    """
    Blend file.
    """
    __slots__ = (
        # file (result of open())
        "handle",
        # str (original name of the file path)
        "filepath_orig",
        # BlendFileHeader
        "header",
        # struct.Struct
        "block_header_struct",
        # BlendFileBlock
        "blocks",
        # [DNAStruct, ...]
        "structs",
        # dict {b'StructName': sdna_index}
        # (where the index is an index into 'structs')
        "sdna_index_from_id",
        # dict {addr_old: block}
        "block_from_offset",
        # int
        "code_index",
        # bool (did we make a change)
        "is_modified",
        # bool (is file gzipped)
        "is_compressed",
        )

    def __init__(self, handle):
        log.debug("initializing reading blend-file")
        self.handle = handle
        self.header = BlendFileHeader(handle)
        self.block_header_struct = self.header.create_block_header_struct()
        self.blocks = []
        self.code_index = {}

        block = BlendFileBlock(handle, self)
        while block.code != b'ENDB':
            if block.code == b'DNA1':
                (self.structs,
                 self.sdna_index_from_id,
                 ) = BlendFile.decode_structs(self.header, block, handle)
            else:
                handle.seek(block.size, os.SEEK_CUR)

            self.blocks.append(block)
            self.code_index.setdefault(block.code, []).append(block)

            block = BlendFileBlock(handle, self)
        self.is_modified = False
        self.blocks.append(block)

        # cache (could lazy init, incase we never use?)
        self.block_from_offset = {block.addr_old: block for block in self.blocks if block.code != b'ENDB'}

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        self.close()

    def find_blocks_from_code(self, code):
        assert(type(code) == bytes)
        if code not in self.code_index:
            return []
        return self.code_index[code]

    def find_block_from_offset(self, offset):
        # same as looking looping over all blocks,
        # then checking ``block.addr_old == offset``
        assert(type(offset) is int)
        return self.block_from_offset.get(offset)

    def close(self):
        """
        Close the blend file
        writes the blend file to disk if changes has happened
        """
        if not self.is_modified:
            self.handle.close()
        else:
            handle = self.handle
            if self.is_compressed:
                log.debug("close compressed blend file")
                handle.seek(os.SEEK_SET, 0)
                log.debug("compressing started")
                fs = gzip.open(self.filepath_orig, "wb")
                data = handle.read(FILE_BUFFER_SIZE)
                while data:
                    fs.write(data)
                    data = handle.read(FILE_BUFFER_SIZE)
                fs.close()
                log.debug("compressing finished")

            handle.close()

    def ensure_subtype_smaller(self, sdna_index_curr, sdna_index_next):
        # never refine to a smaller type
        if (self.structs[sdna_index_curr].size >
            self.structs[sdna_index_next].size):

            raise RuntimeError("cant refine to smaller type (%s -> %s)" %
                               (self.structs[sdna_index_curr].dna_type_id.decode('ascii'),
                                self.structs[sdna_index_next].dna_type_id.decode('ascii')))

    @staticmethod
    def decode_structs(header, block, handle):
        """
        DNACatalog is a catalog of all information in the DNA1 file-block
        """
        log.debug("building DNA catalog")
        shortstruct = DNA_IO.USHORT[header.endian_index]
        shortstruct2 = struct.Struct(header.endian_str + b'HH')
        intstruct = DNA_IO.UINT[header.endian_index]

        data = handle.read(block.size)
        types = []
        names = []

        structs = []
        sdna_index_from_id = {}

        offset = 8
        names_len = intstruct.unpack_from(data, offset)[0]
        offset += 4

        log.debug("building #%d names" % names_len)
        for i in range(names_len):
            tName = DNA_IO.read_data0_offset(data, offset)
            offset = offset + len(tName) + 1
            names.append(DNAName(tName))
        del names_len

        offset = align(offset, 4)
        offset += 4
        types_len = intstruct.unpack_from(data, offset)[0]
        offset += 4
        log.debug("building #%d types" % types_len)
        for i in range(types_len):
            dna_type_id = DNA_IO.read_data0_offset(data, offset)
            # None will be replaced by the DNAStruct, below
            types.append(DNAStruct(dna_type_id))
            offset += len(dna_type_id) + 1

        offset = align(offset, 4)
        offset += 4
        log.debug("building #%d type-lengths" % types_len)
        for i in range(types_len):
            tLen = shortstruct.unpack_from(data, offset)[0]
            offset = offset + 2
            types[i].size = tLen
        del types_len

        offset = align(offset, 4)
        offset += 4

        structs_len = intstruct.unpack_from(data, offset)[0]
        offset += 4
        log.debug("building #%d structures" % structs_len)
        for sdna_index in range(structs_len):
            d = shortstruct2.unpack_from(data, offset)
            struct_type_index = d[0]
            offset += 4
            dna_struct = types[struct_type_index]
            sdna_index_from_id[dna_struct.dna_type_id] = sdna_index
            structs.append(dna_struct)

            fields_len = d[1]
            dna_offset = 0

            for field_index in range(fields_len):
                d2 = shortstruct2.unpack_from(data, offset)
                field_type_index = d2[0]
                field_name_index = d2[1]
                offset += 4
                dna_type = types[field_type_index]
                dna_name = names[field_name_index]
                if dna_name.is_pointer or dna_name.is_method_pointer:
                    dna_size = header.pointer_size * dna_name.array_size
                else:
                    dna_size = dna_type.size * dna_name.array_size

                field = DNAField(dna_type, dna_name, dna_size, dna_offset)
                dna_struct.fields.append(field)
                dna_struct.field_from_name[dna_name.name_only] = field
                dna_offset += dna_size

        return structs, sdna_index_from_id

class BlendFileBlock:
    """
    Instance of a struct.
    """
    __slots__ = (
        # BlendFile
        "file",
        "code",
        "size",
        "addr_old",
        "sdna_index",
        "count",
        "file_offset",
        "user_data",
        )

    def __str__(self):
        return ("<%s.%s (%s), size=%d at %s>" %
                # fields=[%s]
                (self.__class__.__name__,
                 self.dna_type.dna_type_id.decode('ascii'),
                 self.code.decode(),
                 self.size,
                 # b", ".join(f.dna_name.name_only for f in self.dna_type.fields).decode('ascii'),
                 hex(self.addr_old),
                 ))

    def __init__(self, handle, bfile):
        OLDBLOCK = struct.Struct(b'4sI')

        self.file = bfile
        self.user_data = None

        data = handle.read(bfile.block_header_struct.size)
        # header size can be 8, 20, or 24 bytes long
        # 8: old blend files ENDB block (exception)
        # 20: normal headers 32 bit platform
        # 24: normal headers 64 bit platform
        if len(data) > 15:

            blockheader = bfile.block_header_struct.unpack(data)
            self.code = blockheader[0].partition(b'\0')[0]
            if self.code != b'ENDB':
                self.size = blockheader[1]
                self.addr_old = blockheader[2]
                self.sdna_index = blockheader[3]
                self.count = blockheader[4]
                self.file_offset = handle.tell()
            else:
                self.size = 0
                self.addr_old = 0
                self.sdna_index = 0
                self.count = 0
                self.file_offset = 0
        else:
            blockheader = OLDBLOCK.unpack(data)
            self.code = blockheader[0].partition(b'\0')[0]
            self.code = DNA_IO.read_data0(blockheader[0])
            self.size = 0
            self.addr_old = 0
            self.sdna_index = 0
            self.count = 0
            self.file_offset = 0

    @property
    def dna_type(self):
        return self.file.structs[self.sdna_index]

    def refine_type_from_index(self, sdna_index_next):
        assert(type(sdna_index_next) is int)
        sdna_index_curr = self.sdna_index
        self.file.ensure_subtype_smaller(sdna_index_curr, sdna_index_next)
        self.sdna_index = sdna_index_next

    def refine_type(self, dna_type_id):
        assert(type(dna_type_id) is bytes)
        self.refine_type_from_index(self.file.sdna_index_from_id[dna_type_id])

    def get_file_offset(self, path,
            default=...,
            sdna_index_refine=None,
            base_index=0,
            ):
        """
        Return (offset, length)
        """
        assert(type(path) is bytes)

        ofs = self.file_offset
        if base_index != 0:
            assert(base_index < self.count)
            ofs += (self.size // self.count) * base_index
        self.file.handle.seek(ofs, os.SEEK_SET)

        if sdna_index_refine is None:
            sdna_index_refine = self.sdna_index
        else:
            self.file.ensure_subtype_smaller(self.sdna_index, sdna_index_refine)

        dna_struct = self.file.structs[sdna_index_refine]
        field = dna_struct.field_from_path(
                self.file.header, self.file.handle, path)

        return (self.file.handle.tell(), field.dna_name.array_size)

    def get(self, path,
            default=...,
            sdna_index_refine=None,
            use_nil=True, use_str=True,
            base_index=0,
            ):

        ofs = self.file_offset
        if base_index != 0:
            assert(base_index < self.count)
            ofs += (self.size // self.count) * base_index
        self.file.handle.seek(ofs, os.SEEK_SET)

        if sdna_index_refine is None:
            sdna_index_refine = self.sdna_index
        else:
            self.file.ensure_subtype_smaller(self.sdna_index, sdna_index_refine)

        dna_struct = self.file.structs[sdna_index_refine]
        return dna_struct.field_get(
                self.file.header, self.file.handle, path,
                default=default,
                use_nil=use_nil, use_str=use_str,
                )

    def get_recursive_iter(self, path, path_root=b"",
                           default=...,
                           sdna_index_refine=None,
                           use_nil=True, use_str=True,
                           base_index=0,
                           ):
        if path_root:
            path_full = (
                    (path_root if type(path_root) is tuple else (path_root, )) +
                    (path if type(path) is tuple else (path, )))
        else:
            path_full = path

        try:
            yield (path_full, self.get(path_full, default, sdna_index_refine, use_nil, use_str, base_index))
        except NotImplementedError as ex:
            msg, dna_name, dna_type = ex.args
            struct_index = self.file.sdna_index_from_id.get(dna_type.dna_type_id, None)
            if struct_index is None:
                yield (path_full, "<%s>" % dna_type.dna_type_id.decode('ascii'))
            else:
                struct = self.file.structs[struct_index]
                for f in struct.fields:
                    yield from self.get_recursive_iter(
                            f.dna_name.name_only, path_full, default, None, use_nil, use_str, 0)

    def items_recursive_iter(self):
        for k in self.keys():
            yield from self.get_recursive_iter(k, use_str=False)

    def get_data_hash(self):
        """
        Generates a 'hash' that can be used instead of addr_old as block id, and that should be 'stable' across .blend
        file load & save (i.e. it does not changes due to pointer addresses variations).
        """
        # TODO This implementation is most likely far from optimal... and CRC32 is not renown as the best hashing
        #      algo either. But for now does the job!
        import zlib
        def _is_pointer(self, k):
            return self.file.structs[self.sdna_index].field_from_path(
                    self.file.header, self.file.handle, k).dna_name.is_pointer

        hsh = 1
        for k, v in self.items_recursive_iter():
            if not _is_pointer(self, k):
                hsh = zlib.adler32(str(v).encode(), hsh)
        return hsh

    def set(self, path, value,
            sdna_index_refine=None,
            ):

        if sdna_index_refine is None:
            sdna_index_refine = self.sdna_index
        else:
            self.file.ensure_subtype_smaller(self.sdna_index, sdna_index_refine)

        dna_struct = self.file.structs[sdna_index_refine]
        self.file.handle.seek(self.file_offset, os.SEEK_SET)
        self.file.is_modified = True
        return dna_struct.field_set(
                self.file.header, self.file.handle, path, value)

    # ---------------
    # Utility get/set
    #
    #   avoid inline pointer casting
    def get_pointer(
            self, path,
            default=...,
            sdna_index_refine=None,
            base_index=0,
            ):
        if sdna_index_refine is None:
            sdna_index_refine = self.sdna_index
        result = self.get(path, default, sdna_index_refine=sdna_index_refine, base_index=base_index)

        # default
        if type(result) is not int:
            return result

        assert(self.file.structs[sdna_index_refine].field_from_path(
                self.file.header, self.file.handle, path).dna_name.is_pointer)
        if result != 0:
            # possible (but unlikely)
            # that this fails and returns None
            # maybe we want to raise some exception in this case
            return self.file.find_block_from_offset(result)
        else:
            return None

    # ----------------------
    # Python convenience API

    # dict like access
    def __getitem__(self, item):
        return self.get(item, use_str=False)

    def __setitem__(self, item, value):
        self.set(item, value)

    def keys(self):
        return (f.dna_name.name_only for f in self.dna_type.fields)

    def values(self):
        for k in self.keys():
            try:
                yield self[k]
            except NotImplementedError as ex:
                msg, dna_name, dna_type = ex.args
                yield "<%s>" % dna_type.dna_type_id.decode('ascii')

    def items(self):
        for k in self.keys():
            try:
                yield (k, self[k])
            except NotImplementedError as ex:
                msg, dna_name, dna_type = ex.args
                yield (k, "<%s>" % dna_type.dna_type_id.decode('ascii'))

# -----------------------------------------------------------------------------
# Read Magic
#
# magic = str
# pointer_size = int
# is_little_endian = bool
# version = int

class BlendFileHeader:
    """
    BlendFileHeader allocates the first 12 bytes of a blend file
    it contains information about the hardware architecture
    """
    __slots__ = (
        # str
        "magic",
        # int 4/8
        "pointer_size",
        # bool
        "is_little_endian",
        # int
        "version",
        # str, used to pass to 'struct'
        "endian_str",
        # int, used to index common types
        "endian_index",
        )

    def __init__(self, handle):
        FILEHEADER = struct.Struct(b'7s1s1s3s')

        log.debug("reading blend-file-header")
        values = FILEHEADER.unpack(handle.read(FILEHEADER.size))
        self.magic = values[0]
        pointer_size_id = values[1]
        if pointer_size_id == b'-':
            self.pointer_size = 8
        elif pointer_size_id == b'_':
            self.pointer_size = 4
        else:
            assert(0)
        endian_id = values[2]
        if endian_id == b'v':
            self.is_little_endian = True
            self.endian_str = b'<'
            self.endian_index = 0
        elif endian_id == b'V':
            self.is_little_endian = False
            self.endian_index = 1
            self.endian_str = b'>'
        else:
            assert(0)

        version_id = values[3]
        self.version = int(version_id)

    def create_block_header_struct(self):
        return struct.Struct(b''.join((
                self.endian_str,
                b'4sI',
                b'I' if self.pointer_size == 4 else b'Q',
                b'II',
                )))

class DNAName:
    """
    DNAName is a C-type name stored in the DNA
    """
    __slots__ = (
        "name_full",
        "name_only",
        "is_pointer",
        "is_method_pointer",
        "array_size",
        )

    def __init__(self, name_full):
        self.name_full = name_full
        self.name_only = self.calc_name_only()
        self.is_pointer = self.calc_is_pointer()
        self.is_method_pointer = self.calc_is_method_pointer()
        self.array_size = self.calc_array_size()

    def as_reference(self, parent):
        if parent is None:
            result = b''
        else:
            result = parent + b'.'

        result = result + self.name_only
        return result

    def calc_name_only(self):
        result = self.name_full.strip(b'*()')
        index = result.find(b'[')
        if index != -1:
            result = result[:index]
        return result

    def calc_is_pointer(self):
        return (b'*' in self.name_full)

    def calc_is_method_pointer(self):
        return (b'(*' in self.name_full)

    def calc_array_size(self):
        result = 1
        temp = self.name_full
        index = temp.find(b'[')

        while index != -1:
            index_2 = temp.find(b']')
            result *= int(temp[index + 1:index_2])
            temp = temp[index_2 + 1:]
            index = temp.find(b'[')

        return result

class DNAField:
    """
    DNAField is a coupled DNAStruct and DNAName
    and cache offset for reuse
    """
    __slots__ = (
        # DNAName
        "dna_name",
        # tuple of 3 items
        # [bytes (struct name), int (struct size), DNAStruct]
        "dna_type",
        # size on-disk
        "dna_size",
        # cached info (avoid looping over fields each time)
        "dna_offset",
        )

    def __init__(self, dna_type, dna_name, dna_size, dna_offset):
        self.dna_type = dna_type
        self.dna_name = dna_name
        self.dna_size = dna_size
        self.dna_offset = dna_offset

class DNAStruct:
    """
    DNAStruct is a C-type structure stored in the DNA
    """
    __slots__ = (
        "dna_type_id",
        "size",
        "fields",
        "field_from_name",
        "user_data",
        )

    def __init__(self, dna_type_id):
        self.dna_type_id = dna_type_id
        self.fields = []
        self.field_from_name = {}
        self.user_data = None

    def field_from_path(self, header, handle, path):
        """
        Support lookups as bytes or a tuple of bytes and optional index.

        C style 'id.name'   -->  (b'id', b'name')
        C style 'array[4]'  -->  ('array', 4)
        """
        if type(path) is tuple:
            name = path[0]
            if len(path) >= 2 and type(path[1]) is not bytes:
                name_tail = path[2:]
                index = path[1]
                assert(type(index) is int)
            else:
                name_tail = path[1:]
                index = 0
        else:
            name = path
            name_tail = None
            index = 0

        assert(type(name) is bytes)

        field = self.field_from_name.get(name)

        if field is not None:
            handle.seek(field.dna_offset, os.SEEK_CUR)
            if index != 0:
                if field.dna_name.is_pointer:
                    index_offset = header.pointer_size * index
                else:
                    index_offset = field.dna_type.size * index
                assert(index_offset < field.dna_size)
                handle.seek(index_offset, os.SEEK_CUR)
            if not name_tail:  # None or ()
                return field
            else:
                return field.dna_type.field_from_path(header, handle, name_tail)

    def field_get(self, header, handle, path,
                  default=...,
                  use_nil=True, use_str=True,
                  ):
        field = self.field_from_path(header, handle, path)
        if field is None:
            if default is not ...:
                return default
            else:
                raise KeyError("%r not found in %r (%r)" %
                        (path, [f.dna_name.name_only for f in self.fields], self.dna_type_id))

        dna_type = field.dna_type
        dna_name = field.dna_name

        if dna_name.is_pointer:
            return DNA_IO.read_pointer(handle, header)
        elif dna_type.dna_type_id == b'int':
            if dna_name.array_size > 1:
                return [DNA_IO.read_int(handle, header) for i in range(dna_name.array_size)]
            return DNA_IO.read_int(handle, header)
        elif dna_type.dna_type_id == b'short':
            if dna_name.array_size > 1:
                return [DNA_IO.read_short(handle, header) for i in range(dna_name.array_size)]
            return DNA_IO.read_short(handle, header)
        elif dna_type.dna_type_id == b'uint64_t':
            if dna_name.array_size > 1:
                return [DNA_IO.read_ulong(handle, header) for i in range(dna_name.array_size)]
            return DNA_IO.read_ulong(handle, header)
        elif dna_type.dna_type_id == b'float':
            if dna_name.array_size > 1:
                return [DNA_IO.read_float(handle, header) for i in range(dna_name.array_size)]
            return DNA_IO.read_float(handle, header)
        elif dna_type.dna_type_id == b'char':
            if use_str:
                if use_nil:
                    return DNA_IO.read_string0(handle, dna_name.array_size)
                else:
                    return DNA_IO.read_string(handle, dna_name.array_size)
            else:
                if use_nil:
                    return DNA_IO.read_bytes0(handle, dna_name.array_size)
                else:
                    return DNA_IO.read_bytes(handle, dna_name.array_size)
        else:
            raise NotImplementedError("%r exists but isn't pointer, can't resolve field %r" %
                    (path, dna_name.name_only), dna_name, dna_type)

    def field_set(self, header, handle, path, value):
        assert(type(path) == bytes)

        field = self.field_from_path(header, handle, path)
        if field is None:
            raise KeyError("%r not found in %r" %
                    (path, [f.dna_name.name_only for f in self.fields]))

        dna_type = field.dna_type
        dna_name = field.dna_name

        if dna_type.dna_type_id == b'char':
            if type(value) is str:
                return DNA_IO.write_string(handle, value, dna_name.array_size)
            else:
                return DNA_IO.write_bytes(handle, value, dna_name.array_size)
        else:
            raise NotImplementedError("Setting %r is not yet supported" %
                    dna_type[0], dna_name, dna_type)

class DNA_IO:
    """
    Module like class, for read-write utility functions.

    Only stores static methods & constants.
    """

    __slots__ = ()

    def __new__(cls, *args, **kwargs):
        raise RuntimeError("%s should not be instantiated" % cls)

    @staticmethod
    def write_string(handle, astring, fieldlen):
        assert(isinstance(astring, str))
        if len(astring) >= fieldlen:
            stringw = astring[0:fieldlen]
        else:
            stringw = astring + '\0'
        handle.write(stringw.encode('utf-8'))

    @staticmethod
    def write_bytes(handle, astring, fieldlen):
        assert(isinstance(astring, (bytes, bytearray)))
        if len(astring) >= fieldlen:
            stringw = astring[0:fieldlen]
        else:
            stringw = astring + b'\0'

        handle.write(stringw)

    @staticmethod
    def read_bytes(handle, length):
        data = handle.read(length)
        return data

    @staticmethod
    def read_bytes0(handle, length):
        data = handle.read(length)
        return DNA_IO.read_data0(data)

    @staticmethod
    def read_string(handle, length):
        return DNA_IO.read_bytes(handle, length).decode('utf-8')

    @staticmethod
    def read_string0(handle, length):
        return DNA_IO.read_bytes0(handle, length).decode('utf-8')

    @staticmethod
    def read_data0_offset(data, offset):
        add = data.find(b'\0', offset) - offset
        return data[offset:offset + add]

    @staticmethod
    def read_data0(data):
        add = data.find(b'\0')
        return data[:add]

    USHORT = struct.Struct(b'<H'), struct.Struct(b'>H')

    @staticmethod
    def read_ushort(handle, fileheader):
        st = DNA_IO.USHORT[fileheader.endian_index]
        return st.unpack(handle.read(st.size))[0]

    SSHORT = struct.Struct(b'<h'), struct.Struct(b'>h')

    @staticmethod
    def read_short(handle, fileheader):
        st = DNA_IO.SSHORT[fileheader.endian_index]
        return st.unpack(handle.read(st.size))[0]

    UINT = struct.Struct(b'<I'), struct.Struct(b'>I')

    @staticmethod
    def read_uint(handle, fileheader):
        st = DNA_IO.UINT[fileheader.endian_index]
        return st.unpack(handle.read(st.size))[0]

    SINT = struct.Struct(b'<i'), struct.Struct(b'>i')

    @staticmethod
    def read_int(handle, fileheader):
        st = DNA_IO.SINT[fileheader.endian_index]
        return st.unpack(handle.read(st.size))[0]

    FLOAT = struct.Struct(b'<f'), struct.Struct(b'>f')

    @staticmethod
    def read_float(handle, fileheader):
        st = DNA_IO.FLOAT[fileheader.endian_index]
        return st.unpack(handle.read(st.size))[0]

    ULONG = struct.Struct(b'<Q'), struct.Struct(b'>Q')

    @staticmethod
    def read_ulong(handle, fileheader):
        st = DNA_IO.ULONG[fileheader.endian_index]
        return st.unpack(handle.read(st.size))[0]

    @staticmethod
    def read_pointer(handle, header):
        """
        reads an pointer from a file handle
        the pointer size is given by the header (BlendFileHeader)
        """
        if header.pointer_size == 4:
            st = DNA_IO.UINT[header.endian_index]
            return st.unpack(handle.read(st.size))[0]
        if header.pointer_size == 8:
            st = DNA_IO.ULONG[header.endian_index]
            return st.unpack(handle.read(st.size))[0]


text:
package cl.utils.crypto.impl;

import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

/**
 * RSA Decryptor
 */
public class RSADecryptor extends BaseCrypto {

	public static String DEFAULT_DECRYPTION_ALGORITHM = "RSA";

	private RSAPrivateKey privateKey;

	public RSADecryptor(RSAPrivateKey key) {
		privateKey = key;
	}

	public RSADecryptor(String modulus, String exponent) throws RSAException {
		BigInteger modulusBI = KeyMath.hexToBigInt(modulus);
		BigInteger privateExponentBI = KeyMath.hexToBigInt(exponent);

		privateKey = RSAKeyManager.reconstructPrivateKey(modulusBI, privateExponentBI);
	}

	/**
	 *
	 *  Decrypts the text using the given algorithm (depending on the client
	 *  implementation, there may be padding involved)
	 *
	 * @param encryptedText
	 * @param decryptionAlgorithm
	 * @return
	 * @throws RSAException
	 */
	public String decryptText(String encryptedText, String decryptionAlgorithm) throws RSAException {
		String cleartext = null;
		byte[] encryptedTextBytes = KeyMath.hexToBytes(encryptedText);

		try {
			Cipher serverCipher = Cipher.getInstance(decryptionAlgorithm);
			serverCipher.init(Cipher.DECRYPT_MODE, privateKey);
			byte[] clearTextBytes = serverCipher.doFinal(encryptedTextBytes);
			cleartext = new String(clearTextBytes);
		} catch (InvalidKeyException e) {
			throw new RSAException(e);
		} catch (NoSuchAlgorithmException e) {
			throw new RSAException(e);
		} catch (NoSuchPaddingException e) {
			throw new RSAException(e);
		} catch (IllegalBlockSizeException e) {
			throw new RSAException(e);
		} catch (BadPaddingException e) {
			throw new RSAException(e);
		}

		return cleartext;
	}

	/**
	 *
	 *   Decrypts the text using the default algorithm (RSA)
	 *
	 * @param encryptedText (hexadecimal string value of a Big Integer)
	 * @return
	 * @throws RSAException RSA Util exception
	 */
	public String decryptText(String encryptedText) throws RSAException {

		return decryptText(encryptedText,DEFAULT_DECRYPTION_ALGORITHM);
	}

}

redpajama_set_name: RedPajamaGithub


text:
<?php

namespace ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator;

use ProxyManager\Generator\MagicMethodGenerator;
use ReflectionClass;
use ProxyManager\Generator\MethodGenerator;
use ProxyManager\Generator\ParameterGenerator;
use ReflectionProperty;
use Zend\Code\Generator\PropertyGenerator;

/**
 * Magic `__isset` method for lazy loading ghost objects
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 * @license MIT
 */
class MagicIsset extends MagicMethodGenerator
{
    /**
     * Constructor
     */
    public function __construct(ReflectionClass $originalClass, PropertyGenerator $initializerProperty)
    {
        parent::__construct($originalClass, '__isset', array(new ParameterGenerator('name')));

        $override         = $originalClass->hasMethod('__isset');
        $initializer      = $initializerProperty->getName();
        $publicProperties = array_map(
            function (ReflectionProperty $publicProperty) {
                return var_export($publicProperty->getName(), true);
            },
            $originalClass->getProperties(ReflectionProperty::IS_PUBLIC)
        );

        $this->setDocblock(($override ? "{@inheritDoc}\n" : '') . '@param string $name');

        // @todo can be skipped when no public properties are available
        $callParent = 'if (in_array($name, array(' . implode(', ', $publicProperties) . '))) {' . "\n"
            . '    return isset($this->$name);'
            . "\n}\n\n";

        if ($override) {
            // @todo move to private static var to remove overhead!
            $callParent .= 'return parent::__isset($name);';
        } else {
            $callParent .= 'return false;';
        }

        $this->setBody(
            '$this->' . $initializer . ' && $this->' . $initializer
            . '->__invoke($this, \'__isset\', array(\'name\' => $name), $this->' . $initializer . ');'
            . "\n\n" . $callParent
        );
    }
}


text:
.. title:: MochiKit.DOM - painless DOM manipulation API

Name
====

MochiKit.DOM - painless DOM manipulation API

Synopsis
========

::

    var rows = [
        ["dataA1", "dataA2", "dataA3"],
        ["dataB1", "dataB2", "dataB3"]
    ];
    row_display = function (row) {
        return TR(null, map(partial(TD, null), row));
    }
    var newTable = TABLE({'class': 'prettytable'},
        THEAD(null,
            row_display(["head1", "head2", "head3"])),
        TFOOT(null,
            row_display(["foot1", "foot2", "foot3"])),
        TBODY(null,
            map(row_display, rows)));
    // put that in your document.createElement and smoke it!
    swapDOM(oldTable, newTable);

Description
===========

As you probably know, the DOM APIs are some of the most painful
Java-inspired APIs you'll run across from a highly dynamic
language. Don't worry about that though, because they provide a
reasonable basis to build something that sucks a lot less.

MochiKit.DOM takes much of its inspiration from Nevow's [1]_ stan
[2]_.  This means you choose a tag, give it some attributes, then
stuff it full of *whatever objects you want*. MochiKit.DOM isn't
stupid, it knows that a string should be a text node, and that you
want functions to be called, and that ``Array``-like objects should be
expanded, and stupid ``null`` values should be skipped.

Hell, it will let you return strings from functions, and use iterators
from :mochiref:`MochiKit.Iter`. If that's not enough, just teach it
new tricks with :mochiref:`registerDOMConverter`. If you have never
used an API like this for creating DOM elements, you've been wasting
your damn time. Get with it!

Dependencies
============

- :mochiref:`MochiKit.Base`
- :mochiref:`MochiKit.Style` (optional since MochiKit 1.4 for
  backwards-compatibility)
- :mochiref:`MochiKit.Iter` (optional since MochiKit 1.4)

Overview
========

DOM Coercion Rules
------------------

In order of precedence, :mochiref:`createDOM` coerces given arguments
to DOM nodes using the following rules:

1.  Functions are called with a ``this`` and first argument of the
    parent node and their return value is subject to the following
    rules (even this one).
2.  ``undefined`` and ``null`` are ignored.
3.  If :mochiref:`MochiKit.Iter` is loaded, iterables are flattened
    (as if they were passed in-line as nodes) and each return value is
    subject to these rules.
4.  Values that look like DOM nodes (objects with a ``.nodeType > 0``)
    are ``.appendChild``'ed to the created DOM fragment.
5.  Strings are wrapped up with ``document.createTextNode``
6.  Objects that have a ``.dom(node)`` or ``.__dom__(node)`` method
    are called with the parent node and their result is coerced using
    these rules.  (MochiKit 1.4+).
7.  Objects that are not strings are run through the ``domConverters``
    :mochiref:`MochiKit.Base.AdapterRegistry` (see
    :mochiref:`registerDOMConverter`).  The adapted value is subject
    to these same rules (e.g.  if the adapter returns a string, it
    will be coerced to a text node).
8.  If no adapter is available, ``.toString()`` is used to create a
    text node.

Creating DOM Element Trees
--------------------------

:mochiref:`createDOM` provides you with an excellent facility for
creating DOM trees that is easy on the wrists. One of the best ways to
understand how to use it is to take a look at an example::

    var rows = [
        ["dataA1", "dataA2", "dataA3"],
        ["dataB1", "dataB2", "dataB3"]
    ];
    row_display = function (row) {
        return TR(null, map(partial(TD, null), row));
    }
    var newTable = TABLE({'class': 'prettytable'},
        THEAD(null,
            row_display(["head1", "head2", "head3"])),
        TFOOT(null,
            row_display(["foot1", "foot2", "foot3"])),
        TBODY(null,
            map(row_display, rows)));

This will create a table with the following visual layout (if it were
inserted into the document DOM):

    +--------+--------+--------+
    | head1  | head2  | head3  |
    +========+========+========+
    | dataA1 | dataA2 | dataA3 |
    +--------+--------+--------+
    | dataB1 | dataB2 | dataB3 |
    +--------+--------+--------+
    | foot1  | foot2  | foot3  |
    +--------+--------+--------+

Corresponding to the following HTML::

                head1
                head2
                head3

                foot1
                foot2
                foot3

                dataA1
                dataA2
                dataA3

                dataB1
                dataB2
                dataB3

DOM Context
-----------

In order to prevent having to pass a ``window`` and/or ``document``
variable to every MochiKit.DOM function (e.g. when working with a
child window), MochiKit.DOM maintains a context variable for each of
them. They are managed with the :mochiref:`withWindow` and
:mochiref:`withDocument` functions, and can be acquired with
:mochiref:`currentWindow()` and :mochiref:`currentDocument()`

For example, if you are creating DOM nodes in a child window, you
could do something like this::

    withWindow(child, function () {
        var doc = currentDocument();
        appendChildNodes(doc.body, H1(null, "This is in the child!"));
    });

Note that :mochiref:`withWindow(win, ...)` also implies
:mochiref:`withDocument(win.document, ...)`.

DOM Gotchas
-----------

Performance Tradeoff:
    DOM is much easier to get correct and more flexible than working
    directly with markup as strings. Modifying ``innerHTML`` is still
    the fastest way to make document changes.

Internet Explorer:
    Internet Explorer's DOM implementation is quite poor in comparison
    to the other popular implementations. In order to avoid memory
    leaks due to circular references, you should use
    :mochiref:`MochiKit.Signal.connect` for all of your event handling
    needs. Additionally, when creating tables with DOM, it is required
    to use a ``TBODY`` tag (see `Creating DOM Element Trees`_ for an
    example of this).

API Reference
=============

Functions
---------

:mochidef:`$(id[, ...])`:

    An alias for :mochiref:`getElement(id[, ...])`

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`addElementClass(element, className)`:

    Ensure that the given ``element`` has ``className`` set as part of
    its class attribute. This will not disturb other class names.
    ``element`` is looked up with :mochiref:`getElement`, so string
    identifiers are also acceptable.

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`addLoadEvent(func)`:

    Note that :mochiref:`addLoadEvent` can not be used in combination
    with :mochiref:`MochiKit.Signal` if the ``onload`` event is
    connected.  Once an event is connected with
    :mochiref:`MochiKit.Signal`, no other APIs may be used for that
    same event.

    This will stack ``window.onload`` functions on top of each other.
    Each function added will be called after ``onload`` in the order
    that they were added.

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`addToCallStack(target, path, func[, once])`:

    Note that :mochiref:`addToCallStack` is not compatible with
    :mochiref:`MochiKit.Signal`. Once an event is connected with
    :mochiref:`MochiKit.Signal`, no other APIs may be used for that
    same event.

    Set the property ``path`` of ``target`` to a function that calls
    the existing function at that property (if any), then calls
    ``func``.

    If ``target[path]()`` returns exactly ``false``, then ``func``
    will not be called.

    If ``once`` is ``true``, then ``target[path]`` is set to ``null``
    after the function call stack has completed.

    If called several times for the same ``target[path]``, it will
    create a stack of functions (instead of just a pair).

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`appendChildNodes(node[, childNode[, ...]])`:

    Append children to a DOM element using the `DOM Coercion Rules`_.

    ``node``:
        A reference to the DOM element to add children to (if a string
        is given, :mochiref:`getElement(node)` will be used to locate
        the node)

    ``childNode``...:
        All additional arguments, if any, will be coerced into DOM
        nodes that are appended as children using the `DOM Coercion
        Rules`_.

    *returns*:
        The given DOM element

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`insertSiblingNodesBefore(node[, siblingNode[, ...]])`:

    Insert children into the DOM structure using the `DOM Coercion
    Rules`_.

    ``node``:
        A reference to the DOM element you want to insert children
        before (if a string is given, :mochiref:`getElement(node)`
        will be used to locate the node)

    ``siblingNode``...:
        All additional arguments, if any, will be coerced into DOM
        nodes that are inserted as siblings using the `DOM Coercion
        Rules`_.

    *returns*:
        The parent of the given DOM element

    *Availability*:
        Available in MochiKit 1.4+

:mochidef:`insertSiblingNodesAfter(node[, siblingNode[, ...]])`:

    Insert children into the DOM structure using the `DOM Coercion
    Rules`_.

    ``node``:
        A reference to the DOM element you want to insert children
        after (if a string is given, :mochiref:`getElement(node)`
        will be used to locate the node)

    ``siblingNode``...:
        All additional arguments, if any, will be coerced into DOM
        nodes that are inserted as siblings using the `DOM Coercion
        Rules`_.

    *returns*:
        The parent of the given DOM element

    *Availability*:
        Available in MochiKit 1.4+

:mochidef:`createDOM(name[, attrs[, node[, ...]]])`:

    Create a DOM fragment in a really convenient manner, much like
    Nevow`s [1]_ stan [2]_.

    Partially applied versions of this function for common tags are
    available as aliases:

    - ``A``
    - ``BUTTON``
    - ``BR``
    - ``CANVAS``
    - ``DIV``
    - ``FIELDSET``
    - ``FORM``
    - ``H1``
    - ``H2``
    - ``H3``
    - ``HR``
    - ``IMG``
    - ``INPUT``
    - ``LABEL``
    - ``LEGEND``
    - ``LI``
    - ``OL``
    - ``OPTGROUP``
    - ``OPTION``
    - ``P``
    - ``PRE``
    - ``SELECT``
    - ``SPAN``
    - ``STRONG``
    - ``TABLE``
    - ``TBODY``
    - ``TD``
    - ``TEXTAREA``
    - ``TFOOT``
    - ``TH``
    - ``THEAD``
    - ``TR``
    - ``TT``
    - ``UL``

    See `Creating DOM Element Trees`_ for a comprehensive example.

    ``name``:
        The kind of fragment to create (e.g. 'span'), such as you
        would pass to ``document.createElement``.

    ``attrs``:
        An object whose properties will be used as the attributes
        (e.g. ``{'style': 'display:block'}``), or ``null`` if no
        attributes need to be set.

        See :mochiref:`updateNodeAttributes` for more information.

        For convenience, if ``attrs`` is a string, ``null`` is used
        and the string will be considered the first ``node``.

    ``node``...:
        All additional arguments, if any, will be coerced into DOM
        nodes that are appended as children using the `DOM Coercion
        Rules`_.

    *returns*:
        A DOM element

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`createDOMFunc(tag[, attrs[, node[, ...]]])`:

    Convenience function to create a partially applied createDOM
    function. You'd want to use this if you add additional convenience
    functions for creating tags, or if you find yourself creating a
    lot of tags with a bunch of the same attributes or contents.

    See :mochiref:`createDOM` for more detailed descriptions of the
    arguments.

    ``tag``:
        The name of the tag

    ``attrs``:
        Optionally specify the attributes to apply

    ``node``...:
        Optionally specify any children nodes it should have

    *returns*:
        function that takes additional arguments and calls
        :mochiref:`createDOM`

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`currentDocument()`:

    Return the current ``document`` `DOM Context`_. This will always
    be the same as the global ``document`` unless
    :mochiref:`withDocument` or :mochiref:`withWindow` is currently
    executing.

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`currentWindow()`:

    Return the current ``window`` `DOM Context`_. This will always be
    the same as the global ``window`` unless :mochiref:`withWindow` is
    currently executing.

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`emitHTML(dom[, lst])`:

    Convert a DOM tree to an ``Array`` of HTML string fragments. This should
    be used for debugging/testing purposes only.

    The DOM property ``innerHTML`` or ``cloneNode(true)`` method should
    be used for most purposes.

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`escapeHTML(s)`:

    Make a string safe for HTML, converting the usual suspects (lt,
    gt, quot, amp)

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`focusOnLoad(element)`:

    Note that :mochiref:`focusOnLoad` can not be used in combination
    with :mochiref:`MochiKit.Signal` if the ``onload`` event is
    connected.  Once an event is connected with
    :mochiref:`MochiKit.Signal`, no other APIs may be used for that
    same event.

    This adds an onload event to focus the given element.

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`formContents(elem=document.body)`:

    Search the DOM tree, starting at ``elem``, for any elements with a
    ``name`` and ``value`` attribute. Return a 2-element ``Array`` of
    ``names`` and ``values`` suitable for use with
    :mochiref:`MochiKit.Base.queryString`.

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`getElement(id[, ...])`:

    A small quick little function to encapsulate the
    ``getElementById`` method. It includes a check to ensure we can
    use that method.

    If the id isn't a string, it will be returned as-is.

    Also available as :mochiref:`$(...)` for convenience and
    compatibility with other JavaScript frameworks.

    If multiple arguments are given, an ``Array`` will be returned.

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`getElementsByTagAndClassName(tagName, className, parent=document)`:

    Returns an array of elements in ``parent`` that match the tag name
    and class name provided. If ``parent`` is a string, it will be
    looked up with :mochiref:`getElement`.

    If ``tagName`` is ``null`` or ``"*"``, all elements will be
    searched for the matching class.

    If ``className`` is ``null``, all elements matching the provided
    tag are returned.

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`getFirstElementByTagAndClassName(tagName, className, parent=document)`:

    Return the first element in ``parent`` that matches the tag name
    and class name provided. If ``parent`` is a string, it will be
    looked up with :mochiref:`getElement`.

    If ``tagName`` is ``null`` or ``"*"``, all elements will be searched
    for the matching class.

    If ``className`` is ``null``, the first element matching the provided
    tag will be returned.

    *Availability*:
        Available in MochiKit 1.4+

:mochidef:`getFirstParentByTagAndClassName(elem, tagName='*', className=null)`:

    Returns the first parent of ``elem`` matches the tag name and class name
    provided. If parent is a string, it will be looked up using
    :mochiref:`getElement`.

    If ``tagName`` is ``null`` or ``"*"``, all elements will be searched
    for the matching class.

    If ``className`` is ``null``, the first element matching the provided
    tag will be returned.

    *Availability*:
        Available in MochiKit 1.4+

:mochidef:`getNodeAttribute(node, attr)`:

    Get the value of the given attribute for a DOM element without
    ever raising an exception (will return ``null`` on exception).

    ``node``:
        A reference to the DOM element to update (if a string is
        given, :mochiref:`getElement(node)` will be used to locate the
        node)

    ``attr``:
        The name of the attribute

        Note that it will do the right thing for IE, so don't do
        the ``class`` -> ``className`` hack yourself.

    *returns*:
        The attribute's value, or ``null``

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`hasElementClass(element, className[, ...])`:

    Return ``true`` if ``className`` is found on the ``element``.
    ``element`` is looked up with :mochiref:`getElement`, so string
    identifiers are also acceptable.

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`isChildNode(node, maybeParent)`:

    Determine whether ``node`` is a child node of ``maybeParent``.
    Returns ``true`` if so, and ``false`` if not. A node is considered
    a child node of itself for the purposes of this function.

    If either ``node`` or ``maybeParent`` are strings, the related
    nodes will be looked up with :mochiref:`getElement`.

    *Availability*:
        Available in MochiKit 1.4+

:mochidef:`isParent(child, element)`:

    Returns ``true`` if ``element`` contains ``child``. Returns ``false``
    if ``element == child`` or ``child`` is not contained in ``element``.
    If ``child`` or ``element`` are strings, they will be looked up with
    :mochiref:`getElement`.

    *Availability*:
        Available in MochiKit 1.4+

:mochidef:`makeClipping(element)`:

    Ensure that ``element.style.overflow = 'hidden'``. If ``element`` is a
    string, then it will be looked up with :mochiref:`getElement`.

    Returns the original value of ``element.style.overflow``, so that it
    may be restored with :mochiref:`undoClipping(element, overflow)`.

    *Availability*:
        Available in MochiKit 1.4+

:mochidef:`makePositioned(element)`:

    Ensure that ``element.style.position`` is set to ``"relative"`` if it
    is not set or is ``"static"``. If ``element`` is a
    string, then it will be looked up with :mochiref:`getElement`.

    Returns the original value of ``element.style.position``, so that it
    may be restored with :mochiref:`undoPositioned(element, position)`.

    *Availability*:
        Available in MochiKit 1.4+

:mochidef:`registerDOMConverter(name, check, wrap[, override])`:

    Register an adapter to convert objects that match ``check(obj,
    ctx)`` to a DOM element, or something that can be converted to a
    DOM element (i.e. number, bool, string, function, iterable).

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`removeElement(node)`:

    Remove and return ``node`` from a DOM tree.

    ``node``:
        the DOM element (or string id of one) to be removed

    *returns*
        The removed element

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`removeElementClass(element, className)`:

    Ensure that the given ``element`` does not have ``className`` set
    as part of its class attribute. This will not disturb other class
    names.  ``element`` is looked up with :mochiref:`getElement`, so
    string identifiers are also acceptable.

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`removeEmptyTextNodes(node)`:

    Remove all text node children that contain only whitespace from
    ``node``. Useful in situations where such empty text nodes can
    interfere with DOM traversal.

    ``node``:
        the DOM element (or string id of one) to remove whitespace child
        nodes from.

    *Availability*:
        Available in MochiKit 1.4+

:mochidef:`replaceChildNodes(node[, childNode[, ...]])`:

    Remove all children from the given DOM element, then append any
    given childNodes to it (by calling :mochiref:`appendChildNodes`).

    ``node``:
        A reference to the DOM element to add children to (if a string
        is given, :mochiref:`getElement(node)` will be used to locate
        the node)

    ``childNode``...:
        All additional arguments, if any, will be coerced into DOM
        nodes that are appended as children using the `DOM Coercion
        Rules`_.

    *returns*:
        The given DOM element

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`scrapeText(node[, asArray=false])`:

    Walk a DOM tree in-order and scrape all of the text out of it as a
    ``string``.

    If ``asArray`` is ``true``, then an ``Array`` will be returned
    with each individual text node. These two are equivalent::

        assert( scrapeText(node) == scrapeText(node, true).join("") );

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`setElementClass(element, className)`:

    Set the entire class attribute of ``element`` to ``className``.
    ``element`` is looked up with :mochiref:`getElement`, so string
    identifiers are also acceptable.

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`setNodeAttribute(node, attr, value)`:

    Set the value of the given attribute for a DOM element without
    ever raising an exception (will return null on exception). If
    setting more than one attribute, you should use
    :mochiref:`updateNodeAttributes`.

    ``node``:
        A reference to the DOM element to update (if a string is
        given, :mochiref:`getElement(node)` will be used to locate the
        node)

    ``attr``:
        The name of the attribute

        Note that it will do the right thing for IE, so don't do the
        ``class`` -> ``className`` hack yourself.

    ``value``:
        The value of the attribute, may be an object to be merged
        (e.g. for setting style).

    *returns*:
        The given DOM element or ``null`` on failure

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`swapDOM(dest, src)`:

    Replace ``dest`` in a DOM tree with ``src``, returning ``src``.

    ``dest``:
        a DOM element (or string id of one) to be replaced

    ``src``:
        the DOM element (or string id of one) to replace it with, or
        ``null`` if ``dest`` is to be removed (replaced with nothing).

    *returns*:
        a DOM element (``src``)

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`swapElementClass(element, fromClass, toClass)`:

    If ``fromClass`` is set on ``element``, replace it with
    ``toClass``.  This will not disturb other classes on that element.
    ``element`` is looked up with :mochiref:`getElement`, so string
    identifiers are also acceptable.

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`toggleElementClass(className[, element[, ...]])`:

    Toggle the presence of a given ``className`` in the class
    attribute of all given elements. All elements will be looked up
    with :mochiref:`getElement`, so string identifiers are acceptable.

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`toHTML(dom)`:

    Convert a DOM tree to a HTML string using :mochiref:`emitHTML`.
    This should be used for debugging/testing purposes only.

    The DOM property ``innerHTML`` or ``cloneNode(true)`` method should
    be used for most purposes.

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`undoClipping(element, overflow)`:

    Restore the setting of ``element.style.overflow`` set by
    :mochiref:`makeClipping(element)`. If ``element`` is a string, then
    it will be looked up with :mochiref:`getElement`.

    *Availability*:
        Available in MochiKit 1.4+

:mochidef:`undoPositioned(element, overflow)`:

    Restore the setting of ``element.style.position`` set by
    :mochiref:`makePositioned(element)`. If ``element`` is a string, then
    it will be looked up with :mochiref:`getElement`.

    *Availability*:
        Available in MochiKit 1.4+

:mochidef:`updateNodeAttributes(node, attrs)`:

    Update the attributes of a DOM element from a given object.

    ``node``:
        A reference to the DOM element to update (if a string is
        given, :mochiref:`getElement(node)` will be used to locate the
        node)

    ``attrs``:
        An object whose properties will be used to set the attributes
        (e.g. ``{'class': 'invisible'}``), or ``null`` if no
        attributes need to be set. If an object is given for the
        attribute value (e.g. ``{'style': {'display': 'block'}}``)
        then :mochiref:`MochiKit.Base.updatetree` will be used to set
        that attribute.

        Note that it will do the right thing for IE, so don't do the
        ``class`` -> ``className`` hack yourself, and it deals with
        setting "on..." event handlers correctly.

    *returns*:
        The given DOM element

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`withWindow(win, func)`:

    Call ``func`` with the ``window`` `DOM Context`_ set to ``win``
    and the ``document`` `DOM Context`_ set to ``win.document``. When
    ``func()`` returns or throws an error, the `DOM Context`_ will be
    restored to its previous state.

    The return value of ``func()`` is returned by this function.

    *Availability*:
        Available in MochiKit 1.3.1+

:mochidef:`withDocument(doc, func)`:

    Call ``func`` with the ``doc`` `DOM Context`_ set to ``doc``.
    When ``func()`` returns or throws an error, the `DOM Context`_
    will be restored to its previous state.

    The return value of ``func()`` is returned by this function.

    *Availability*:
        Available in MochiKit 1.3.1+

Style Functions
---------------

These functions are available in MochiKit 1.3.1, but have been moved to
:mochiref:`MochiKit.Style` in 1.4+.

:mochidef:`computedStyle(htmlElement, cssProperty, mozillaEquivalentCSS)`:

    Looks up a CSS property for the given element. The element can be
    specified as either a string with the element's ID or the element
    object itself.

    ``cssProperty``:
        MochiKit 1.3.1 expects camel case, e.g. ``backgroundColor``.
        MochiKit 1.4+ expects CSS selector case, e.g. ``background-color``,
        but will accept camel case for backwards-compatibility.

    ``mozillaEquivalentCSS``:
        MochiKit 1.3.1 expects selector case.
        MochiKit 1.4+ ignores this argument.

    *Availability*:
        Available in MochiKit 1.3.1, deprecated in favor of
        :mochiref:`MochiKit.Style.getStyle` in 1.4+

:mochidef:`elementDimensions(element)`:

    Return the absolute pixel width and height (including padding and border,
    but not margins) of ``element`` as an object with ``w`` and ``h``
    properties, or ``undefined`` if ``element`` is not in the document.
    ``element`` may be specified as a string to be looked up with
    :mochiref:`getElement`, a DOM element, or trivially as an object with
    ``w`` and/or ``h`` properties.

    *Availability*:
        Available in MochiKit 1.3.1, deprecated in favor of
        :mochiref:`MochiKit.Style.getElementDimensions` in 1.4+

:mochidef:`elementPosition(element[, relativeTo={x: 0, y: 0}])`:

    Return the absolute pixel position of ``element`` in the document
    as an object with ``x`` and ``y`` properties, or ``undefined`` if
    ``element`` is not in the document. ``element`` may be specified
    as a string to be looked up with :mochiref:`getElement`, a DOM
    element, or trivially as an object with ``x`` and/or ``y``
    properties.

    If ``relativeTo`` is given, then its coordinates are subtracted from
    the absolute position of ``element``, e.g.::

        var elemPos = elementPosition(elem);
        var anotherElemPos = elementPosition(anotherElem);
        var relPos = elementPosition(elem, anotherElem);
        assert( relPos.x == (elemPos.x - anotherElemPos.x) );
        assert( relPos.y == (elemPos.y - anotherElemPos.y) );

    ``relativeTo`` may be specified as a string to be looked up with
    :mochiref:`getElement`, a DOM element, or trivially as an object
    with ``x`` and/or ``y`` properties.

    *Availability*:
        Available in MochiKit 1.3.1, deprecated in favor of
        :mochiref:`MochiKit.Style.getElementPosition` in 1.4+

:mochidef:`getViewportDimensions()`:

    Return the pixel width and height of the viewport as an object
    with ``w`` and ``h`` properties. ``element`` is looked up with
    :mochiref:`getElement`, so string identifiers are also acceptable.

    *Availability*:
        Available in MochiKit 1.3.1, moved to
        :mochiref:`MochiKit.Style.getViewportDimensions` in 1.4+

:mochidef:`hideElement(element, ...)`:

    Partial form of :mochiref:`setDisplayForElement`, specifically::

        partial(setDisplayForElement, "none")

    For information about the caveats of using a ``style.display``
    based show/hide mechanism, and a CSS based alternative, see
    `Element Visibility`_.

.. _`Element Visibility`: Style.html#element-visibility

    *Availability*:
        Available in MochiKit 1.3.1, moved to
        :mochiref:`MochiKit.Style.hideElement` in 1.4+

:mochidef:`setElementDimensions(element, dimensions[, units='px'])`:

    Sets the dimensions of ``element`` in the document from an object
    with ``w`` and ``h`` properties.

    ``node``:
        A reference to the DOM element to update (if a string is
        given, :mochiref:`getElement(node)` will be used to locate the
        node)

    ``dimensions``:
        An object with ``w`` and ``h`` properties

    ``units``:
        Optionally set the units to use, default is ``px``

    *Availability*:
        Available in MochiKit 1.3.1, moved to
        :mochiref:`MochiKit.Style.setElementDimensions` in 1.4+

:mochidef:`setElementPosition(element, position[, units='px'])`:

    Sets the absolute position of ``element`` in the document from an
    object with ``x`` and ``y`` properties.

    ``node``:
        A reference to the DOM element to update (if a string is
        given, :mochiref:`getElement(node)` will be used to locate the
        node)

    ``position``:
        An object with ``x`` and ``y`` properties

    ``units``:
        Optionally set the units to use, default is ``px``

    *Availability*:
        Available in MochiKit 1.3.1, moved to
        :mochiref:`MochiKit.Style.setElementPosition` in 1.4+

:mochidef:`setDisplayForElement(display, element[, ...])`:

    Change the ``style.display`` for the given element(s). Usually
    used as the partial forms:

    - :mochiref:`showElement(element, ...)`
    - :mochiref:`hideElement(element, ...)`

    Elements are looked up with :mochiref:`getElement`, so string
    identifiers are acceptable.

    For information about the caveats of using a ``style.display``
    based show/hide mechanism, and a CSS based alternative, see
    `Element Visibility`_.

    *Availability*:
        Available in MochiKit 1.3.1, moved to
        :mochiref:`MochiKit.Style.setDisplayForElement` in 1.4+

:mochidef:`setOpacity(element, opacity)`:

    Sets ``opacity`` for ``element``. Valid ``opacity`` values range
    from 0 (invisible) to 1 (opaque). ``element`` is looked up with
    :mochiref:`getElement`, so string identifiers are also acceptable.

    *Availability*:
        Available in MochiKit 1.3.1, moved to
        :mochiref:`MochiKit.Style.setOpacity` in 1.4+

:mochidef:`showElement(element, ...)`:

    Partial form of :mochiref:`setDisplayForElement`, specifically::

        partial(setDisplayForElement, "block")

    For information about the caveats of using a ``style.display``
    based show/hide mechanism, and a CSS based alternative, see
    `Element Visibility`_.

    *Availability*:
        Available in MochiKit 1.3.1, moved to
        :mochiref:`MochiKit.Style.showElement` in 1.4+

Style Objects
-------------

These objects are available in MochiKit 1.3.1, but have been moved to
:mochiref:`MochiKit.Style` in 1.4+.

:mochidef:`Coordinates(x, y)`:

    Constructs an object with ``x`` and ``y`` properties. ``obj.toString()``
    returns something like ``{x: 0, y: 42}`` for debugging.

    *Availability*:
    Available in MochiKit 1.3.1, moved to
    :mochiref:`MochiKit.Style.Coordinates` in 1.4+

:mochidef:`Dimensions(w, h)`:

    Constructs an object with ``w`` and ``h`` properties. ``obj.toString()``
    returns something like ``{w: 0, h: 42}`` for debugging.

    *Availability*:
    Available in MochiKit 1.3.1, moved to
    :mochiref:`MochiKit.Style.Dimensions` in 1.4+

See Also
========

.. [1] Nevow, a web application construction kit for Python:
       http://divmod.org/trac/wiki/DivmodNevow
.. [2] nevow.stan is a domain specific language for Python (read as
       "crazy getitem/call overloading abuse") that Donovan and I
       schemed up at PyCon 2003 at this super ninja Python/C++
       programmer's (David Abrahams) hotel room. Donovan later
       inflicted this upon the masses in Nevow. Check out the Nevow
       Guide for some examples:
       http://divmod.org/trac/wiki/DivmodNevow

Authors
=======

- Bob Ippolito <bob@redivi.com>

Copyright
=========

Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is
dual-licensed free software; you can redistribute it and/or modify it
under the terms of the `MIT License`_ or the `Academic Free License
v2.1`_.

.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php


text:
@interface ATMessageCenterViewController : ATMessageCenterBaseViewController <ATMessageCenterDataSourceDelegate, ATMessageInputViewDelegate, UIActionSheetDelegate, UIScrollViewDelegate, UITableViewDataSource, UITableViewDelegate>
@property (retain, nonatomic) IBOutlet UITableView *tableView;
@property (retain, nonatomic) IBOutlet ATAutomatedMessageCell *automatedCell;
@property (retain, nonatomic) IBOutlet ATTextMessageUserCell *userCell;
@property (retain, nonatomic) IBOutlet ATTextMessageUserCell *developerCell;
@property (retain, nonatomic) IBOutlet ATFileMessageCell *userFileMessageCell;

- (id)init;
@end


text:
<!DOCTYPE html>

  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width initial-scale=1" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge">

  <title>Atarantado</title>
  <meta name="description" content="Las Cosas son como deben, no como deberían Ser.">
  <meta name="author" content="Mauricio Navarro Miranda">
  <meta name="HandheldFriendly" content="True">
  <meta name="MobileOptimized" content="320">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

  <meta name="twitter:card" content="summary">
  <meta name="twitter:title" content="El rincón de mautemático">
  <meta name="twitter:description" content="Las Cosas son como deben, no como deberían Ser.">

  <meta property="og:type" content="article">
  <meta property="og:title" content="El rincón de mautemático">
  <meta property="og:description" content="Las Cosas son como deben, no como deberían Ser.">

  <link rel="apple-touch-icon" sizes="57x57" href="/images/favicons/apple-touch-icon-57x57.png">
  <link rel="apple-touch-icon" sizes="60x60" href="/images/favicons/apple-touch-icon-60x60.png">
  <link rel="apple-touch-icon" sizes="72x72" href="/images/favicons/apple-touch-icon-72x72.png">
  <link rel="apple-touch-icon" sizes="76x76" href="/images/favicons/apple-touch-icon-76x76.png">
  <link rel="apple-touch-icon" sizes="114x114" href="/images/favicons/apple-touch-icon-114x114.png">
  <link rel="apple-touch-icon" sizes="120x120" href="/images/favicons/apple-touch-icon-120x120.png">
  <link rel="apple-touch-icon" sizes="144x144" href="/images/favicons/apple-touch-icon-144x144.png">
  <link rel="apple-touch-icon" sizes="152x152" href="/images/favicons/apple-touch-icon-152x152.png">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/favicons/apple-touch-icon-180x180.png">
  <link rel="icon" type="image/png" href="/images/favicons/favicon-32x32.png" sizes="32x32">
  <link rel="icon" type="image/png" href="/images/favicons/favicon-194x194.png" sizes="194x194">
  <link rel="icon" type="image/png" href="/images/favicons/favicon-96x96.png" sizes="96x96">
  <link rel="icon" type="image/png" href="/images/favicons/android-chrome-192x192.png" sizes="192x192">
  <link rel="icon" type="image/png" href="/images/favicons/favicon-16x16.png" sizes="16x16">
  <link rel="manifest" href="/images/favicons/manifest.json">
  <link rel="shortcut icon" href="/images/favicons/favicon.ico">
  <meta name="msapplication-TileColor" content="#ffc40d">
  <meta name="msapplication-TileImage" content="/images/favicons/mstile-144x144.png">
  <meta name="theme-color" content="#ffffff">

  <link rel="stylesheet" href="/css/main.css">
  <link rel="canonical" href="https://blog.mautematico.com//2014/atarantado.html">
  <link rel="alternate" type="application/rss+xml" title="El rincón de mautemático" href="/feed.xml">

El rincón de mautemático

Las Cosas son como deben, no como deberían Ser.

Blog

                  Twitter

                  GitHub

                  Email

                RSS

      <time datetime="11 Oct 2014" class="post-meta__date date">11 Oct 2014</time> • on

Atarantado

Ando menso, torpe.

Atolondrado.

Atarantado. Y no me ha picado una tarántula; aunque imagino que si me picara (y suponiendo que no muero como desenlace de una reacción alérgica), descubriría por qué nos gusta usar la misma palabra para dos cosas tan distantes.

Estoy escuchando a Andrés Calamaro:

Antes de comenzar a escribir, pensé que quizás atarantado era un regionalismo. Y no:

http://www.fundeu.es/noticia/la-palabra-atarantado-4293/

Menos mal que la actualización de anoche hizo que automágicamente funcionara el scroll multitouch de mi touchpad, sin romper nada a cambio.

Continuaré atarantado hasta nuevo aviso.

  © 2020 Mauricio Navarro Miranda. All rights reserved.


text:
package org.apache.catalina.tribes.group;

import org.apache.catalina.tribes.ErrorHandler;

/**
 * @version 1.0
 */
public class InterceptorPayload  {
    private ErrorHandler errorHandler;

    public ErrorHandler getErrorHandler() {
        return errorHandler;
    }

    public void setErrorHandler(ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }
}


text:
Greeting to the user according to the time.

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'day-magick'
```

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install day-magick

## Usage

In your view pages simply call

<%= day_magick %>

Now message will be changed automatically change according to the time.

And that's it!

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/sethukarthik/day-magick. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.

## License

The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).


text:
/*
* OS and machine specific utility functions
* (C) 2015,2016,2017,2018 Jack Lloyd
* (C) 2016 Daniel Neus
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/internal/os_utils.h>
#include <botan/internal/cpuid.h>
#include <botan/exceptn.h>
#include <botan/mem_ops.h>

#include <algorithm>
#include <chrono>
#include <cstdlib>

#if defined(BOTAN_TARGET_OS_HAS_THREADS)
  #include <thread>
#endif

#if defined(BOTAN_TARGET_OS_HAS_EXPLICIT_BZERO)
  #include <string.h>
#endif

#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
  #include <sys/types.h>
  #include <sys/resource.h>
  #include <sys/mman.h>
  #include <signal.h>
  #include <stdlib.h>
  #include <setjmp.h>
  #include <unistd.h>
  #include <errno.h>
  #include <termios.h>
  #undef B0
#endif

#if defined(BOTAN_TARGET_OS_IS_EMSCRIPTEN)
  #include <emscripten/emscripten.h>
#endif

#if defined(BOTAN_TARGET_OS_HAS_GETAUXVAL) || defined(BOTAN_TARGET_OS_IS_ANDROID) || \
  defined(BOTAN_TARGET_OS_HAS_ELF_AUX_INFO)
  #include <sys/auxv.h>
#endif

#if defined(BOTAN_TARGET_OS_HAS_AUXINFO)
  #include <dlfcn.h>
  #include <elf.h>
#endif

#if defined(BOTAN_TARGET_OS_HAS_WIN32)
  #define NOMINMAX 1
  #define _WINSOCKAPI_ // stop windows.h including winsock.h
  #include <windows.h>
#endif

#if defined(BOTAN_TARGET_OS_IS_ANDROID)
  #include <elf.h>
  extern "C" char **environ;
#endif

#if defined(BOTAN_TARGET_OS_IS_IOS) || defined(BOTAN_TARGET_OS_IS_MACOS)
  #include <sys/types.h>
  #include <sys/sysctl.h>
  #include <mach/vm_statistics.h>
#endif

#if defined(BOTAN_TARGET_OS_HAS_PRCTL)
  #include <sys/prctl.h>
  #if !defined(PR_SET_VMA)
    #define PR_SET_VMA 0x53564d41
    #define PR_SET_VMA_ANON_NAME 0
  #endif
#endif

namespace Botan {

// Not defined in OS namespace for historical reasons
void secure_scrub_memory(void* ptr, size_t n)
   {
#if defined(BOTAN_TARGET_OS_HAS_RTLSECUREZEROMEMORY)
   ::RtlSecureZeroMemory(ptr, n);

#elif defined(BOTAN_TARGET_OS_HAS_EXPLICIT_BZERO)
   ::explicit_bzero(ptr, n);

#elif defined(BOTAN_TARGET_OS_HAS_EXPLICIT_MEMSET)
   (void)::explicit_memset(ptr, 0, n);

#elif defined(BOTAN_USE_VOLATILE_MEMSET_FOR_ZERO) && (BOTAN_USE_VOLATILE_MEMSET_FOR_ZERO == 1)
   /*
   Call memset through a static volatile pointer, which the compiler
   should not elide. This construct should be safe in conforming
   compilers, but who knows. I did confirm that on x86-64 GCC 6.1 and
   Clang 3.8 both create code that saves the memset address in the
   data segment and unconditionally loads and jumps to that address.
   */
   static void* (*const volatile memset_ptr)(void*, int, size_t) = std::memset;
   (memset_ptr)(ptr, 0, n);
#else

   volatile uint8_t* p = reinterpret_cast<volatile uint8_t*>(ptr);

   for(size_t i = 0; i != n; ++i)
      p[i] = 0;
#endif
   }

uint32_t OS::get_process_id()
   {
#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
   return ::getpid();
#elif defined(BOTAN_TARGET_OS_HAS_WIN32)
   return ::GetCurrentProcessId();
#elif defined(BOTAN_TARGET_OS_IS_INCLUDEOS) || defined(BOTAN_TARGET_OS_IS_LLVM) || defined(BOTAN_TARGET_OS_IS_NONE)
   return 0; // truly no meaningful value
#else
   #error "Missing get_process_id"
#endif
   }

size_t OS::get_cache_line_size()
   {
#if defined(BOTAN_TARGET_OS_IS_IOS) || defined(BOTAN_TARGET_OS_IS_MACOS)
   unsigned long cache_line_size_vl;
   size_t size = sizeof(cache_line_size_vl);
   if(::sysctlbyname("hw.cachelinesize", &cache_line_size_vl, &size, nullptr, 0) == 0)
      return static_cast<size_t>(cache_line_size_vl);
#endif

#if defined(BOTAN_TARGET_OS_HAS_POSIX1) && defined(_SC_LEVEL1_DCACHE_LINESIZE)
   const long res = ::sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
   if(res > 0)
      return static_cast<size_t>(res);
#endif

#if defined(BOTAN_TARGET_OS_HAS_GETAUXVAL)

   #if defined(AT_L1D_CACHEGEOMETRY)
   // Cache line size is bottom 16 bits
   const unsigned long dcache_info = OS::get_auxval(AT_L1D_CACHEGEOMETRY);
   if(dcache_info != 0)
      return static_cast<size_t>(dcache_info & 0xFFFF);
   #endif

   #if defined(AT_DCACHEBSIZE)
   const unsigned long dcache_bsize = OS::get_auxval(AT_DCACHEBSIZE);
   if(dcache_bsize != 0)
      return static_cast<size_t>(dcache_bsize);
   #endif

#endif

   // TODO: on Windows this is returned by GetLogicalProcessorInformation

   // not available on this platform
   return 0;
   }

unsigned long OS::get_auxval(unsigned long id)
   {
#if defined(BOTAN_TARGET_OS_HAS_GETAUXVAL)
   return ::getauxval(id);
#elif defined(BOTAN_TARGET_OS_IS_ANDROID) && defined(BOTAN_TARGET_ARCH_IS_ARM32)

   if(id == 0)
      return 0;

   char **p = environ;

   while(*p++ != nullptr)
      ;

   Elf32_auxv_t *e = reinterpret_cast<Elf32_auxv_t*>(p);

   while(e != nullptr)
      {
      if(e->a_type == id)
         return e->a_un.a_val;
      e++;
      }

   return 0;
#elif defined(BOTAN_TARGET_OS_HAS_ELF_AUX_INFO)
   unsigned long auxinfo = 0;
   ::elf_aux_info(static_cast<int>(id), &auxinfo, sizeof(auxinfo));
   return auxinfo;
#elif defined(BOTAN_TARGET_OS_HAS_AUXINFO)
   for (const AuxInfo *auxinfo = static_cast<AuxInfo *>(::_dlauxinfo()); auxinfo != AT_NULL; ++auxinfo)
      {
      if (id == auxinfo->a_type)
          return auxinfo->a_v;
      }

   return 0;
#else
   BOTAN_UNUSED(id);
   return 0;
#endif
   }

bool OS::running_in_privileged_state()
   {
#if defined(AT_SECURE)
   return OS::get_auxval(AT_SECURE) != 0;
#elif defined(BOTAN_TARGET_OS_HAS_POSIX1)
   return (::getuid() != ::geteuid()) || (::getgid() != ::getegid());
#else
   return false;
#endif
   }

uint64_t OS::get_cpu_cycle_counter()
   {
   uint64_t rtc = 0;

#if defined(BOTAN_TARGET_OS_HAS_WIN32)
   LARGE_INTEGER tv;
   ::QueryPerformanceCounter(&tv);
   rtc = tv.QuadPart;

#elif defined(BOTAN_USE_GCC_INLINE_ASM)

#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)

   if(CPUID::has_rdtsc())
      {
      uint32_t rtc_low = 0, rtc_high = 0;
      asm volatile("rdtsc" : "=d" (rtc_high), "=a" (rtc_low));
      rtc = (static_cast<uint64_t>(rtc_high) << 32) | rtc_low;
      }

#elif defined(BOTAN_TARGET_ARCH_IS_PPC64)

   for(;;)
      {
      uint32_t rtc_low = 0, rtc_high = 0, rtc_high2 = 0;
      asm volatile("mftbu %0" : "=r" (rtc_high));
      asm volatile("mftb %0" : "=r" (rtc_low));
      asm volatile("mftbu %0" : "=r" (rtc_high2));

      if(rtc_high == rtc_high2)
         {
         rtc = (static_cast<uint64_t>(rtc_high) << 32) | rtc_low;
         break;
         }
      }

#elif defined(BOTAN_TARGET_ARCH_IS_ALPHA)
   asm volatile("rpcc %0" : "=r" (rtc));

   // OpenBSD does not trap access to the %tick register
#elif defined(BOTAN_TARGET_ARCH_IS_SPARC64) && !defined(BOTAN_TARGET_OS_IS_OPENBSD)
   asm volatile("rd %%tick, %0" : "=r" (rtc));

#elif defined(BOTAN_TARGET_ARCH_IS_IA64)
   asm volatile("mov %0=ar.itc" : "=r" (rtc));

#elif defined(BOTAN_TARGET_ARCH_IS_S390X)
   asm volatile("stck 0(%0)" : : "a" (&rtc) : "memory", "cc");

#elif defined(BOTAN_TARGET_ARCH_IS_HPPA)
   asm volatile("mfctl 16,%0" : "=r" (rtc)); // 64-bit only?

#else
   //#warning "OS::get_cpu_cycle_counter not implemented"
#endif

#endif

   return rtc;
   }

size_t OS::get_cpu_available()
   {
#if defined(BOTAN_TARGET_OS_HAS_POSIX1)

#if defined(_SC_NPROCESSORS_ONLN)
   const long cpu_online = ::sysconf(_SC_NPROCESSORS_ONLN);
   if(cpu_online > 0)
      return static_cast<size_t>(cpu_online);
#endif

#if defined(_SC_NPROCESSORS_CONF)
   const long cpu_conf = ::sysconf(_SC_NPROCESSORS_CONF);
   if(cpu_conf > 0)
      return static_cast<size_t>(cpu_conf);
#endif

#endif

#if defined(BOTAN_TARGET_OS_HAS_THREADS)
   // hardware_concurrency is allowed to return 0 if the value is not
   // well defined or not computable.
   const size_t hw_concur = std::thread::hardware_concurrency();

   if(hw_concur > 0)
      return hw_concur;
#endif

   return 1;
   }

uint64_t OS::get_high_resolution_clock()
   {
   if(uint64_t cpu_clock = OS::get_cpu_cycle_counter())
      return cpu_clock;

#if defined(BOTAN_TARGET_OS_IS_EMSCRIPTEN)
   return emscripten_get_now();
#endif

   /*
   If we got here either we either don't have an asm instruction
   above, or (for x86) RDTSC is not available at runtime. Try some
   clock_gettimes and return the first one that works, or otherwise
   fall back to std::chrono.
   */

#if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME)

   // The ordering here is somewhat arbitrary...
   const clockid_t clock_types[] = {
#if defined(CLOCK_MONOTONIC_HR)
      CLOCK_MONOTONIC_HR,
#endif
#if defined(CLOCK_MONOTONIC_RAW)
      CLOCK_MONOTONIC_RAW,
#endif
#if defined(CLOCK_MONOTONIC)
      CLOCK_MONOTONIC,
#endif
#if defined(CLOCK_PROCESS_CPUTIME_ID)
      CLOCK_PROCESS_CPUTIME_ID,
#endif
#if defined(CLOCK_THREAD_CPUTIME_ID)
      CLOCK_THREAD_CPUTIME_ID,
#endif
   };

   for(clockid_t clock : clock_types)
      {
      struct timespec ts;
      if(::clock_gettime(clock, &ts) == 0)
         {
         return (static_cast<uint64_t>(ts.tv_sec) * 1000000000) + static_cast<uint64_t>(ts.tv_nsec);
         }
      }
#endif

   // Plain C++11 fallback
   auto now = std::chrono::high_resolution_clock::now().time_since_epoch();
   return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
   }

uint64_t OS::get_system_timestamp_ns()
   {
#if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME)
   struct timespec ts;
   if(::clock_gettime(CLOCK_REALTIME, &ts) == 0)
      {
      return (static_cast<uint64_t>(ts.tv_sec) * 1000000000) + static_cast<uint64_t>(ts.tv_nsec);
      }
#endif

   auto now = std::chrono::system_clock::now().time_since_epoch();
   return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
   }

size_t OS::system_page_size()
   {
   const size_t default_page_size = 4096;

#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
   long p = ::sysconf(_SC_PAGESIZE);
   if(p > 1)
      return static_cast<size_t>(p);
   else
      return default_page_size;
#elif defined(BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK)
   BOTAN_UNUSED(default_page_size);
   SYSTEM_INFO sys_info;
   ::GetSystemInfo(&sys_info);
   return sys_info.dwPageSize;
#else
   return default_page_size;
#endif
   }

size_t OS::get_memory_locking_limit()
   {
#if defined(BOTAN_TARGET_OS_HAS_POSIX1) && defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK) && defined(RLIMIT_MEMLOCK)
   /*
   * If RLIMIT_MEMLOCK is not defined, likely the OS does not support
   * unprivileged mlock calls.
   *
   * Linux defaults to only 64 KiB of mlockable memory per process
   * (too small) but BSDs offer a small fraction of total RAM (more
   * than we need). Bound the total mlock size to 512 KiB which is
   * enough to run the entire test suite without spilling to non-mlock
   * memory (and thus presumably also enough for many useful
   * programs), but small enough that we should not cause problems
   * even if many processes are mlocking on the same machine.
   */
   const size_t user_req = read_env_variable_sz("BOTAN_MLOCK_POOL_SIZE", BOTAN_MLOCK_ALLOCATOR_MAX_LOCKED_KB);

   const size_t mlock_requested = std::min<size_t>(user_req, BOTAN_MLOCK_ALLOCATOR_MAX_LOCKED_KB);

   if(mlock_requested > 0)
      {
      struct ::rlimit limits;

      ::getrlimit(RLIMIT_MEMLOCK, &limits);

      if(limits.rlim_cur < limits.rlim_max)
         {
         limits.rlim_cur = limits.rlim_max;
         ::setrlimit(RLIMIT_MEMLOCK, &limits);
         ::getrlimit(RLIMIT_MEMLOCK, &limits);
         }

      return std::min<size_t>(limits.rlim_cur, mlock_requested * 1024);
      }

#elif defined(BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK)
   SIZE_T working_min = 0, working_max = 0;
   if(!::GetProcessWorkingSetSize(::GetCurrentProcess(), &working_min, &working_max))
      {
      return 0;
      }

   // According to Microsoft MSDN:
   // The maximum number of pages that a process can lock is equal to the number of pages in its minimum working set minus a small overhead
   // In the book "Windows Internals Part 2": the maximum lockable pages are minimum working set size - 8 pages
   // But the information in the book seems to be inaccurate/outdated
   // I've tested this on Windows 8.1 x64, Windows 10 x64 and Windows 7 x86
   // On all three OS the value is 11 instead of 8
   const size_t overhead = OS::system_page_size() * 11;
   if(working_min > overhead)
      {
      const size_t lockable_bytes = working_min - overhead;
      return std::min<size_t>(lockable_bytes, BOTAN_MLOCK_ALLOCATOR_MAX_LOCKED_KB * 1024);
      }
#endif

   // Not supported on this platform
   return 0;
   }

bool OS::read_env_variable(std::string& value_out, const std::string& name)
   {
   value_out = "";

   if(running_in_privileged_state())
      return false;

#if defined(BOTAN_TARGET_OS_HAS_WIN32) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
   char val[128] = { 0 };
   size_t req_size = 0;
   if(getenv_s(&req_size, val, sizeof(val), name.c_str()) == 0)
      {
      value_out = std::string(val, req_size);
      return true;
      }
#else
   if(const char* val = std::getenv(name.c_str()))
      {
      value_out = val;
      return true;
      }
#endif

   return false;
   }

size_t OS::read_env_variable_sz(const std::string& name, size_t def)
   {
   std::string value;
   if(read_env_variable(value, name))
      {
      try
         {
         const size_t val = std::stoul(value, nullptr);
         return val;
         }
      catch(std::exception&) { /* ignore it */ }
      }

   return def;
   }

#if defined(BOTAN_TARGET_OS_HAS_POSIX1) && defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)

namespace {

int get_locked_fd()
   {
#if defined(BOTAN_TARGET_OS_IS_IOS) || defined(BOTAN_TARGET_OS_IS_MACOS)
   // On Darwin, tagging anonymous pages allows vmmap to track these.
   // Allowed from 240 to 255 for userland applications
   static constexpr int default_locked_fd = 255;
   int locked_fd = default_locked_fd;

   if(size_t locked_fdl = OS::read_env_variable_sz("BOTAN_LOCKED_FD", default_locked_fd))
      {
      if(locked_fdl < 240 || locked_fdl > 255)
         {
         locked_fdl = default_locked_fd;
         }
      locked_fd = static_cast<int>(locked_fdl);
      }
   return VM_MAKE_TAG(locked_fd);
#else
   return -1;
#endif
   }

}

#endif

std::vector<void*> OS::allocate_locked_pages(size_t count)
   {
   std::vector<void*> result;

#if (defined(BOTAN_TARGET_OS_HAS_POSIX1) && defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)) || defined(BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK)

   result.reserve(count);

   const size_t page_size = OS::system_page_size();

#if defined(BOTAN_TARGET_OS_HAS_POSIX1) && defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
   static const int locked_fd = get_locked_fd();
#endif

   for(size_t i = 0; i != count; ++i)
      {
      void* ptr = nullptr;

#if defined(BOTAN_TARGET_OS_HAS_POSIX1) && defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)

#if !defined(MAP_ANONYMOUS)
   #define MAP_ANONYMOUS MAP_ANON
#endif

#if !defined(MAP_NOCORE)
#if defined(MAP_CONCEAL)
   #define MAP_NOCORE MAP_CONCEAL
#else
   #define MAP_NOCORE 0
#endif
#endif

#if !defined(PROT_MAX)
   #define PROT_MAX(p) 0
#endif
      const int pflags = PROT_READ | PROT_WRITE;

      ptr = ::mmap(nullptr, 3*page_size,
                   pflags | PROT_MAX(pflags),
                   MAP_ANONYMOUS | MAP_PRIVATE | MAP_NOCORE,
                   /*fd=*/locked_fd, /*offset=*/0);

      if(ptr == MAP_FAILED)
         {
         continue;
         }

      // lock the data page
      if(::mlock(static_cast<uint8_t*>(ptr) + page_size, page_size) != 0)
         {
         ::munmap(ptr, 3*page_size);
         continue;
         }

#if defined(MADV_DONTDUMP)
      // we ignore errors here, as DONTDUMP is just a bonus
      ::madvise(static_cast<uint8_t*>(ptr) + page_size, page_size, MADV_DONTDUMP);
#endif

#elif defined(BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK)
      ptr = ::VirtualAlloc(nullptr, 3*page_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

      if(ptr == nullptr)
         continue;

      if(::VirtualLock(static_cast<uint8_t*>(ptr) + page_size, page_size) == 0)
         {
         ::VirtualFree(ptr, 0, MEM_RELEASE);
         continue;
         }
#endif

      std::memset(ptr, 0, 3*page_size); // zero data page and both guard pages

      // Attempts to name the data page
      page_named(ptr, 3*page_size);
      // Make guard page preceeding the data page
      page_prohibit_access(static_cast<uint8_t*>(ptr));
      // Make guard page following the data page
      page_prohibit_access(static_cast<uint8_t*>(ptr) + 2*page_size);

      result.push_back(static_cast<uint8_t*>(ptr) + page_size);
      }
#else
   BOTAN_UNUSED(count);
#endif

   return result;
   }

void OS::page_allow_access(void* page)
   {
#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
   const size_t page_size = OS::system_page_size();
   ::mprotect(page, page_size, PROT_READ | PROT_WRITE);
#elif defined(BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK)
   const size_t page_size = OS::system_page_size();
   DWORD old_perms = 0;
   ::VirtualProtect(page, page_size, PAGE_READWRITE, &old_perms);
   BOTAN_UNUSED(old_perms);
#else
   BOTAN_UNUSED(page);
#endif
   }

void OS::page_prohibit_access(void* page)
   {
#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
   const size_t page_size = OS::system_page_size();
   ::mprotect(page, page_size, PROT_NONE);
#elif defined(BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK)
   const size_t page_size = OS::system_page_size();
   DWORD old_perms = 0;
   ::VirtualProtect(page, page_size, PAGE_NOACCESS, &old_perms);
   BOTAN_UNUSED(old_perms);
#else
   BOTAN_UNUSED(page);
#endif
   }

void OS::free_locked_pages(const std::vector<void*>& pages)
   {
   const size_t page_size = OS::system_page_size();

   for(size_t i = 0; i != pages.size(); ++i)
      {
      void* ptr = pages[i];

      secure_scrub_memory(ptr, page_size);

      // ptr points to the data page, guard pages are before and after
      page_allow_access(static_cast<uint8_t*>(ptr) - page_size);
      page_allow_access(static_cast<uint8_t*>(ptr) + page_size);

#if defined(BOTAN_TARGET_OS_HAS_POSIX1) && defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
      ::munlock(ptr, page_size);
      ::munmap(static_cast<uint8_t*>(ptr) - page_size, 3*page_size);
#elif defined(BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK)
      ::VirtualUnlock(ptr, page_size);
      ::VirtualFree(static_cast<uint8_t*>(ptr) - page_size, 0, MEM_RELEASE);
#endif
      }
   }

void OS::page_named(void* page, size_t size)
   {
#if defined(BOTAN_TARGET_OS_HAS_PRCTL)
   static constexpr char name[] = "Botan mlock pool";
   int r = prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, reinterpret_cast<uintptr_t>(page), size, name);
   BOTAN_UNUSED(r);
#else
   BOTAN_UNUSED(page, size);
#endif
   }

#if defined(BOTAN_TARGET_OS_HAS_POSIX1) && !defined(BOTAN_TARGET_OS_IS_EMSCRIPTEN)

namespace {

::sigjmp_buf g_sigill_jmp_buf;

void botan_sigill_handler(int /*unused*/)
   {
   siglongjmp(g_sigill_jmp_buf, /*non-zero return value*/1);
   }

}

#endif

int OS::run_cpu_instruction_probe(const std::function<int ()>& probe_fn)
   {
   volatile int probe_result = -3;

#if defined(BOTAN_TARGET_OS_HAS_POSIX1) && !defined(BOTAN_TARGET_OS_IS_EMSCRIPTEN)
   struct sigaction old_sigaction;
   struct sigaction sigaction;

   sigaction.sa_handler = botan_sigill_handler;
   sigemptyset(&sigaction.sa_mask);
   sigaction.sa_flags = 0;

   int rc = ::sigaction(SIGILL, &sigaction, &old_sigaction);

   if(rc != 0)
      throw System_Error("run_cpu_instruction_probe sigaction failed", errno);

   rc = sigsetjmp(g_sigill_jmp_buf, /*save sigs*/1);

   if(rc == 0)
      {
      // first call to sigsetjmp
      probe_result = probe_fn();
      }
   else if(rc == 1)
      {
      // non-local return from siglongjmp in signal handler: return error
      probe_result = -1;
      }

   // Restore old SIGILL handler, if any
   rc = ::sigaction(SIGILL, &old_sigaction, nullptr);
   if(rc != 0)
      throw System_Error("run_cpu_instruction_probe sigaction restore failed", errno);

#else
   BOTAN_UNUSED(probe_fn);
#endif

   return probe_result;
   }

std::unique_ptr<OS::Echo_Suppression> OS::suppress_echo_on_terminal()
   {
#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
   class POSIX_Echo_Suppression : public Echo_Suppression
      {
      public:
         POSIX_Echo_Suppression()
            {
            m_stdin_fd = fileno(stdin);
            if(::tcgetattr(m_stdin_fd, &m_old_termios) != 0)
               throw System_Error("Getting terminal status failed", errno);

            struct termios noecho_flags = m_old_termios;
            noecho_flags.c_lflag &= ~ECHO;
            noecho_flags.c_lflag |= ECHONL;

            if(::tcsetattr(m_stdin_fd, TCSANOW, &noecho_flags) != 0)
               throw System_Error("Clearing terminal echo bit failed", errno);
            }

         void reenable_echo() override
            {
            if(m_stdin_fd > 0)
               {
               if(::tcsetattr(m_stdin_fd, TCSANOW, &m_old_termios) != 0)
                  throw System_Error("Restoring terminal echo bit failed", errno);
               m_stdin_fd = -1;
               }
            }

         ~POSIX_Echo_Suppression() override
            {
            try
               {
               reenable_echo();
               }
            catch(...)
               {
               }
            }

         POSIX_Echo_Suppression(const POSIX_Echo_Suppression& other) = delete;
         POSIX_Echo_Suppression(POSIX_Echo_Suppression&& other) = delete;
         POSIX_Echo_Suppression& operator=(const POSIX_Echo_Suppression& other) = delete;
         POSIX_Echo_Suppression& operator=(POSIX_Echo_Suppression&& other) = delete;

      private:
         int m_stdin_fd;
         struct termios m_old_termios;
      };

   return std::make_unique<POSIX_Echo_Suppression>();

#elif defined(BOTAN_TARGET_OS_HAS_WIN32)

   class Win32_Echo_Suppression : public Echo_Suppression
      {
      public:
         Win32_Echo_Suppression()
            {
            m_input_handle = ::GetStdHandle(STD_INPUT_HANDLE);
            if(::GetConsoleMode(m_input_handle, &m_console_state) == 0)
               throw System_Error("Getting console mode failed", ::GetLastError());

            DWORD new_mode = ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
            if(::SetConsoleMode(m_input_handle, new_mode) == 0)
               throw System_Error("Setting console mode failed", ::GetLastError());
            }

         void reenable_echo() override
            {
            if(m_input_handle != INVALID_HANDLE_VALUE)
               {
               if(::SetConsoleMode(m_input_handle, m_console_state) == 0)
                  throw System_Error("Setting console mode failed", ::GetLastError());
               m_input_handle = INVALID_HANDLE_VALUE;
               }
            }

         ~Win32_Echo_Suppression() override
            {
            try
               {
               reenable_echo();
               }
            catch(...)
               {
               }
            }

         Win32_Echo_Suppression(const Win32_Echo_Suppression& other) = delete;
         Win32_Echo_Suppression(Win32_Echo_Suppression&& other) = delete;
         Win32_Echo_Suppression& operator=(const Win32_Echo_Suppression& other) = delete;
         Win32_Echo_Suppression& operator=(Win32_Echo_Suppression&& other) = delete;

      private:
         HANDLE m_input_handle;
         DWORD m_console_state;
      };

   return std::make_unique<Win32_Echo_Suppression>();

#else

   // Not supported on this platform, return null
   return nullptr;
#endif
   }

}


text:
ACCEPTED

#### According to
Index Fungorum

#### Published in
Geophytology 16(2): 261 (1987)

#### Original name
Pleurotheliopsis andamanensis Ajay Singh & Upreti

### Remarks
null