text:
from __future__ import print_function
import os, sys
from ctypes import *
from ctypes.util import find_library

# load libc to access free, etc.
libcpath = find_library("c")
if not libcpath:
    raise ImportError("Unable to find libc")
libc = cdll.LoadLibrary(libcpath)
libc.free.argtypes = [c_void_p]
libc.free.restype = None

def return_fresh_string(char_p):
    s = string_at(char_p)
    libc.free(char_p)
    return s

# czmq
try:
    # If LD_LIBRARY_PATH or your OSs equivalent is set, this is the only way to
    # load the library.  If we use find_library below, we get the wrong result.
    if os.name == 'posix':
        if sys.platform == 'darwin':
            lib = cdll.LoadLibrary('libczmq.3.dylib')
        else:
            lib = cdll.LoadLibrary("libczmq.so.3")
    elif os.name == 'nt':
        lib = cdll.LoadLibrary('libczmq.dll')
except OSError:
    libpath = find_library("czmq")
    if not libpath:
        raise ImportError("Unable to find libczmq")
    lib = cdll.LoadLibrary(libpath)

class zsock_t(Structure):
    pass # Empty - only for type checking
zsock_p = POINTER(zsock_t)

class zactor_t(Structure):
    pass # Empty - only for type checking
zactor_p = POINTER(zactor_t)

class zmsg_t(Structure):
    pass # Empty - only for type checking
zmsg_p = POINTER(zmsg_t)

class zdir_t(Structure):
    pass # Empty - only for type checking
zdir_p = POINTER(zdir_t)

class zlist_t(Structure):
    pass # Empty - only for type checking
zlist_p = POINTER(zlist_t)

class zhash_t(Structure):
    pass # Empty - only for type checking
zhash_p = POINTER(zhash_t)

class FILE(Structure):
    pass # Empty - only for type checking
FILE_p = POINTER(FILE)

class zfile_t(Structure):
    pass # Empty - only for type checking
zfile_p = POINTER(zfile_t)

class zdir_patch_t(Structure):
    pass # Empty - only for type checking
zdir_patch_p = POINTER(zdir_patch_t)

class zchunk_t(Structure):
    pass # Empty - only for type checking
zchunk_p = POINTER(zchunk_t)

class zframe_t(Structure):
    pass # Empty - only for type checking
zframe_p = POINTER(zframe_t)

class zhashx_t(Structure):
    pass # Empty - only for type checking
zhashx_p = POINTER(zhashx_t)

class zlistx_t(Structure):
    pass # Empty - only for type checking
zlistx_p = POINTER(zlistx_t)

class ziflist_t(Structure):
    pass # Empty - only for type checking
ziflist_p = POINTER(ziflist_t)

class zloop_t(Structure):
    pass # Empty - only for type checking
zloop_p = POINTER(zloop_t)

class zmq_pollitem_t(Structure):
    pass # Empty - only for type checking
zmq_pollitem_p = POINTER(zmq_pollitem_t)

class zpoller_t(Structure):
    pass # Empty - only for type checking
zpoller_p = POINTER(zpoller_t)

class va_list_t(Structure):
    pass # Empty - only for type checking
va_list_p = POINTER(va_list_t)

class char_t(Structure):
    pass # Empty - only for type checking
char_p = POINTER(char_t)

class ztrie_t(Structure):
    pass # Empty - only for type checking
ztrie_p = POINTER(ztrie_t)

class zuuid_t(Structure):
    pass # Empty - only for type checking
zuuid_p = POINTER(zuuid_t)

PyFile_FromFile_close_cb = CFUNCTYPE(c_int, FILE_p)
PyFile_FromFile = pythonapi.PyFile_FromFile
PyFile_FromFile.restype = py_object
PyFile_FromFile.argtypes = [FILE_p,
                            c_char_p,
                            c_char_p,
                            PyFile_FromFile_close_cb]
def return_py_file(c_file):
    return PyFile_FromFile(c_file, "", "r+", PyFile_FromFile_close_cb())

PyFile_AsFile = pythonapi.PyFile_AsFile
PyFile_AsFile.restype = FILE_p
PyFile_AsFile.argtypes = [py_object]
def coerce_py_file(obj):
    if isinstance(obj, FILE_p):
        return obj
    else:
        return PyFile_AsFile(obj)

# zactor
zactor_fn = CFUNCTYPE(None, zsock_p, c_void_p)
lib.zactor_new.restype = zactor_p
lib.zactor_new.argtypes = [zactor_fn, c_void_p]
lib.zactor_destroy.restype = None
lib.zactor_destroy.argtypes = [POINTER(zactor_p)]
lib.zactor_send.restype = c_int
lib.zactor_send.argtypes = [zactor_p, POINTER(zmsg_p)]
lib.zactor_recv.restype = zmsg_p
lib.zactor_recv.argtypes = [zactor_p]
lib.zactor_is.restype = c_bool
lib.zactor_is.argtypes = [c_void_p]
lib.zactor_resolve.restype = c_void_p
lib.zactor_resolve.argtypes = [c_void_p]
lib.zactor_sock.restype = zsock_p
lib.zactor_sock.argtypes = [zactor_p]
lib.zactor_test.restype = None
lib.zactor_test.argtypes = [c_bool]

class Zactor(object):
    """actor"""

    def __init__(self, *args):
        """Create a new actor passing arbitrary arguments reference."""
        if len(args) == 2 and type(args[0]) is c_void_p and isinstance(args[1], bool):
            self._as_parameter_ = cast(args[0], zactor_p) # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        elif len(args) == 2 and type(args[0]) is zactor_p and isinstance(args[1], bool):
            self._as_parameter_ = args[0] # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        else:
            assert(len(args) == 2)
            self._as_parameter_ = lib.zactor_new(args[0], args[1]) # Creation of new raw type
            self.allow_destruct = True

    def __del__(self):
        """Destroy an actor."""
        if self.allow_destruct:
            lib.zactor_destroy(byref(self._as_parameter_))

    def __bool__(self):
        "Determine whether the object is valid by converting to boolean" # Python 3
        return self._as_parameter_.__bool__()

    def __nonzero__(self):
        "Determine whether the object is valid by converting to boolean" # Python 2
        return self._as_parameter_.__nonzero__()

    def send(self, msg_p):
        """Send a zmsg message to the actor, take ownership of the message
and destroy when it has been sent."""
        return lib.zactor_send(self._as_parameter_, byref(zmsg_p.from_param(msg_p)))

    def recv(self):
        """Receive a zmsg message from the actor. Returns NULL if the actor
was interrupted before the message could be received, or if there
was a timeout on the actor."""
        return Zmsg(lib.zactor_recv(self._as_parameter_), True)

    @staticmethod
    def is_(self):
        """Probe the supplied object, and report if it looks like a zactor_t."""
        return lib.zactor_is(self)

    @staticmethod
    def resolve(self):
        """Probe the supplied reference. If it looks like a zactor_t instance,
return the underlying libzmq actor handle; else if it looks like
a libzmq actor handle, return the supplied value."""
        return c_void_p(lib.zactor_resolve(self))

    def sock(self):
        """Return the actor's zsock handle. Use this when you absolutely need
to work with the zsock instance rather than the actor."""
        return Zsock(lib.zactor_sock(self._as_parameter_), False)

    @staticmethod
    def test(verbose):
        """Self test of this class."""
        return lib.zactor_test(verbose)

# zdir
lib.zdir_new.restype = zdir_p
lib.zdir_new.argtypes = [c_char_p, c_char_p]
lib.zdir_destroy.restype = None
lib.zdir_destroy.argtypes = [POINTER(zdir_p)]
lib.zdir_path.restype = c_char_p
lib.zdir_path.argtypes = [zdir_p]
lib.zdir_modified.restype = c_int
lib.zdir_modified.argtypes = [zdir_p]
lib.zdir_cursize.restype = c_int
lib.zdir_cursize.argtypes = [zdir_p]
lib.zdir_count.restype = c_size_t
lib.zdir_count.argtypes = [zdir_p]
lib.zdir_list.restype = zlist_p
lib.zdir_list.argtypes = [zdir_p]
lib.zdir_remove.restype = None
lib.zdir_remove.argtypes = [zdir_p, c_bool]
lib.zdir_diff.restype = zlist_p
lib.zdir_diff.argtypes = [zdir_p, zdir_p, c_char_p]
lib.zdir_resync.restype = zlist_p
lib.zdir_resync.argtypes = [zdir_p, c_char_p]
lib.zdir_cache.restype = zhash_p
lib.zdir_cache.argtypes = [zdir_p]
lib.zdir_fprint.restype = None
lib.zdir_fprint.argtypes = [zdir_p, FILE_p, c_int]
lib.zdir_print.restype = None
lib.zdir_print.argtypes = [zdir_p, c_int]
lib.zdir_watch.restype = None
lib.zdir_watch.argtypes = [zsock_p, c_void_p]
lib.zdir_test.restype = None
lib.zdir_test.argtypes = [c_bool]

class Zdir(object):
    """work with file-system directories"""

    def __init__(self, *args):
        """Create a new directory item that loads in the full tree of the specified
path, optionally located under some parent path. If parent is "-", then
loads only the top-level directory, and does not use parent as a path."""
        if len(args) == 2 and type(args[0]) is c_void_p and isinstance(args[1], bool):
            self._as_parameter_ = cast(args[0], zdir_p) # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        elif len(args) == 2 and type(args[0]) is zdir_p and isinstance(args[1], bool):
            self._as_parameter_ = args[0] # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        else:
            assert(len(args) == 2)
            self._as_parameter_ = lib.zdir_new(args[0], args[1]) # Creation of new raw type
            self.allow_destruct = True

    def __del__(self):
        """Destroy a directory tree and all children it contains."""
        if self.allow_destruct:
            lib.zdir_destroy(byref(self._as_parameter_))

    def __bool__(self):
        "Determine whether the object is valid by converting to boolean" # Python 3
        return self._as_parameter_.__bool__()

    def __nonzero__(self):
        "Determine whether the object is valid by converting to boolean" # Python 2
        return self._as_parameter_.__nonzero__()

    def path(self):
        """Return directory path"""
        return lib.zdir_path(self._as_parameter_)

    def modified(self):
        """Return last modification time for directory."""
        return lib.zdir_modified(self._as_parameter_)

    def cursize(self):
        """Return total hierarchy size, in bytes of data contained in all files
in the directory tree."""
        return lib.zdir_cursize(self._as_parameter_)

    def count(self):
        """Return directory count"""
        return lib.zdir_count(self._as_parameter_)

    def list(self):
        """Returns a sorted list of zfile objects; Each entry in the list is a pointer
to a zfile_t item already allocated in the zdir tree. Do not destroy the
original zdir tree until you are done with this list."""
        return Zlist(lib.zdir_list(self._as_parameter_), True)

    def remove(self, force):
        """Remove directory, optionally including all files that it contains, at
all levels. If force is false, will only remove the directory if empty.
If force is true, will remove all files and all subdirectories."""
        return lib.zdir_remove(self._as_parameter_, force)

    @staticmethod
    def diff(older, newer, alias):
        """Calculate differences between two versions of a directory tree.
Returns a list of zdir_patch_t patches. Either older or newer may
be null, indicating the directory is empty/absent. If alias is set,
generates virtual filename (minus path, plus alias)."""
        return Zlist(lib.zdir_diff(older, newer, alias), True)

    def resync(self, alias):
        """Return full contents of directory as a zdir_patch list."""
        return Zlist(lib.zdir_resync(self._as_parameter_, alias), True)

    def cache(self):
        """Load directory cache; returns a hash table containing the SHA-1 digests
of every file in the tree. The cache is saved between runs in .cache."""
        return Zhash(lib.zdir_cache(self._as_parameter_), True)

    def fprint(self, file, indent):
        """Print contents of directory to open stream"""
        return lib.zdir_fprint(self._as_parameter_, coerce_py_file(file), indent)

    def print(self, indent):
        """Print contents of directory to stdout"""
        return lib.zdir_print(self._as_parameter_, indent)

    @staticmethod
    def watch(pipe, unused):
        """Create a new zdir_watch actor instance:

    zactor_t *watch = zactor_new (zdir_watch, NULL);

Destroy zdir_watch instance:

    zactor_destroy (&watch);

Enable verbose logging of commands and activity:

    zstr_send (watch, "VERBOSE");

Subscribe to changes to a directory path:

    zsock_send (watch, "ss", "SUBSCRIBE", "directory_path");

Unsubscribe from changes to a directory path:

    zsock_send (watch, "ss", "UNSUBSCRIBE", "directory_path");

Receive directory changes:
    zsock_recv (watch, "sp", &path, &patches);

    // Delete the received data.
    free (path);
    zlist_destroy (&patches);"""
        return lib.zdir_watch(pipe, unused)

    @staticmethod
    def test(verbose):
        """Self test of this class."""
        return lib.zdir_test(verbose)

# zdir patch
lib.zdir_patch_new.restype = zdir_patch_p
lib.zdir_patch_new.argtypes = [c_char_p, zfile_p, c_int, c_char_p]
lib.zdir_patch_destroy.restype = None
lib.zdir_patch_destroy.argtypes = [POINTER(zdir_patch_p)]
lib.zdir_patch_dup.restype = zdir_patch_p
lib.zdir_patch_dup.argtypes = [zdir_patch_p]
lib.zdir_patch_path.restype = c_char_p
lib.zdir_patch_path.argtypes = [zdir_patch_p]
lib.zdir_patch_file.restype = zfile_p
lib.zdir_patch_file.argtypes = [zdir_patch_p]
lib.zdir_patch_op.restype = c_int
lib.zdir_patch_op.argtypes = [zdir_patch_p]
lib.zdir_patch_vpath.restype = c_char_p
lib.zdir_patch_vpath.argtypes = [zdir_patch_p]
lib.zdir_patch_digest_set.restype = None
lib.zdir_patch_digest_set.argtypes = [zdir_patch_p]
lib.zdir_patch_digest.restype = c_char_p
lib.zdir_patch_digest.argtypes = [zdir_patch_p]
lib.zdir_patch_test.restype = None
lib.zdir_patch_test.argtypes = [c_bool]

