text:
#!/usr/bin/env python3
#
# VK
#
# Copyright (c) 2015-2016 The Khronos Group Inc.
# Copyright (c) 2015-2016 Valve Corporation
# Copyright (c) 2015-2016 LunarG, Inc.
# Copyright (c) 2015-2016 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Author: Tobin Ehlis <tobine@google.com>
# Author: Courtney Goeltzenleuchter <courtneygo@google.com>
# Author: Jon Ashburn <jon@lunarg.com>
# Author: Mark Lobodzinski <mark@lunarg.com>
# Author: Mike Stroyan <stroyan@google.com>
# Author: Tony Barbour <tony@LunarG.com>
# Author: Chia-I Wu <olv@google.com>
# Author: Gwan-gyeong Mun <kk.moon@samsung.com>

import sys
import os
import re

import vulkan
import vk_helper
from source_line_info import sourcelineinfo
from collections import defaultdict

def proto_is_global(proto):
    global_function_names = [
        "CreateInstance",
        "EnumerateInstanceLayerProperties",
        "EnumerateInstanceExtensionProperties",
        "EnumerateDeviceLayerProperties",
        "EnumerateDeviceExtensionProperties",
        "CreateXcbSurfaceKHR",
        "GetPhysicalDeviceXcbPresentationSupportKHR",
        "CreateXlibSurfaceKHR",
        "GetPhysicalDeviceXlibPresentationSupportKHR",
        "CreateWaylandSurfaceKHR",
        "GetPhysicalDeviceWaylandPresentationSupportKHR",
        "CreateMirSurfaceKHR",
        "GetPhysicalDeviceMirPresentationSupportKHR",
        "CreateAndroidSurfaceKHR",
        "CreateWin32SurfaceKHR",
        "GetPhysicalDeviceWin32PresentationSupportKHR",
        "GetPhysicalDeviceDisplayPropertiesKHR",
        "GetPhysicalDeviceDisplayPlanePropertiesKHR",
        "GetDisplayPlaneSupportedDisplaysKHR",
        "GetDisplayModePropertiesKHR",
        "CreateDisplayModeKHR",
        "GetDisplayPlaneCapabilitiesKHR",
        "CreateDisplayPlaneSurfaceKHR"
    ]
    if proto.params[0].ty == "VkInstance" or proto.params[0].ty == "VkPhysicalDevice" or proto.name in global_function_names:
       return True
    else:
       return False

def wsi_name(ext_name):
    wsi_prefix = ""
    if 'Xcb' in ext_name:
        wsi_prefix = 'XCB'
    elif 'Xlib' in ext_name:
        wsi_prefix = 'XLIB'
    elif 'Win32' in ext_name:
        wsi_prefix = 'WIN32'
    elif 'Mir' in ext_name:
        wsi_prefix = 'MIR'
    elif 'Wayland' in ext_name:
        wsi_prefix = 'WAYLAND'
    elif 'Android' in ext_name:
        wsi_prefix = 'ANDROID'
    else:
        wsi_prefix = ''
    return wsi_prefix

def wsi_ifdef(ext_name):
    wsi_prefix = wsi_name(ext_name)
    if not wsi_prefix:
        return ''
    else:
        return "#ifdef VK_USE_PLATFORM_%s_KHR" % wsi_prefix

def wsi_endif(ext_name):
    wsi_prefix = wsi_name(ext_name)
    if not wsi_prefix:
        return ''
    else:
        return "#endif  // VK_USE_PLATFORM_%s_KHR" % wsi_prefix

def generate_get_proc_addr_check(name):
    return "    if (!%s || %s[0] != 'v' || %s[1] != 'k')\n" \
           "        return NULL;" % ((name,) * 3)

def ucc_to_U_C_C(CamelCase):
    temp = re.sub('(.)([A-Z][a-z]+)',  r'\1_\2', CamelCase)
    return re.sub('([a-z0-9])([A-Z])', r'\1_\2', temp).upper()

# Parse complete struct chain and add any new ndo_uses to the dict
def gather_object_uses_in_struct(obj_list, struct_type):
    struct_uses = {}
    if vk_helper.typedef_rev_dict[struct_type] in vk_helper.struct_dict:
        struct_type = vk_helper.typedef_rev_dict[struct_type]
        # Parse elements of this struct param to identify objects and/or arrays of objects
        for m in sorted(vk_helper.struct_dict[struct_type]):
            array_len = "%s" % (str(vk_helper.struct_dict[struct_type][m]['array_size']))
            base_type = vk_helper.struct_dict[struct_type][m]['type']
            mem_name = vk_helper.struct_dict[struct_type][m]['name']
            if array_len != '0':
                mem_name = "%s[%s]" % (mem_name, array_len)
            if base_type in obj_list:
                #if array_len not in ndo_uses:
                #    struct_uses[array_len] = []
                #struct_uses[array_len].append("%s%s,%s" % (name_prefix, struct_name, base_type))
                struct_uses[mem_name] = base_type
            elif vk_helper.is_type(base_type, 'struct'):
                sub_uses = gather_object_uses_in_struct(obj_list, base_type)
                if len(sub_uses) > 0:
                    struct_uses[mem_name] = sub_uses
    return struct_uses

# For the given list of object types, Parse the given list of params
#  and return dict of params that use one of the obj_list types
# Format of the dict is that terminal elements have <name>,<type>
#  non-terminal elements will have <name>[<array_size>]
# TODO : This analysis could be done up-front at vk_helper time
def get_object_uses(obj_list, params):
    obj_uses = {}
    local_decls = {}
    param_count = 'NONE' # track params that give array sizes
    for p in params:
        base_type = p.ty.replace('const ', '').strip('*')
        array_len = ''
        is_ptr = False
        if 'count' in p.name.lower():
            param_count = p.name
        ptr_txt = ''
        if '*' in p.ty:
            is_ptr = True
            ptr_txt = '*'
        if base_type in obj_list:
            if is_ptr and 'const' in p.ty and param_count != 'NONE':
                array_len = "[%s]" % param_count
                # Non-arrays we can overwrite in place, but need local decl for arrays
                local_decls[p.name] = '%s%s' % (base_type, ptr_txt)
            #if array_len not in obj_uses:
            #    obj_uses[array_len] = {}
            # obj_uses[array_len][p.name] = base_type
            obj_uses["%s%s" % (p.name, array_len)] = base_type
        elif vk_helper.is_type(base_type, 'struct'):
            struct_name = p.name
            if 'NONE' != param_count:
                struct_name = "%s[%s]" % (struct_name, param_count)
            struct_uses = gather_object_uses_in_struct(obj_list, base_type)
            if len(struct_uses) > 0:
                obj_uses[struct_name] = struct_uses
                # This is a top-level struct w/ uses below it, so need local decl
                local_decls['%s' % (p.name)] = '%s%s' % (base_type, ptr_txt)
    return (obj_uses, local_decls)

