# Path: symsynd/exceptions.py
# class SymbolicationError(Exception):
#     message = None
# 
#     def __init__(self, message):
#         if isinstance(message, bytes):
#             message = message.decode('utf-8', 'replace')
#         Exception.__init__(self, message)
#         self.message = message
# 
#     def __str__(self):
#         return self.message.encode('utf-8')
# 
#     def __unicode__(self):
#         return self.message
# 
# Path: symsynd/libdebug.py
# class DebugInfo(object):
# 
#     def __init__(self):
#         raise TypeError('Cannot instanciate debug infos')
# 
#     @staticmethod
#     def _from_ptr(ptr):
#         rv = object.__new__(DebugInfo)
#         rv._ptr = ptr
#         return rv
# 
#     @staticmethod
#     def open_path(path):
#         di = rustcall(_lib.debug_info_open_path, to_bytes(path))
#         return DebugInfo._from_ptr(di)
# 
#     def _get_ptr(self):
#         if self._ptr is None:
#             raise RuntimeError('Debug info closed')
#         return self._ptr
# 
#     def get_compilation_dir(self, cpu_name, path):
#         ptr = self._get_ptr()
# 
#         try:
#             rv = rustcall(_lib.debug_info_get_compilation_dir,
#                           ptr, to_bytes(cpu_name), to_bytes(path))
#             rv = _ffi.string(rv)
#             if isinstance(path, text_type):
#                 rv = rv.decode('utf-8')
#             return rv
#         except exceptions.DwarfLookupError:
#             pass
# 
#     def get_variants(self):
#         ptr = self._get_ptr()
#         count = _ffi.new('int *')
#         arr = rustcall(_lib.debug_info_get_variants, ptr, count)
#         return [Variant(arr[x]) for x in range(count[0])]
# 
#     def get_variant(self, uuid_or_cpu_name):
#         if isinstance(uuid_or_cpu_name, uuid.UUID):
#             id = uuid_or_cpu_name
#             cpu_name = None
#         else:
#             try:
#                 id = uuid.UUID(uuid_or_cpu_name)
#                 cpu_name = None
#             except ValueError:
#                 id = None
#                 cpu_name = uuid_or_cpu_name
#         for variant in self.get_variants():
#             if (id is not None and variant.uuid == id) or \
#                (cpu_name is not None and variant.cpu_name == cpu_name):
#                 return variant
# 
#     def close(self):
#         if self._ptr:
#             _lib.debug_info_free(self._ptr)
#         self._ptr = None
# 
#     def __del__(self):
#         try:
#             self.close()
#         except Exception:
#             pass
# 
# Path: symsynd/_compat.py
# PY2 = sys.version_info[0] == 2
# def to_bytes(x):


import os
import posixpath
from threading import Lock
from symsynd.exceptions import SymbolicationError
from symsynd.libdebug import DebugInfo
from symsynd._symbolizer import ffi
from symsynd._compat import to_bytes, itervalues

def _symstr(ptr):
    if ptr == ffi.NULL:
        return None
    val = ffi.string(ptr)
    if val == '<invalid>':
        return None
    return val.decode('utf-8', 'replace')


class Symbolizer(object):

    def __init__(self):
        _init_lib()
        self._ptr = lib.llvm_symbolizer_new()
        self._debug_infos = {}

    def close(self):
        if self._ptr is not None:
            lib.llvm_symbolizer_free(self._ptr)
            self._ptr = None
        if self._debug_infos:
            for di in itervalues(self._debug_infos):
                di.close()
            self._debug_infos.clear()

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, tb):

# Path: symsynd/exceptions.py
# class SymbolicationError(Exception):
#     message = None
# 
#     def __init__(self, message):
#         if isinstance(message, bytes):
#             message = message.decode('utf-8', 'replace')
#         Exception.__init__(self, message)
#         self.message = message
# 
#     def __str__(self):
#         return self.message.encode('utf-8')
# 
#     def __unicode__(self):
#         return self.message
# 
# Path: symsynd/libdebug.py
# class DebugInfo(object):
# 
#     def __init__(self):
#         raise TypeError('Cannot instanciate debug infos')
# 
#     @staticmethod
#     def _from_ptr(ptr):
#         rv = object.__new__(DebugInfo)
#         rv._ptr = ptr
#         return rv
# 
#     @staticmethod
#     def open_path(path):
#         di = rustcall(_lib.debug_info_open_path, to_bytes(path))
#         return DebugInfo._from_ptr(di)
# 
#     def _get_ptr(self):
#         if self._ptr is None:
#             raise RuntimeError('Debug info closed')
#         return self._ptr
# 
#     def get_compilation_dir(self, cpu_name, path):
#         ptr = self._get_ptr()
# 
#         try:
#             rv = rustcall(_lib.debug_info_get_compilation_dir,
#                           ptr, to_bytes(cpu_name), to_bytes(path))
#             rv = _ffi.string(rv)
#             if isinstance(path, text_type):
#                 rv = rv.decode('utf-8')
#             return rv
#         except exceptions.DwarfLookupError:
#             pass
# 
#     def get_variants(self):
#         ptr = self._get_ptr()
#         count = _ffi.new('int *')
#         arr = rustcall(_lib.debug_info_get_variants, ptr, count)
#         return [Variant(arr[x]) for x in range(count[0])]
# 
#     def get_variant(self, uuid_or_cpu_name):
#         if isinstance(uuid_or_cpu_name, uuid.UUID):
#             id = uuid_or_cpu_name
#             cpu_name = None
#         else:
#             try:
#                 id = uuid.UUID(uuid_or_cpu_name)
#                 cpu_name = None
#             except ValueError:
#                 id = None
#                 cpu_name = uuid_or_cpu_name
#         for variant in self.get_variants():
#             if (id is not None and variant.uuid == id) or \
#                (cpu_name is not None and variant.cpu_name == cpu_name):
#                 return variant
# 
#     def close(self):
#         if self._ptr:
#             _lib.debug_info_free(self._ptr)
#         self._ptr = None
# 
#     def __del__(self):
#         try:
#             self.close()
#         except Exception:
#             pass
# 
# Path: symsynd/_compat.py
# PY2 = sys.version_info[0] == 2
# def to_bytes(x):


# Path: symsynd/libsymbolizer.py
import os
import posixpath
from threading import Lock
from symsynd.exceptions import SymbolicationError
from symsynd.libdebug import DebugInfo
from symsynd._symbolizer import ffi
from symsynd._compat import to_bytes, itervalues


def _symstr(ptr):
    if ptr == ffi.NULL:
        return None
    val = ffi.string(ptr)
    if val == '<invalid>':
        return None
    return val.decode('utf-8', 'replace')


class Symbolizer(object):

    def __init__(self):
        _init_lib()
        self._ptr = lib.llvm_symbolizer_new()
        self._debug_infos = {}

    def close(self):
        if self._ptr is not None:
            lib.llvm_symbolizer_free(self._ptr)
            self._ptr = None
        if self._debug_infos:
            for di in itervalues(self._debug_infos):
                di.close()
            self._debug_infos.clear()

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, tb):

        self.close()