class ZdirPatch(object):
    """work with directory patches"""

    Op = {
        'create': 1,
        'delete': 2,
    }

    Op_out = {
         1: 'create',
         2: 'delete',
    }

    def __init__(self, *args):
        """Create new patch"""
        if len(args) == 2 and type(args[0]) is c_void_p and isinstance(args[1], bool):
            self._as_parameter_ = cast(args[0], zdir_patch_p) # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        elif len(args) == 2 and type(args[0]) is zdir_patch_p and isinstance(args[1], bool):
            self._as_parameter_ = args[0] # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        else:
            assert(len(args) == 4)
            self._as_parameter_ = lib.zdir_patch_new(args[0], args[1], ZdirPatch.Op[args[2]], args[3]) # Creation of new raw type
            self.allow_destruct = True

    def __del__(self):
        """Destroy a patch"""
        if self.allow_destruct:
            lib.zdir_patch_destroy(byref(self._as_parameter_))

    def __bool__(self):
        "Determine whether the object is valid by converting to boolean" # Python 3
        return self._as_parameter_.__bool__()

    def __nonzero__(self):
        "Determine whether the object is valid by converting to boolean" # Python 2
        return self._as_parameter_.__nonzero__()

    def dup(self):
        """Create copy of a patch. If the patch is null, or memory was exhausted,
returns null."""
        return ZdirPatch(lib.zdir_patch_dup(self._as_parameter_), True)

    def path(self):
        """Return patch file directory path"""
        return lib.zdir_patch_path(self._as_parameter_)

    def file(self):
        """Return patch file item"""
        return Zfile(lib.zdir_patch_file(self._as_parameter_), False)

    def op(self):
        """Return operation"""
        return ZdirPatch.Op_out[lib.zdir_patch_op(self._as_parameter_)]

    def vpath(self):
        """Return patch virtual file path"""
        return lib.zdir_patch_vpath(self._as_parameter_)

    def digest_set(self):
        """Calculate hash digest for file (create only)"""
        return lib.zdir_patch_digest_set(self._as_parameter_)

    def digest(self):
        """Return hash digest for patch file"""
        return lib.zdir_patch_digest(self._as_parameter_)

    @staticmethod
    def test(verbose):
        """Self test of this class."""
        return lib.zdir_patch_test(verbose)

# zfile
lib.zfile_new.restype = zfile_p
lib.zfile_new.argtypes = [c_char_p, c_char_p]
lib.zfile_destroy.restype = None
lib.zfile_destroy.argtypes = [POINTER(zfile_p)]
lib.zfile_dup.restype = zfile_p
lib.zfile_dup.argtypes = [zfile_p]
lib.zfile_filename.restype = c_char_p
lib.zfile_filename.argtypes = [zfile_p, c_char_p]
lib.zfile_restat.restype = None
lib.zfile_restat.argtypes = [zfile_p]
lib.zfile_modified.restype = c_int
lib.zfile_modified.argtypes = [zfile_p]
lib.zfile_cursize.restype = c_int
lib.zfile_cursize.argtypes = [zfile_p]
lib.zfile_is_directory.restype = c_bool
lib.zfile_is_directory.argtypes = [zfile_p]
lib.zfile_is_regular.restype = c_bool
lib.zfile_is_regular.argtypes = [zfile_p]
lib.zfile_is_readable.restype = c_bool
lib.zfile_is_readable.argtypes = [zfile_p]
lib.zfile_is_writeable.restype = c_bool
lib.zfile_is_writeable.argtypes = [zfile_p]
lib.zfile_is_stable.restype = c_bool
lib.zfile_is_stable.argtypes = [zfile_p]
lib.zfile_has_changed.restype = c_bool
lib.zfile_has_changed.argtypes = [zfile_p]
lib.zfile_remove.restype = None
lib.zfile_remove.argtypes = [zfile_p]
lib.zfile_input.restype = c_int
lib.zfile_input.argtypes = [zfile_p]
lib.zfile_output.restype = c_int
lib.zfile_output.argtypes = [zfile_p]
lib.zfile_read.restype = zchunk_p
lib.zfile_read.argtypes = [zfile_p, c_size_t, c_int]
lib.zfile_eof.restype = c_bool
lib.zfile_eof.argtypes = [zfile_p]
lib.zfile_write.restype = c_int
lib.zfile_write.argtypes = [zfile_p, zchunk_p, c_int]
lib.zfile_readln.restype = c_char_p
lib.zfile_readln.argtypes = [zfile_p]
lib.zfile_close.restype = None
lib.zfile_close.argtypes = [zfile_p]
lib.zfile_handle.restype = FILE_p
lib.zfile_handle.argtypes = [zfile_p]
lib.zfile_digest.restype = c_char_p
lib.zfile_digest.argtypes = [zfile_p]
lib.zfile_test.restype = None
lib.zfile_test.argtypes = [c_bool]

class Zfile(object):
    """helper functions for working with files."""

    def __init__(self, *args):
        """If file exists, populates properties. CZMQ supports portable symbolic
links, which are files with the extension ".ln". A symbolic link is a
text file containing one line, the filename of a target file. Reading
data from the symbolic link actually reads from the target file. Path
may be NULL, in which case it is not used."""
        if len(args) == 2 and type(args[0]) is c_void_p and isinstance(args[1], bool):
            self._as_parameter_ = cast(args[0], zfile_p) # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        elif len(args) == 2 and type(args[0]) is zfile_p and isinstance(args[1], bool):
            self._as_parameter_ = args[0] # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        else:
            assert(len(args) == 2)
            self._as_parameter_ = lib.zfile_new(args[0], args[1]) # Creation of new raw type
            self.allow_destruct = True

    def __del__(self):
        """Destroy a file item"""
        if self.allow_destruct:
            lib.zfile_destroy(byref(self._as_parameter_))

    def __bool__(self):
        "Determine whether the object is valid by converting to boolean" # Python 3
        return self._as_parameter_.__bool__()

    def __nonzero__(self):
        "Determine whether the object is valid by converting to boolean" # Python 2
        return self._as_parameter_.__nonzero__()

    def dup(self):
        """Duplicate a file item, returns a newly constructed item. If the file
is null, or memory was exhausted, returns null."""
        return Zfile(lib.zfile_dup(self._as_parameter_), True)

    def filename(self, path):
        """Return file name, remove path if provided"""
        return lib.zfile_filename(self._as_parameter_, path)

    def restat(self):
        """Refresh file properties from disk; this is not done automatically
on access methods, otherwise it is not possible to compare directory
snapshots."""
        return lib.zfile_restat(self._as_parameter_)

    def modified(self):
        """Return when the file was last modified. If you want this to reflect the
current situation, call zfile_restat before checking this property."""
        return lib.zfile_modified(self._as_parameter_)

    def cursize(self):
        """Return the last-known size of the file. If you want this to reflect the
current situation, call zfile_restat before checking this property."""
        return lib.zfile_cursize(self._as_parameter_)

    def is_directory(self):
        """Return true if the file is a directory. If you want this to reflect
any external changes, call zfile_restat before checking this property."""
        return lib.zfile_is_directory(self._as_parameter_)

    def is_regular(self):
        """Return true if the file is a regular file. If you want this to reflect
any external changes, call zfile_restat before checking this property."""
        return lib.zfile_is_regular(self._as_parameter_)

    def is_readable(self):
        """Return true if the file is readable by this process. If you want this to
reflect any external changes, call zfile_restat before checking this
property."""
        return lib.zfile_is_readable(self._as_parameter_)

    def is_writeable(self):
        """Return true if the file is writeable by this process. If you want this
to reflect any external changes, call zfile_restat before checking this
property."""
        return lib.zfile_is_writeable(self._as_parameter_)

    def is_stable(self):
        """Check if file has stopped changing and can be safely processed.
Updates the file statistics from disk at every call."""
        return lib.zfile_is_stable(self._as_parameter_)

    def has_changed(self):
        """Return true if the file was changed on disk since the zfile_t object
was created, or the last zfile_restat() call made on it."""
        return lib.zfile_has_changed(self._as_parameter_)

    def remove(self):
        """Remove the file from disk"""
        return lib.zfile_remove(self._as_parameter_)

    def input(self):
        """Open file for reading
Returns 0 if OK, -1 if not found or not accessible"""
        return lib.zfile_input(self._as_parameter_)

    def output(self):
        """Open file for writing, creating directory if needed
File is created if necessary; chunks can be written to file at any
location. Returns 0 if OK, -1 if error."""
        return lib.zfile_output(self._as_parameter_)

    def read(self, bytes, offset):
        """Read chunk from file at specified position. If this was the last chunk,
sets the eof property. Returns a null chunk in case of error."""
        return lib.zfile_read(self._as_parameter_, bytes, offset)

    def eof(self):
        """Returns true if zfile_read() just read the last chunk in the file."""
        return lib.zfile_eof(self._as_parameter_)

    def write(self, chunk, offset):
        """Write chunk to file at specified position
Return 0 if OK, else -1"""
        return lib.zfile_write(self._as_parameter_, chunk, offset)

    def readln(self):
        """Read next line of text from file. Returns a pointer to the text line,
or NULL if there was nothing more to read from the file."""
        return lib.zfile_readln(self._as_parameter_)

    def close(self):
        """Close file, if open"""
        return lib.zfile_close(self._as_parameter_)

    def handle(self):
        """Return file handle, if opened"""
        return return_py_file(lib.zfile_handle(self._as_parameter_))

    def digest(self):
        """Calculate SHA1 digest for file, using zdigest class."""
        return lib.zfile_digest(self._as_parameter_)

    @staticmethod
    def test(verbose):
        """Self test of this class."""
        return lib.zfile_test(verbose)

# zframe
lib.zframe_new.restype = zframe_p
lib.zframe_new.argtypes = [c_void_p, c_size_t]
lib.zframe_destroy.restype = None
lib.zframe_destroy.argtypes = [POINTER(zframe_p)]
lib.zframe_new_empty.restype = zframe_p
lib.zframe_new_empty.argtypes = []
lib.zframe_from.restype = zframe_p
lib.zframe_from.argtypes = [c_char_p]
lib.zframe_recv.restype = zframe_p
lib.zframe_recv.argtypes = [c_void_p]
lib.zframe_send.restype = c_int
lib.zframe_send.argtypes = [POINTER(zframe_p), c_void_p, c_int]
lib.zframe_send_reply.restype = c_int
lib.zframe_send_reply.argtypes = [POINTER(zframe_p), zframe_p, c_void_p, c_int]
lib.zframe_size.restype = c_size_t
lib.zframe_size.argtypes = [zframe_p]
lib.zframe_data.restype = POINTER(c_byte)
lib.zframe_data.argtypes = [zframe_p]
lib.zframe_dup.restype = zframe_p
lib.zframe_dup.argtypes = [zframe_p]
lib.zframe_strhex.restype = POINTER(c_char)
lib.zframe_strhex.argtypes = [zframe_p]
lib.zframe_strdup.restype = POINTER(c_char)
lib.zframe_strdup.argtypes = [zframe_p]
lib.zframe_streq.restype = c_bool
lib.zframe_streq.argtypes = [zframe_p, c_char_p]
lib.zframe_more.restype = c_int
lib.zframe_more.argtypes = [zframe_p]
lib.zframe_set_more.restype = None
lib.zframe_set_more.argtypes = [zframe_p, c_int]
lib.zframe_routing_id.restype = c_size_t
lib.zframe_routing_id.argtypes = [zframe_p]
lib.zframe_set_routing_id.restype = None
lib.zframe_set_routing_id.argtypes = [zframe_p, c_size_t]
lib.zframe_eq.restype = c_bool
lib.zframe_eq.argtypes = [zframe_p, zframe_p]
lib.zframe_reset.restype = None
lib.zframe_reset.argtypes = [zframe_p, c_void_p, c_size_t]
lib.zframe_print.restype = None
lib.zframe_print.argtypes = [zframe_p, c_char_p]
lib.zframe_is.restype = c_bool
lib.zframe_is.argtypes = [c_void_p]
lib.zframe_test.restype = None
lib.zframe_test.argtypes = [c_bool]

class Zframe(object):
    """working with single message frames

-    zframe_routing_id (zframe_t *self);"""

    MORE = 1 #
    REUSE = 2 #
    DONTWAIT = 4 #
    def __init__(self, *args):
        """Create a new frame. If size is not null, allocates the frame data
to the specified size. If additionally, data is not null, copies
size octets from the specified data into the frame body."""
        if len(args) == 2 and type(args[0]) is c_void_p and isinstance(args[1], bool):
            self._as_parameter_ = cast(args[0], zframe_p) # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        elif len(args) == 2 and type(args[0]) is zframe_p and isinstance(args[1], bool):
            self._as_parameter_ = args[0] # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        else:
            assert(len(args) == 2)
            self._as_parameter_ = lib.zframe_new(args[0], args[1]) # Creation of new raw type
            self.allow_destruct = True

    def __del__(self):
        """Destroy a frame"""
        if self.allow_destruct:
            lib.zframe_destroy(byref(self._as_parameter_))

    def __bool__(self):
        "Determine whether the object is valid by converting to boolean" # Python 3
        return self._as_parameter_.__bool__()

    def __nonzero__(self):
        "Determine whether the object is valid by converting to boolean" # Python 2
        return self._as_parameter_.__nonzero__()

    @staticmethod
    def new_empty():
        """Create an empty (zero-sized) frame"""
        return Zframe(lib.zframe_new_empty(), True)

    @staticmethod
    def from_(string):
        """Create a frame with a specified string content."""
        return Zframe(lib.zframe_from(string), True)

    @staticmethod
    def recv(source):
        """Receive frame from socket, returns zframe_t object or NULL if the recv
was interrupted. Does a blocking recv, if you want to not block then use
zpoller or zloop."""
        return Zframe(lib.zframe_recv(source), True)

    @staticmethod
    def send(self_p, dest, flags):
        """Send a frame to a socket, destroy frame after sending.
Return -1 on error, 0 on success."""
        return lib.zframe_send(byref(zframe_p.from_param(self_p)), dest, flags)

    @staticmethod
    def send_reply(self_p, source_msg, dest, flags):
        """Send a reply frame to a server socket, copy the routing id from source message, destroy frame after sending.
Return -1 on error, 0 on success."""
        return lib.zframe_send_reply(byref(zframe_p.from_param(self_p)), source_msg, dest, flags)

    def size(self):
        """Return number of bytes in frame data"""
        return lib.zframe_size(self._as_parameter_)

    def data(self):
        """Return address of frame data"""
        return lib.zframe_data(self._as_parameter_)

    def dup(self):
        """Create a new frame that duplicates an existing frame. If frame is null,
or memory was exhausted, returns null."""
        return Zframe(lib.zframe_dup(self._as_parameter_), True)

    def strhex(self):
        """Return frame data encoded as printable hex string, useful for 0MQ UUIDs.
Caller must free string when finished with it."""
        return return_fresh_string(lib.zframe_strhex(self._as_parameter_))

    def strdup(self):
        """Return frame data copied into freshly allocated string
Caller must free string when finished with it."""
        return return_fresh_string(lib.zframe_strdup(self._as_parameter_))

    def streq(self, string):
        """Return TRUE if frame body is equal to string, excluding terminator"""
        return lib.zframe_streq(self._as_parameter_, string)

    def more(self):
        """Return frame MORE indicator (1 or 0), set when reading frame from socket
or by the zframe_set_more() method"""
        return lib.zframe_more(self._as_parameter_)

    def set_more(self, more):
        """Set frame MORE indicator (1 or 0). Note this is NOT used when sending
frame to socket, you have to specify flag explicitly."""
        return lib.zframe_set_more(self._as_parameter_, more)

    def routing_id(self):
        """Return frame routing id, set when reading frame from server socket
or by the zframe_set_routing_id() method."""
        return lib.zframe_routing_id(self._as_parameter_)

    def set_routing_id(self, routing_id):
        """Set frame routing id. Only relevant when sending to server socket."""
        return lib.zframe_set_routing_id(self._as_parameter_, routing_id)

    def eq(self, other):
        """Return TRUE if two frames have identical size and data
If either frame is NULL, equality is always false."""
        return lib.zframe_eq(self._as_parameter_, other)

    def reset(self, data, size):
        """Set new contents for frame"""
        return lib.zframe_reset(self._as_parameter_, data, size)

    def print(self, prefix):
        """Send message to zsys log sink (may be stdout, or system facility as
configured by zsys_set_logstream). Prefix shows before frame, if not null."""
        return lib.zframe_print(self._as_parameter_, prefix)

    @staticmethod
    def is_(self):
        """Probe the supplied object, and report if it looks like a zframe_t."""
        return lib.zframe_is(self)

    @staticmethod
    def test(verbose):
        """Self test of this class"""
        return lib.zframe_test(verbose)