class Subcommand(object):
    def __init__(self, outfile):
        self.outfile = outfile
        self.headers = vulkan.headers
        self.protos = vulkan.protos
        self.no_addr = False
        self.layer_name = ""
        self.lineinfo = sourcelineinfo()
        self.wsi = sys.argv[1]

    def run(self):
        if self.outfile:
            with open(self.outfile, "w") as outfile:
                outfile.write(self.generate())
        else:
            print(self.generate())

    def generate(self):
        copyright = self.generate_copyright()
        header = self.generate_header()
        body = self.generate_body()
        footer = self.generate_footer()

        contents = []
        if copyright:
            contents.append(copyright)
        if header:
            contents.append(header)
        if body:
            contents.append(body)
        if footer:
            contents.append(footer)

        return "\n\n".join(contents)

    def generate_copyright(self):
        return """/* THIS FILE IS GENERATED.  DO NOT EDIT. */

/*
 * Copyright (c) 2015-2016 The Khronos Group Inc.
 * Copyright (c) 2015-2016 Valve Corporation
 * Copyright (c) 2015-2016 LunarG, Inc.
 * Copyright (c) 2015-2016 Google, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Author: Tobin Ehlis <tobine@google.com>
 * Author: Courtney Goeltzenleuchter <courtneygo@google.com>
 * Author: Jon Ashburn <jon@lunarg.com>
 * Author: Mark Lobodzinski <mark@lunarg.com>
 * Author: Mike Stroyan <stroyan@google.com>
 * Author: Tony Barbour <tony@LunarG.com>
 */"""

    def generate_header(self):
        return "\n".join(["#include <" + h + ">" for h in self.headers])

    def generate_body(self):
        pass

    def generate_footer(self):
        pass

    # Return set of printf '%' qualifier and input to that qualifier
    def _get_printf_params(self, vk_type, name, output_param, cpp=False):
        # TODO : Need ENUM and STRUCT checks here
        if vk_helper.is_type(vk_type, 'enum'):#"_TYPE" in vk_type: # TODO : This should be generic ENUM check
            return ("%s", "string_%s(%s)" % (vk_type.replace('const ', '').strip('*'), name))
        if "char*" == vk_type:
            return ("%s", name)
        if "uint64" in vk_type:
            if '*' in vk_type:
                return ("%lu", "*%s" % name)
            return ("%lu", name)
        if vk_type.strip('*') in vulkan.object_non_dispatch_list:
            if '*' in vk_type:
                return ("%lu", "%s" % name)
            return ("%lu", "%s" % name)
        if "size" in vk_type:
            if '*' in vk_type:
                return ("%lu", "(unsigned long)*%s" % name)
            return ("%lu", "(unsigned long)%s" % name)
        if "float" in vk_type:
            if '[' in vk_type: # handle array, current hard-coded to 4 (TODO: Make this dynamic)
                if cpp:
                    return ("[%i, %i, %i, %i]", '"[" << %s[0] << "," << %s[1] << "," << %s[2] << "," << %s[3] << "]"' % (name, name, name, name))
                return ("[%f, %f, %f, %f]", "%s[0], %s[1], %s[2], %s[3]" % (name, name, name, name))
            return ("%f", name)
        if "bool" in vk_type.lower() or 'xcb_randr_crtc_t' in vk_type:
            return ("%u", name)
        if True in [t in vk_type.lower() for t in ["int", "flags", "mask", "xcb_window_t"]]:
            if '[' in vk_type: # handle array, current hard-coded to 4 (TODO: Make this dynamic)
                if cpp:
                    return ("[%i, %i, %i, %i]", "%s[0] << %s[1] << %s[2] << %s[3]" % (name, name, name, name))
                return ("[%i, %i, %i, %i]", "%s[0], %s[1], %s[2], %s[3]" % (name, name, name, name))
            if '*' in vk_type:
                if 'pUserData' == name:
                    return ("%i", "((pUserData == 0) ? 0 : *(pUserData))")
                if 'const' in vk_type.lower():
                    return ("0x%p", "(void*)(%s)" % name)
                return ("%i", "*(%s)" % name)
            return ("%i", name)
        # TODO : This is special-cased as there's only one "format" param currently and it's nice to expand it
        if "VkFormat" == vk_type:
            if cpp:
                return ("0x%p", "&%s" % name)
            return ("{%s.channelFormat = %%s, %s.numericFormat = %%s}" % (name, name), "string_VK_COLOR_COMPONENT_FORMAT(%s.channelFormat), string_VK_FORMAT_RANGE_SIZE(%s.numericFormat)" % (name, name))
        if output_param:
            return ("0x%p", "(void*)*%s" % name)
        if vk_helper.is_type(vk_type, 'struct') and '*' not in vk_type:
            return ("0x%p", "(void*)(&%s)" % name)
        return ("0x%p", "(void*)(%s)" % name)

    def _gen_create_msg_callback(self):
        r_body = []
        r_body.append('%s' % self.lineinfo.get())
        r_body.append('VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(')
        r_body.append('        VkInstance                                   instance,')
        r_body.append('        const VkDebugReportCallbackCreateInfoEXT*    pCreateInfo,')
        r_body.append('        const VkAllocationCallbacks*                 pAllocator,')
        r_body.append('        VkDebugReportCallbackEXT*                    pCallback)')
        r_body.append('{')
        # Switch to this code section for the new per-instance storage and debug callbacks
        if self.layer_name in ['unique_objects']:
            r_body.append('    VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
            r_body.append('    VkResult result = pInstanceTable->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);')
            r_body.append('    if (VK_SUCCESS == result) {')
            r_body.append('        layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
            r_body.append('        result = layer_create_msg_callback(my_data->report_data,')
            r_body.append('                                           false,')
            r_body.append('                                           pCreateInfo,')
            r_body.append('                                           pAllocator,')
            r_body.append('                                           pCallback);')
            r_body.append('    }')
            r_body.append('    return result;')
        else:
            r_body.append('    VkResult result = instance_dispatch_table(instance)->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);')
            r_body.append('    if (VK_SUCCESS == result) {')
            r_body.append('        layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
            r_body.append('        result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pCallback);')
            r_body.append('    }')
            r_body.append('    return result;')
        r_body.append('}')
        return "\n".join(r_body)

    def _gen_destroy_msg_callback(self):
        r_body = []
        r_body.append('%s' % self.lineinfo.get())
        r_body.append('VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, const VkAllocationCallbacks *pAllocator)')
        r_body.append('{')
        # Switch to this code section for the new per-instance storage and debug callbacks
        if self.layer_name in ['unique_objects']:
            r_body.append('    VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
        else:
            r_body.append('    VkLayerInstanceDispatchTable *pInstanceTable = instance_dispatch_table(instance);')
        r_body.append('    pInstanceTable->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);')
        r_body.append('    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
        r_body.append('    layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);')
        r_body.append('}')
        return "\n".join(r_body)

    def _gen_debug_report_msg(self):
        r_body = []
        r_body.append('%s' % self.lineinfo.get())
        r_body.append('VKAPI_ATTR void VKAPI_CALL DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT    flags, VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg)')
        r_body.append('{')
        # Switch to this code section for the new per-instance storage and debug callbacks
        r_body.append('    VkLayerInstanceDispatchTable *pInstanceTable = instance_dispatch_table(instance);')
        r_body.append('    pInstanceTable->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);')
        r_body.append('}')
        return "\n".join(r_body)

    def _gen_layer_logging_workaround(self):
        body = []
        body.append('%s' % self.lineinfo.get())
        body.append('// vk_layer_logging.h expects these to be defined')
        body.append('')
        body.append('VKAPI_ATTR VkResult VKAPI_CALL')
        body.append('vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,')
        body.append('                               const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {')
        body.append('    return %s::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);' % self.layer_name)
        body.append('}')
        body.append('')
        body.append('VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,')
        body.append('                                                                           VkDebugReportCallbackEXT msgCallback,')
        body.append('                                                                           const VkAllocationCallbacks *pAllocator) {')
        body.append('    %s::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);' % self.layer_name)
        body.append('}')
        body.append('')
        body.append('VKAPI_ATTR void VKAPI_CALL')
        body.append('vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,')
        body.append('                        size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {')
        body.append('    %s::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);' % self.layer_name)
        body.append('}')

        return "\n".join(body)

    def _gen_layer_interface_v0_functions(self):
        body = []
        body.append('%s' % self.lineinfo.get())
        body.append('// loader-layer interface v0, just wrappers since there is only a layer')
        body.append('')

        body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,  VkExtensionProperties* pProperties)')
        body.append('{')
        body.append('    return %s::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);' % self.layer_name)
        body.append('}')
        body.append('')
        body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,  VkLayerProperties* pProperties)')
        body.append('{')
        body.append('    return %s::EnumerateInstanceLayerProperties(pCount, pProperties);' % self.layer_name)
        body.append('}')
        body.append('')
        body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties* pProperties)')
        body.append('{')
        body.append('    // the layer command handles VK_NULL_HANDLE just fine internally')
        body.append('    assert(physicalDevice == VK_NULL_HANDLE);')
        body.append('    return %s::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);' % self.layer_name)
        body.append('}')
        body.append('')
        body.append('VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName)')
        body.append('{')
        body.append('    return %s::GetDeviceProcAddr(dev, funcName);' % self.layer_name)
        body.append('}')
        body.append('')
        body.append('VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName)')
        body.append('{')
        body.append('    return %s::GetInstanceProcAddr(instance, funcName);' % self.layer_name)
        body.append('}')
        body.append('')
        body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,')
        body.append('                                                                                const char *pLayerName, uint32_t *pCount,')
        body.append('                                                                                VkExtensionProperties *pProperties)')
        body.append('{')
        body.append('    // the layer command handles VK_NULL_HANDLE just fine internally')
        body.append('    assert(physicalDevice == VK_NULL_HANDLE);')
        body.append('    return %s::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);' % self.layer_name)
        body.append('}')

        return "\n".join(body)

    def _generate_dispatch_entrypoints(self, qual=""):
        if qual:
            qual += " "

        funcs = []
        intercepted = []
        for proto in self.protos:
            if proto.name in ["EnumerateInstanceExtensionProperties",
                              "EnumerateInstanceLayerProperties",
                              "EnumerateDeviceLayerProperties",
                              "GetDeviceProcAddr",
                              "GetInstanceProcAddr"]:
                funcs.append(proto.c_func(attr="VKAPI") + ';')
                intercepted.append(proto)
            else:
                intercept = self.generate_intercept(proto, qual)
                if intercept is None:
                    # fill in default intercept for certain entrypoints
                    if 'CreateDebugReportCallbackEXT' == proto.name:
                        intercept = self._gen_layer_dbg_create_msg_callback()
                    elif 'DestroyDebugReportCallbackEXT' == proto.name:
                        intercept = self._gen_layer_dbg_destroy_msg_callback()
                    elif 'DebugReportMessageEXT' == proto.name:
                        intercept = self._gen_debug_report_msg()
                    elif 'CreateDevice' == proto.name:
                        funcs.append('/* CreateDevice HERE */')

                if intercept is not None:
                    funcs.append(intercept)
                    if not "KHR" in proto.name:
                        intercepted.append(proto)

        instance_lookups = []
        device_lookups = []
        for proto in intercepted:
            if proto_is_global(proto):
                instance_lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
                instance_lookups.append("    return (PFN_vkVoidFunction) %s;" % (proto.name))
            else:
                device_lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
                device_lookups.append("    return (PFN_vkVoidFunction) %s;" % (proto.name))

        # add customized intercept_core_device_command
        body = []
        body.append('%s' % self.lineinfo.get())
        body.append("static inline PFN_vkVoidFunction intercept_core_device_command(const char *name)")
        body.append("{")
        body.append(generate_get_proc_addr_check("name"))
        body.append("")
        body.append("    name += 2;")
        body.append("    %s" % "\n    ".join(device_lookups))
        body.append("")
        body.append("    return NULL;")
        body.append("}")
        # add intercept_core_instance_command
        body.append("static inline PFN_vkVoidFunction intercept_core_instance_command(const char *name)")
        body.append("{")
        body.append(generate_get_proc_addr_check("name"))
        body.append("")
        body.append("    name += 2;")
        body.append("    %s" % "\n    ".join(instance_lookups))
        body.append("")
        body.append("    return NULL;")
        body.append("}")

        funcs.append("\n".join(body))
        return "\n\n".join(funcs)

    def _generate_extensions(self):
        exts = []
        exts.append('%s' % self.lineinfo.get())
        exts.append(self._gen_create_msg_callback())
        exts.append(self._gen_destroy_msg_callback())
        exts.append(self._gen_debug_report_msg())
        return "\n".join(exts)

    def _generate_layer_introspection_function(self):
        body = []
        body.append('%s' % self.lineinfo.get())
        body.append('static const VkLayerProperties globalLayerProps = {')
        body.append('    "VK_LAYER_GOOGLE_%s",' % self.layer_name)
        body.append('    VK_LAYER_API_VERSION, // specVersion')
        body.append('    1, // implementationVersion')
        body.append('    "Google Validation Layer"')
        body.append('};')
        body.append('')

        body.append('VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount,  VkLayerProperties* pProperties)')
        body.append('{')
        body.append('    return util_GetLayerProperties(1, &globalLayerProps, pCount, pProperties);')
        body.append('}')
        body.append('')
        body.append('VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties* pProperties)')
        body.append('{')
        body.append('    return util_GetLayerProperties(1, &globalLayerProps, pCount, pProperties);')
        body.append('}')
        body.append('')
        body.append('VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,  VkExtensionProperties* pProperties)')
        body.append('{')
        body.append('    if (pLayerName && !strcmp(pLayerName, globalLayerProps.layerName))')
        body.append('        return util_GetExtensionProperties(0, NULL, pCount, pProperties);')
        body.append('')
        body.append('    return VK_ERROR_LAYER_NOT_PRESENT;')
        body.append('}')
        body.append('')
        body.append('VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,')
        body.append('                                                                  const char *pLayerName, uint32_t *pCount,')
        body.append('                                                                  VkExtensionProperties *pProperties)')
        body.append('{')
        body.append('    if (pLayerName && !strcmp(pLayerName, globalLayerProps.layerName))')
        body.append('        return util_GetExtensionProperties(0, nullptr, pCount, pProperties);')
        body.append('')
        body.append('    assert(physicalDevice);')
        body.append('    VkLayerInstanceDispatchTable* pTable = get_dispatch_table(%s_instance_table_map, physicalDevice);' % self.layer_name)
        body.append('    return pTable->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);')
        body.append('}')

        return "\n".join(body)

    def _generate_layer_gpa_function(self, extensions=[], instance_extensions=[]):
        func_body = []
#
# New style of GPA Functions for the new layer_data/layer_logging changes
#
        if self.layer_name in ['unique_objects']:
            for ext_enable, ext_list in extensions:
                func_body.append('%s' % self.lineinfo.get())
                func_body.append('static inline PFN_vkVoidFunction intercept_%s_command(const char *name, VkDevice dev)' % ext_enable)
                func_body.append('{')
                func_body.append('    if (dev) {')
                func_body.append('        layer_data *my_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map);')
                func_body.append('        if (!my_data->%s)' % ext_enable)
                func_body.append('            return nullptr;')
                func_body.append('    }\n')

                for ext_name in ext_list:
                    func_body.append('    if (!strcmp("%s", name))\n'
                                     '        return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (ext_name, ext_name[2:]))
                func_body.append('\n    return nullptr;')
                func_body.append('}\n')

            func_body.append("VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char* funcName)\n"
                             "{\n"
                             "    PFN_vkVoidFunction addr;\n"
                             "    addr = intercept_core_device_command(funcName);\n"
                             "    if (addr)\n"
                             "        return addr;\n"
                             "    assert(device);\n")
            for ext_enable, _ in extensions:
                func_body.append('    addr = intercept_%s_command(funcName, device);' % ext_enable)
                func_body.append('    if (addr)\n'
                                 '        return addr;')
            func_body.append("\n    if (get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr == NULL)\n"
                             "        return NULL;\n"
                             "    return get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr(device, funcName);\n"
                             "}\n" % (self.layer_name, self.layer_name))

            # The WSI-related extensions have independent extension enables
            wsi_sub_enables = {'WIN32': 'win32_enabled',
                               'XLIB': 'xlib_enabled',
                               'XCB': 'xcb_enabled',
                               'MIR': 'mir_enabled',
                               'WAYLAND': 'wayland_enabled',
                               'ANDROID': 'android_enabled'}

            for ext_enable, ext_list in instance_extensions:
                func_body.append('%s' % self.lineinfo.get())
                func_body.append('static inline PFN_vkVoidFunction intercept_%s_command(const char *name, VkInstance instance)' % ext_enable)
                func_body.append('{')
                if ext_enable == 'msg_callback_get_proc_addr':
                    func_body.append("    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);\n"
                                     "    return debug_report_get_instance_proc_addr(my_data->report_data, name);")
                else:
                    func_body.append("    VkLayerInstanceDispatchTable* pTable = get_dispatch_table(%s_instance_table_map, instance);" % self.layer_name)
                    func_body.append('    if (instanceExtMap.size() == 0 || !instanceExtMap[pTable].%s)' % ext_enable)
                    func_body.append('        return nullptr;\n')

                    for ext_name in ext_list:
                        if wsi_name(ext_name):
                            func_body.append('%s' % wsi_ifdef(ext_name))
                            if wsi_sub_enables[wsi_name(ext_name)]:
                                func_body.append('    if ((instanceExtMap[pTable].%s == true) && !strcmp("%s", name))\n'
                                                 '        return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (wsi_sub_enables[wsi_name(ext_name)], ext_name, ext_name[2:]))
                        else:
                            func_body.append('    if (!strcmp("%s", name))\n'
                                             '        return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (ext_name, ext_name[2:]))
                        if wsi_name(ext_name):
                            func_body.append('%s' % wsi_endif(ext_name))

                    func_body.append('\n    return nullptr;')
                func_body.append('}\n')

            func_body.append("VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
                             "{\n"
                             "    PFN_vkVoidFunction addr;\n"
                             "    addr = intercept_core_instance_command(funcName);\n"
                             "    if (!addr) {\n"
                             "        addr = intercept_core_device_command(funcName);\n"
                             "    }")

            for ext_enable, _ in extensions:
                func_body.append("    if (!addr) {\n"
                                 "        addr = intercept_%s_command(funcName, VkDevice(VK_NULL_HANDLE));\n"
                                 "    }" % ext_enable)

            func_body.append("    if (addr) {\n"
                             "        return addr;\n"
                             "    }\n"
                             "    assert(instance);\n"
                             )

            for ext_enable, _ in instance_extensions:
                func_body.append('    addr = intercept_%s_command(funcName, instance);' % ext_enable)
                func_body.append('    if (addr)\n'
                                 '        return addr;\n')

            func_body.append("    if (get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr == NULL) {\n"
                             "        return NULL;\n"
                             "    }\n"
                             "    return get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr(instance, funcName);\n"
                             "}\n" % (self.layer_name, self.layer_name))
            return "\n".join(func_body)
        else:
            func_body.append('%s' % self.lineinfo.get())
            func_body.append("VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char* funcName)\n"
                             "{\n"
                             "    PFN_vkVoidFunction addr;\n")
            func_body.append("\n"
                             "    loader_platform_thread_once(&initOnce, init%s);\n\n"
                             "    addr = intercept_core_device_command(funcName);\n"
                             "    if (addr)\n"
                             "        return addr;" % self.layer_name)
            func_body.append("    assert(device);\n")
            func_body.append('')
            func_body.append('    VkLayerDispatchTable *pDisp =  device_dispatch_table(device);')
            if 0 != len(extensions):
                extra_space = ""
                for (ext_enable, ext_list) in extensions:
                    if 0 != len(ext_enable):
                        func_body.append('    if (deviceExtMap.size() != 0 && deviceExtMap[pDisp].%s)' % ext_enable)
                        func_body.append('    {')
                        extra_space = "    "
                    for ext_name in ext_list:
                        func_body.append('    %sif (!strcmp("%s", funcName))\n'
                                         '            return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
                    if 0 != len(ext_enable):
                        func_body.append('    }')
            func_body.append('%s' % self.lineinfo.get())
            func_body.append("    {\n"
                             "        if (pDisp->GetDeviceProcAddr == NULL)\n"
                             "            return NULL;\n"
                             "        return pDisp->GetDeviceProcAddr(device, funcName);\n"
                             "    }\n"
                             "}\n")
            func_body.append('%s' % self.lineinfo.get())
            func_body.append("VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
                             "{\n"
                             "    PFN_vkVoidFunction addr;\n"
                             )
            func_body.append(
                             "    loader_platform_thread_once(&initOnce, init%s);\n\n"
                             "    addr = intercept_core_instance_command(funcName);\n"
                             "    if (addr)\n"
                             "        return addr;" % self.layer_name)
            func_body.append("    assert(instance);\n")
            func_body.append("")
            func_body.append("    VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);\n")
            if 0 != len(instance_extensions):
                extra_space = ""
                for (ext_enable, ext_list) in instance_extensions:
                    if 0 != len(ext_enable):
                        if ext_enable == 'msg_callback_get_proc_addr':
                            func_body.append("    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);\n"
                                     "    addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);\n"
                                     "    if (addr) {\n"
                                     "        return addr;\n"
                                     "    }\n")
                        else:
                            func_body.append('    if (instanceExtMap.size() != 0 && instanceExtMap[pTable].%s)' % ext_enable)
                            func_body.append('    {')
                            extra_space = "    "
                            for ext_name in ext_list:
                                if wsi_name(ext_name):
                                    func_body.append('%s' % wsi_ifdef(ext_name))
                                func_body.append('    %sif (!strcmp("%s", funcName))\n'
                                         '            return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
                                if wsi_name(ext_name):
                                    func_body.append('%s' % wsi_endif(ext_name))
                            if 0 != len(ext_enable):
                                func_body.append('    }\n')

            func_body.append("    if (pTable->GetInstanceProcAddr == NULL)\n"
                             "        return NULL;\n"
                             "    return pTable->GetInstanceProcAddr(instance, funcName);\n"
                             "}\n")
            return "\n".join(func_body)

    def _generate_layer_initialization(self, init_opts=False, prefix='vk', lockname=None, condname=None):
        func_body = ["#include \"vk_dispatch_table_helper.h\""]
        func_body.append('%s' % self.lineinfo.get())
        func_body.append('static void init_%s(layer_data *my_data, const VkAllocationCallbacks *pAllocator)\n'
                         '{\n' % self.layer_name)
        if init_opts:
            func_body.append('%s' % self.lineinfo.get())
            func_body.append('')
            func_body.append('    layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_%s");' % self.layer_name)
            func_body.append('')
        if lockname is not None:
            func_body.append('%s' % self.lineinfo.get())
            func_body.append("    if (!%sLockInitialized)" % lockname)
            func_body.append("    {")
            func_body.append("        // TODO/TBD: Need to delete this mutex sometime.  How???")
            func_body.append("        loader_platform_thread_create_mutex(&%sLock);" % lockname)
            if condname is not None:
                func_body.append("        loader_platform_thread_init_cond(&%sCond);" % condname)
            func_body.append("        %sLockInitialized = 1;" % lockname)
            func_body.append("    }")
        func_body.append("}\n")
        func_body.append('')
        return "\n".join(func_body)

class UniqueObjectsSubcommand(Subcommand):
    def generate_header(self):
        header_txt = []
        header_txt.append('%s' % self.lineinfo.get())
        header_txt.append('#include "unique_objects.h"')
        return "\n".join(header_txt)

    # Generate UniqueObjects code for given struct_uses dict of objects that need to be unwrapped
    # vector_name_set is used to make sure we don't replicate vector names
    # first_level_param indicates if elements are passed directly into the function else they're below a ptr/struct
    # TODO : Comment this code
    def _gen_obj_code(self, struct_uses, param_type, indent, prefix, array_index, vector_name_set, first_level_param):
        decls = ''
        pre_code = ''
        post_code = ''
        for obj in sorted(struct_uses):
            name = obj
            array = ''
            if '[' in obj:
                (name, array) = obj.split('[')
                array = array.strip(']')
            ptr_type = False
            if 'p' == obj[0] and obj[1] != obj[1].lower(): # TODO : Not ideal way to determine ptr
                ptr_type = True
            if isinstance(struct_uses[obj], dict):
                local_prefix = ''
                name = '%s%s' % (prefix, name)
                if ptr_type:
                    if first_level_param and name in param_type:
                        pre_code += '%sif (%s) {\n' % (indent, name)
                    else: # shadow ptr will have been initialized at this point so check it vs. source ptr
                        pre_code += '%sif (local_%s) {\n' % (indent, name)
                    indent += '    '
                if array != '':
                    if 'p' == array[0] and array[1] != array[1].lower(): # TODO : Not ideal way to determine ptr
                        count_prefix = '*'
                    else:
                        count_prefix = ''
                    idx = 'idx%s' % str(array_index)
                    array_index += 1
                    if first_level_param and name in param_type:
                        pre_code += '%slocal_%s = new safe_%s[%s%s];\n' % (indent, name, param_type[name].strip('*'), count_prefix, array)
                        post_code += '    if (local_%s)\n' % (name)
                        post_code += '        delete[] local_%s;\n' % (name)
                    pre_code += '%sfor (uint32_t %s=0; %s<%s%s%s; ++%s) {\n' % (indent, idx, idx, count_prefix, prefix, array, idx)
                    indent += '    '
                    if first_level_param:
                        pre_code += '%slocal_%s[%s].initialize(&%s[%s]);\n' % (indent, name, idx, name, idx)
                    local_prefix = '%s[%s].' % (name, idx)
                elif ptr_type:
                    if first_level_param and name in param_type:
                        pre_code += '%slocal_%s = new safe_%s(%s);\n' % (indent, name, param_type[name].strip('*'), name)
                        post_code += '    if (local_%s)\n' % (name)
                        post_code += '        delete local_%s;\n' % (name)
                    local_prefix = '%s->' % (name)
                else:
                    local_prefix = '%s.' % (name)
                assert isinstance(decls, object)
                (tmp_decl, tmp_pre, tmp_post) = self._gen_obj_code(struct_uses[obj], param_type, indent, local_prefix, array_index, vector_name_set, False)
                decls += tmp_decl
                pre_code += tmp_pre
                post_code += tmp_post
                if array != '':
                    indent = indent[4:]
                    pre_code += '%s}\n' % (indent)
                if ptr_type:
                    indent = indent[4:]
                    pre_code += '%s}\n' % (indent)
            else:
                if (array_index > 0) or array != '': # TODO : This is not ideal, really want to know if we're anywhere under an array
                    if first_level_param:
                        decls += '%s%s* local_%s = NULL;\n' % (indent, struct_uses[obj], name)
                    if array != '' and not first_level_param: # ptrs under structs will have been initialized so use local_*
                        pre_code += '%sif (local_%s%s) {\n' %(indent, prefix, name)
                    else:
                        pre_code += '%sif (%s%s) {\n' %(indent, prefix, name)
                    indent += '    '
                    if array != '':
                        idx = 'idx%s' % str(array_index)
                        array_index += 1
                        if first_level_param:
                            pre_code += '%slocal_%s = new %s[%s];\n' % (indent, name, struct_uses[obj], array)
                            post_code += '    if (local_%s)\n' % (name)
                            post_code += '        delete[] local_%s;\n' % (name)
                        pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
                        indent += '    '
                        name = '%s[%s]' % (name, idx)
                    if name not in vector_name_set:
                        vector_name_set.add(name)
                    pre_code += '%slocal_%s%s = (%s)my_map_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(%s%s)];\n' % (indent, prefix, name, struct_uses[obj], prefix, name)
                    if array != '':
                        indent = indent[4:]
                        pre_code += '%s}\n' % (indent)
                    indent = indent[4:]
                    pre_code += '%s}\n' % (indent)
                else:
                    pre_code += '%s\n' % (self.lineinfo.get())
                    if '->' in prefix: # need to update local struct
                        pre_code += '%slocal_%s%s = (%s)my_map_data->unique_id_mapping[reinterpret_cast<const uint64_t &>(%s%s)];\n' % (indent, prefix, name, struct_uses[obj], prefix, name)
                    else:
                        pre_code += '%s%s = (%s)my_map_data->unique_id_mapping[reinterpret_cast<uint64_t &>(%s)];\n' % (indent, name, struct_uses[obj], name)
        return decls, pre_code, post_code

    def generate_intercept(self, proto, qual):
        create_func = False
        destroy_func = False
        last_param_index = None #typcially we look at all params for ndos
        pre_call_txt = '' # code prior to calling down chain such as unwrap uses of ndos
        post_call_txt = '' # code following call down chain such to wrap newly created ndos, or destroy local wrap struct
        funcs = []
        indent = '    ' # indent level for generated code
        decl = proto.c_func(attr="VKAPI")
        # A few API cases that are manual code
        # TODO : Special case Create*Pipelines funcs to handle creating multiple unique objects
        explicit_unique_objects_functions = ['GetSwapchainImagesKHR',
                                             'CreateSwapchainKHR',
                                             'CreateInstance',
                                             'DestroyInstance',
                                             'CreateDevice',
                                             'DestroyDevice',
                                             'AllocateMemory',
                                             'CreateComputePipelines',
                                             'CreateGraphicsPipelines',
                                             'GetPhysicalDeviceDisplayPropertiesKHR',
                                             'GetDisplayPlaneSupportedDisplaysKHR',
                                             'GetDisplayModePropertiesKHR'
                                             ]
        # TODO : This is hacky, need to make this a more general-purpose solution for all layers
        ifdef_dict = {'CreateXcbSurfaceKHR': 'VK_USE_PLATFORM_XCB_KHR',
                      'CreateAndroidSurfaceKHR': 'VK_USE_PLATFORM_ANDROID_KHR',
                      'CreateWin32SurfaceKHR': 'VK_USE_PLATFORM_WIN32_KHR',
                      'CreateXlibSurfaceKHR': 'VK_USE_PLATFORM_XLIB_KHR',
                      'CreateWaylandSurfaceKHR': 'VK_USE_PLATFORM_WAYLAND_KHR',
                      'CreateMirSurfaceKHR': 'VK_USE_PLATFORM_MIR_KHR'}
        # Give special treatment to create functions that return multiple new objects
        # This dict stores array name and size of array
        custom_create_dict = {'pDescriptorSets' : 'pAllocateInfo->descriptorSetCount'}
        pre_call_txt += '%s\n' % (self.lineinfo.get())
        if proto.name in explicit_unique_objects_functions:
            funcs.append('%s%s\n'
                     '{\n'
                     '    return explicit_%s;\n'
                     '}' % (qual, decl, proto.c_call()))
            return "".join(funcs)
        if True in [create_txt in proto.name for create_txt in ['Create', 'Allocate']]:
            create_func = True
            last_param_index = -1 # For create funcs don't care if last param is ndo
        if True in [destroy_txt in proto.name for destroy_txt in ['Destroy', 'Free']]:
            destroy_obj_type = proto.params[-2].ty
            if destroy_obj_type in vulkan.object_non_dispatch_list:
                destroy_func = True

        # First thing we need to do is gather uses of non-dispatchable-objects (ndos)
        (struct_uses, local_decls) = get_object_uses(vulkan.object_non_dispatch_list, proto.params[1:last_param_index])

        dispatch_param = proto.params[0].name
        if 'CreateInstance' in proto.name:
           dispatch_param = '*' + proto.params[1].name
        pre_call_txt += '%slayer_data *my_map_data = get_my_data_ptr(get_dispatch_key(%s), layer_data_map);\n' % (indent, dispatch_param)
        if len(struct_uses) > 0:
            pre_call_txt += '// STRUCT USES:%s\n' % sorted(struct_uses)
            if len(local_decls) > 0:
                pre_call_txt += '//LOCAL DECLS:%s\n' % sorted(local_decls)
            if destroy_func: # only one object
                pre_call_txt += '%sstd::unique_lock<std::mutex> lock(global_lock);\n' % (indent)
                for del_obj in sorted(struct_uses):
                    pre_call_txt += '%suint64_t local_%s = reinterpret_cast<uint64_t &>(%s);\n' % (indent, del_obj, del_obj)
                    pre_call_txt += '%s%s = (%s)my_map_data->unique_id_mapping[local_%s];\n' % (indent, del_obj, struct_uses[del_obj], del_obj)
                pre_call_txt += '%smy_map_data->unique_id_mapping.erase(local_%s);\n' % (indent, proto.params[-2].name)
                pre_call_txt += '%slock.unlock();\n' % (indent)
                (pre_decl, pre_code, post_code) = ('', '', '')
            else:
                (pre_decl, pre_code, post_code) = self._gen_obj_code(struct_uses, local_decls, '    ', '', 0, set(), True)
            # This is a bit hacky but works for now. Need to decl local versions of top-level structs
            for ld in sorted(local_decls):
                init_null_txt = 'NULL';
                if '*' not in local_decls[ld]:
                    init_null_txt = '{}';
                if local_decls[ld].strip('*') not in vulkan.object_non_dispatch_list:
                    pre_decl += '    safe_%s local_%s = %s;\n' % (local_decls[ld], ld, init_null_txt)
            if pre_code != '': # lock around map uses
                pre_code = '%s{\n%sstd::lock_guard<std::mutex> lock(global_lock);\n%s%s}\n' % (indent, indent, pre_code, indent)
            pre_call_txt += '%s%s' % (pre_decl, pre_code)
            post_call_txt += '%s' % (post_code)
        elif create_func:
            base_type = proto.params[-1].ty.replace('const ', '').strip('*')
            if base_type not in vulkan.object_non_dispatch_list:
                return None
        else:
            return None

        ret_val = ''
        ret_stmt = ''
        if proto.ret != "void":
            ret_val = "%s result = " % proto.ret
            ret_stmt = "    return result;\n"
        if create_func:
            obj_type = proto.params[-1].ty.strip('*')
            obj_name = proto.params[-1].name
            if obj_type in vulkan.object_non_dispatch_list:
                local_name = "unique%s" % obj_type[2:]
                post_call_txt += '%sif (VK_SUCCESS == result) {\n' % (indent)
                indent += '    '
                post_call_txt += '%sstd::lock_guard<std::mutex> lock(global_lock);\n' % (indent)
                if obj_name in custom_create_dict:
                    post_call_txt += '%s\n' % (self.lineinfo.get())
                    local_name = '%ss' % (local_name) # add 's' to end for vector of many
                    post_call_txt += '%sfor (uint32_t i=0; i<%s; ++i) {\n' % (indent, custom_create_dict[obj_name])
                    indent += '    '
                    post_call_txt += '%suint64_t unique_id = global_unique_id++;\n' % (indent)
                    post_call_txt += '%smy_map_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(%s[i]);\n' % (indent, obj_name)
                    post_call_txt += '%s%s[i] = reinterpret_cast<%s&>(unique_id);\n' % (indent, obj_name, obj_type)
                    indent = indent[4:]
                    post_call_txt += '%s}\n' % (indent)
                else:
                    post_call_txt += '%s\n' % (self.lineinfo.get())
                    post_call_txt += '%suint64_t unique_id = global_unique_id++;\n' % (indent)
                    post_call_txt += '%smy_map_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(*%s);\n' % (indent, obj_name)
                    post_call_txt += '%s*%s = reinterpret_cast<%s&>(unique_id);\n' % (indent, obj_name, obj_type)
                indent = indent[4:]
                post_call_txt += '%s}\n' % (indent)

        call_sig = proto.c_call()
        # Replace default params with any custom local params
        for ld in local_decls:
            const_qualifier = ''
            for p in proto.params:
                if ld == p.name and 'const' in p.ty:
                    const_qualifier = 'const'
            call_sig = call_sig.replace(ld, '(%s %s)local_%s' % (const_qualifier, local_decls[ld], ld))
        if proto_is_global(proto):
            table_type = "instance"
        else:
            table_type = "device"
        pre_call_txt += '%s\n' % (self.lineinfo.get())
        open_ifdef = ''
        close_ifdef = ''
        if proto.name in ifdef_dict:
            open_ifdef = '#ifdef %s\n' % (ifdef_dict[proto.name])
            close_ifdef = '#endif\n'
        funcs.append('%s'
                     '%s%s\n'
                     '{\n'
                     '%s'
                     '    %sget_dispatch_table(unique_objects_%s_table_map, %s)->%s;\n'
                     '%s'
                     '%s'
                     '}\n'
                     '%s' % (open_ifdef, qual, decl, pre_call_txt, ret_val, table_type, dispatch_param, call_sig, post_call_txt, ret_stmt, close_ifdef))
        return "\n\n".join(funcs)

    def generate_body(self):
        self.layer_name = "unique_objects"
        extensions=[('wsi_enabled',
                     ['vkCreateSwapchainKHR',
                      'vkDestroySwapchainKHR', 'vkGetSwapchainImagesKHR',
                      'vkAcquireNextImageKHR', 'vkQueuePresentKHR'])]
        surface_wsi_instance_exts = [
                      'vkDestroySurfaceKHR',
                      'vkGetPhysicalDeviceSurfaceSupportKHR',
                      'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
                      'vkGetPhysicalDeviceSurfaceFormatsKHR',
                      'vkGetPhysicalDeviceSurfacePresentModesKHR']
        display_wsi_instance_exts = [
                      'vkGetPhysicalDeviceDisplayPropertiesKHR',
                      'vkGetPhysicalDeviceDisplayPlanePropertiesKHR',
                      'vkGetDisplayPlaneSupportedDisplaysKHR',
                      'vkGetDisplayModePropertiesKHR',
                      'vkCreateDisplayModeKHR',
                      'vkGetDisplayPlaneCapabilitiesKHR',
                      'vkCreateDisplayPlaneSurfaceKHR']
        if self.wsi == 'Win32':
            instance_extensions=[('wsi_enabled', surface_wsi_instance_exts),
                                 ('display_enabled', display_wsi_instance_exts),
                                 ('win32_enabled', ['vkCreateWin32SurfaceKHR'])]
        elif self.wsi == 'Android':
            instance_extensions=[('wsi_enabled', surface_wsi_instance_exts),
                                 ('android_enabled', ['vkCreateAndroidSurfaceKHR'])]
        elif self.wsi == 'Xcb' or self.wsi == 'Xlib' or self.wsi == 'Wayland' or self.wsi == 'Mir':
            instance_extensions=[('wsi_enabled', surface_wsi_instance_exts),
                                 ('display_enabled', display_wsi_instance_exts),
                                 ('xcb_enabled', ['vkCreateXcbSurfaceKHR']),
                                 ('xlib_enabled', ['vkCreateXlibSurfaceKHR']),
                                 ('wayland_enabled',  ['vkCreateWaylandSurfaceKHR']),
                                 ('mir_enabled', ['vkCreateMirSurfaceKHR'])]
        else:
            print('Error: Undefined DisplayServer')
            instance_extensions=[]

        body = ["namespace %s {" % self.layer_name,
                self._generate_dispatch_entrypoints(),
                self._generate_layer_introspection_function(),
                self._generate_layer_gpa_function(extensions,
                                                  instance_extensions),
                "} // namespace %s" % self.layer_name,
                self._gen_layer_interface_v0_functions()]
        return "\n\n".join(body)

def main():
    wsi = {
            "Win32",
            "Android",
            "Xcb",
            "Xlib",
            "Wayland",
            "Mir",
    }

    subcommands = {
            "unique_objects" : UniqueObjectsSubcommand,
    }

    if len(sys.argv) < 4 or sys.argv[1] not in wsi or sys.argv[2] not in subcommands or not os.path.exists(sys.argv[3]):
        print("Usage: %s <wsi> <subcommand> <input_header> [outdir]" % sys.argv[0])
        print
        print("Available subcommands are: %s" % " ".join(subcommands))
        exit(1)

    hfp = vk_helper.HeaderFileParser(sys.argv[3])
    hfp.parse()
    vk_helper.enum_val_dict = hfp.get_enum_val_dict()
    vk_helper.enum_type_dict = hfp.get_enum_type_dict()
    vk_helper.struct_dict = hfp.get_struct_dict()
    vk_helper.typedef_fwd_dict = hfp.get_typedef_fwd_dict()
    vk_helper.typedef_rev_dict = hfp.get_typedef_rev_dict()
    vk_helper.types_dict = hfp.get_types_dict()

    outfile = None
    if len(sys.argv) >= 5:
        outfile = sys.argv[4]

    subcmd = subcommands[sys.argv[2]](outfile)
    subcmd.run()

if __name__ == "__main__":
    main()


text:
Sample application demonstrating how to do some real work with Spring LDAP. This is a fully functional LDAP user
administration application. It uses many of the useful concepts in Spring LDAP and would serve as a
good example for best practices and various useful tricks.

### Users and Groups in LDAP

Users in LDAP are usually represented as `organizationalPerson` or `inetOrgPerson` entries in the LDAP tree.
The attributes in these entries represent the basic information on the users, e.g. (subset of available attributes):

* `cn`: Common Name, or full name of the user
* `sn`: Surname
* `mail`: Email address
* `telephoneNumber`: Phone number
* ...several more attributes are available

Groups in LDAP are typically organized in `groupOfName` or `groupOfUniqueName` entries. These entries have a name,
an optional description, and an attribute containing the distinguished names (i.e. the unique identifiers) of all
members of the group. This attribute is named `member` and `uniqueMember` respectively.

Thus, user administration in LDAP typically involves creating and manipulating `orgalizationalPerson` or `inetOrgPerson`
entries and adding or removing references to these entries in `groupOfName` or `groupOfUniqueName` entries.

This application demonstrates to do this easily and efficiently using Spring LDAP.

### Application Structure

The core Spring application context of the sample is defined in resources/applicationContext.xml.
By default this ApplicationContext will start an in-process Apache Directory Server instance, automatically populated
with some test data. The data will be reset every time the application is restarted.

### Running the Example

To run the example, do `gradle jettyRun`, or `mvn jetty:run`, and then navigate to `http://localhost:8080/spring-ldap-user-admin-sample`

It is also possible to run this sample application against a remote LDAP server as opposed to starting an in-process
LDAP server. To do this, use the following system properties:

* `spring.profiles.active` - set this to `no-apacheds` to prevent the in-process ApacheDs to be launched
* `sample.ldap.url` - the URL of the target LDAP server
* `sample.ldap.userDn` - principal to use for authentication against the LDAP server
* `sample.ldap.password` - authentication password
* `sample.ldap.base` - the directory root to use - note that by default all data under this node will be deleted and replaced with test data
* `sample.ldap.clean` - set this property to false to *not* clear the root node
* `sample.ldap.directory.type` - NORMAL or AD. Specify AD if running against Active Directory in order to enable some particular AD tweaks

Example:

    gradle jettyRun -Dspring.profiles.active=no-apacheds -Dsample.ldap.url=ldaps://127.0.0.1:636 \
     -Dsample.ldap.userDn=CN=ldaptest,CN=Users,DC=261consulting,DC=local -Dsample.ldap.password=secret \
     -Dsample.ldap.base=ou=test,dc=261consulting,dc=local -Dsample.ldap.directory.type=AD

    mvn jetty:run -Dspring.profiles.active=no-apacheds -Dsample.ldap.url=ldaps://127.0.0.1:636 \
     -Dsample.ldap.userDn=CN=ldaptest,CN=Users,DC=261consulting,DC=local -Dsample.ldap.password=secret \
     -Dsample.ldap.base=ou=test,dc=261consulting,dc=local -Dsample.ldap.directory.type=AD

This sample uses Bootstrap to present a decent web design - copyright 2013 Twitter, Inc; distributed under the Apache 2 License.

redpajama_set_name: RedPajamaGithub


text:
require 'cinch'
require 'time-lord'
require 'cinch/toolbox'
require 'cinch/cooldown'

module Cinch
  module Plugins
    # Cinch Cooldown for PAX countdowns
    class PaxTimer
      include Cinch::Plugin

      self.help = 'Use .pax for the next pax or .east, .west, .south or ' \
                  '.aus for the time to a specific pax.'

      match(/pax\z/, method: :next_pax)

      def next_pax(m)
        m.reply get_next_pax
      end

      PAXES.map { |p| p[:type] }.each do |pax|
        match(/(#{pax}|pax#{pax})\z/, method: "next_#{pax}")

        define_method "next_#{pax}" do |m|
          debug "#{pax}"
          m.reply get_next_pax(pax.to_s)
        end
      end

      private

      def get_next_pax(type = nil)
        @pax = get_next_pax_for(type)

        return 'I don\'t have info for the next one of those PAXes' if @pax.nil?

        message = ["#{@pax[:name]} is"]
        message << 'approximately' if @pax[:estimated]

        # Uncomment this once we can specify granularity in Time Lord.
        # message << TimeLord::Period.new(@pax[:date], Time.now).to_words
        message << Cinch::Toolbox.time_format(@pax[:date] - Time.now, [:days])
        message << 'from now'

        message << ' (No official date, yet)' if @pax[:estimated]
        message.join(' ')
      end

      def get_next_pax_for(type)
        paxes = PAXES.dup

        paxes.delete_if { |pax| pax[:date] - Time.now < 0 }
        paxes.delete_if { |pax| pax[:type] != type } unless type.nil?
        paxes.sort! { |a, b| b[:date] <=> a[:date] }

        paxes.last
      end
    end
  end
end


text:
package path_finding

func Minimax(array []int, t int) bool {
return true
}


text:
/**
* app configuration
*
* Description
* Main configuration for the application
*/
(function (define) {
  "use strict";
  var module = function configModuleF() {
    var configFunc = function configFuncF($provider, $httpProvider) {
      /*jslint maxlen: 85*/
      $httpProvider.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
      /*jslint maxlen: 75*/
      $provider.value('appVersion', '0.0.1');
      $provider.value('appName', 'Inventory management system');
    };
    return ['$provider', '$httpProvider', configFunc];
  };
  define([], module);
}(this.define));


text:
package org.apache.giraph.comm.netty.handler;

import org.apache.hadoop.conf.Configuration;
import org.apache.log4j.Logger;

import java.util.concurrent.ConcurrentMap;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;

import static org.apache.giraph.conf.GiraphConstants.NETTY_SIMULATE_FIRST_RESPONSE_FAILED;

/**
 * Generic handler of responses.
 */
public class ResponseClientHandler extends ChannelInboundHandlerAdapter {
  /** Class logger */
  private static final Logger LOG =
      Logger.getLogger(ResponseClientHandler.class);
  /** Already dropped first response? (used if dropFirstResponse == true) */
  private static volatile boolean ALREADY_DROPPED_FIRST_RESPONSE = false;
  /** Drop first response (used for simulating failure) */
  private final boolean dropFirstResponse;
  /** Outstanding worker request map */
  private final ConcurrentMap<ClientRequestId,
      RequestInfo> workerIdOutstandingRequestMap;

  /**
   * Constructor.
   *
   * @param workerIdOutstandingRequestMap Map of worker ids to outstanding
   *                                      requests
   * @param conf Configuration
   */
  public ResponseClientHandler(
      ConcurrentMap<ClientRequestId, RequestInfo>
          workerIdOutstandingRequestMap,
      Configuration conf) {
    this.workerIdOutstandingRequestMap = workerIdOutstandingRequestMap;
    dropFirstResponse = NETTY_SIMULATE_FIRST_RESPONSE_FAILED.get(conf);
  }

  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg)
    throws Exception {
    if (!(msg instanceof ByteBuf)) {
      throw new IllegalStateException("messageReceived: Got a " +
          "non-ByteBuf message " + msg);
    }

    ByteBuf buf = (ByteBuf) msg;
    int senderId = -1;
    long requestId = -1;
    int response = -1;
    try {
      senderId = buf.readInt();
      requestId = buf.readLong();
      response = buf.readByte();
    } catch (IndexOutOfBoundsException e) {
      throw new IllegalStateException(
          "channelRead: Got IndexOutOfBoundsException ", e);
    }
    ReferenceCountUtil.release(buf);

    // Simulate a failed response on the first response (if desired)
    if (dropFirstResponse && !ALREADY_DROPPED_FIRST_RESPONSE) {
      LOG.info("messageReceived: Simulating dropped response " + response +
          " for request " + requestId);
      setAlreadyDroppedFirstResponse();
      synchronized (workerIdOutstandingRequestMap) {
        workerIdOutstandingRequestMap.notifyAll();
      }
      return;
    }

    if (response == 1) {
      LOG.info("messageReceived: Already completed request (taskId = " +
          senderId + ", requestId = " + requestId + ")");
    } else if (response != 0) {
      throw new IllegalStateException(
          "messageReceived: Got illegal response " + response);
    }

    RequestInfo requestInfo = workerIdOutstandingRequestMap.remove(
        new ClientRequestId(senderId, requestId));
    if (requestInfo == null) {
      LOG.info("messageReceived: Already received response for (taskId = " +
          senderId + ", requestId = " + requestId + ")");
    } else {
      if (LOG.isDebugEnabled()) {
        LOG.debug("messageReceived: Completed (taskId = " + senderId + ")" +
            requestInfo + ".  Waiting on " + workerIdOutstandingRequestMap
            .size() + " requests");
      }
    }

    // Help NettyClient#waitSomeRequests() to finish faster
    synchronized (workerIdOutstandingRequestMap) {
      workerIdOutstandingRequestMap.notifyAll();
    }
  }

  /**
   * Set already dropped first response flag
   */
  private static void setAlreadyDroppedFirstResponse() {
    ALREADY_DROPPED_FIRST_RESPONSE = true;
  }

  @Override
  public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    if (LOG.isDebugEnabled()) {
      LOG.debug("channelClosed: Closed the channel on " +
          ctx.channel().remoteAddress());
    }
    ctx.fireChannelInactive();
  }

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
    throws Exception {
    LOG.warn("exceptionCaught: Channel failed with " +
        "remote address " + ctx.channel().remoteAddress(), cause);
  }
}


text: ansibleplaybooks


text:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.geccocrawler</groupId>
	<artifactId>socks5-netty</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>1.9</maven.compiler.source>
		<maven.compiler.target>1.9</maven.compiler.target>
	</properties>
	<dependencies>
		<dependency>
			<groupId>io.netty</groupId>
			<artifactId>netty-all</artifactId>
			<version>4.1.6.Final</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.21</version>
		</dependency>
		<dependency>
			<groupId>commons-codec</groupId>
			<artifactId>commons-codec</artifactId>
			<version>1.10</version>
		</dependency>
		<dependency>
			<groupId>com.squareup.okhttp3</groupId>
			<artifactId>okhttp</artifactId>
			<version>3.5.0</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<version>2.6</version>
				<configuration>
					<archive>
						<manifest>
							<addClasspath>true</addClasspath>
							<!--<classpathPrefix>lib/</classpathPrefix>-->
							<mainClass>com.geccocrawler.socks5.ProxyServer</mainClass>
						</manifest>
					</archive>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<version>2.10</version>
				<executions>
					<execution>
						<id>copy-dependencies</id>
						<phase>package</phase>
						<goals>
							<goal>copy-dependencies</goal>
						</goals>
						<configuration>
							<outputDirectory>${project.build.directory}/lib</outputDirectory>
						</configuration>
					</execution>
				</executions>
			</plugin>

		</plugins>
	</build>
</project>


text:
Feihong's setup scripts
=======================

These are a bunch of scripts I use to set up my development environments on Ubuntu and Mac.


text:
package org.jboss.resteasy.plugins.server.netty;

import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.resteasy.core.Headers;
import org.jboss.resteasy.specimpl.ResteasyHttpHeaders;
import org.jboss.resteasy.spi.ResteasyUriInfo;
import org.jboss.resteasy.util.CookieParser;
import org.jboss.resteasy.util.HttpHeaderNames;
import org.jboss.resteasy.util.MediaTypeHelper;
import org.jboss.resteasy.util.PathHelper;

import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriBuilder;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Bill Burke
 * @version $Revision: 1 $
 */
public class NettyUtil
{
   public static ResteasyUriInfo extractUriInfo(HttpRequest request, String contextPath, String protocol)
   {
      String host = HttpHeaders.getHost(request, "unknown");
      String uri = request.getUri();

      URI absoluteURI = URI.create(protocol + "://" + host + uri);

      String path = PathHelper.getEncodedPathInfo(absoluteURI.getRawPath(), contextPath);
      if (!path.startsWith("/"))
      {
         path = "/" + path;
      }

      URI baseURI = absoluteURI;
      if (!path.trim().equals(""))
      {
         String tmpContextPath = contextPath;
         if (!tmpContextPath.endsWith("/")) tmpContextPath += "/";
         baseURI = UriBuilder.fromUri(absoluteURI).replacePath(tmpContextPath).replaceQuery(null).build();
      }
      else
      {
         baseURI = UriBuilder.fromUri(absoluteURI).replaceQuery(null).build();
      }
      URI relativeURI = UriBuilder.fromUri(path).replaceQuery(absoluteURI.getRawQuery()).build();
      //System.out.println("path: " + path);
      //System.out.println("query string: " + request.getQueryString());
      ResteasyUriInfo uriInfo = new ResteasyUriInfo(baseURI, relativeURI);
      return uriInfo;
   }

   public static ResteasyHttpHeaders extractHttpHeaders(HttpRequest request)
   {

      MultivaluedMap<String, String> requestHeaders = extractRequestHeaders(request);
      ResteasyHttpHeaders headers = new ResteasyHttpHeaders(requestHeaders);

      Map<String, Cookie> cookies = extractCookies(requestHeaders);
      headers.setCookies(cookies);
      // test parsing should throw an exception on error
      headers.testParsing();
      return headers;

   }

   static Map<String, Cookie> extractCookies(MultivaluedMap<String, String> headers)
   {
      Map<String, Cookie> cookies = new HashMap<String, Cookie>();
      List<String> cookieHeaders = headers.get("Cookie");
      if (cookieHeaders == null) return cookies;

      for (String cookieHeader : cookieHeaders)
      {
         for (Cookie cookie : CookieParser.parseCookies(cookieHeader))
         {
            cookies.put(cookie.getName(), cookie);
         }
      }
      return cookies;
   }

   public static List<MediaType> extractAccepts(MultivaluedMap<String, String> requestHeaders)
   {
      List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
      List<String> accepts = requestHeaders.get(HttpHeaderNames.ACCEPT);
      if (accepts == null) return acceptableMediaTypes;

      for (String accept : accepts)
      {
         acceptableMediaTypes.addAll(MediaTypeHelper.parseHeader(accept));
      }
      return acceptableMediaTypes;
   }

   public static List<String> extractLanguages(MultivaluedMap<String, String> requestHeaders)
   {
      List<String> acceptable = new ArrayList<String>();
      List<String> accepts = requestHeaders.get(HttpHeaderNames.ACCEPT_LANGUAGE);
      if (accepts == null) return acceptable;

      for (String accept : accepts)
      {
         String[] splits = accept.split(",");
         for (String split : splits) acceptable.add(split.trim());
      }
      return acceptable;
   }

   public static MultivaluedMap<String, String> extractRequestHeaders(HttpRequest request)
   {
      Headers<String> requestHeaders = new Headers<String>();

      for (Map.Entry<String, String> header : request.getHeaders())
      {
         requestHeaders.add(header.getKey(), header.getValue());
      }
      return requestHeaders;
   }
}


text:
Details about using the *[Muhimbi PDF Converter Services Online](https://support.muhimbi.com/hc/en-us/articles/115002813708-About-the-PDF-Converter-Services-Online)* from Java can be found below. If you prefer to bypass these wrapper libraries, and rather send JSON code to the REST based service directly, then please see the section containing [raw JSON examples](../json)

*If a cloud-based service is not suitable to your needs (e.g. for security or regulatory reasons), and you have the ability to deploy software to your own (Windows) server, then check out the [Muhimbi PDF Converter Services](http://www.muhimbi.com/Products/PDF-Converter-Services/summary.aspx) and [this sample code](https://support.muhimbi.com/hc/en-us/articles/228089807-Where-can-I-find-sample-code-).*

## Table of contents

- [Prerequisites](#prerequisites)
  - [Linux](#linux)
  - [Windows](#windows)
- [Client libraries](#client-libraries)
  - [Installing the pre-generated client](#installing-the-pre-generated-client)
  - [Generating the client from scratch](#generating-the-client-from-scratch)
    - [Using the command line](#using-the-command-line)
    - [Using editor.swagger.io](#using-editorswaggerio)
- [Sample code](#sample-code)
- [API / Documentation](#api--documentation)

## Prerequisites

Prerequisites for using the PDF Converter in combination with Java are as follows:

- JDK 7 or later

The PDF Converter Java client has the following dependencies:

- [Gson](https://github.com/google/gson) - 2.6.2 or later
- [Joda-Time](https://github.com/JodaOrg/joda-time) - 2.9.3 or later
- [OkHttp](https://github.com/square/okhttp) - 2.7.5 or later
- [Okio](https://github.com/square/okio) - 1.6.0 or later

These dependencies are shipped alongside our libraries. However, if you integrate our software in an existing product / solution that utilise the same dependencies, then make sure the version numbers are correct.

Exact deployment and configuration steps for the various platforms vary slightly. The ones for Linux, tested with Ubuntu, and Windows are provided below.

### Linux

There are multiple options for compiling and executing Java code on Linux, the examples provided in this section have been tested with the standard Java Development Kit.

```
sudo apt-get install default-jdk
```

This single install is sufficient for compiling and executing code that use our pre-built libraries.

### Windows

For Windows developers we recommend using [Oracle's official JDK](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html). The examples provided in this section have been tested on Windows with this JDK.

## Client libraries

With the prerequisites in place, install the PDF Converter's client libraries using one of the methods described below.

### Installing the pre-generated client

Time is precious, so with that in mind, the easiest way to get going is to [download the pre-generated client libraries](https://github.com/Muhimbi/PDF-Converter-Services-Online/raw/master/clients/v1/java/muhimbi-pdf-online-client-java.zip) and unzip them to a location in your project.

### Generating the client from scratch

:exclamation: **This is an advanced topic, most developers do not need to generate the client from scratch** :exclamation:

If the pre-generated client libraries are not suiting your needs, then you may want to manually generate them. If you need more control over namespaces then this is the way forward.

#### Using the command line

All the PDF Converter's client libraries are generated from the [Swagger API definition file](../../../swagger/) using [swagger-codegen](https://github.com/swagger-api/swagger-codegen).

You can either download a precompiled version of `swagger-codegen` or build it from scratch.

Download the precompiled version as follows:

```sh
wget https://oss.sonatype.org/content/repositories/releases/io/swagger/swagger-codegen-cli/2.2.2/swagger-codegen-cli-2.2.2.jar -O swagger-codegen-cli.jar

java -jar swagger-codegen-cli.jar help
```

This downloads version 2.2.2 and, assuming all is well, shows a brief help section. As newer versions are released from time to time, you may want to [check what the latest version number is](https://github.com/swagger-api/swagger-codegen#prerequisites).

If, rather than taking a 'fixed-in-time' precompiled version of `swagger-codegen`, you prefer the very latest version then you can compile it as described below.

To build from source, you need the following installed and available in your $PATH:
- JDK 7 or later
- Apache maven 3.3.3 or greater

Instructions for Linux (Tested in Ubuntu) are as follows.

```sh
sudo apt-get install default-jdk
sudo apt-get install maven
git clone https://github.com/swagger-api/swagger-codegen
cd swagger-codegen
mvn clean package
```

This installs the Java Development Kit, the Maven build system, downloads the latest `swagger-codegen` source and builds it. Assuming the build process completes without error, `swagger-codegen-cli.jar` can be found under `modules/swagger-codegen-cli/target/`.

Instructions are correct at the time of writing, but for the latest details about building codegen, compiling on different platforms, or downloading a pre-compiled version of `swagger-codegen-cli.jar`, see [codegen's Readme file](https://github.com/swagger-api/swagger-codegen/blob/master/README.md).

Regardless of `swagger-codegen-cli.jar` being downloaded or compiled, the Java client libraries can now be generated as follows:

```sh
java -jar swagger-codegen-cli.jar \
	generate \
	-i https://api.muhimbi.com/api-docs/v1/swagger.json \
	-l java \
	-o MuhimbiPDFOnline-client \
	--type-mappings ByteArray=String
```

You may need to adjust the path to the jar file.

Please note that we have added a type-mapping as the current version of codegen is not consistent with the other clients generated by codegen. The Muhimbi REST service expects a Base64 encoded string, not a raw byte array. You can find more details in [this GitHub issue](https://github.com/swagger-api/swagger-codegen/issues/4824).

The command provided above generates the Java client using the default settings, including a unit-test framework and incomplete documentation. As this is of no use to us, and we need to tweak some other settings as well, you can find the exact command we used in [`generate-client.sh`](generate-client.sh)

Once the client code has been generated it must be build using the Java compiler. The commands for carrying out the build can be found in `client/build.sh` (Linux). You may need to make some changes to suit your requirements.

#### Using editor.swagger.io

For a quick-and-dirty way to generate client libraries for the language of your choice, use the web based `editor.swagger.io` system.

1. Open [editor.swagger.io](http://editor.swagger.io)
2. From the `File` menu select `Import URL`
3. Enter `https://raw.githubusercontent.com/Muhimbi/PDF-Converter-Services-Online/master/swagger/v1/muhimbi-pdf-online-swagger.json`
4. From the `Generate Client` menu select the language of your choice.

## Sample code

Sample code, and related files, for the various facilities provided by this service can be found below. It is recommended to copy all samples to your local system using one of the following options:

- **Git:** Use the following command to clone the entire repository to your system. This will download all files associated with this repository, and is most likely overkill, but it is the only easy way to download files using Git. Once downloaded, you can find the examples under the `clients/v1/java/samples` folder.

     `git clone https://github.com/Muhimbi/PDF-Converter-Services-Online/`

- **SVN:** A common trick to download only part of a Git repository  is to use `svn`. Download only the Java client and sample code using the following command.

     `svn export https://github.com/Muhimbi/PDF-Converter-Services-Online/trunk/clients/v1/java`

- **ZIP:** [Download](https://github.com/Muhimbi/PDF-Converter-Services-Online/zipball/master/) a ZIP archive of the entire repository. Once downloaded, you can find the examples under the `clients/v1/java/samples` folder.

An example is provided for each individual REST endpoint. A full overview can be found below.

Sample											| Description
------------------------------------------------|---------------------------------------------------------
[convert](samples/convert/)						| Convert a single file to PDF or other [supported output format](https://support.muhimbi.com/hc/en-us/articles/228089047-What-file-formats-types-are-supported-for-conversion-).
[convert_LRO](samples/convert_LRO/)				| Convert a single file to PDF or other formats using asynchronous pattern for long running uperations.
[convert_to_pdfa](samples/convert_to_pdfa/)		| Convert a single file to a PDF/A document (or to other PDF profiles).
[export_form_data](samples/export_form_data/)	| Export PDF Forms Data into various formats (.fdf, .xfdf and .xml).
[import_form_data](samples/import_form_data/)	| Import data (.fdf, .xfdf or .xml) into PDF forms.
[merge_to_pdf](samples/merge_to_pdf/)			| Combine multiple files, and URLs, into a single PDF.
[ocr_pdf](samples/ocr_pdf/)						| Convert a scan, fax or other image into a searchable PDF.
[ocr_text](samples/ocr_text/)					| Use OCR to extract text from a scan, fax or other image.
[secure_document](samples/secure_document/)		| Apply security settings, passwords and restrictions to a PDF or MS Office documents.
[secure_pdf](samples/secure_pdf/)				| Apply security settings, passwords and restrictions to a PDF.
[split_pdf](samples/split_pdf/)					| Split a large PDF into smaller PDFs.
**Specialized Conversions**										|
   [convert_cad](samples/convert_cad/)			| Convert a CAD drawing to PDF.
   [convert_email](samples/convert_email/)		| Convert an email (.msg or .eml) into PDF.
   [convert_excel](samples/convert_excel/)		| Convert a Microsoft Excel document into PDF (or other formats).
   [convert_html](samples/convert_html/)			| Convert an HTML fragment, or URL, to PDF.
   [convert_infopath](samples/convert_infopath/)	| Convert an InfoPath document into PDF (or other formats).
   [convert_pdfa](samples/convert_pdfa/)			| Convert a PDF into a PDF/A document (or other PDF profiles).
   [convert_powerpoint](samples/convert_powerpoint/)	| Convert a Microsoft PowerPoint document into PDF (or other formats).
   [convert_visio](samples/convert_visio/)		| Convert a Visio document into PDF (or other formats).
   [convert_word](samples/convert_word/)			| Convert a Microsoft Word document into PDF (or other formats).
**[watermarking](samples/watermarking/)**											|
   [composite_watermark](samples/watermarking/composite_watermark/)	| Add a number of different watermarks to a PDF file in a single operation.
   [ellipse_watermark](samples/watermarking/ellipse_watermark/)		| Add an ellipse based watermark to a PDF file.
   [image_watermark](samples/watermarking/image_watermark/)			| Add an image based watermark to a PDF file.
   [linear_barcode_watermark](samples/watermarking/linear_barcode_watermark/)	| Add a Linear Barcode to a PDF file.
   [line_watermark](samples/watermarking/line_watermark/)			| Add a line based watermark to a PDF file.
   [pdf_watermark](samples/watermarking/pdf_watermark/)				| Add a PDF based watermark to a PDF file.
   [qr_code_watermark](samples/watermarking/qr_code_watermark/)		| Add a QR Code to a PDF file.
   [rectangle_watermark](samples/watermarking/rectangle_watermark/)	| Add a rectangle based watermark to a PDF file.
   [rtf_watermark](samples/watermarking/rtf_watermark/)				| Add a rich text (RTF) based watermark to a PDF file.
   [text_watermark](samples/watermarking/text_watermark/)			| Add a simple text watermark to a PDF file.
**[watermarking_ms_office](samples/watermarking_ms_office/)**									|
   [composite_watermark](samples/watermarking_ms_office/composite_watermark/)	| Add a number of different watermarks to a PDF or MS Office document in a single operation.
   [qr_code_watermark](samples/watermarking_ms_office/qr_code_watermark/)		| Add a QR Code to a PDF or MS Office document.
   [text_watermark](samples/watermarking_ms_office/text_watermark/)				| Add a simple text watermark to a PDF or MS Office document.

## API / Documentation

Although the API is largely self-describing, especially when used in code editors with *intellisense* and *code-complete*, from time to time it may be easier to consult the full API documentation. An overview of the entire object model can be found [in the Wiki](https://github.com/Muhimbi/PDF-Converter-Services-Online/wiki/API).

If you have any questions or comments then please contact [our friendly support desk](http://www.muhimbi-online.com/contact).


text:
package com.pontydysgu.data;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class LoginData {

	private String username;
	private String password;

	// see http://androidsnippets.com/sha-1-hash-function
	public String sha1(String s) {
		MessageDigest digest = null;
		try {
			digest = MessageDigest.getInstance("SHA-1");
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		digest.reset();
		byte[] data = digest.digest(s.getBytes());
		return String.format("%0" + (data.length * 2) + "X", new BigInteger(1,
				data));
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username.toLowerCase().trim();
	}

	public String getPassword() {
		return sha1(password).toLowerCase().trim();
	}

	public void setPassword(String password) {
		this.password = password;
	}

}


text:
package com.emitrom.lienzo.client.core.shape;

import com.emitrom.lienzo.client.core.Attribute;
import com.emitrom.lienzo.client.core.Context2D;
import com.emitrom.lienzo.client.core.shape.json.IFactory;
import com.emitrom.lienzo.client.core.shape.json.ShapeFactory;
import com.emitrom.lienzo.client.core.shape.json.validators.ValidationContext;
import com.emitrom.lienzo.client.core.types.Point2D;
import com.emitrom.lienzo.client.core.types.Point2DArray;
import com.emitrom.lienzo.shared.core.types.ShapeType;
import com.google.gwt.json.client.JSONObject;

/**
 * A triangle is one of the basic shapes of geometry: a polygon with three corners or vertices and three sides
 * or edges which are line segments.
 * In Euclidean geometry any three points, when non-collinear, determine a unique triangle and a unique plane
 * (i.e. a two-dimensional Euclidean space).
 */
public class Triangle extends Shape<Triangle>
{
    /**
     * Constructor. Creates an instance of a triangle.
     *
     * @param 3 points {@link Point2D}
     */
    public Triangle(Point2D a, Point2D b, Point2D c)
    {
        super(ShapeType.TRIANGLE);

        setPoints(a, b, c);
    }

    protected Triangle(JSONObject node)
    {
        super(ShapeType.TRIANGLE, node);
    }

    /**
     * Draws this polygon.
     *
     * @param context
     */
    @Override
    public boolean prepare(Context2D context, Attributes attr, double alpha)
    {
        Point2DArray list = getPoints();

        if ((null != list) && (list.getLength() > 2))
        {
            Point2D point0 = list.getPoint(0);

            Point2D point1 = list.getPoint(1);

            Point2D point2 = list.getPoint(2);

            context.beginPath();

            context.moveTo(point0.getX(), point0.getY());

            context.lineTo(point1.getX(), point1.getY());

            context.lineTo(point2.getX(), point2.getY());

            context.closePath();

            return true;
        }
        return false;
    }

    /**
     * Gets this triangles points.
     *
     * @return {@link Point2DArray}
     */
    public Point2DArray getPoints()
    {
        return getAttributes().getPoints();
    }

    /**
     * Sets this triangles points.
     *
     * @param 3 points {@link Point2D}
     * @return this Triangle
     */
    public Triangle setPoints(Point2D a, Point2D b, Point2D c)
    {
        getAttributes().setPoints(new Point2DArray(a, b, c));

        return this;
    }

    @Override
    public IFactory<?> getFactory()
    {
        return new TriangleFactory();
    }

    // TODO - add triangle math methods, inner angles, etc

    public static class TriangleFactory extends ShapeFactory<Triangle>
    {
        public TriangleFactory()
        {
            super(ShapeType.TRIANGLE);

            addAttribute(Attribute.POINTS, true);
        }

        @Override
        public Triangle create(JSONObject node, ValidationContext ctx)
        {
            return new Triangle(node);
        }
    }
}