# zhashx
zhashx_destructor_fn = CFUNCTYPE(None, POINTER(c_void_p))
zhashx_duplicator_fn = CFUNCTYPE(c_void_p, c_void_p)
zhashx_comparator_fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
zhashx_free_fn = CFUNCTYPE(None, c_void_p)
zhashx_hash_fn = CFUNCTYPE(c_size_t, c_void_p)
zhashx_foreach_fn = CFUNCTYPE(c_int, c_char_p, c_void_p, c_void_p)
lib.zhashx_new.restype = zhashx_p
lib.zhashx_new.argtypes = []
lib.zhashx_destroy.restype = None
lib.zhashx_destroy.argtypes = [POINTER(zhashx_p)]
lib.zhashx_insert.restype = c_int
lib.zhashx_insert.argtypes = [zhashx_p, c_void_p, c_void_p]
lib.zhashx_update.restype = None
lib.zhashx_update.argtypes = [zhashx_p, c_void_p, c_void_p]
lib.zhashx_delete.restype = None
lib.zhashx_delete.argtypes = [zhashx_p, c_void_p]
lib.zhashx_purge.restype = None
lib.zhashx_purge.argtypes = [zhashx_p]
lib.zhashx_lookup.restype = c_void_p
lib.zhashx_lookup.argtypes = [zhashx_p, c_void_p]
lib.zhashx_rename.restype = c_int
lib.zhashx_rename.argtypes = [zhashx_p, c_void_p, c_void_p]
lib.zhashx_freefn.restype = c_void_p
lib.zhashx_freefn.argtypes = [zhashx_p, c_void_p, zhashx_free_fn]
lib.zhashx_size.restype = c_size_t
lib.zhashx_size.argtypes = [zhashx_p]
lib.zhashx_keys.restype = zlistx_p
lib.zhashx_keys.argtypes = [zhashx_p]
lib.zhashx_values.restype = zlistx_p
lib.zhashx_values.argtypes = [zhashx_p]
lib.zhashx_first.restype = c_void_p
lib.zhashx_first.argtypes = [zhashx_p]
lib.zhashx_next.restype = c_void_p
lib.zhashx_next.argtypes = [zhashx_p]
lib.zhashx_cursor.restype = c_void_p
lib.zhashx_cursor.argtypes = [zhashx_p]
lib.zhashx_comment.restype = None
lib.zhashx_comment.argtypes = [zhashx_p, c_char_p]
lib.zhashx_save.restype = c_int
lib.zhashx_save.argtypes = [zhashx_p, c_char_p]
lib.zhashx_load.restype = c_int
lib.zhashx_load.argtypes = [zhashx_p, c_char_p]
lib.zhashx_refresh.restype = c_int
lib.zhashx_refresh.argtypes = [zhashx_p]
lib.zhashx_pack.restype = zframe_p
lib.zhashx_pack.argtypes = [zhashx_p]
lib.zhashx_unpack.restype = zhashx_p
lib.zhashx_unpack.argtypes = [zframe_p]
lib.zhashx_dup.restype = zhashx_p
lib.zhashx_dup.argtypes = [zhashx_p]
lib.zhashx_set_destructor.restype = None
lib.zhashx_set_destructor.argtypes = [zhashx_p, zhashx_destructor_fn]
lib.zhashx_set_duplicator.restype = None
lib.zhashx_set_duplicator.argtypes = [zhashx_p, zhashx_duplicator_fn]
lib.zhashx_set_key_destructor.restype = None
lib.zhashx_set_key_destructor.argtypes = [zhashx_p, zhashx_destructor_fn]
lib.zhashx_set_key_duplicator.restype = None
lib.zhashx_set_key_duplicator.argtypes = [zhashx_p, zhashx_duplicator_fn]
lib.zhashx_set_key_comparator.restype = None
lib.zhashx_set_key_comparator.argtypes = [zhashx_p, zhashx_comparator_fn]
lib.zhashx_set_key_hasher.restype = None
lib.zhashx_set_key_hasher.argtypes = [zhashx_p, zhashx_hash_fn]
lib.zhashx_dup_v2.restype = zhashx_p
lib.zhashx_dup_v2.argtypes = [zhashx_p]
lib.zhashx_autofree.restype = None
lib.zhashx_autofree.argtypes = [zhashx_p]
lib.zhashx_foreach.restype = c_int
lib.zhashx_foreach.argtypes = [zhashx_p, zhashx_foreach_fn, c_void_p]
lib.zhashx_test.restype = None
lib.zhashx_test.argtypes = [c_int]

class Zhashx(object):
    """extended generic type-free hash container"""

    def __init__(self, *args):
        """Create a new, empty hash container"""
        if len(args) == 2 and type(args[0]) is c_void_p and isinstance(args[1], bool):
            self._as_parameter_ = cast(args[0], zhashx_p) # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        elif len(args) == 2 and type(args[0]) is zhashx_p and isinstance(args[1], bool):
            self._as_parameter_ = args[0] # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        else:
            assert(len(args) == 0)
            self._as_parameter_ = lib.zhashx_new() # Creation of new raw type
            self.allow_destruct = True

    def __del__(self):
        """Destroy a hash container and all items in it"""
        if self.allow_destruct:
            lib.zhashx_destroy(byref(self._as_parameter_))

    def __bool__(self):
        "Determine whether the object is valid by converting to boolean" # Python 3
        return self._as_parameter_.__bool__()

    def __nonzero__(self):
        "Determine whether the object is valid by converting to boolean" # Python 2
        return self._as_parameter_.__nonzero__()

    def insert(self, key, item):
        """Insert item into hash table with specified key and item.
If key is already present returns -1 and leaves existing item unchanged
Returns 0 on success."""
        return lib.zhashx_insert(self._as_parameter_, key, item)

    def update(self, key, item):
        """Update or insert item into hash table with specified key and item. If the
key is already present, destroys old item and inserts new one. If you set
a container item destructor, this is called on the old value. If the key
was not already present, inserts a new item. Sets the hash cursor to the
new item."""
        return lib.zhashx_update(self._as_parameter_, key, item)

    def delete(self, key):
        """Remove an item specified by key from the hash table. If there was no such
item, this function does nothing."""
        return lib.zhashx_delete(self._as_parameter_, key)

    def purge(self):
        """Delete all items from the hash table. If the key destructor is
set, calls it on every key. If the item destructor is set, calls
it on every item."""
        return lib.zhashx_purge(self._as_parameter_)

    def lookup(self, key):
        """Return the item at the specified key, or null"""
        return c_void_p(lib.zhashx_lookup(self._as_parameter_, key))

    def rename(self, old_key, new_key):
        """Reindexes an item from an old key to a new key. If there was no such
item, does nothing. Returns 0 if successful, else -1."""
        return lib.zhashx_rename(self._as_parameter_, old_key, new_key)

    def freefn(self, key, free_fn):
        """Set a free function for the specified hash table item. When the item is
destroyed, the free function, if any, is called on that item.
Use this when hash items are dynamically allocated, to ensure that
you don't have memory leaks. You can pass 'free' or NULL as a free_fn.
Returns the item, or NULL if there is no such item."""
        return c_void_p(lib.zhashx_freefn(self._as_parameter_, key, free_fn))

    def size(self):
        """Return the number of keys/items in the hash table"""
        return lib.zhashx_size(self._as_parameter_)

    def keys(self):
        """Return a zlistx_t containing the keys for the items in the
table. Uses the key_duplicator to duplicate all keys and sets the
key_destructor as destructor for the list."""
        return lib.zhashx_keys(self._as_parameter_)

    def values(self):
        """Return a zlistx_t containing the values for the items in the
table. Uses the duplicator to duplicate all items and sets the
destructor as destructor for the list."""
        return lib.zhashx_values(self._as_parameter_)

    def first(self):
        """Simple iterator; returns first item in hash table, in no given order,
or NULL if the table is empty. This method is simpler to use than the
foreach() method, which is deprecated. To access the key for this item
use zhashx_cursor(). NOTE: do NOT modify the table while iterating."""
        return c_void_p(lib.zhashx_first(self._as_parameter_))

    def next(self):
        """Simple iterator; returns next item in hash table, in no given order,
or NULL if the last item was already returned. Use this together with
zhashx_first() to process all items in a hash table. If you need the
items in sorted order, use zhashx_keys() and then zlistx_sort(). To
access the key for this item use zhashx_cursor(). NOTE: do NOT modify
the table while iterating."""
        return c_void_p(lib.zhashx_next(self._as_parameter_))

    def cursor(self):
        """After a successful first/next method, returns the key for the item that
was returned. This is a constant string that you may not modify or
deallocate, and which lasts as long as the item in the hash. After an
unsuccessful first/next, returns NULL."""
        return c_void_p(lib.zhashx_cursor(self._as_parameter_))

    def comment(self, format, *args):
        """Add a comment to hash table before saving to disk. You can add as many
comment lines as you like. These comment lines are discarded when loading
the file. If you use a null format, all comments are deleted."""
        return lib.zhashx_comment(self._as_parameter_, format, *args)

    def save(self, filename):
        """Save hash table to a text file in name=value format. Hash values must be
printable strings; keys may not contain '=' character. Returns 0 if OK,
else -1 if a file error occurred."""
        return lib.zhashx_save(self._as_parameter_, filename)

    def load(self, filename):
        """Load hash table from a text file in name=value format; hash table must
already exist. Hash values must printable strings; keys may not contain
'=' character. Returns 0 if OK, else -1 if a file was not readable."""
        return lib.zhashx_load(self._as_parameter_, filename)

    def refresh(self):
        """When a hash table was loaded from a file by zhashx_load, this method will
reload the file if it has been modified since, and is "stable", i.e. not
still changing. Returns 0 if OK, -1 if there was an error reloading the
file."""
        return lib.zhashx_refresh(self._as_parameter_)

    def pack(self):
        """Serialize hash table to a binary frame that can be sent in a message.
The packed format is compatible with the 'dictionary' type defined in
http://rfc.zeromq.org/spec:35/FILEMQ, and implemented by zproto:

   ; A list of name/value pairs
   dictionary      = dict-count *( dict-name dict-value )
   dict-count      = number-4
   dict-value      = longstr
   dict-name       = string

   ; Strings are always length + text contents
   longstr         = number-4 *VCHAR
   string          = number-1 *VCHAR

   ; Numbers are unsigned integers in network byte order
   number-1        = 1OCTET
   number-4        = 4OCTET

Comments are not included in the packed data. Item values MUST be
strings."""
        return Zframe(lib.zhashx_pack(self._as_parameter_), True)

    @staticmethod
    def unpack(frame):
        """Unpack binary frame into a new hash table. Packed data must follow format
defined by zhashx_pack. Hash table is set to autofree. An empty frame
unpacks to an empty hash table."""
        return Zhashx(lib.zhashx_unpack(frame), True)

    def dup(self):
        """Make a copy of the list; items are duplicated if you set a duplicator
for the list, otherwise not. Copying a null reference returns a null
reference. Note that this method's behavior changed slightly for CZMQ
v3.x, as it does not set nor respect autofree. It does however let you
duplicate any hash table safely. The old behavior is in zhashx_dup_v2."""
        return Zhashx(lib.zhashx_dup(self._as_parameter_), True)

    def set_destructor(self, destructor):
        """Set a user-defined deallocator for hash items; by default items are not
freed when the hash is destroyed."""
        return lib.zhashx_set_destructor(self._as_parameter_, destructor)

    def set_duplicator(self, duplicator):
        """Set a user-defined duplicator for hash items; by default items are not
copied when the hash is duplicated."""
        return lib.zhashx_set_duplicator(self._as_parameter_, duplicator)

    def set_key_destructor(self, destructor):
        """Set a user-defined deallocator for keys; by default keys are freed
when the hash is destroyed using free()."""
        return lib.zhashx_set_key_destructor(self._as_parameter_, destructor)

    def set_key_duplicator(self, duplicator):
        """Set a user-defined duplicator for keys; by default keys are duplicated
using strdup."""
        return lib.zhashx_set_key_duplicator(self._as_parameter_, duplicator)

    def set_key_comparator(self, comparator):
        """Set a user-defined comparator for keys; by default keys are
compared using strcmp."""
        return lib.zhashx_set_key_comparator(self._as_parameter_, comparator)

    def set_key_hasher(self, hasher):
        """Set a user-defined comparator for keys; by default keys are
compared using strcmp."""
        return lib.zhashx_set_key_hasher(self._as_parameter_, hasher)

    def dup_v2(self):
        """Make copy of hash table; if supplied table is null, returns null.
Does not copy items themselves. Rebuilds new table so may be slow on
very large tables. NOTE: only works with item values that are strings
since there's no other way to know how to duplicate the item value."""
        return Zhashx(lib.zhashx_dup_v2(self._as_parameter_), False)

    def autofree(self):
        """DEPRECATED as clumsy -- use set_destructor instead
Set hash for automatic value destruction"""
        return lib.zhashx_autofree(self._as_parameter_)

    def foreach(self, callback, argument):
        """DEPRECATED as clumsy -- use zhashx_first/_next instead
Apply function to each item in the hash table. Items are iterated in no
defined order. Stops if callback function returns non-zero and returns
final return code from callback function (zero = success).
Callback function for zhashx_foreach method"""
        return lib.zhashx_foreach(self._as_parameter_, callback, argument)

    @staticmethod
    def test(verbose):
        """Self test of this class"""
        return lib.zhashx_test(verbose)

# ziflist
lib.ziflist_new.restype = ziflist_p
lib.ziflist_new.argtypes = []
lib.ziflist_destroy.restype = None
lib.ziflist_destroy.argtypes = [POINTER(ziflist_p)]
lib.ziflist_print.restype = None
lib.ziflist_print.argtypes = [ziflist_p]
lib.ziflist_reload.restype = None
lib.ziflist_reload.argtypes = [ziflist_p]
lib.ziflist_size.restype = c_size_t
lib.ziflist_size.argtypes = [ziflist_p]
lib.ziflist_first.restype = c_char_p
lib.ziflist_first.argtypes = [ziflist_p]
lib.ziflist_next.restype = c_char_p
lib.ziflist_next.argtypes = [ziflist_p]
lib.ziflist_address.restype = c_char_p
lib.ziflist_address.argtypes = [ziflist_p]
lib.ziflist_broadcast.restype = c_char_p
lib.ziflist_broadcast.argtypes = [ziflist_p]
lib.ziflist_netmask.restype = c_char_p
lib.ziflist_netmask.argtypes = [ziflist_p]
lib.ziflist_test.restype = None
lib.ziflist_test.argtypes = [c_bool]

class Ziflist(object):
    """List of network interfaces available on system"""

    def __init__(self, *args):
        """Get a list of network interfaces currently defined on the system"""
        if len(args) == 2 and type(args[0]) is c_void_p and isinstance(args[1], bool):
            self._as_parameter_ = cast(args[0], ziflist_p) # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        elif len(args) == 2 and type(args[0]) is ziflist_p and isinstance(args[1], bool):
            self._as_parameter_ = args[0] # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        else:
            assert(len(args) == 0)
            self._as_parameter_ = lib.ziflist_new() # Creation of new raw type
            self.allow_destruct = True

    def __del__(self):
        """Destroy a ziflist instance"""
        if self.allow_destruct:
            lib.ziflist_destroy(byref(self._as_parameter_))

    def __bool__(self):
        "Determine whether the object is valid by converting to boolean" # Python 3
        return self._as_parameter_.__bool__()

    def __nonzero__(self):
        "Determine whether the object is valid by converting to boolean" # Python 2
        return self._as_parameter_.__nonzero__()

    def print(self):
        """Print properties of the ziflist object."""
        return lib.ziflist_print(self._as_parameter_)

    def reload(self):
        """Reload network interfaces from system"""
        return lib.ziflist_reload(self._as_parameter_)

    def size(self):
        """Return the number of network interfaces on system"""
        return lib.ziflist_size(self._as_parameter_)

    def first(self):
        """Get first network interface, return NULL if there are none"""
        return lib.ziflist_first(self._as_parameter_)

    def next(self):
        """Get next network interface, return NULL if we hit the last one"""
        return lib.ziflist_next(self._as_parameter_)

    def address(self):
        """Return the current interface IP address as a printable string"""
        return lib.ziflist_address(self._as_parameter_)

    def broadcast(self):
        """Return the current interface broadcast address as a printable string"""
        return lib.ziflist_broadcast(self._as_parameter_)

    def netmask(self):
        """Return the current interface network mask as a printable string"""
        return lib.ziflist_netmask(self._as_parameter_)

    @staticmethod
    def test(verbose):
        """Self test of this class."""
        return lib.ziflist_test(verbose)

# zloop
zloop_reader_fn = CFUNCTYPE(c_int, zloop_p, zsock_p, c_void_p)
zloop_fn = CFUNCTYPE(c_int, zloop_p, zmq_pollitem_p, c_void_p)
zloop_timer_fn = CFUNCTYPE(c_int, zloop_p, c_int, c_void_p)
lib.zloop_new.restype = zloop_p
lib.zloop_new.argtypes = []
lib.zloop_destroy.restype = None
lib.zloop_destroy.argtypes = [POINTER(zloop_p)]
lib.zloop_reader.restype = c_int
lib.zloop_reader.argtypes = [zloop_p, zsock_p, zloop_reader_fn, c_void_p]
lib.zloop_reader_end.restype = None
lib.zloop_reader_end.argtypes = [zloop_p, zsock_p]
lib.zloop_reader_set_tolerant.restype = None
lib.zloop_reader_set_tolerant.argtypes = [zloop_p, zsock_p]
lib.zloop_poller.restype = c_int
lib.zloop_poller.argtypes = [zloop_p, zmq_pollitem_p, zloop_fn, c_void_p]
lib.zloop_poller_end.restype = None
lib.zloop_poller_end.argtypes = [zloop_p, zmq_pollitem_p]
lib.zloop_poller_set_tolerant.restype = None
lib.zloop_poller_set_tolerant.argtypes = [zloop_p, zmq_pollitem_p]
lib.zloop_timer.restype = c_int
lib.zloop_timer.argtypes = [zloop_p, c_size_t, c_size_t, zloop_timer_fn, c_void_p]
lib.zloop_timer_end.restype = c_int
lib.zloop_timer_end.argtypes = [zloop_p, c_int]
lib.zloop_ticket.restype = c_void_p
lib.zloop_ticket.argtypes = [zloop_p, zloop_timer_fn, c_void_p]
lib.zloop_ticket_reset.restype = None
lib.zloop_ticket_reset.argtypes = [zloop_p, c_void_p]
lib.zloop_ticket_delete.restype = None
lib.zloop_ticket_delete.argtypes = [zloop_p, c_void_p]
lib.zloop_set_ticket_delay.restype = None
lib.zloop_set_ticket_delay.argtypes = [zloop_p, c_size_t]
lib.zloop_set_max_timers.restype = None
lib.zloop_set_max_timers.argtypes = [zloop_p, c_size_t]
lib.zloop_set_verbose.restype = None
lib.zloop_set_verbose.argtypes = [zloop_p, c_bool]
lib.zloop_start.restype = c_int
lib.zloop_start.argtypes = [zloop_p]
lib.zloop_ignore_interrupts.restype = None
lib.zloop_ignore_interrupts.argtypes = [zloop_p]
lib.zloop_test.restype = None
lib.zloop_test.argtypes = [c_bool]

class Zloop(object):
    """event-driven reactor"""

    def __init__(self, *args):
        """Create a new zloop reactor"""
        if len(args) == 2 and type(args[0]) is c_void_p and isinstance(args[1], bool):
            self._as_parameter_ = cast(args[0], zloop_p) # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        elif len(args) == 2 and type(args[0]) is zloop_p and isinstance(args[1], bool):
            self._as_parameter_ = args[0] # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        else:
            assert(len(args) == 0)
            self._as_parameter_ = lib.zloop_new() # Creation of new raw type
            self.allow_destruct = True

    def __del__(self):
        """Destroy a reactor"""
        if self.allow_destruct:
            lib.zloop_destroy(byref(self._as_parameter_))

    def __bool__(self):
        "Determine whether the object is valid by converting to boolean" # Python 3
        return self._as_parameter_.__bool__()

    def __nonzero__(self):
        "Determine whether the object is valid by converting to boolean" # Python 2
        return self._as_parameter_.__nonzero__()

    def reader(self, sock, handler, arg):
        """Register socket reader with the reactor. When the reader has messages,
the reactor will call the handler, passing the arg. Returns 0 if OK, -1
if there was an error. If you register the same socket more than once,
each instance will invoke its corresponding handler."""
        return lib.zloop_reader(self._as_parameter_, sock, handler, arg)

    def reader_end(self, sock):
        """Cancel a socket reader from the reactor. If multiple readers exist for
same socket, cancels ALL of them."""
        return lib.zloop_reader_end(self._as_parameter_, sock)

    def reader_set_tolerant(self, sock):
        """Configure a registered reader to ignore errors. If you do not set this,
then readers that have errors are removed from the reactor silently."""
        return lib.zloop_reader_set_tolerant(self._as_parameter_, sock)

    def poller(self, item, handler, arg):
        """Register low-level libzmq pollitem with the reactor. When the pollitem
is ready, will call the handler, passing the arg. Returns 0 if OK, -1
if there was an error. If you register the pollitem more than once, each
instance will invoke its corresponding handler. A pollitem with
socket=NULL and fd=0 means 'poll on FD zero'."""
        return lib.zloop_poller(self._as_parameter_, item, handler, arg)

    def poller_end(self, item):
        """Cancel a pollitem from the reactor, specified by socket or FD. If both
are specified, uses only socket. If multiple poll items exist for same
socket/FD, cancels ALL of them."""
        return lib.zloop_poller_end(self._as_parameter_, item)

    def poller_set_tolerant(self, item):
        """Configure a registered poller to ignore errors. If you do not set this,
then poller that have errors are removed from the reactor silently."""
        return lib.zloop_poller_set_tolerant(self._as_parameter_, item)

    def timer(self, delay, times, handler, arg):
        """Register a timer that expires after some delay and repeats some number of
times. At each expiry, will call the handler, passing the arg. To run a
timer forever, use 0 times. Returns a timer_id that is used to cancel the
timer in the future. Returns -1 if there was an error."""
        return lib.zloop_timer(self._as_parameter_, delay, times, handler, arg)

    def timer_end(self, timer_id):
        """Cancel a specific timer identified by a specific timer_id (as returned by
zloop_timer)."""
        return lib.zloop_timer_end(self._as_parameter_, timer_id)

    def ticket(self, handler, arg):
        """Register a ticket timer. Ticket timers are very fast in the case where
you use a lot of timers (thousands), and frequently remove and add them.
The main use case is expiry timers for servers that handle many clients,
and which reset the expiry timer for each message received from a client.
Whereas normal timers perform poorly as the number of clients grows, the
cost of ticket timers is constant, no matter the number of clients. You
must set the ticket delay using zloop_set_ticket_delay before creating a
ticket. Returns a handle to the timer that you should use in
zloop_ticket_reset and zloop_ticket_delete."""
        return c_void_p(lib.zloop_ticket(self._as_parameter_, handler, arg))

    def ticket_reset(self, handle):
        """Reset a ticket timer, which moves it to the end of the ticket list and
resets its execution time. This is a very fast operation."""
        return lib.zloop_ticket_reset(self._as_parameter_, handle)

    def ticket_delete(self, handle):
        """Delete a ticket timer. We do not actually delete the ticket here, as
other code may still refer to the ticket. We mark as deleted, and remove
later and safely."""
        return lib.zloop_ticket_delete(self._as_parameter_, handle)

    def set_ticket_delay(self, ticket_delay):
        """Set the ticket delay, which applies to all tickets. If you lower the
delay and there are already tickets created, the results are undefined."""
        return lib.zloop_set_ticket_delay(self._as_parameter_, ticket_delay)

    def set_max_timers(self, max_timers):
        """Set hard limit on number of timers allowed. Setting more than a small
number of timers (10-100) can have a dramatic impact on the performance
of the reactor. For high-volume cases, use ticket timers. If the hard
limit is reached, the reactor stops creating new timers and logs an
error."""
        return lib.zloop_set_max_timers(self._as_parameter_, max_timers)

    def set_verbose(self, verbose):
        """Set verbose tracing of reactor on/off"""
        return lib.zloop_set_verbose(self._as_parameter_, verbose)

    def start(self):
        """Start the reactor. Takes control of the thread and returns when the 0MQ
context is terminated or the process is interrupted, or any event handler
returns -1. Event handlers may register new sockets and timers, and
cancel sockets. Returns 0 if interrupted, -1 if cancelled by a handler."""
        return lib.zloop_start(self._as_parameter_)

    def ignore_interrupts(self):
        """Ignore zsys_interrupted flag in this loop. By default, a zloop_start will
exit as soon as it detects zsys_interrupted is set to something other than
zero. Calling zloop_ignore_interrupts will supress this behavior."""
        return lib.zloop_ignore_interrupts(self._as_parameter_)

    @staticmethod
    def test(verbose):
        """Self test of this class"""
        return lib.zloop_test(verbose)

# zmsg
lib.zmsg_new.restype = zmsg_p
lib.zmsg_new.argtypes = []
lib.zmsg_destroy.restype = None
lib.zmsg_destroy.argtypes = [POINTER(zmsg_p)]
lib.zmsg_recv.restype = zmsg_p
lib.zmsg_recv.argtypes = [c_void_p]
lib.zmsg_send.restype = c_int
lib.zmsg_send.argtypes = [POINTER(zmsg_p), c_void_p]
lib.zmsg_sendm.restype = c_int
lib.zmsg_sendm.argtypes = [POINTER(zmsg_p), c_void_p]
lib.zmsg_size.restype = c_size_t
lib.zmsg_size.argtypes = [zmsg_p]
lib.zmsg_content_size.restype = c_size_t
lib.zmsg_content_size.argtypes = [zmsg_p]
lib.zmsg_prepend.restype = c_int
lib.zmsg_prepend.argtypes = [zmsg_p, POINTER(zframe_p)]
lib.zmsg_append.restype = c_int
lib.zmsg_append.argtypes = [zmsg_p, POINTER(zframe_p)]
lib.zmsg_pop.restype = zframe_p
lib.zmsg_pop.argtypes = [zmsg_p]
lib.zmsg_pushmem.restype = c_int
lib.zmsg_pushmem.argtypes = [zmsg_p, c_void_p, c_size_t]
lib.zmsg_addmem.restype = c_int
lib.zmsg_addmem.argtypes = [zmsg_p, c_void_p, c_size_t]
lib.zmsg_pushstr.restype = c_int
lib.zmsg_pushstr.argtypes = [zmsg_p, c_char_p]
lib.zmsg_addstr.restype = c_int
lib.zmsg_addstr.argtypes = [zmsg_p, c_char_p]
lib.zmsg_pushstrf.restype = c_int
lib.zmsg_pushstrf.argtypes = [zmsg_p, c_char_p]
lib.zmsg_addstrf.restype = c_int
lib.zmsg_addstrf.argtypes = [zmsg_p, c_char_p]
lib.zmsg_popstr.restype = POINTER(c_char)
lib.zmsg_popstr.argtypes = [zmsg_p]
lib.zmsg_addmsg.restype = c_int
lib.zmsg_addmsg.argtypes = [zmsg_p, POINTER(zmsg_p)]
lib.zmsg_popmsg.restype = zmsg_p
lib.zmsg_popmsg.argtypes = [zmsg_p]
lib.zmsg_remove.restype = None
lib.zmsg_remove.argtypes = [zmsg_p, zframe_p]
lib.zmsg_first.restype = zframe_p
lib.zmsg_first.argtypes = [zmsg_p]
lib.zmsg_next.restype = zframe_p
lib.zmsg_next.argtypes = [zmsg_p]
lib.zmsg_last.restype = zframe_p
lib.zmsg_last.argtypes = [zmsg_p]
lib.zmsg_save.restype = c_int
lib.zmsg_save.argtypes = [zmsg_p, FILE_p]
lib.zmsg_load.restype = zmsg_p
lib.zmsg_load.argtypes = [zmsg_p, FILE_p]
lib.zmsg_encode.restype = c_size_t
lib.zmsg_encode.argtypes = [zmsg_p, POINTER(POINTER(c_byte))]
lib.zmsg_decode.restype = zmsg_p
lib.zmsg_decode.argtypes = [POINTER(c_byte), c_size_t]
lib.zmsg_dup.restype = zmsg_p
lib.zmsg_dup.argtypes = [zmsg_p]
lib.zmsg_print.restype = None
lib.zmsg_print.argtypes = [zmsg_p]
lib.zmsg_eq.restype = c_bool
lib.zmsg_eq.argtypes = [zmsg_p, zmsg_p]
lib.zmsg_new_signal.restype = zmsg_p
lib.zmsg_new_signal.argtypes = [c_ubyte]
lib.zmsg_signal.restype = c_int
lib.zmsg_signal.argtypes = [zmsg_p]
lib.zmsg_is.restype = c_bool
lib.zmsg_is.argtypes = [c_void_p]
lib.zmsg_test.restype = None
lib.zmsg_test.argtypes = [c_bool]

class Zmsg(object):
    """working with multipart messages"""

    def __init__(self, *args):
        """Create a new empty message object"""
        if len(args) == 2 and type(args[0]) is c_void_p and isinstance(args[1], bool):
            self._as_parameter_ = cast(args[0], zmsg_p) # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        elif len(args) == 2 and type(args[0]) is zmsg_p and isinstance(args[1], bool):
            self._as_parameter_ = args[0] # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        else:
            assert(len(args) == 0)
            self._as_parameter_ = lib.zmsg_new() # Creation of new raw type
            self.allow_destruct = True

    def __del__(self):
        """Destroy a message object and all frames it contains"""
        if self.allow_destruct:
            lib.zmsg_destroy(byref(self._as_parameter_))

    def __bool__(self):
        "Determine whether the object is valid by converting to boolean" # Python 3
        return self._as_parameter_.__bool__()

    def __nonzero__(self):
        "Determine whether the object is valid by converting to boolean" # Python 2
        return self._as_parameter_.__nonzero__()

    @staticmethod
    def recv(source):
        """Receive message from socket, returns zmsg_t object or NULL if the recv
was interrupted. Does a blocking recv. If you want to not block then use
the zloop class or zmsg_recv_nowait or zmq_poll to check for socket input
before receiving."""
        return Zmsg(lib.zmsg_recv(source), True)

    @staticmethod
    def send(self_p, dest):
        """Send message to destination socket, and destroy the message after sending
it successfully. If the message has no frames, sends nothing but destroys
the message anyhow. Nullifies the caller's reference to the message (as
it is a destructor)."""
        return lib.zmsg_send(byref(zmsg_p.from_param(self_p)), dest)

    @staticmethod
    def sendm(self_p, dest):
        """Send message to destination socket as part of a multipart sequence, and
destroy the message after sending it successfully. Note that after a
zmsg_sendm, you must call zmsg_send or another method that sends a final
message part. If the message has no frames, sends nothing but destroys
the message anyhow. Nullifies the caller's reference to the message (as
it is a destructor)."""
        return lib.zmsg_sendm(byref(zmsg_p.from_param(self_p)), dest)

    def size(self):
        """Return size of message, i.e. number of frames (0 or more)."""
        return lib.zmsg_size(self._as_parameter_)

    def content_size(self):
        """Return total size of all frames in message."""
        return lib.zmsg_content_size(self._as_parameter_)

    def prepend(self, frame_p):
        """Push frame to the front of the message, i.e. before all other frames.
Message takes ownership of frame, will destroy it when message is sent.
Returns 0 on success, -1 on error. Deprecates zmsg_push, which did not
nullify the caller's frame reference."""
        return lib.zmsg_prepend(self._as_parameter_, byref(zframe_p.from_param(frame_p)))

    def append(self, frame_p):
        """Add frame to the end of the message, i.e. after all other frames.
Message takes ownership of frame, will destroy it when message is sent.
Returns 0 on success. Deprecates zmsg_add, which did not nullify the
caller's frame reference."""
        return lib.zmsg_append(self._as_parameter_, byref(zframe_p.from_param(frame_p)))

    def pop(self):
        """Remove first frame from message, if any. Returns frame, or NULL."""
        return Zframe(lib.zmsg_pop(self._as_parameter_), True)

    def pushmem(self, src, size):
        """Push block of memory to front of message, as a new frame.
Returns 0 on success, -1 on error."""
        return lib.zmsg_pushmem(self._as_parameter_, src, size)

    def addmem(self, src, size):
        """Add block of memory to the end of the message, as a new frame.
Returns 0 on success, -1 on error."""
        return lib.zmsg_addmem(self._as_parameter_, src, size)

    def pushstr(self, string):
        """Push string as new frame to front of message.
Returns 0 on success, -1 on error."""
        return lib.zmsg_pushstr(self._as_parameter_, string)

    def addstr(self, string):
        """Push string as new frame to end of message.
Returns 0 on success, -1 on error."""
        return lib.zmsg_addstr(self._as_parameter_, string)

    def pushstrf(self, format, *args):
        """Push formatted string as new frame to front of message.
Returns 0 on success, -1 on error."""
        return lib.zmsg_pushstrf(self._as_parameter_, format, *args)

    def addstrf(self, format, *args):
        """Push formatted string as new frame to end of message.
Returns 0 on success, -1 on error."""
        return lib.zmsg_addstrf(self._as_parameter_, format, *args)

    def popstr(self):
        """Pop frame off front of message, return as fresh string. If there were
no more frames in the message, returns NULL."""
        return return_fresh_string(lib.zmsg_popstr(self._as_parameter_))

    def addmsg(self, msg_p):
        """Push encoded message as a new frame. Message takes ownership of
submessage, so the original is destroyed in this call. Returns 0 on
success, -1 on error."""
        return lib.zmsg_addmsg(self._as_parameter_, byref(zmsg_p.from_param(msg_p)))

    def popmsg(self):
        """Remove first submessage from message, if any. Returns zmsg_t, or NULL if
decoding was not succesfull."""
        return Zmsg(lib.zmsg_popmsg(self._as_parameter_), True)

    def remove(self, frame):
        """Remove specified frame from list, if present. Does not destroy frame."""
        return lib.zmsg_remove(self._as_parameter_, frame)

    def first(self):
        """Set cursor to first frame in message. Returns frame, or NULL, if the
message is empty. Use this to navigate the frames as a list."""
        return Zframe(lib.zmsg_first(self._as_parameter_), False)

    def next(self):
        """Return the next frame. If there are no more frames, returns NULL. To move
to the first frame call zmsg_first(). Advances the cursor."""
        return Zframe(lib.zmsg_next(self._as_parameter_), False)

    def last(self):
        """Return the last frame. If there are no frames, returns NULL."""
        return Zframe(lib.zmsg_last(self._as_parameter_), False)

    def save(self, file):
        """Save message to an open file, return 0 if OK, else -1. The message is
saved as a series of frames, each with length and data. Note that the
file is NOT guaranteed to be portable between operating systems, not
versions of CZMQ. The file format is at present undocumented and liable
to arbitrary change."""
        return lib.zmsg_save(self._as_parameter_, coerce_py_file(file))

    @staticmethod
    def load(self, file):
        """Load/append an open file into message, create new message if
null message provided. Returns NULL if the message could not
be loaded."""
        return Zmsg(lib.zmsg_load(self, coerce_py_file(file)), True)

    def encode(self, buffer):
        """Serialize multipart message to a single buffer. Use this method to send
structured messages across transports that do not support multipart data.
Allocates and returns a new buffer containing the serialized message.
To decode a serialized message buffer, use zmsg_decode ()."""
        return lib.zmsg_encode(self._as_parameter_, byref(POINTER(c_byte).from_param(buffer)))

    @staticmethod
    def decode(buffer, buffer_size):
        """Decodes a serialized message buffer created by zmsg_encode () and returns
a new zmsg_t object. Returns NULL if the buffer was badly formatted or
there was insufficient memory to work."""
        return Zmsg(lib.zmsg_decode(buffer, buffer_size), True)

    def dup(self):
        """Create copy of message, as new message object. Returns a fresh zmsg_t
object. If message is null, or memory was exhausted, returns null."""
        return Zmsg(lib.zmsg_dup(self._as_parameter_), True)

    def print(self):
        """Send message to zsys log sink (may be stdout, or system facility as
configured by zsys_set_logstream)."""
        return lib.zmsg_print(self._as_parameter_)

    def eq(self, other):
        """Return true if the two messages have the same number of frames and each
frame in the first message is identical to the corresponding frame in the
other message. As with zframe_eq, return false if either message is NULL."""
        return lib.zmsg_eq(self._as_parameter_, other)

    @staticmethod
    def new_signal(status):
        """Generate a signal message encoding the given status. A signal is a short
message carrying a 1-byte success/failure code (by convention, 0 means
OK). Signals are encoded to be distinguishable from "normal" messages."""
        return Zmsg(lib.zmsg_new_signal(status), True)

    def signal(self):
        """Return signal value, 0 or greater, if message is a signal, -1 if not."""
        return lib.zmsg_signal(self._as_parameter_)

    @staticmethod
    def is_(self):
        """Probe the supplied object, and report if it looks like a zmsg_t."""
        return lib.zmsg_is(self)

    @staticmethod
    def test(verbose):
        """Self test of this class"""
        return lib.zmsg_test(verbose)

# zpoller
lib.zpoller_new.restype = zpoller_p
lib.zpoller_new.argtypes = [c_void_p]
lib.zpoller_destroy.restype = None
lib.zpoller_destroy.argtypes = [POINTER(zpoller_p)]
lib.zpoller_add.restype = c_int
lib.zpoller_add.argtypes = [zpoller_p, c_void_p]
lib.zpoller_remove.restype = c_int
lib.zpoller_remove.argtypes = [zpoller_p, c_void_p]
lib.zpoller_wait.restype = c_void_p
lib.zpoller_wait.argtypes = [zpoller_p, c_int]
lib.zpoller_expired.restype = c_bool
lib.zpoller_expired.argtypes = [zpoller_p]
lib.zpoller_terminated.restype = c_bool
lib.zpoller_terminated.argtypes = [zpoller_p]
lib.zpoller_ignore_interrupts.restype = None
lib.zpoller_ignore_interrupts.argtypes = [zpoller_p]
lib.zpoller_test.restype = None
lib.zpoller_test.argtypes = [c_bool]

class Zpoller(object):
    """event-driven reactor"""

    def __init__(self, *args):
        """Create new poller; the reader can be a libzmq socket (void *), a zsock_t
instance, or a zactor_t instance."""
        if len(args) == 2 and type(args[0]) is c_void_p and isinstance(args[1], bool):
            self._as_parameter_ = cast(args[0], zpoller_p) # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        elif len(args) == 2 and type(args[0]) is zpoller_p and isinstance(args[1], bool):
            self._as_parameter_ = args[0] # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        else:
            assert(len(args) == 2)
            self._as_parameter_ = lib.zpoller_new(args[0], *args[index()-1:]) # Creation of new raw type
            self.allow_destruct = True

    def __del__(self):
        """Destroy a poller"""
        if self.allow_destruct:
            lib.zpoller_destroy(byref(self._as_parameter_))

    def __bool__(self):
        "Determine whether the object is valid by converting to boolean" # Python 3
        return self._as_parameter_.__bool__()

    def __nonzero__(self):
        "Determine whether the object is valid by converting to boolean" # Python 2
        return self._as_parameter_.__nonzero__()

    def add(self, reader):
        """Add a reader to be polled. Returns 0 if OK, -1 on failure. The reader may
be a libzmq void * socket, a zsock_t instance, or a zactor_t instance."""
        return lib.zpoller_add(self._as_parameter_, reader)

    def remove(self, reader):
        """Remove a reader from the poller; returns 0 if OK, -1 on failure. The
reader may be a libzmq void * socket, a zsock_t instance, or a zactor_t
instance."""
        return lib.zpoller_remove(self._as_parameter_, reader)

    def wait(self, timeout):
        """Poll the registered readers for I/O, return first reader that has input.
The reader will be a libzmq void * socket, or a zsock_t or zactor_t
instance as specified in zpoller_new/zpoller_add. The timeout should be
zero or greater, or -1 to wait indefinitely. Socket priority is defined
by their order in the poll list. If you need a balanced poll, use the low
level zmq_poll method directly. If the poll call was interrupted (SIGINT),
or the ZMQ context was destroyed, or the timeout expired, returns NULL.
You can test the actual exit condition by calling zpoller_expired () and
zpoller_terminated (). The timeout is in msec."""
        return c_void_p(lib.zpoller_wait(self._as_parameter_, timeout))

    def expired(self):
        """Return true if the last zpoller_wait () call ended because the timeout
expired, without any error."""
        return lib.zpoller_expired(self._as_parameter_)

    def terminated(self):
        """Return true if the last zpoller_wait () call ended because the process
was interrupted, or the parent context was destroyed."""
        return lib.zpoller_terminated(self._as_parameter_)

    def ignore_interrupts(self):
        """Ignore zsys_interrupted flag in this poller. By default, a zpoller_wait will
return immediately if detects zsys_interrupted is set to something other than
zero. Calling zpoller_ignore_interrupts will supress this behavior."""
        return lib.zpoller_ignore_interrupts(self._as_parameter_)

    @staticmethod
    def test(verbose):
        """Self test of this class"""
        return lib.zpoller_test(verbose)

# zsock
lib.zsock_new.restype = zsock_p
lib.zsock_new.argtypes = [c_int]
lib.zsock_destroy.restype = None
lib.zsock_destroy.argtypes = [POINTER(zsock_p)]
lib.zsock_new_pub.restype = zsock_p
lib.zsock_new_pub.argtypes = [c_char_p]
lib.zsock_new_sub.restype = zsock_p
lib.zsock_new_sub.argtypes = [c_char_p, c_char_p]
lib.zsock_new_req.restype = zsock_p
lib.zsock_new_req.argtypes = [c_char_p]
lib.zsock_new_rep.restype = zsock_p
lib.zsock_new_rep.argtypes = [c_char_p]
lib.zsock_new_dealer.restype = zsock_p
lib.zsock_new_dealer.argtypes = [c_char_p]
lib.zsock_new_router.restype = zsock_p
lib.zsock_new_router.argtypes = [c_char_p]
lib.zsock_new_push.restype = zsock_p
lib.zsock_new_push.argtypes = [c_char_p]
lib.zsock_new_pull.restype = zsock_p
lib.zsock_new_pull.argtypes = [c_char_p]
lib.zsock_new_xpub.restype = zsock_p
lib.zsock_new_xpub.argtypes = [c_char_p]
lib.zsock_new_xsub.restype = zsock_p
lib.zsock_new_xsub.argtypes = [c_char_p]
lib.zsock_new_pair.restype = zsock_p
lib.zsock_new_pair.argtypes = [c_char_p]
lib.zsock_new_stream.restype = zsock_p
lib.zsock_new_stream.argtypes = [c_char_p]
lib.zsock_new_server.restype = zsock_p
lib.zsock_new_server.argtypes = [c_char_p]
lib.zsock_new_client.restype = zsock_p
lib.zsock_new_client.argtypes = [c_char_p]
lib.zsock_bind.restype = c_int
lib.zsock_bind.argtypes = [zsock_p, c_char_p]
lib.zsock_endpoint.restype = c_char_p
lib.zsock_endpoint.argtypes = [zsock_p]
lib.zsock_unbind.restype = c_int
lib.zsock_unbind.argtypes = [zsock_p, c_char_p]
lib.zsock_connect.restype = c_int
lib.zsock_connect.argtypes = [zsock_p, c_char_p]
lib.zsock_disconnect.restype = c_int
lib.zsock_disconnect.argtypes = [zsock_p, c_char_p]
lib.zsock_attach.restype = c_int
lib.zsock_attach.argtypes = [zsock_p, c_char_p, c_bool]
lib.zsock_type_str.restype = c_char_p
lib.zsock_type_str.argtypes = [zsock_p]
lib.zsock_send.restype = c_int
lib.zsock_send.argtypes = [zsock_p, c_char_p]
lib.zsock_vsend.restype = c_int
lib.zsock_vsend.argtypes = [zsock_p, c_char_p, va_list_p]
lib.zsock_recv.restype = c_int
lib.zsock_recv.argtypes = [zsock_p, c_char_p]
lib.zsock_vrecv.restype = c_int
lib.zsock_vrecv.argtypes = [zsock_p, c_char_p, va_list_p]
lib.zsock_bsend.restype = c_int
lib.zsock_bsend.argtypes = [zsock_p, c_char_p]
lib.zsock_brecv.restype = c_int
lib.zsock_brecv.argtypes = [zsock_p, c_char_p]
lib.zsock_set_unbounded.restype = None
lib.zsock_set_unbounded.argtypes = [zsock_p]
lib.zsock_signal.restype = c_int
lib.zsock_signal.argtypes = [zsock_p, c_ubyte]
lib.zsock_wait.restype = c_int
lib.zsock_wait.argtypes = [zsock_p]
lib.zsock_flush.restype = None
lib.zsock_flush.argtypes = [zsock_p]
lib.zsock_is.restype = c_bool
lib.zsock_is.argtypes = [c_void_p]
lib.zsock_resolve.restype = c_void_p
lib.zsock_resolve.argtypes = [c_void_p]
lib.zsock_test.restype = None
lib.zsock_test.argtypes = [c_bool]

class Zsock(object):
    """high-level socket API that hides libzmq contexts and sockets"""

    def __init__(self, *args):
        """Create a new socket. Returns the new socket, or NULL if the new socket
could not be created. Note that the symbol zsock_new (and other
constructors/destructors for zsock) are redirected to the *_checked
variant, enabling intelligent socket leak detection. This can have
performance implications if you use a LOT of sockets. To turn off this
redirection behaviour, define ZSOCK_NOCHECK."""
        if len(args) == 2 and type(args[0]) is c_void_p and isinstance(args[1], bool):
            self._as_parameter_ = cast(args[0], zsock_p) # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        elif len(args) == 2 and type(args[0]) is zsock_p and isinstance(args[1], bool):
            self._as_parameter_ = args[0] # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        else:
            assert(len(args) == 1)
            self._as_parameter_ = lib.zsock_new(args[0]) # Creation of new raw type
            self.allow_destruct = True

    def __del__(self):
        """Destroy the socket. You must use this for any socket created via the
zsock_new method."""
        if self.allow_destruct:
            lib.zsock_destroy(byref(self._as_parameter_))

    def __bool__(self):
        "Determine whether the object is valid by converting to boolean" # Python 3
        return self._as_parameter_.__bool__()

    def __nonzero__(self):
        "Determine whether the object is valid by converting to boolean" # Python 2
        return self._as_parameter_.__nonzero__()

    @staticmethod
    def new_pub(endpoint):
        """Create a PUB socket. Default action is bind."""
        return Zsock(lib.zsock_new_pub(endpoint), True)

    @staticmethod
    def new_sub(endpoint, subscribe):
        """Create a SUB socket, and optionally subscribe to some prefix string. Default
action is connect."""
        return Zsock(lib.zsock_new_sub(endpoint, subscribe), True)

    @staticmethod
    def new_req(endpoint):
        """Create a REQ socket. Default action is connect."""
        return Zsock(lib.zsock_new_req(endpoint), True)

    @staticmethod
    def new_rep(endpoint):
        """Create a REP socket. Default action is bind."""
        return Zsock(lib.zsock_new_rep(endpoint), True)

    @staticmethod
    def new_dealer(endpoint):
        """Create a DEALER socket. Default action is connect."""
        return Zsock(lib.zsock_new_dealer(endpoint), True)

    @staticmethod
    def new_router(endpoint):
        """Create a ROUTER socket. Default action is bind."""
        return Zsock(lib.zsock_new_router(endpoint), True)

    @staticmethod
    def new_push(endpoint):
        """Create a PUSH socket. Default action is connect."""
        return Zsock(lib.zsock_new_push(endpoint), True)

    @staticmethod
    def new_pull(endpoint):
        """Create a PULL socket. Default action is bind."""
        return Zsock(lib.zsock_new_pull(endpoint), True)

    @staticmethod
    def new_xpub(endpoint):
        """Create an XPUB socket. Default action is bind."""
        return Zsock(lib.zsock_new_xpub(endpoint), True)

    @staticmethod
    def new_xsub(endpoint):
        """Create an XSUB socket. Default action is connect."""
        return Zsock(lib.zsock_new_xsub(endpoint), True)

    @staticmethod
    def new_pair(endpoint):
        """Create a PAIR socket. Default action is connect."""
        return Zsock(lib.zsock_new_pair(endpoint), True)

    @staticmethod
    def new_stream(endpoint):
        """Create a STREAM socket. Default action is connect."""
        return Zsock(lib.zsock_new_stream(endpoint), True)

    @staticmethod
    def new_server(endpoint):
        """Create a SERVER socket. Default action is bind."""
        return Zsock(lib.zsock_new_server(endpoint), True)

    @staticmethod
    def new_client(endpoint):
        """Create a CLIENT socket. Default action is connect."""
        return Zsock(lib.zsock_new_client(endpoint), True)

    def bind(self, format, *args):
        """Bind a socket to a formatted endpoint. For tcp:// endpoints, supports
ephemeral ports, if you specify the port number as "*". By default
zsock uses the IANA designated range from C000 (49152) to FFFF (65535).
To override this range, follow the "*" with "[first-last]". Either or
both first and last may be empty. To bind to a random port within the
range, use "!" in place of "*".

Examples:
    tcp://127.0.0.1:*           bind to first free port from C000 up
    tcp://127.0.0.1:!           bind to random port from C000 to FFFF
    tcp://127.0.0.1:*[60000-]   bind to first free port from 60000 up
    tcp://127.0.0.1:![-60000]   bind to random port from C000 to 60000
    tcp://127.0.0.1:![55000-55999]
                                bind to random port from 55000 to 55999

On success, returns the actual port number used, for tcp:// endpoints,
and 0 for other transports. On failure, returns -1. Note that when using
ephemeral ports, a port may be reused by different services without
clients being aware. Protocols that run on ephemeral ports should take
this into account."""
        return lib.zsock_bind(self._as_parameter_, format, *args)

    def endpoint(self):
        """Returns last bound endpoint, if any."""
        return lib.zsock_endpoint(self._as_parameter_)

    def unbind(self, format, *args):
        """Unbind a socket from a formatted endpoint.
Returns 0 if OK, -1 if the endpoint was invalid or the function
isn't supported."""
        return lib.zsock_unbind(self._as_parameter_, format, *args)

    def connect(self, format, *args):
        """Connect a socket to a formatted endpoint
Returns 0 if OK, -1 if the endpoint was invalid."""
        return lib.zsock_connect(self._as_parameter_, format, *args)

    def disconnect(self, format, *args):
        """Disconnect a socket from a formatted endpoint
Returns 0 if OK, -1 if the endpoint was invalid or the function
isn't supported."""
        return lib.zsock_disconnect(self._as_parameter_, format, *args)

    def attach(self, endpoints, serverish):
        """Attach a socket to zero or more endpoints. If endpoints is not null,
parses as list of ZeroMQ endpoints, separated by commas, and prefixed by
'@' (to bind the socket) or '>' (to connect the socket). Returns 0 if all
endpoints were valid, or -1 if there was a syntax error. If the endpoint
does not start with '@' or '>', the serverish argument defines whether
it is used to bind (serverish = true) or connect (serverish = false)."""
        return lib.zsock_attach(self._as_parameter_, endpoints, serverish)

    def type_str(self):
        """Returns socket type as printable constant string."""
        return lib.zsock_type_str(self._as_parameter_)

    def send(self, picture, *args):
        """Send a 'picture' message to the socket (or actor). The picture is a
string that defines the type of each frame. This makes it easy to send
a complex multiframe message in one call. The picture can contain any
of these characters, each corresponding to one or two arguments:

    i = int (signed)
    1 = uint8_t
    2 = uint16_t
    4 = uint32_t
    8 = uint64_t
    s = char *
    b = byte *, size_t (2 arguments)
    c = zchunk_t *
    f = zframe_t *
    h = zhashx_t *
    U = zuuid_t *
    p = void * (sends the pointer value, only meaningful over inproc)
    m = zmsg_t * (sends all frames in the zmsg)
    z = sends zero-sized frame (0 arguments)
    u = uint (deprecated)

Note that s, b, c, and f are encoded the same way and the choice is
offered as a convenience to the sender, which may or may not already
have data in a zchunk or zframe. Does not change or take ownership of
any arguments. Returns 0 if successful, -1 if sending failed for any
reason."""
        return lib.zsock_send(self._as_parameter_, picture, *args)

    def vsend(self, picture, argptr):
        """Send a 'picture' message to the socket (or actor). This is a va_list
version of zsock_send (), so please consult its documentation for the
details."""
        return lib.zsock_vsend(self._as_parameter_, picture, argptr)

    def recv(self, picture, *args):
        """Receive a 'picture' message to the socket (or actor). See zsock_send for
the format and meaning of the picture. Returns the picture elements into
a series of pointers as provided by the caller:

    i = int * (stores signed integer)
    4 = uint32_t * (stores 32-bit unsigned integer)
    8 = uint64_t * (stores 64-bit unsigned integer)
    s = char ** (allocates new string)
    b = byte **, size_t * (2 arguments) (allocates memory)
    c = zchunk_t ** (creates zchunk)
    f = zframe_t ** (creates zframe)
    U = zuuid_t * (creates a zuuid with the data)
    h = zhashx_t ** (creates zhashx)
    p = void ** (stores pointer)
    m = zmsg_t ** (creates a zmsg with the remaing frames)
    z = null, asserts empty frame (0 arguments)
    u = uint * (stores unsigned integer, deprecated)

Note that zsock_recv creates the returned objects, and the caller must
destroy them when finished with them. The supplied pointers do not need
to be initialized. Returns 0 if successful, or -1 if it failed to recv
a message, in which case the pointers are not modified. When message
frames are truncated (a short message), sets return values to zero/null.
If an argument pointer is NULL, does not store any value (skips it).
An 'n' picture matches an empty frame; if the message does not match,
the method will return -1."""
        return lib.zsock_recv(self._as_parameter_, picture, *args)

    def vrecv(self, picture, argptr):
        """Receive a 'picture' message from the socket (or actor). This is a
va_list version of zsock_recv (), so please consult its documentation
for the details."""
        return lib.zsock_vrecv(self._as_parameter_, picture, argptr)

    def bsend(self, picture, *args):
        """Send a binary encoded 'picture' message to the socket (or actor). This
method is similar to zsock_send, except the arguments are encoded in a
binary format that is compatible with zproto, and is designed to reduce
memory allocations. The pattern argument is a string that defines the
type of each argument. Supports these argument types:

 pattern    C type                  zproto type:
    1       uint8_t                 type = "number" size = "1"
    2       uint16_t                type = "number" size = "2"
    4       uint32_t                type = "number" size = "3"
    8       uint64_t                type = "number" size = "4"
    s       char *, 0-255 chars     type = "string"
    S       char *, 0-2^32-1 chars  type = "longstr"
    c       zchunk_t *              type = "chunk"
    f       zframe_t *              type = "frame"
    u       zuuid_t *               type = "uuid"
    m       zmsg_t *                type = "msg"
    p       void *, sends pointer value, only over inproc

Does not change or take ownership of any arguments. Returns 0 if
successful, -1 if sending failed for any reason."""
        return lib.zsock_bsend(self._as_parameter_, picture, *args)

    def brecv(self, picture, *args):
        """Receive a binary encoded 'picture' message from the socket (or actor).
This method is similar to zsock_recv, except the arguments are encoded
in a binary format that is compatible with zproto, and is designed to
reduce memory allocations. The pattern argument is a string that defines
the type of each argument. See zsock_bsend for the supported argument
types. All arguments must be pointers; this call sets them to point to
values held on a per-socket basis. Do not modify or destroy the returned
values. Returns 0 if successful, or -1 if it failed to read a message."""
        return lib.zsock_brecv(self._as_parameter_, picture, *args)

    def set_unbounded(self):
        """Set socket to use unbounded pipes (HWM=0); use this in cases when you are
totally certain the message volume can fit in memory. This method works
across all versions of ZeroMQ. Takes a polymorphic socket reference."""
        return lib.zsock_set_unbounded(self._as_parameter_)

    def signal(self, status):
        """Send a signal over a socket. A signal is a short message carrying a
success/failure code (by convention, 0 means OK). Signals are encoded
to be distinguishable from "normal" messages. Accepts a zock_t or a
zactor_t argument, and returns 0 if successful, -1 if the signal could
not be sent. Takes a polymorphic socket reference."""
        return lib.zsock_signal(self._as_parameter_, status)

    def wait(self):
        """Wait on a signal. Use this to coordinate between threads, over pipe
pairs. Blocks until the signal is received. Returns -1 on error, 0 or
greater on success. Accepts a zsock_t or a zactor_t as argument.
Takes a polymorphic socket reference."""
        return lib.zsock_wait(self._as_parameter_)

    def flush(self):
        """If there is a partial message still waiting on the socket, remove and
discard it. This is useful when reading partial messages, to get specific
message types."""
        return lib.zsock_flush(self._as_parameter_)

    @staticmethod
    def is_(self):
        """Probe the supplied object, and report if it looks like a zsock_t.
Takes a polymorphic socket reference."""
        return lib.zsock_is(self)

    @staticmethod
    def resolve(self):
        """Probe the supplied reference. If it looks like a zsock_t instance, return
the underlying libzmq socket handle; else if it looks like a file
descriptor, return NULL; else if it looks like a libzmq socket handle,
return the supplied value. Takes a polymorphic socket reference."""
        return c_void_p(lib.zsock_resolve(self))

    @staticmethod
    def test(verbose):
        """Self test of this class"""
        return lib.zsock_test(verbose)

# zstr
lib.zstr_recv.restype = c_char_p
lib.zstr_recv.argtypes = [c_void_p]
lib.zstr_send.restype = c_int
lib.zstr_send.argtypes = [c_void_p, c_char_p]
lib.zstr_sendm.restype = c_int
lib.zstr_sendm.argtypes = [c_void_p, c_char_p]
lib.zstr_sendf.restype = c_int
lib.zstr_sendf.argtypes = [c_void_p, c_char_p]
lib.zstr_sendfm.restype = c_int
lib.zstr_sendfm.argtypes = [c_void_p, c_char_p]
lib.zstr_sendx.restype = c_int
lib.zstr_sendx.argtypes = [c_void_p, c_char_p]
lib.zstr_recvx.restype = c_int
lib.zstr_recvx.argtypes = [c_void_p, POINTER(c_char_p)]
lib.zstr_free.restype = None
lib.zstr_free.argtypes = [POINTER(c_char_p)]
lib.zstr_test.restype = None
lib.zstr_test.argtypes = [c_bool]

class Zstr(object):
    """sending and receiving strings"""

    def __bool__(self):
        "Determine whether the object is valid by converting to boolean" # Python 3
        return self._as_parameter_.__bool__()

    def __nonzero__(self):
        "Determine whether the object is valid by converting to boolean" # Python 2
        return self._as_parameter_.__nonzero__()

    @staticmethod
    def recv(source):
        """Receive C string from socket. Caller must free returned string using
zstr_free(). Returns NULL if the context is being terminated or the
process was interrupted."""
        return lib.zstr_recv(source)

    @staticmethod
    def send(dest, string):
        """Send a C string to a socket, as a frame. The string is sent without
trailing null byte; to read this you can use zstr_recv, or a similar
method that adds a null terminator on the received string. String
may be NULL, which is sent as ""."""
        return lib.zstr_send(dest, string)

    @staticmethod
    def sendm(dest, string):
        """Send a C string to a socket, as zstr_send(), with a MORE flag, so that
you can send further strings in the same multi-part message."""
        return lib.zstr_sendm(dest, string)

    @staticmethod
    def sendf(dest, format, *args):
        """Send a formatted string to a socket. Note that you should NOT use
user-supplied strings in the format (they may contain '%' which
will create security holes)."""
        return lib.zstr_sendf(dest, format, *args)

    @staticmethod
    def sendfm(dest, format, *args):
        """Send a formatted string to a socket, as for zstr_sendf(), with a
MORE flag, so that you can send further strings in the same multi-part
message."""
        return lib.zstr_sendfm(dest, format, *args)

    @staticmethod
    def sendx(dest, string, *args):
        """Send a series of strings (until NULL) as multipart data
Returns 0 if the strings could be sent OK, or -1 on error."""
        return lib.zstr_sendx(dest, string, *args)

    @staticmethod
    def recvx(source, string_p, *args):
        """Receive a series of strings (until NULL) from multipart data.
Each string is allocated and filled with string data; if there
are not enough frames, unallocated strings are set to NULL.
Returns -1 if the message could not be read, else returns the
number of strings filled, zero or more. Free each returned string
using zstr_free(). If not enough strings are provided, remaining
multipart frames in the message are dropped."""
        return lib.zstr_recvx(source, byref(c_char_p.from_param(string_p)), *args)

    @staticmethod
    def free(string_p):
        """Free a provided string, and nullify the parent pointer. Safe to call on
a null pointer."""
        return lib.zstr_free(byref(c_char_p.from_param(string_p)))

    @staticmethod
    def test(verbose):
        """Self test of this class"""
        return lib.zstr_test(verbose)

# ztrie
ztrie_destroy_data_fn = CFUNCTYPE(None, POINTER(c_void_p))
lib.ztrie_new.restype = ztrie_p
lib.ztrie_new.argtypes = [char_p]
lib.ztrie_destroy.restype = None
lib.ztrie_destroy.argtypes = [POINTER(ztrie_p)]
lib.ztrie_print.restype = None
lib.ztrie_print.argtypes = [ztrie_p]
lib.ztrie_insert_route.restype = c_int
lib.ztrie_insert_route.argtypes = [ztrie_p, c_char_p, c_void_p, POINTER(ztrie_destroy_data_fn)]
lib.ztrie_remove_route.restype = c_int
lib.ztrie_remove_route.argtypes = [ztrie_p, c_char_p]
lib.ztrie_matches.restype = c_bool
lib.ztrie_matches.argtypes = [ztrie_p, c_char_p]
lib.ztrie_hit_data.restype = c_void_p
lib.ztrie_hit_data.argtypes = [ztrie_p]
lib.ztrie_hit_parameter_count.restype = c_size_t
lib.ztrie_hit_parameter_count.argtypes = [ztrie_p]
lib.ztrie_hit_parameters.restype = zhashx_p
lib.ztrie_hit_parameters.argtypes = [ztrie_p]
lib.ztrie_hit_asterisk_match.restype = c_char_p
lib.ztrie_hit_asterisk_match.argtypes = [ztrie_p]
lib.ztrie_test.restype = None
lib.ztrie_test.argtypes = [c_int]

class Ztrie(object):
    """simple trie for tokenizable strings"""

    def __init__(self, *args):
        """Creates a new ztrie."""
        if len(args) == 2 and type(args[0]) is c_void_p and isinstance(args[1], bool):
            self._as_parameter_ = cast(args[0], ztrie_p) # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        elif len(args) == 2 and type(args[0]) is ztrie_p and isinstance(args[1], bool):
            self._as_parameter_ = args[0] # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        else:
            assert(len(args) == 1)
            self._as_parameter_ = lib.ztrie_new(args[0]) # Creation of new raw type
            self.allow_destruct = True

    def __del__(self):
        """Destroy the ztrie."""
        if self.allow_destruct:
            lib.ztrie_destroy(byref(self._as_parameter_))

    def __bool__(self):
        "Determine whether the object is valid by converting to boolean" # Python 3
        return self._as_parameter_.__bool__()

    def __nonzero__(self):
        "Determine whether the object is valid by converting to boolean" # Python 2
        return self._as_parameter_.__nonzero__()

    def print(self):
        """Print properties of the ztrie object."""
        return lib.ztrie_print(self._as_parameter_)

    def insert_route(self, path, data, destroy_data_fn):
        """Inserts a new route into the tree and attaches the data. Returns -1
if the route already exists, otherwise 0. This method takes ownership of
the provided data if a destroy_data_fn is provided."""
        return lib.ztrie_insert_route(self._as_parameter_, path, data, byref(ztrie_destroy_data_fn.from_param(destroy_data_fn)))

    def remove_route(self, path):
        """Removes a route from the trie and destroys its data. Returns -1 if the
route does not exists, otherwise 0.
the start of the list call zlist_first (). Advances the cursor."""
        return lib.ztrie_remove_route(self._as_parameter_, path)

    def matches(self, path):
        """Returns true if the path matches a route in the tree, otherwise false."""
        return lib.ztrie_matches(self._as_parameter_, path)

    def hit_data(self):
        """Returns the data of a matched route from last ztrie_matches. If the path
did not match, returns NULL. Do not delete the data as it's owned by
ztrie."""
        return c_void_p(lib.ztrie_hit_data(self._as_parameter_))

    def hit_parameter_count(self):
        """Returns the count of parameters that a matched route has."""
        return lib.ztrie_hit_parameter_count(self._as_parameter_)

    def hit_parameters(self):
        """Returns the parameters of a matched route with named regexes from last
ztrie_matches. If the path did not match or the route did not contain any
named regexes, returns NULL."""
        return Zhashx(lib.ztrie_hit_parameters(self._as_parameter_), False)

    def hit_asterisk_match(self):
        """Returns the asterisk matched part of a route, if there has been no match
or no asterisk match, returns NULL."""
        return lib.ztrie_hit_asterisk_match(self._as_parameter_)

    @staticmethod
    def test(verbose):
        """Self test of this class"""
        return lib.ztrie_test(verbose)

# zuuid
lib.zuuid_new.restype = zuuid_p
lib.zuuid_new.argtypes = []
lib.zuuid_destroy.restype = None
lib.zuuid_destroy.argtypes = [POINTER(zuuid_p)]
lib.zuuid_print.restype = None
lib.zuuid_print.argtypes = [zuuid_p]
lib.zuuid_new_from.restype = zuuid_p
lib.zuuid_new_from.argtypes = [POINTER(c_byte)]
lib.zuuid_set.restype = None
lib.zuuid_set.argtypes = [zuuid_p, POINTER(c_byte)]
lib.zuuid_set_str.restype = c_int
lib.zuuid_set_str.argtypes = [zuuid_p, c_char_p]
lib.zuuid_data.restype = POINTER(c_byte)
lib.zuuid_data.argtypes = [zuuid_p]
lib.zuuid_size.restype = c_size_t
lib.zuuid_size.argtypes = [zuuid_p]
lib.zuuid_str.restype = c_char_p
lib.zuuid_str.argtypes = [zuuid_p]
lib.zuuid_str_canonical.restype = c_char_p
lib.zuuid_str_canonical.argtypes = [zuuid_p]
lib.zuuid_export.restype = None
lib.zuuid_export.argtypes = [zuuid_p, POINTER(c_byte)]
lib.zuuid_eq.restype = c_bool
lib.zuuid_eq.argtypes = [zuuid_p, POINTER(c_byte)]
lib.zuuid_neq.restype = c_bool
lib.zuuid_neq.argtypes = [zuuid_p, POINTER(c_byte)]
lib.zuuid_dup.restype = zuuid_p
lib.zuuid_dup.argtypes = [zuuid_p]
lib.zuuid_test.restype = None
lib.zuuid_test.argtypes = [c_bool]

class Zuuid(object):
    """UUID support class"""

    def __init__(self, *args):
        """Constructor"""
        if len(args) == 2 and type(args[0]) is c_void_p and isinstance(args[1], bool):
            self._as_parameter_ = cast(args[0], zuuid_p) # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        elif len(args) == 2 and type(args[0]) is zuuid_p and isinstance(args[1], bool):
            self._as_parameter_ = args[0] # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        else:
            assert(len(args) == 0)
            self._as_parameter_ = lib.zuuid_new() # Creation of new raw type
            self.allow_destruct = True

    def __del__(self):
        """Destructor"""
        if self.allow_destruct:
            lib.zuuid_destroy(byref(self._as_parameter_))

    def __bool__(self):
        "Determine whether the object is valid by converting to boolean" # Python 3
        return self._as_parameter_.__bool__()

    def __nonzero__(self):
        "Determine whether the object is valid by converting to boolean" # Python 2
        return self._as_parameter_.__nonzero__()

    def print(self):
        """Print properties of the zuuid object."""
        return lib.zuuid_print(self._as_parameter_)

    @staticmethod
    def new_from(source):
        """Create UUID object from supplied ZUUID_LEN-octet value."""
        return Zuuid(lib.zuuid_new_from(source), True)

    def set(self, source):
        """Set UUID to new supplied ZUUID_LEN-octet value."""
        return lib.zuuid_set(self._as_parameter_, source)

    def set_str(self, source):
        """Set UUID to new supplied string value skipping '-' and '{' '}'
optional delimiters. Return 0 if OK, else returns -1."""
        return lib.zuuid_set_str(self._as_parameter_, source)

    def data(self):
        """Return UUID binary data."""
        return lib.zuuid_data(self._as_parameter_)

    def size(self):
        """Return UUID binary size"""
        return lib.zuuid_size(self._as_parameter_)

    def str(self):
        """Returns UUID as string"""
        return lib.zuuid_str(self._as_parameter_)

    def str_canonical(self):
        """Return UUID in the canonical string format: 8-4-4-4-12, in lower
case. Caller does not modify or free returned value. See
http://en.wikipedia.org/wiki/Universally_unique_identifier"""
        return lib.zuuid_str_canonical(self._as_parameter_)

    def export(self, target):
        """Store UUID blob in target array"""
        return lib.zuuid_export(self._as_parameter_, target)

    def eq(self, compare):
        """Check if UUID is same as supplied value"""
        return lib.zuuid_eq(self._as_parameter_, compare)

    def neq(self, compare):
        """Check if UUID is different from supplied value"""
        return lib.zuuid_neq(self._as_parameter_, compare)

    def dup(self):
        """Make copy of UUID object; if uuid is null, or memory was exhausted,
returns null."""
        return Zuuid(lib.zuuid_dup(self._as_parameter_), False)

    @staticmethod
    def test(verbose):
        """Self test of this class"""
        return lib.zuuid_test(verbose)

# zhash
zhash_free_fn = CFUNCTYPE(None, c_void_p)
zhash_foreach_fn = CFUNCTYPE(c_int, c_char_p, c_void_p, c_void_p)
lib.zhash_new.restype = zhash_p
lib.zhash_new.argtypes = []
lib.zhash_destroy.restype = None
lib.zhash_destroy.argtypes = [POINTER(zhash_p)]
lib.zhash_insert.restype = c_int
lib.zhash_insert.argtypes = [zhash_p, c_char_p, c_void_p]
lib.zhash_update.restype = None
lib.zhash_update.argtypes = [zhash_p, c_char_p, c_void_p]
lib.zhash_delete.restype = None
lib.zhash_delete.argtypes = [zhash_p, c_char_p]
lib.zhash_lookup.restype = c_void_p
lib.zhash_lookup.argtypes = [zhash_p, c_char_p]
lib.zhash_rename.restype = c_int
lib.zhash_rename.argtypes = [zhash_p, c_char_p, c_char_p]
lib.zhash_freefn.restype = c_void_p
lib.zhash_freefn.argtypes = [zhash_p, c_char_p, zhash_free_fn]
lib.zhash_size.restype = c_size_t
lib.zhash_size.argtypes = [zhash_p]
lib.zhash_dup.restype = zhash_p
lib.zhash_dup.argtypes = [zhash_p]
lib.zhash_keys.restype = zlist_p
lib.zhash_keys.argtypes = [zhash_p]
lib.zhash_first.restype = c_void_p
lib.zhash_first.argtypes = [zhash_p]
lib.zhash_next.restype = c_void_p
lib.zhash_next.argtypes = [zhash_p]
lib.zhash_cursor.restype = c_char_p
lib.zhash_cursor.argtypes = [zhash_p]
lib.zhash_comment.restype = None
lib.zhash_comment.argtypes = [zhash_p, c_char_p]
lib.zhash_pack.restype = zframe_p
lib.zhash_pack.argtypes = [zhash_p]
lib.zhash_unpack.restype = zhash_p
lib.zhash_unpack.argtypes = [zframe_p]
lib.zhash_save.restype = c_int
lib.zhash_save.argtypes = [zhash_p, c_char_p]
lib.zhash_load.restype = c_int
lib.zhash_load.argtypes = [zhash_p, c_char_p]
lib.zhash_refresh.restype = c_int
lib.zhash_refresh.argtypes = [zhash_p]
lib.zhash_autofree.restype = None
lib.zhash_autofree.argtypes = [zhash_p]
lib.zhash_foreach.restype = c_int
lib.zhash_foreach.argtypes = [zhash_p, zhash_foreach_fn, c_void_p]
lib.zhash_test.restype = None
lib.zhash_test.argtypes = [c_int]

class Zhash(object):
    """generic type-free hash container (simple)"""

    def __init__(self, *args):
        """Create a new, empty hash container"""
        if len(args) == 2 and type(args[0]) is c_void_p and isinstance(args[1], bool):
            self._as_parameter_ = cast(args[0], zhash_p) # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        elif len(args) == 2 and type(args[0]) is zhash_p and isinstance(args[1], bool):
            self._as_parameter_ = args[0] # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        else:
            assert(len(args) == 0)
            self._as_parameter_ = lib.zhash_new() # Creation of new raw type
            self.allow_destruct = True

    def __del__(self):
        """Destroy a hash container and all items in it"""
        if self.allow_destruct:
            lib.zhash_destroy(byref(self._as_parameter_))

    def __bool__(self):
        "Determine whether the object is valid by converting to boolean" # Python 3
        return self._as_parameter_.__bool__()

    def __nonzero__(self):
        "Determine whether the object is valid by converting to boolean" # Python 2
        return self._as_parameter_.__nonzero__()

    def insert(self, key, item):
        """Insert item into hash table with specified key and item.
If key is already present returns -1 and leaves existing item unchanged
Returns 0 on success."""
        return lib.zhash_insert(self._as_parameter_, key, item)

    def update(self, key, item):
        """Update item into hash table with specified key and item.
If key is already present, destroys old item and inserts new one.
Use free_fn method to ensure deallocator is properly called on item."""
        return lib.zhash_update(self._as_parameter_, key, item)

    def delete(self, key):
        """Remove an item specified by key from the hash table. If there was no such
item, this function does nothing."""
        return lib.zhash_delete(self._as_parameter_, key)

    def lookup(self, key):
        """Return the item at the specified key, or null"""
        return c_void_p(lib.zhash_lookup(self._as_parameter_, key))

    def rename(self, old_key, new_key):
        """Reindexes an item from an old key to a new key. If there was no such
item, does nothing. Returns 0 if successful, else -1."""
        return lib.zhash_rename(self._as_parameter_, old_key, new_key)

    def freefn(self, key, free_fn):
        """Set a free function for the specified hash table item. When the item is
destroyed, the free function, if any, is called on that item.
Use this when hash items are dynamically allocated, to ensure that
you don't have memory leaks. You can pass 'free' or NULL as a free_fn.
Returns the item, or NULL if there is no such item."""
        return c_void_p(lib.zhash_freefn(self._as_parameter_, key, free_fn))

    def size(self):
        """Return the number of keys/items in the hash table"""
        return lib.zhash_size(self._as_parameter_)

    def dup(self):
        """Make copy of hash table; if supplied table is null, returns null.
Does not copy items themselves. Rebuilds new table so may be slow on
very large tables. NOTE: only works with item values that are strings
since there's no other way to know how to duplicate the item value."""
        return Zhash(lib.zhash_dup(self._as_parameter_), True)

    def keys(self):
        """Return keys for items in table"""
        return Zlist(lib.zhash_keys(self._as_parameter_), True)

    def first(self):
        """Simple iterator; returns first item in hash table, in no given order,
or NULL if the table is empty. This method is simpler to use than the
foreach() method, which is deprecated. To access the key for this item
use zhash_cursor(). NOTE: do NOT modify the table while iterating."""
        return c_void_p(lib.zhash_first(self._as_parameter_))

    def next(self):
        """Simple iterator; returns next item in hash table, in no given order,
or NULL if the last item was already returned. Use this together with
zhash_first() to process all items in a hash table. If you need the
items in sorted order, use zhash_keys() and then zlist_sort(). To
access the key for this item use zhash_cursor(). NOTE: do NOT modify
the table while iterating."""
        return c_void_p(lib.zhash_next(self._as_parameter_))

    def cursor(self):
        """After a successful first/next method, returns the key for the item that
was returned. This is a constant string that you may not modify or
deallocate, and which lasts as long as the item in the hash. After an
unsuccessful first/next, returns NULL."""
        return lib.zhash_cursor(self._as_parameter_)

    def comment(self, format, *args):
        """Add a comment to hash table before saving to disk. You can add as many
comment lines as you like. These comment lines are discarded when loading
the file. If you use a null format, all comments are deleted."""
        return lib.zhash_comment(self._as_parameter_, format, *args)

    def pack(self):
        """Serialize hash table to a binary frame that can be sent in a message.
The packed format is compatible with the 'dictionary' type defined in
http://rfc.zeromq.org/spec:35/FILEMQ, and implemented by zproto:

   ; A list of name/value pairs
   dictionary      = dict-count *( dict-name dict-value )
   dict-count      = number-4
   dict-value      = longstr
   dict-name       = string

   ; Strings are always length + text contents
   longstr         = number-4 *VCHAR
   string          = number-1 *VCHAR

   ; Numbers are unsigned integers in network byte order
   number-1        = 1OCTET
   number-4        = 4OCTET

Comments are not included in the packed data. Item values MUST be
strings."""
        return Zframe(lib.zhash_pack(self._as_parameter_), True)

    @staticmethod
    def unpack(frame):
        """Unpack binary frame into a new hash table. Packed data must follow format
defined by zhash_pack. Hash table is set to autofree. An empty frame
unpacks to an empty hash table."""
        return Zhash(lib.zhash_unpack(frame), True)

    def save(self, filename):
        """Save hash table to a text file in name=value format. Hash values must be
printable strings; keys may not contain '=' character. Returns 0 if OK,
else -1 if a file error occurred."""
        return lib.zhash_save(self._as_parameter_, filename)

    def load(self, filename):
        """Load hash table from a text file in name=value format; hash table must
already exist. Hash values must printable strings; keys may not contain
'=' character. Returns 0 if OK, else -1 if a file was not readable."""
        return lib.zhash_load(self._as_parameter_, filename)

    def refresh(self):
        """When a hash table was loaded from a file by zhash_load, this method will
reload the file if it has been modified since, and is "stable", i.e. not
still changing. Returns 0 if OK, -1 if there was an error reloading the
file."""
        return lib.zhash_refresh(self._as_parameter_)

    def autofree(self):
        """Set hash for automatic value destruction"""
        return lib.zhash_autofree(self._as_parameter_)

    def foreach(self, callback, argument):
        """DEPRECATED as clumsy -- use zhash_first/_next instead
Apply function to each item in the hash table. Items are iterated in no
defined order. Stops if callback function returns non-zero and returns
final return code from callback function (zero = success).
Callback function for zhash_foreach method"""
        return lib.zhash_foreach(self._as_parameter_, callback, argument)

    @staticmethod
    def test(verbose):
        """Self test of this class"""
        return lib.zhash_test(verbose)

# zlist
zlist_compare_fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
zlist_free_fn = CFUNCTYPE(None, c_void_p)
lib.zlist_new.restype = zlist_p
lib.zlist_new.argtypes = []
lib.zlist_destroy.restype = None
lib.zlist_destroy.argtypes = [POINTER(zlist_p)]
lib.zlist_first.restype = c_void_p
lib.zlist_first.argtypes = [zlist_p]
lib.zlist_next.restype = c_void_p
lib.zlist_next.argtypes = [zlist_p]
lib.zlist_last.restype = c_void_p
lib.zlist_last.argtypes = [zlist_p]
lib.zlist_head.restype = c_void_p
lib.zlist_head.argtypes = [zlist_p]
lib.zlist_tail.restype = c_void_p
lib.zlist_tail.argtypes = [zlist_p]
lib.zlist_item.restype = c_void_p
lib.zlist_item.argtypes = [zlist_p]
lib.zlist_append.restype = c_int
lib.zlist_append.argtypes = [zlist_p, c_void_p]
lib.zlist_push.restype = c_int
lib.zlist_push.argtypes = [zlist_p, c_void_p]
lib.zlist_pop.restype = c_void_p
lib.zlist_pop.argtypes = [zlist_p]
lib.zlist_exists.restype = c_bool
lib.zlist_exists.argtypes = [zlist_p, c_void_p]
lib.zlist_remove.restype = None
lib.zlist_remove.argtypes = [zlist_p, c_void_p]
lib.zlist_dup.restype = zlist_p
lib.zlist_dup.argtypes = [zlist_p]
lib.zlist_purge.restype = None
lib.zlist_purge.argtypes = [zlist_p]
lib.zlist_size.restype = c_size_t
lib.zlist_size.argtypes = [zlist_p]
lib.zlist_sort.restype = None
lib.zlist_sort.argtypes = [zlist_p, zlist_compare_fn]
lib.zlist_autofree.restype = None
lib.zlist_autofree.argtypes = [zlist_p]
lib.zlist_comparefn.restype = None
lib.zlist_comparefn.argtypes = [zlist_p, zlist_compare_fn]
lib.zlist_freefn.restype = c_void_p
lib.zlist_freefn.argtypes = [zlist_p, c_void_p, zlist_free_fn, c_bool]
lib.zlist_test.restype = None
lib.zlist_test.argtypes = [c_int]

class Zlist(object):
    """simple generic list container"""

    def __init__(self, *args):
        """Create a new list container"""
        if len(args) == 2 and type(args[0]) is c_void_p and isinstance(args[1], bool):
            self._as_parameter_ = cast(args[0], zlist_p) # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        elif len(args) == 2 and type(args[0]) is zlist_p and isinstance(args[1], bool):
            self._as_parameter_ = args[0] # Conversion from raw type to binding
            self.allow_destruct = args[1] # This is a 'fresh' value, owned by us
        else:
            assert(len(args) == 0)
            self._as_parameter_ = lib.zlist_new() # Creation of new raw type
            self.allow_destruct = True

    def __del__(self):
        """Destroy a list container"""
        if self.allow_destruct:
            lib.zlist_destroy(byref(self._as_parameter_))

    def __bool__(self):
        "Determine whether the object is valid by converting to boolean" # Python 3
        return self._as_parameter_.__bool__()

    def __nonzero__(self):
        "Determine whether the object is valid by converting to boolean" # Python 2
        return self._as_parameter_.__nonzero__()

    def first(self):
        """Return the item at the head of list. If the list is empty, returns NULL.
Leaves cursor pointing at the head item, or NULL if the list is empty."""
        return c_void_p(lib.zlist_first(self._as_parameter_))

    def next(self):
        """Return the next item. If the list is empty, returns NULL. To move to
the start of the list call zlist_first (). Advances the cursor."""
        return c_void_p(lib.zlist_next(self._as_parameter_))

    def last(self):
        """Return the item at the tail of list. If the list is empty, returns NULL.
Leaves cursor pointing at the tail item, or NULL if the list is empty."""
        return c_void_p(lib.zlist_last(self._as_parameter_))

    def head(self):
        """Return first item in the list, or null, leaves the cursor"""
        return c_void_p(lib.zlist_head(self._as_parameter_))

    def tail(self):
        """Return last item in the list, or null, leaves the cursor"""
        return c_void_p(lib.zlist_tail(self._as_parameter_))

    def item(self):
        """Return the current item of list. If the list is empty, returns NULL.
Leaves cursor pointing at the current item, or NULL if the list is empty."""
        return c_void_p(lib.zlist_item(self._as_parameter_))

    def append(self, item):
        """Append an item to the end of the list, return 0 if OK or -1 if this
failed for some reason (out of memory). Note that if a duplicator has
been set, this method will also duplicate the item."""
        return lib.zlist_append(self._as_parameter_, item)

    def push(self, item):
        """Push an item to the start of the list, return 0 if OK or -1 if this
failed for some reason (out of memory). Note that if a duplicator has
been set, this method will also duplicate the item."""
        return lib.zlist_push(self._as_parameter_, item)

    def pop(self):
        """Pop the item off the start of the list, if any"""
        return c_void_p(lib.zlist_pop(self._as_parameter_))

    def exists(self, item):
        """Checks if an item already is present. Uses compare method to determine if
items are equal. If the compare method is NULL the check will only compare
pointers. Returns true if item is present else false."""
        return lib.zlist_exists(self._as_parameter_, item)

    def remove(self, item):
        """Remove the specified item from the list if present"""
        return lib.zlist_remove(self._as_parameter_, item)

    def dup(self):
        """Make a copy of list. If the list has autofree set, the copied list will
duplicate all items, which must be strings. Otherwise, the list will hold
pointers back to the items in the original list. If list is null, returns
NULL."""
        return Zlist(lib.zlist_dup(self._as_parameter_), True)

    def purge(self):
        """Purge all items from list"""
        return lib.zlist_purge(self._as_parameter_)

    def size(self):
        """Return number of items in the list"""
        return lib.zlist_size(self._as_parameter_)

    def sort(self, compare):
        """Sort the list by ascending key value using a straight ASCII comparison.
The sort is not stable, so may reorder items with the same keys."""
        return lib.zlist_sort(self._as_parameter_, compare)

    def autofree(self):
        """Set list for automatic item destruction; item values MUST be strings.
By default a list item refers to a value held elsewhere. When you set
this, each time you append or push a list item, zlist will take a copy
of the string value. Then, when you destroy the list, it will free all
item values automatically. If you use any other technique to allocate
list values, you must free them explicitly before destroying the list.
The usual technique is to pop list items and destroy them, until the
list is empty."""
        return lib.zlist_autofree(self._as_parameter_)

    def comparefn(self, fn):
        """Sets a compare function for this list. The function compares two items.
It returns an integer less than, equal to, or greater than zero if the
first item is found, respectively, to be less than, to match, or be
greater than the second item.
This function is used for sorting, removal and exists checking."""
        return lib.zlist_comparefn(self._as_parameter_, fn)

    def freefn(self, item, fn, at_tail):
        """Set a free function for the specified list item. When the item is
destroyed, the free function, if any, is called on that item.
Use this when list items are dynamically allocated, to ensure that
you don't have memory leaks. You can pass 'free' or NULL as a free_fn.
Returns the item, or NULL if there is no such item."""
        return c_void_p(lib.zlist_freefn(self._as_parameter_, item, fn, at_tail))

    @staticmethod
    def test(verbose):
        """Self test of this class"""
        return lib.zlist_test(verbose)

################################################################################
#  THIS FILE IS 100% GENERATED BY ZPROJECT; DO NOT EDIT EXCEPT EXPERIMENTALLY  #
#  Please refer to the README for information about making permanent changes.  #
################################################################################