# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""
=============
TAP plus
=============

@author: Juan Carlos Segovia
@contact: juan.carlos.segovia@sciops.esa.int

European Space Astronomy Centre (ESAC)
European Space Agency (ESA)

Created on 30 jun. 2016

"""

try:
    # python 3
    import http.client as httplib
except ImportError:
    # python 2
    import httplib
import mimetypes
import time

from six.moves.urllib.parse import urlencode

from astroquery.utils.tap.xmlparser import utils
from astroquery.utils.tap import taputils

import requests

__all__ = ['TapConn']

CONTENT_TYPE_POST_DEFAULT = "application/x-www-form-urlencoded"

class TapConn(object):
    """TAP plus connection class
    Provides low level HTTP connection capabilities
    """

    def __init__(self, ishttps,
                 host,
                 server_context=None,
                 port=80,
                 sslport=443,
                 connhandler=None,
                 tap_context=None,
                 upload_context=None,
                 table_edit_context=None,
                 data_context=None,
                 datalink_context=None):

        """Constructor

        Parameters
        ----------
        ishttps: bool, mandatory
            'True' is the protocol to use is HTTPS
        host : str, mandatory
            host name
        server_context : str, mandatory
            server context
        tap_context : str, optional
            tap context
        upload_context : str, optional
            upload context
        table_edit_context : str, optional
            table edit context
        data_context : str, optional
            data context
        datalink_context : str, optional
            datalink context
        port : int, optional, default 80
            HTTP port
        sslport : int, optional, default 443
            HTTPS port
        connhandler connection handler object, optional, default None
            HTTP(s) connection hander (creator). If no handler is provided, a
            new one is created.
        """
        self.__interna_init()
        self.__isHttps = ishttps
        self.__connHost = host
        self.__connPort = port
        self.__connPortSsl = sslport
        if server_context is not None:
            if(server_context.startswith("/")):
                self.__serverContext = server_context
            else:
                self.__serverContext = "/" + server_context
        else:
            self.__serverContext = ""
        self.__tapContext = self.__create_context(tap_context)
        self.__dataContext = self.__create_context(data_context)
        self.__datalinkContext = self.__create_context(datalink_context)
        self.__uploadContext = self.__create_context(upload_context)
        self.__tableEditContext = self.__create_context(table_edit_context)
        if connhandler is None:
            self.__connectionHandler = ConnectionHandler(self.__connHost,
                                                         self.__connPort,
                                                         self.__connPortSsl)
        else:
            self.__connectionHandler = connhandler

    def __create_context(self, context):
        if (context is not None and context != ""):
            if(str(context).startswith("/")):
                return self.__serverContext + str(context)
            else:
                return self.__serverContext + "/" + str(context)
        else:
            return self.__serverContext

    def __interna_init(self):
        self.__connectionHandler = None
        self.__isHttps = False
        self.__connHost = ""
        self.__connPort = 80
        self.__connPortSsl = 443
        self.__serverContext = None
        self.__tapContext = None
        self.__postHeaders = {
            "Content-type": CONTENT_TYPE_POST_DEFAULT,
            "Accept": "text/plain"
            }
        self.__getHeaders = {}
        self.__cookie = None
        self.__currentStatus = 0
        self.__currentReason = ""

    def __get_tap_context(self, subContext):
        return self.__tapContext + "/" + subContext

    def __get_data_context(self, encodedData=None):
        if self.__dataContext is None:
            raise ValueError("data_context must be specified at TAP object " +
                             "creation for this action to be performed")
        if encodedData is not None:
            return self.__dataContext + "?" + str(encodedData)
        else:
            return self.__dataContext

    def __get_datalink_context(self, subContext, encodedData=None):
        if self.__datalinkContext is None:
            raise ValueError("datalink_context must be specified at TAP " +
                             "object creation for this action to be " +
                             "performed")
        if encodedData is not None:
            return self.__datalinkContext + "/" + subContext + "?" +\
                encodedData
        else:
            return self.__datalinkContext + "/" + subContext

    def __get_upload_context(self):
        if self.__uploadContext is None:
            raise ValueError("upload_context must be specified at TAP " +
                             "object creation for this action to be " +
                             "performed")
        return self.__uploadContext

    def __get_table_edit_context(self):
        if self.__tableEditContext is None:
            raise ValueError("table_edit_context must be specified at TAP " +
                             "object creation for this action to be " +
                             "performed")
        return self.__tableEditContext

    def __get_server_context(self, subContext):
        return self.__serverContext + "/" + subContext

    def execute_tapget(self, subcontext, verbose=False):
        """Executes a TAP GET request
        The connection is done through HTTP or HTTPS depending on the login
        status (logged in -> HTTPS)

        Parameters
        ----------
        subcontext : str, mandatory
            context to be added to host+serverContext+tapContext, usually the
            TAP list name
        verbose : bool, optional, default 'False'
            flag to display information about the process

        Returns
        -------
        An HTTP(s) response object
        """
        if subcontext.startswith("http"):
            # absolute url
            return self.__execute_get(subcontext, verbose)
        else:
            context = self.__get_tap_context(subcontext)
            return self.__execute_get(context, verbose)

    def execute_dataget(self, query, verbose=False):
        """Executes a data GET request
        The connection is done through HTTP or HTTPS depending on the login
        status (logged in -> HTTPS)

        Parameters
        ----------
        query : str, mandatory
            URL encoded data (query string)
        verbose : bool, optional, default 'False'
            flag to display information about the process

        Returns
        -------
        An HTTP(s) response object
        """
        context = self.__get_data_context(query)
        return self.__execute_get(context, verbose)

    def execute_datalinkget(self, subcontext, query, verbose=False):
        """Executes a datalink GET request
        The connection is done through HTTP or HTTPS depending on the login
        status (logged in -> HTTPS)

        Parameters
        ----------
        subcontext : str, mandatory
            datalink subcontext
        query : str, mandatory
            URL encoded data (query string)
        verbose : bool, optional, default 'False'
            flag to display information about the process

        Returns
        -------
        An HTTP(s) response object
        """
        context = self.__get_datalink_context(subcontext, query)
        return self.__execute_get(context, verbose)

    def __execute_get(self, context, verbose=False):
        conn = self.__get_connection(verbose)
        if verbose:
            print("host = " + str(conn.host) + ":" + str(conn.port))
            print("context = " + context)
        conn.request("GET", context, None, self.__getHeaders)
        response = conn.getresponse()
        self.__currentReason = response.reason
        self.__currentStatus = response.status
        return response

    def execute_tappost(self, subcontext, data,
                        content_type=CONTENT_TYPE_POST_DEFAULT,
                        verbose=False):
        """Executes a POST request
        The connection is done through HTTP or HTTPS depending on the login
        status (logged in -> HTTPS)

        Parameters
        ----------
        subcontext : str, mandatory
            context to be added to host+serverContext+tapContext, usually the
            TAP list name
        data : str, mandatory
            POST data
        content_type: str, optional, default: application/x-www-form-urlencoded
            HTTP(s) content-type header value
        verbose : bool, optional, default 'False'
            flag to display information about the process

        Returns
        -------
        An HTTP(s) response object
        """
        context = self.__get_tap_context(subcontext)
        return self.__execute_post(context, data, content_type, verbose)

    def execute_datapost(self, data,
                         content_type=CONTENT_TYPE_POST_DEFAULT,
                         verbose=False):
        """Executes a POST request
        The connection is done through HTTP or HTTPS depending on the login
        status (logged in -> HTTPS)

        Parameters
        ----------
        data : str, mandatory
            POST data
        content_type: str, optional, default: application/x-www-form-urlencoded
            HTTP(s) content-type header value
        verbose : bool, optional, default 'False'
            flag to display information about the process

        Returns
        -------
        An HTTP(s) response object
        """
        context = self.__get_data_context()
        return self.__execute_post(context, data, content_type, verbose)

    def execute_datalinkpost(self, subcontext, data,
                             content_type=CONTENT_TYPE_POST_DEFAULT,
                             verbose=False):
        """Executes a POST request
        The connection is done through HTTP or HTTPS depending on the login
        status (logged in -> HTTPS)

        Parameters
        ----------
        subcontext : str, mandatory
            datalink subcontext (e.g. 'capabilities', 'availability',
            'links', etc.)
        data : str, mandatory
            POST data
        content_type: str, optional, default: application/x-www-form-urlencoded
            HTTP(s) content-type header value
        verbose : bool, optional, default 'False'
            flag to display information about the process

        Returns
        -------
        An HTTP(s) response object
        """
        context = self.__get_datalink_context(subcontext)
        return self.__execute_post(context, data, content_type, verbose)

    def execute_upload(self, data,
                       content_type=CONTENT_TYPE_POST_DEFAULT,
                       verbose=False):
        """Executes a POST upload request
        The connection is done through HTTP or HTTPS depending on the login
        status (logged in -> HTTPS)

        Parameters
        ----------
        data : str, mandatory
            POST data
        content_type: str, optional, default: application/x-www-form-urlencoded
            HTTP(s) content-type header value
        verbose : bool, optional, default 'False'
            flag to display information about the process

        Returns
        -------
        An HTTP(s) response object
        """
        context = self.__get_upload_context()
        return self.__execute_post(context, data, content_type, verbose)

    def execute_share(self, data, verbose=False):
        """Executes a POST upload request
        The connection is done through HTTP or HTTPS depending on the login
        status (logged in -> HTTPS)

        Parameters
        ----------
        data : str, mandatory
            POST data
        content_type: str, optional, default: application/x-www-form-urlencoded
            HTTP(s) content-type header value
        verbose : bool, optional, default 'False'
            flag to display information about the process

        Returns
        -------
        An HTTP(s) response object
        """
        context = self.__get_tap_context("share")
        return self.__execute_post(context,
                                   data,
                                   content_type=CONTENT_TYPE_POST_DEFAULT,
                                   verbose=verbose)

    def execute_table_edit(self, data,
                           content_type=CONTENT_TYPE_POST_DEFAULT,
                           verbose=False):
        """Executes a POST upload request
        The connection is done through HTTP or HTTPS depending on the login
        status (logged in -> HTTPS)

        Parameters
        ----------
        data : str, mandatory
            POST data
        content_type: str, optional, default: application/x-www-form-urlencoded
            HTTP(s) content-type header value
        verbose : bool, optional, default 'False'
            flag to display information about the process

        Returns
        -------
        An HTTP(s) response object
        """
        context = self.__get_table_edit_context()
        return self.__execute_post(context, data, content_type, verbose)

    def __execute_post(self, context, data,
                       content_type=CONTENT_TYPE_POST_DEFAULT,
                       verbose=False):
        conn = self.__get_connection(verbose)
        if verbose:
            print("host = " + str(conn.host) + ":" + str(conn.port))
            print("context = " + context)
            print("Content-type = " + str(content_type))
        self.__postHeaders["Content-type"] = content_type
        conn.request("POST", context, data, self.__postHeaders)
        response = conn.getresponse()
        self.__currentReason = response.reason
        self.__currentStatus = response.status
        return response

    def execute_secure(self, subcontext, data, verbose=False):
        """Executes a secure POST request
        The connection is done through HTTPS

        Parameters
        ----------
        subcontext : str, mandatory
            context to be added to host+serverContext+tapContext
        data : str, mandatory
            POST data
        verbose : bool, optional, default 'False'
            flag to display information about the process

        Returns
        -------
        An HTTPS response object
        """
        conn = self.__get_connection_secure(verbose)
        context = self.__get_server_context(subcontext)
        self.__postHeaders["Content-type"] = CONTENT_TYPE_POST_DEFAULT
        conn.request("POST", context, data, self.__postHeaders)
        response = conn.getresponse()
        self.__currentReason = response.reason
        self.__currentStatus = response.status
        return response

    def get_response_status(self):
        """Returns the latest connection status

        Returns
        -------
        The current (latest) HTTP(s) response status
        """
        return self.__currentStatus

    def get_response_reason(self):
        """Returns the latest connection reason (message)

        Returns
        -------
        The current (latest) HTTP(s) response reason
        """
        return self.__currentReason

    def url_encode(self, data):
        """Encodes the provided dictionary

        Parameters
        ----------
        data : dictionary, mandatory
            dictionary to be encoded
        """
        return urlencode(data)

    def find_header(self, headers, key):
        """Searches for the specified keyword

        Parameters
        ----------
        headers : HTTP(s) headers object, mandatory
            HTTP(s) response headers
        key : str, mandatory
            header key to be searched for

        Returns
        -------
        The requested header value or None if the header is not found
        """
        return taputils.taputil_find_header(headers, key)

    def dump_to_file(self, output, response):
        """Writes the connection response into the specified output

        Parameters
        ----------
        output : file, mandatory
            output file
        response : HTTP(s) response object, mandatory
            HTTP(s) response object
        """
        with open(output, "wb") as f:
            while True:
                data = response.read(4096)
                if len(data) < 1:
                    break
                f.write(data)
            f.close()

    def get_suitable_extension_by_format(self, output_format):
        """Returns the suitable extension for a file based on the output format

        Parameters
        ----------
        output_format : output format, mandatory

        Returns
        -------
        The suitable file extension based on the output format
        """
        if output_format is None:
            return ".vot"
        ext = ""
        outputFormat = output_format.lower()
        if "vot" in outputFormat:
            ext += ".vot"
        elif "xml" in outputFormat:
            ext += ".xml"
        elif "json" in outputFormat:
            ext += ".json"
        elif "plain" in outputFormat:
            ext += ".txt"
        elif "csv" in outputFormat:
            ext += ".csv"
        elif "ascii" in outputFormat:
            ext += ".ascii"
        return ext

    def get_suitable_extension(self, headers):
        """Returns the suitable extension for a file based on the headers
        received

        Parameters
        ----------
        headers : HTTP(s) response headers object, mandatory
            HTTP(s) response headers

        Returns
        -------
        The suitable file extension based on the HTTP(s) headers
        """
        if headers is None:
            return ""
        ext = ""
        contentType = self.find_header(headers, 'Content-Type')
        if contentType is not None:
            contentType = contentType.lower()
            if "xml" in contentType:
                ext += ".xml"
            elif "json" in contentType:
                ext += ".json"
            elif "plain" in contentType:
                ext += ".txt"
            elif "csv" in contentType:
                ext += ".csv"
            elif "ascii" in contentType:
                ext += ".ascii"
        contentEncoding = self.find_header(headers, 'Content-Encoding')
        if contentEncoding is not None:
            if "gzip" == contentEncoding.lower():
                ext += ".gz"
        return ext

    def get_file_from_header(self, headers):
        """Returns the file name returned in header Content-Disposition
        Usually, that header contains the following:
        Content-Disposition: attachment;filename="1591707060129DEV-aandres1591707060227.tar.gz"
        This method returns the value of 'filename'

        Parameters
        ----------
        headers: HTTP response headers list

        Returns
        -------
        The value of 'filename' in Content-Disposition header
        """
        content_disposition = self.find_header(headers, 'Content-Disposition')
        if content_disposition is not None:
            p = content_disposition.find('filename="')
            if p >= 0:
                filename = content_disposition[p+10:len(content_disposition)-1]
                content_encoding = self.find_header(headers, 'Content-Encoding')
                if content_encoding is not None:
                    if "gzip" == content_encoding.lower():
                        filename += ".gz"
                    elif "zip" == content_encoding.lower():
                        filename += ".zip"
                return filename
        return None

    def set_cookie(self, cookie):
        """Sets the login cookie
        When a cookie is set, GET and POST requests are done using HTTPS

        Parameters
        ----------
        cookie : str, mandatory
            login cookie
        """
        self.__cookie = cookie
        self.__postHeaders['Cookie'] = cookie
        self.__getHeaders['Cookie'] = cookie

    def unset_cookie(self):
        """Removes the login cookie
        When a cookie is not set, GET and POST requests are done using HTTP
        """
        self.__cookie = None
        self.__postHeaders.pop('Cookie')
        self.__getHeaders.pop('Cookie')

    def get_host_url(self):
        """Returns the host+port+serverContext

        Returns
        -------
        A string composed of: 'host:port/server_context'
        """
        return str(self.__connHost) + ":" + str(self.__connPort) \
            + str(self.__get_tap_context(""))

    def get_host_url_secure(self):
        """Returns the host+portSsl+serverContext

        Returns
        -------
        A string composed of: 'host:portSsl/server_context'
        """
        return str(self.__connHost) + ":" + str(self.__connPortSsl) \
            + str(self.__get_tap_context(""))

    def check_launch_response_status(self, response, debug,
                                     expected_response_status,
                                     raise_exception=True):
        """Checks the response status code
        Returns True if the response status code is the
        expected_response_status argument

        Parameters
        ----------
        response : HTTP(s) response object, mandatory
            HTTP(s) response
        debug : bool, mandatory
            flag to display information about the process
        expected_response_status : int, mandatory
            expected response status code
        raise_exception : boolean, optional, default True
            if 'True' and the response status is not the
            expected one, an exception is raised.

        Returns
        -------
        'True' if the HTTP(s) response status is the provided
        'expected_response_status' argument
        """
        isError = False
        if response.status != expected_response_status:
            if debug:
                print("ERROR: " + str(response.status) + ": " +
                      str(response.reason))
            isError = True
        if isError and raise_exception:
            errMsg = taputils.get_http_response_error(response)
            print(response.status, errMsg)
            raise requests.exceptions.HTTPError(errMsg)
        else:
            return isError

    def __get_connection(self, verbose=False):
        return self.__connectionHandler.get_connection(self.__isHttps,
                                                       self.__cookie,
                                                       verbose)

    def __get_connection_secure(self, verbose=False):
        return self.__connectionHandler.get_connection_secure(verbose)

    def encode_multipart(self, fields, files):
        """Encodes a multipart form request

        Parameters
        ----------
        fields : dictionary, mandatory
            dictionary with keywords and values
        files : array with key, filename and value, mandatory
            array with key, filename, value

        Returns
        -------
        The suitable content-type and the body for the request
        """
        timeMillis = int(round(time.time() * 1000))
        boundary = '===%s===' % str(timeMillis)
        CRLF = '\r\n'
        multiparItems = []
        for key in fields:
            multiparItems.append('--' + boundary + CRLF)
            multiparItems.append(
                'Content-Disposition: form-data; name="%s"%s' % (key, CRLF))
            multiparItems.append(CRLF)
            multiparItems.append(fields[key]+CRLF)
        for (key, filename, value) in files:
            multiparItems.append('--' + boundary + CRLF)
            multiparItems.append(
                'Content-Disposition: form-data; name="%s"; filename="%s"%s' %
                (key, filename, CRLF))
            multiparItems.append(
                'Content-Type: %s%s' %
                (mimetypes.guess_extension(filename), CRLF))
            multiparItems.append(CRLF)
            multiparItems.append(value)
            multiparItems.append(CRLF)
        multiparItems.append('--' + boundary + '--' + CRLF)
        multiparItems.append(CRLF)
        body = utils.util_create_string_from_buffer(multiparItems)
        contentType = 'multipart/form-data; boundary=%s' % boundary
        return contentType, body.encode('utf-8')

    def __str__(self):
        return "\tHost: " + str(self.__connHost) + "\n\tUse HTTPS: " \
            + str(self.__isHttps) \
            + "\n\tPort: " + str(self.__connPort) + "\n\tSSL Port: " \
            + str(self.__connPortSsl)

class ConnectionHandler(object):
    def __init__(self, host, port, sslport):
        self.__connHost = host
        self.__connPort = port
        self.__connPortSsl = sslport

    def get_connection(self, ishttps=False, cookie=None, verbose=False):
        if (ishttps) or (cookie is not None):
            if verbose:
                print("------>https")
            return self.get_connection_secure(verbose)
        else:
            if verbose:
                print("------>http")
            return httplib.HTTPConnection(self.__connHost, self.__connPort)

    def get_connection_secure(self, verbose):
        return httplib.HTTPSConnection(self.__connHost, self.__connPortSsl)


module DropboxApi::Errors
  class UploadWriteFailedError < BasicError
    ErrorSubtypes = {
      :reason => WriteError
    }.freeze
  end
end


/*
  Template for Signa1, Signal2, ... classes that support signals
  with 1, 2, ... parameters

  Begin: 2007-01-23
*/
// Copyright Frank Mori Hess 2007-2008
//
// Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// This file is included iteratively, and should not be protected from multiple inclusion

#ifdef BOOST_NO_VARIADIC_TEMPLATES
#define BOOST_SIGNALS2_NUM_ARGS BOOST_PP_ITERATION()
#else
#define BOOST_SIGNALS2_NUM_ARGS 1
#endif

// R, T1, T2, ..., TN, Combiner, Group, GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex
#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION \
  BOOST_SIGNALS2_SIGNATURE_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS), \
  Combiner, Group, GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex

namespace boost
{
  namespace signals2
  {
    namespace detail
    {
      // helper for bound_extended_slot_function that handles specialization for void return
      template<typename R>
        class BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(BOOST_SIGNALS2_NUM_ARGS)
      {
      public:
        typedef R result_type;
        template<typename ExtendedSlotFunction BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
          BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
          result_type operator()(ExtendedSlotFunction &func, const connection &conn
            BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
            BOOST_SIGNALS2_FULL_REF_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
        {
          return func(conn BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
            BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
        }
      };
#ifdef BOOST_NO_VOID_RETURNS
      template<>
        class BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(BOOST_SIGNALS2_NUM_ARGS)<void>
      {
      public:
        typedef result_type_wrapper<void>::type result_type;
        template<typename ExtendedSlotFunction BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
          BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
          result_type operator()(ExtendedSlotFunction &func, const connection &conn
            BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
            BOOST_SIGNALS2_FULL_REF_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
        {
          func(conn BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
            BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
          return result_type();
        }
      };
#endif
// wrapper around an signalN::extended_slot_function which binds the
// connection argument so it looks like a normal
// signalN::slot_function

      template<typename ExtendedSlotFunction>
        class BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(BOOST_SIGNALS2_NUM_ARGS)
      {
      public:
        typedef typename result_type_wrapper<typename ExtendedSlotFunction::result_type>::type result_type;
        BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(BOOST_SIGNALS2_NUM_ARGS)(const ExtendedSlotFunction &fun):
          _fun(fun), _connection(new connection)
        {}
        void set_connection(const connection &conn)
        {
          *_connection = conn;
        }

#if BOOST_SIGNALS2_NUM_ARGS > 0
        template<BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
#endif // BOOST_SIGNALS2_NUM_ARGS > 0
          result_type operator()(BOOST_SIGNALS2_FULL_REF_ARGS(BOOST_SIGNALS2_NUM_ARGS))
        {
          return BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(BOOST_SIGNALS2_NUM_ARGS)
            <typename ExtendedSlotFunction::result_type>()
            (_fun, *_connection BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
              BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
        }
        // const overload
#if BOOST_SIGNALS2_NUM_ARGS > 0
        template<BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
#endif // BOOST_SIGNALS2_NUM_ARGS > 0
          result_type operator()(BOOST_SIGNALS2_FULL_REF_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
        {
          return BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(BOOST_SIGNALS2_NUM_ARGS)
            <typename ExtendedSlotFunction::result_type>()
            (_fun, *_connection BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
              BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
        }
        template<typename T>
          bool operator==(const T &other) const
        {
          return _fun == other;
        }
      private:
        BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(BOOST_SIGNALS2_NUM_ARGS)()
        {}

        ExtendedSlotFunction _fun;
        boost::shared_ptr<connection> _connection;
      };

      template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
        class BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);

      template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(BOOST_SIGNALS2_NUM_ARGS)>
      class BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION
      {
      public:
        typedef SlotFunction slot_function_type;
        // typedef slotN<Signature, SlotFunction> slot_type;
        typedef BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
          <BOOST_SIGNALS2_SIGNATURE_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS),
          slot_function_type> slot_type;
        typedef ExtendedSlotFunction extended_slot_function_type;
        // typedef slotN+1<R, const connection &, T1, T2, ..., TN, extended_slot_function_type> extended_slot_type;
        typedef BOOST_SIGNALS2_EXTENDED_SLOT_TYPE(BOOST_SIGNALS2_NUM_ARGS) extended_slot_type;
        typedef typename nonvoid<typename slot_function_type::result_type>::type nonvoid_slot_result_type;
      private:
#ifdef BOOST_NO_VARIADIC_TEMPLATES
        class slot_invoker;
#else // BOOST_NO_VARIADIC_TEMPLATES
        typedef variadic_slot_invoker<nonvoid_slot_result_type, Args...> slot_invoker;
#endif // BOOST_NO_VARIADIC_TEMPLATES
        typedef slot_call_iterator_cache<nonvoid_slot_result_type, slot_invoker> slot_call_iterator_cache_type;
        typedef typename group_key<Group>::type group_key_type;
        typedef shared_ptr<connection_body<group_key_type, slot_type, Mutex> > connection_body_type;
        typedef grouped_list<Group, GroupCompare, connection_body_type> connection_list_type;
        typedef BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(BOOST_SIGNALS2_NUM_ARGS)<extended_slot_function_type>
          bound_extended_slot_function_type;
      public:
        typedef Combiner combiner_type;
        typedef typename result_type_wrapper<typename combiner_type::result_type>::type result_type;
        typedef Group group_type;
        typedef GroupCompare group_compare_type;
        typedef typename detail::slot_call_iterator_t<slot_invoker,
          typename connection_list_type::iterator, connection_body<group_key_type, slot_type, Mutex> > slot_call_iterator;

        BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const combiner_type &combiner,
          const group_compare_type &group_compare):
          _shared_state(new invocation_state(connection_list_type(group_compare), combiner)),
          _garbage_collector_it(_shared_state->connection_bodies().end())
        {}
        // connect slot
        connection connect(const slot_type &slot, connect_position position = at_back)
        {
          unique_lock<mutex_type> lock(_mutex);
          return nolock_connect(slot, position);
        }
        connection connect(const group_type &group,
          const slot_type &slot, connect_position position = at_back)
        {
          unique_lock<Mutex> lock(_mutex);
          return nolock_connect(group, slot, position);
        }
        // connect extended slot
        connection connect_extended(const extended_slot_type &ext_slot, connect_position position = at_back)
        {
          unique_lock<mutex_type> lock(_mutex);
          bound_extended_slot_function_type bound_slot(ext_slot.slot_function());
          slot_type slot = replace_slot_function<slot_type>(ext_slot, bound_slot);
          connection conn = nolock_connect(slot, position);
          bound_slot.set_connection(conn);
          return conn;
        }
        connection connect_extended(const group_type &group,
          const extended_slot_type &ext_slot, connect_position position = at_back)
        {
          unique_lock<Mutex> lock(_mutex);
          bound_extended_slot_function_type bound_slot(ext_slot.slot_function());
          slot_type slot = replace_slot_function<slot_type>(ext_slot, bound_slot);
          connection conn = nolock_connect(group, slot, position);
          bound_slot.set_connection(conn);
          return conn;
        }
        // disconnect slot(s)
        void disconnect_all_slots()
        {
          shared_ptr<invocation_state> local_state =
            get_readable_state();
          typename connection_list_type::iterator it;
          for(it = local_state->connection_bodies().begin();
            it != local_state->connection_bodies().end(); ++it)
          {
            (*it)->disconnect();
          }
        }
        void disconnect(const group_type &group)
        {
          shared_ptr<invocation_state> local_state =
            get_readable_state();
          group_key_type group_key(grouped_slots, group);
          typename connection_list_type::iterator it;
          typename connection_list_type::iterator end_it =
            local_state->connection_bodies().upper_bound(group_key);
          for(it = local_state->connection_bodies().lower_bound(group_key);
            it != end_it; ++it)
          {
            (*it)->disconnect();
          }
        }
        template <typename T>
        void disconnect(const T &slot)
        {
          typedef mpl::bool_<(is_convertible<T, group_type>::value)> is_group;
          do_disconnect(slot, is_group());
        }
        // emit signal
        result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
        {
          shared_ptr<invocation_state> local_state;
          typename connection_list_type::iterator it;
          {
            unique_lock<mutex_type> list_lock(_mutex);
            // only clean up if it is safe to do so
            if(_shared_state.unique())
              nolock_cleanup_connections(false, 1);
            /* Make a local copy of _shared_state while holding mutex, so we are
            thread safe against the combiner or connection list getting modified
            during invocation. */
            local_state = _shared_state;
          }
          slot_invoker invoker = slot_invoker(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
          slot_call_iterator_cache_type cache(invoker);
          invocation_janitor janitor(cache, *this, &local_state->connection_bodies());
          return detail::combiner_invoker<typename combiner_type::result_type>()
            (
              local_state->combiner(),
              slot_call_iterator(local_state->connection_bodies().begin(), local_state->connection_bodies().end(), cache),
              slot_call_iterator(local_state->connection_bodies().end(), local_state->connection_bodies().end(), cache)
            );
        }
        result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
        {
          shared_ptr<invocation_state> local_state;
          typename connection_list_type::iterator it;
          {
            unique_lock<mutex_type> list_lock(_mutex);
            // only clean up if it is safe to do so
            if(_shared_state.unique())
              nolock_cleanup_connections(false, 1);
            /* Make a local copy of _shared_state while holding mutex, so we are
            thread safe against the combiner or connection list getting modified
            during invocation. */
            local_state = _shared_state;
          }
          slot_invoker invoker = slot_invoker(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
          slot_call_iterator_cache_type cache(invoker);
          invocation_janitor janitor(cache, *this, &local_state->connection_bodies());
          return detail::combiner_invoker<typename combiner_type::result_type>()
            (
              local_state->combiner(),
              slot_call_iterator(local_state->connection_bodies().begin(), local_state->connection_bodies().end(), cache),
              slot_call_iterator(local_state->connection_bodies().end(), local_state->connection_bodies().end(), cache)
            );
        }
        std::size_t num_slots() const
        {
          shared_ptr<invocation_state> local_state =
            get_readable_state();
          typename connection_list_type::iterator it;
          std::size_t count = 0;
          for(it = local_state->connection_bodies().begin();
            it != local_state->connection_bodies().end(); ++it)
          {
            if((*it)->connected()) ++count;
          }
          return count;
        }
        bool empty() const
        {
          shared_ptr<invocation_state> local_state =
            get_readable_state();
          typename connection_list_type::iterator it;
          for(it = local_state->connection_bodies().begin();
            it != local_state->connection_bodies().end(); ++it)
          {
            if((*it)->connected()) return false;
          }
          return true;
        }
        combiner_type combiner() const
        {
          unique_lock<mutex_type> lock(_mutex);
          return _shared_state->combiner();
        }
        void set_combiner(const combiner_type &combiner)
        {
          unique_lock<mutex_type> lock(_mutex);
          if(_shared_state.unique())
            _shared_state->combiner() = combiner;
          else
            _shared_state.reset(new invocation_state(*_shared_state, combiner));
        }
      private:
        typedef Mutex mutex_type;

        // slot_invoker is passed to slot_call_iterator_t to run slots
#ifdef BOOST_NO_VARIADIC_TEMPLATES
        class slot_invoker
        {
        public:
          typedef nonvoid_slot_result_type result_type;
// typename add_reference<Tn>::type argn
#define BOOST_SIGNALS2_ADD_REF_ARG(z, n, data) \
  typename add_reference<BOOST_PP_CAT(T, BOOST_PP_INC(n))>::type \
  BOOST_SIGNALS2_SIGNATURE_ARG_NAME(~, n, ~)
// typename add_reference<T1>::type arg1, typename add_reference<T2>::type arg2, ..., typename add_reference<Tn>::type argn
#define BOOST_SIGNALS2_ADD_REF_ARGS(arity) \
  BOOST_PP_ENUM(arity, BOOST_SIGNALS2_ADD_REF_ARG, ~)
          slot_invoker(BOOST_SIGNALS2_ADD_REF_ARGS(BOOST_SIGNALS2_NUM_ARGS)) BOOST_PP_IF(BOOST_SIGNALS2_NUM_ARGS, :, )
#undef BOOST_SIGNALS2_ADD_REF_ARGS

// argn ( argn ) ,
#define BOOST_SIGNALS2_MISC_STATEMENT(z, n, data) \
  BOOST_PP_CAT(arg, n) ( BOOST_PP_CAT(arg, n) )
// arg1(arg1), arg2(arg2), ..., argn(argn)
            BOOST_PP_ENUM_SHIFTED(BOOST_PP_INC(BOOST_SIGNALS2_NUM_ARGS), BOOST_SIGNALS2_MISC_STATEMENT, ~)
#undef BOOST_SIGNALS2_MISC_STATEMENT
          {}
          result_type operator ()(const connection_body_type &connectionBody) const
          {
            result_type *resolver = 0;
            return m_invoke(connectionBody,
              resolver);
          }
        private:
#define BOOST_SIGNALS2_ADD_REF_ARG_STATEMENT(z, n, data) \
  BOOST_SIGNALS2_ADD_REF_ARG(z, n, data) ;
          BOOST_PP_REPEAT(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_ADD_REF_ARG_STATEMENT, ~)
#undef BOOST_SIGNALS2_ADD_REF_ARG_STATEMENT
#undef BOOST_SIGNALS2_ADD_REF_ARG
          result_type m_invoke(const connection_body_type &connectionBody,
            const void_type *) const
          {
            connectionBody->slot.slot_function()(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
            return void_type();
          }
          result_type m_invoke(const connection_body_type &connectionBody, ...) const
          {
            return connectionBody->slot.slot_function()(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
          }
        };
#endif // BOOST_NO_VARIADIC_TEMPLATES
        // a struct used to optimize (minimize) the number of shared_ptrs that need to be created
        // inside operator()
        class invocation_state
        {
        public:
          invocation_state(const connection_list_type &connections_in,
            const combiner_type &combiner_in): _connection_bodies(new connection_list_type(connections_in)),
            _combiner(new combiner_type(combiner_in))
          {}
          invocation_state(const invocation_state &other, const connection_list_type &connections_in):
            _connection_bodies(new connection_list_type(connections_in)),
            _combiner(other._combiner)
          {}
          invocation_state(const invocation_state &other, const combiner_type &combiner_in):
            _connection_bodies(other._connection_bodies),
            _combiner(new combiner_type(combiner_in))
          {}
          connection_list_type & connection_bodies() { return *_connection_bodies; }
          const connection_list_type & connection_bodies() const { return *_connection_bodies; }
          combiner_type & combiner() { return *_combiner; }
          const combiner_type & combiner() const { return *_combiner; }
        private:
          invocation_state(const invocation_state &);

          shared_ptr<connection_list_type> _connection_bodies;
          shared_ptr<combiner_type> _combiner;
        };
        // Destructor of invocation_janitor does some cleanup when a signal invocation completes.
        // Code can't be put directly in signal's operator() due to complications from void return types.
        class invocation_janitor
        {
        public:
          typedef BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) signal_type;
          invocation_janitor
          (
            const slot_call_iterator_cache_type &cache,
            const signal_type &sig,
            const connection_list_type *connection_bodies
          ):_cache(cache), _sig(sig), _connection_bodies(connection_bodies)
          {}
          ~invocation_janitor()
          {
            // force a full cleanup of disconnected slots if there are too many
            if(_cache.disconnected_slot_count > _cache.connected_slot_count)
            {
              _sig.force_cleanup_connections(_connection_bodies);
            }
          }
        private:
          const slot_call_iterator_cache_type &_cache;
          const signal_type &_sig;
          const connection_list_type *_connection_bodies;
        };

        // clean up disconnected connections
        void nolock_cleanup_connections_from(bool grab_tracked,
          const typename connection_list_type::iterator &begin, unsigned count = 0) const
        {
          BOOST_ASSERT(_shared_state.unique());
          typename connection_list_type::iterator it;
          unsigned i;
          for(it = begin, i = 0;
            it != _shared_state->connection_bodies().end() && (count == 0 || i < count);
            ++i)
          {
            bool connected;
            {
              unique_lock<connection_body_base> lock(**it);
              if(grab_tracked)
                (*it)->nolock_slot_expired();
              connected = (*it)->nolock_nograb_connected();
            }// scoped lock destructs here, safe to erase now
            if(connected == false)
            {
              it = _shared_state->connection_bodies().erase((*it)->group_key(), it);
            }else
            {
              ++it;
            }
          }
          _garbage_collector_it = it;
        }
        // clean up a few connections in constant time
        void nolock_cleanup_connections(bool grab_tracked, unsigned count) const
        {
          BOOST_ASSERT(_shared_state.unique());
          typename connection_list_type::iterator begin;
          if(_garbage_collector_it == _shared_state->connection_bodies().end())
          {
            begin = _shared_state->connection_bodies().begin();
          }else
          {
            begin = _garbage_collector_it;
          }
          nolock_cleanup_connections_from(grab_tracked, begin, count);
        }
        /* Make a new copy of the slot list if it is currently being read somewhere else
        */
        void nolock_force_unique_connection_list()
        {
          if(_shared_state.unique() == false)
          {
            _shared_state.reset(new invocation_state(*_shared_state, _shared_state->connection_bodies()));
            nolock_cleanup_connections_from(true, _shared_state->connection_bodies().begin());
          }else
          {
            /* We need to try and check more than just 1 connection here to avoid corner
            cases where certain repeated connect/disconnect patterns cause the slot
            list to grow without limit. */
            nolock_cleanup_connections(true, 2);
          }
        }
        // force a full cleanup of the connection list
        void force_cleanup_connections(const connection_list_type *connection_bodies) const
        {
          unique_lock<mutex_type> list_lock(_mutex);
          // if the connection list passed in as a parameter is no longer in use,
          // we don't need to do any cleanup.
          if(&_shared_state->connection_bodies() != connection_bodies)
          {
            return;
          }
          if(_shared_state.unique() == false)
          {
            _shared_state.reset(new invocation_state(*_shared_state, _shared_state->connection_bodies()));
          }
          nolock_cleanup_connections_from(false, _shared_state->connection_bodies().begin());
        }
        shared_ptr<invocation_state> get_readable_state() const
        {
          unique_lock<mutex_type> list_lock(_mutex);
          return _shared_state;
        }
        connection_body_type create_new_connection(const slot_type &slot)
        {
          nolock_force_unique_connection_list();
          return connection_body_type(new connection_body<group_key_type, slot_type, Mutex>(slot));
        }
        void do_disconnect(const group_type &group, mpl::bool_<true> is_group)
        {
          disconnect(group);
        }
        template<typename T>
        void do_disconnect(const T &slot, mpl::bool_<false> is_group)
        {
          shared_ptr<invocation_state> local_state =
            get_readable_state();
          typename connection_list_type::iterator it;
          for(it = local_state->connection_bodies().begin();
            it != local_state->connection_bodies().end(); ++it)
          {
            unique_lock<connection_body_base> lock(**it);
            if((*it)->slot.slot_function() == slot)
            {
              (*it)->nolock_disconnect();
            }else
            {
              // check for wrapped extended slot
              bound_extended_slot_function_type *fp;
              fp = (*it)->slot.slot_function().template target<bound_extended_slot_function_type>();
              if(fp && *fp == slot)
              {
                (*it)->nolock_disconnect();
              }
            }
          }
        }
        // connect slot
        connection nolock_connect(const slot_type &slot, connect_position position)
        {
          connection_body_type newConnectionBody =
            create_new_connection(slot);
          group_key_type group_key;
          if(position == at_back)
          {
            group_key.first = back_ungrouped_slots;
            _shared_state->connection_bodies().push_back(group_key, newConnectionBody);
          }else
          {
            group_key.first = front_ungrouped_slots;
            _shared_state->connection_bodies().push_front(group_key, newConnectionBody);
          }
          newConnectionBody->set_group_key(group_key);
          return connection(newConnectionBody);
        }
        connection nolock_connect(const group_type &group,
          const slot_type &slot, connect_position position)
        {
          connection_body_type newConnectionBody =
            create_new_connection(slot);
          // update map to first connection body in group if needed
          group_key_type group_key(grouped_slots, group);
          newConnectionBody->set_group_key(group_key);
          if(position == at_back)
          {
            _shared_state->connection_bodies().push_back(group_key, newConnectionBody);
          }else  // at_front
          {
            _shared_state->connection_bodies().push_front(group_key, newConnectionBody);
          }
          return connection(newConnectionBody);
        }

        // _shared_state is mutable so we can do force_cleanup_connections during a const invocation
        mutable shared_ptr<invocation_state> _shared_state;
        mutable typename connection_list_type::iterator _garbage_collector_it;
        // connection list mutex must never be locked when attempting a blocking lock on a slot,
        // or you could deadlock.
        mutable mutex_type _mutex;
      };

      template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
        class BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
    }

    template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DEFAULTED_DECL(BOOST_SIGNALS2_NUM_ARGS)>
      class BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);

    template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(BOOST_SIGNALS2_NUM_ARGS)>
    class BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
      BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION: public signal_base,
      public detail::BOOST_SIGNALS2_STD_FUNCTIONAL_BASE
        (typename detail::result_type_wrapper<typename Combiner::result_type>::type)
    {
      typedef detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
        <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> impl_class;
    public:
      typedef detail::BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
        <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> weak_signal_type;
      friend class detail::BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
        <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION>;

      typedef SlotFunction slot_function_type;
      // typedef slotN<Signature, SlotFunction> slot_type;
      typedef typename impl_class::slot_type slot_type;
      typedef typename impl_class::extended_slot_function_type extended_slot_function_type;
      typedef typename impl_class::extended_slot_type extended_slot_type;
      typedef typename slot_function_type::result_type slot_result_type;
      typedef Combiner combiner_type;
      typedef typename impl_class::result_type result_type;
      typedef Group group_type;
      typedef GroupCompare group_compare_type;
      typedef typename impl_class::slot_call_iterator
        slot_call_iterator;
      typedef typename mpl::identity<BOOST_SIGNALS2_SIGNATURE_FUNCTION_TYPE(BOOST_SIGNALS2_NUM_ARGS)>::type signature_type;

#ifdef BOOST_NO_VARIADIC_TEMPLATES

// typedef Tn argn_type;
#define BOOST_SIGNALS2_MISC_STATEMENT(z, n, data) \
  typedef BOOST_PP_CAT(T, BOOST_PP_INC(n)) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(n)), _type);
      BOOST_PP_REPEAT(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_MISC_STATEMENT, ~)
#undef BOOST_SIGNALS2_MISC_STATEMENT
#if BOOST_SIGNALS2_NUM_ARGS == 1
      typedef arg1_type argument_type;
#elif BOOST_SIGNALS2_NUM_ARGS == 2
      typedef arg1_type first_argument_type;
      typedef arg2_type second_argument_type;
#endif

      template<unsigned n> class arg : public
        detail::BOOST_SIGNALS2_PREPROCESSED_ARG_N_TYPE_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
        <n BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
        BOOST_SIGNALS2_ARGS_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS)>
      {};

      BOOST_STATIC_CONSTANT(int, arity = BOOST_SIGNALS2_NUM_ARGS);

#else // BOOST_NO_VARIADIC_TEMPLATES

      template<unsigned n> class arg
      {
      public:
        typedef typename detail::variadic_arg_type<n, Args...>::type type;
      };
      BOOST_STATIC_CONSTANT(int, arity = sizeof...(Args));

#endif // BOOST_NO_VARIADIC_TEMPLATES

      BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const combiner_type &combiner = combiner_type(),
        const group_compare_type &group_compare = group_compare_type()):
        _pimpl(new impl_class(combiner, group_compare))
      {};
      virtual ~BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)()
      {
        disconnect_all_slots();
      }
      connection connect(const slot_type &slot, connect_position position = at_back)
      {
        return (*_pimpl).connect(slot, position);
      }
      connection connect(const group_type &group,
        const slot_type &slot, connect_position position = at_back)
      {
        return (*_pimpl).connect(group, slot, position);
      }
      connection connect_extended(const extended_slot_type &slot, connect_position position = at_back)
      {
        return (*_pimpl).connect_extended(slot, position);
      }
      connection connect_extended(const group_type &group,
        const extended_slot_type &slot, connect_position position = at_back)
      {
        return (*_pimpl).connect_extended(group, slot, position);
      }
      void disconnect_all_slots()
      {
        (*_pimpl).disconnect_all_slots();
      }
      void disconnect(const group_type &group)
      {
        (*_pimpl).disconnect(group);
      }
      template <typename T>
      void disconnect(const T &slot)
      {
        (*_pimpl).disconnect(slot);
      }
      result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
      {
        return (*_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
      }
      result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
      {
        return (*_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
      }
      std::size_t num_slots() const
      {
        return (*_pimpl).num_slots();
      }
      bool empty() const
      {
        return (*_pimpl).empty();
      }
      combiner_type combiner() const
      {
        return (*_pimpl).combiner();
      }
      void set_combiner(const combiner_type &combiner)
      {
        return (*_pimpl).set_combiner(combiner);
      }
    protected:
      virtual shared_ptr<void> lock_pimpl() const
      {
        return _pimpl;
      }
    private:
      shared_ptr<impl_class>
        _pimpl;
    };

    namespace detail
    {
      // wrapper class for storing other signals as slots with automatic lifetime tracking
      template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
        class BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);

      template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(BOOST_SIGNALS2_NUM_ARGS)>
        class BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
        BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION
      {
      public:
        typedef typename BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
          <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION>::result_type
          result_type;

        BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
          (const BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
          <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION>
          &signal):
          _weak_pimpl(signal._pimpl)
        {}
        result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
        {
          shared_ptr<detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
            <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> >
            shared_pimpl(_weak_pimpl.lock());
          if(shared_pimpl == 0) boost::throw_exception(expired_slot());
          return (*shared_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
        }
        result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
        {
          shared_ptr<detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
            <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> >
            shared_pimpl(_weak_pimpl.lock());
          if(shared_pimpl == 0) boost::throw_exception(expired_slot());
          return (*shared_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
        }
      private:
        boost::weak_ptr<detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
          <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> > _weak_pimpl;
      };

#ifndef BOOST_NO_VARIADIC_TEMPLATES
      template<int arity, typename Signature>
        class extended_signature: public variadic_extended_signature<Signature>
      {};
#else // BOOST_NO_VARIADIC_TEMPLATES
      template<int arity, typename Signature>
        class extended_signature;
      // partial template specialization
      template<typename Signature>
        class extended_signature<BOOST_SIGNALS2_NUM_ARGS, Signature>
      {
      public:
// typename function_traits<Signature>::result_type (
// const boost::signals2::connection &,
// typename function_traits<Signature>::arg1_type,
// typename function_traits<Signature>::arg2_type,
// ...,
// typename function_traits<Signature>::argn_type)
#define BOOST_SIGNALS2_EXT_SIGNATURE(arity, Signature) \
  typename function_traits<Signature>::result_type ( \
  const boost::signals2::connection & BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS) \
  BOOST_PP_ENUM(arity, BOOST_SIGNALS2_SIGNATURE_TO_ARGN_TYPE, Signature) )
        typedef function<BOOST_SIGNALS2_EXT_SIGNATURE(BOOST_SIGNALS2_NUM_ARGS, Signature)> function_type;
#undef BOOST_SIGNALS2_EXT_SIGNATURE
      };

      template<unsigned arity, typename Signature, typename Combiner,
        typename Group, typename GroupCompare, typename SlotFunction,
        typename ExtendedSlotFunction, typename Mutex>
      class signalN;
      // partial template specialization
      template<typename Signature, typename Combiner, typename Group,
        typename GroupCompare, typename SlotFunction,
        typename ExtendedSlotFunction, typename Mutex>
      class signalN<BOOST_SIGNALS2_NUM_ARGS, Signature, Combiner, Group,
        GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex>
      {
      public:
        typedef BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)<
          BOOST_SIGNALS2_PORTABLE_SIGNATURE(BOOST_SIGNALS2_NUM_ARGS, Signature),
          Combiner, Group,
          GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex> type;
      };

#endif // BOOST_NO_VARIADIC_TEMPLATES

    } // namespace detail
  } // namespace signals2
} // namespace boost

#undef BOOST_SIGNALS2_NUM_ARGS
#undef BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION


// +build !windows

package main

import (
	"encoding/json"
	"fmt"

	"github.com/docker/docker/api/types/swarm"
	"github.com/docker/docker/integration-cli/checker"
	"github.com/go-check/check"
)

func (s *DockerSwarmSuite) TestServiceUpdateLabel(c *check.C) {
	d := s.AddDaemon(c, true, true)
	out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name=test", "busybox", "top")
	c.Assert(err, checker.IsNil, check.Commentf("%s", out))
	service := d.GetService(c, "test")
	c.Assert(service.Spec.Labels, checker.HasLen, 0)

	// add label to empty set
	out, err = d.Cmd("service", "update", "--detach", "test", "--label-add", "foo=bar")
	c.Assert(err, checker.IsNil, check.Commentf("%s", out))
	service = d.GetService(c, "test")
	c.Assert(service.Spec.Labels, checker.HasLen, 1)
	c.Assert(service.Spec.Labels["foo"], checker.Equals, "bar")

	// add label to non-empty set
	out, err = d.Cmd("service", "update", "--detach", "test", "--label-add", "foo2=bar")
	c.Assert(err, checker.IsNil, check.Commentf("%s", out))
	service = d.GetService(c, "test")
	c.Assert(service.Spec.Labels, checker.HasLen, 2)
	c.Assert(service.Spec.Labels["foo2"], checker.Equals, "bar")

	out, err = d.Cmd("service", "update", "--detach", "test", "--label-rm", "foo2")
	c.Assert(err, checker.IsNil, check.Commentf("%s", out))
	service = d.GetService(c, "test")
	c.Assert(service.Spec.Labels, checker.HasLen, 1)
	c.Assert(service.Spec.Labels["foo2"], checker.Equals, "")

	out, err = d.Cmd("service", "update", "--detach", "test", "--label-rm", "foo")
	c.Assert(err, checker.IsNil, check.Commentf("%s", out))
	service = d.GetService(c, "test")
	c.Assert(service.Spec.Labels, checker.HasLen, 0)
	c.Assert(service.Spec.Labels["foo"], checker.Equals, "")

	// now make sure we can add again
	out, err = d.Cmd("service", "update", "--detach", "test", "--label-add", "foo=bar")
	c.Assert(err, checker.IsNil, check.Commentf("%s", out))
	service = d.GetService(c, "test")
	c.Assert(service.Spec.Labels, checker.HasLen, 1)
	c.Assert(service.Spec.Labels["foo"], checker.Equals, "bar")
}

func (s *DockerSwarmSuite) TestServiceUpdateSecrets(c *check.C) {
	d := s.AddDaemon(c, true, true)
	testName := "test_secret"
	id := d.CreateSecret(c, swarm.SecretSpec{
		Annotations: swarm.Annotations{
			Name: testName,
		},
		Data: []byte("TESTINGDATA"),
	})
	c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
	testTarget := "testing"
	serviceName := "test"

	out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", serviceName, "busybox", "top")
	c.Assert(err, checker.IsNil, check.Commentf("%s", out))

	// add secret
	out, err = d.Cmd("service", "update", "--detach", "test", "--secret-add", fmt.Sprintf("source=%s,target=%s", testName, testTarget))
	c.Assert(err, checker.IsNil, check.Commentf("%s", out))

	out, err = d.Cmd("service", "inspect", "--format", "{{ json .Spec.TaskTemplate.ContainerSpec.Secrets }}", serviceName)
	c.Assert(err, checker.IsNil)

	var refs []swarm.SecretReference
	c.Assert(json.Unmarshal([]byte(out), &refs), checker.IsNil)
	c.Assert(refs, checker.HasLen, 1)

	c.Assert(refs[0].SecretName, checker.Equals, testName)
	c.Assert(refs[0].File, checker.Not(checker.IsNil))
	c.Assert(refs[0].File.Name, checker.Equals, testTarget)

	// remove
	out, err = d.Cmd("service", "update", "--detach", "test", "--secret-rm", testName)
	c.Assert(err, checker.IsNil, check.Commentf("%s", out))

	out, err = d.Cmd("service", "inspect", "--format", "{{ json .Spec.TaskTemplate.ContainerSpec.Secrets }}", serviceName)
	c.Assert(err, checker.IsNil)

	c.Assert(json.Unmarshal([]byte(out), &refs), checker.IsNil)
	c.Assert(refs, checker.HasLen, 0)
}

func (s *DockerSwarmSuite) TestServiceUpdateConfigs(c *check.C) {
	d := s.AddDaemon(c, true, true)
	testName := "test_config"
	id := d.CreateConfig(c, swarm.ConfigSpec{
		Annotations: swarm.Annotations{
			Name: testName,
		},
		Data: []byte("TESTINGDATA"),
	})
	c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("configs: %s", id))
	testTarget := "/testing"
	serviceName := "test"

	out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", serviceName, "busybox", "top")
	c.Assert(err, checker.IsNil, check.Commentf("%s", out))

	// add config
	out, err = d.Cmd("service", "update", "--detach", "test", "--config-add", fmt.Sprintf("source=%s,target=%s", testName, testTarget))
	c.Assert(err, checker.IsNil, check.Commentf("%s", out))

	out, err = d.Cmd("service", "inspect", "--format", "{{ json .Spec.TaskTemplate.ContainerSpec.Configs }}", serviceName)
	c.Assert(err, checker.IsNil)

	var refs []swarm.ConfigReference
	c.Assert(json.Unmarshal([]byte(out), &refs), checker.IsNil)
	c.Assert(refs, checker.HasLen, 1)

	c.Assert(refs[0].ConfigName, checker.Equals, testName)
	c.Assert(refs[0].File, checker.Not(checker.IsNil))
	c.Assert(refs[0].File.Name, checker.Equals, testTarget)

	// remove
	out, err = d.Cmd("service", "update", "--detach", "test", "--config-rm", testName)
	c.Assert(err, checker.IsNil, check.Commentf("%s", out))

	out, err = d.Cmd("service", "inspect", "--format", "{{ json .Spec.TaskTemplate.ContainerSpec.Configs }}", serviceName)
	c.Assert(err, checker.IsNil)

	c.Assert(json.Unmarshal([]byte(out), &refs), checker.IsNil)
	c.Assert(refs, checker.HasLen, 0)
}


<!DOCTYPE HTML>

<title>HTMLLabelElement (Java SE 12 & JDK 12 )</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="keywords" content="org.w3c.dom.html.HTMLLabelElement interface">
<meta name="keywords" content="getForm()">
<meta name="keywords" content="getAccessKey()">
<meta name="keywords" content="setAccessKey()">
<meta name="keywords" content="getHtmlFor()">
<meta name="keywords" content="setHtmlFor()">
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
<link rel="stylesheet" type="text/css" href="../../../../../jquery/jquery-ui.css" title="Style">

JavaScript is disabled on your browser.

Skip navigation links

Overview

Module

Package

Class

Use

Tree

Deprecated

Index

Help

Java SE 12 & JDK 12

Summary:

Nested |

Field |

Constr |

Method

Detail:

Field |

Constr |

Method

SEARCH:
<input type="text" id="search" value="search" disabled="disabled">
<input type="reset" id="reset" value="reset" disabled="disabled">

Module jdk.xml.dom

Package org.w3c.dom.html

Interface HTMLLabelElement

All Superinterfaces:

Element, HTMLElement, Node

public interface HTMLLabelElement
extends HTMLElement

Form field label text. See the  LABEL element definition in HTML 4.0.

See also the Document Object Model (DOM) Level 2 Specification.

Since:

1.4, DOM Level 2

Field Summary

Fields declared in interface org.w3c.dom.Node

ATTRIBUTE_NODE, CDATA_SECTION_NODE, COMMENT_NODE, DOCUMENT_FRAGMENT_NODE, DOCUMENT_NODE, DOCUMENT_POSITION_CONTAINED_BY, DOCUMENT_POSITION_CONTAINS, DOCUMENT_POSITION_DISCONNECTED, DOCUMENT_POSITION_FOLLOWING, DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC, DOCUMENT_POSITION_PRECEDING, DOCUMENT_TYPE_NODE, ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE, NOTATION_NODE, PROCESSING_INSTRUCTION_NODE, TEXT_NODE

Method Summary

<button role="tab" aria-selected="true" aria-controls="memberSummary_tabpanel" tabindex="0" onkeydown="switchTab(event)" id="t0" class="activeTableTab">All Methods</button><button role="tab" aria-selected="false" aria-controls="memberSummary_tabpanel" tabindex="-1" onkeydown="switchTab(event)" id="t2" class="tableTab" onclick="show(2);">Instance Methods</button><button role="tab" aria-selected="false" aria-controls="memberSummary_tabpanel" tabindex="-1" onkeydown="switchTab(event)" id="t3" class="tableTab" onclick="show(4);">Abstract Methods</button>

Modifier and Type
Method
Description

String
getAccessKey()

A single character access key to give access to the form control.

HTMLFormElement
getForm()

Returns the FORM element containing this control.

String
getHtmlFor()

This attribute links this label with another form control by
 id attribute.

void
setAccessKey(String accessKey)

void
setHtmlFor(String htmlFor)

Methods declared in interface org.w3c.dom.Element

getAttribute, getAttributeNode, getAttributeNodeNS, getAttributeNS, getElementsByTagName, getElementsByTagNameNS, getSchemaTypeInfo, getTagName, hasAttribute, hasAttributeNS, removeAttribute, removeAttributeNode, removeAttributeNS, setAttribute, setAttributeNode, setAttributeNodeNS, setAttributeNS, setIdAttribute, setIdAttributeNode, setIdAttributeNS

Methods declared in interface org.w3c.dom.html.HTMLElement

getClassName, getDir, getId, getLang, getTitle, setClassName, setDir, setId, setLang, setTitle

Methods declared in interface org.w3c.dom.Node

appendChild, cloneNode, compareDocumentPosition, getAttributes, getBaseURI, getChildNodes, getFeature, getFirstChild, getLastChild, getLocalName, getNamespaceURI, getNextSibling, getNodeName, getNodeType, getNodeValue, getOwnerDocument, getParentNode, getPrefix, getPreviousSibling, getTextContent, getUserData, hasAttributes, hasChildNodes, insertBefore, isDefaultNamespace, isEqualNode, isSameNode, isSupported, lookupNamespaceURI, lookupPrefix, normalize, removeChild, replaceChild, setNodeValue, setPrefix, setTextContent, setUserData

Method Detail

getForm

HTMLFormElement getForm()

Returns the FORM element containing this control. Returns
 null if this control is not within the context of a form.

getAccessKey

String getAccessKey()

A single character access key to give access to the form control. See
 the  accesskey attribute definition in HTML 4.0.

setAccessKey

void setAccessKey(String accessKey)

getHtmlFor

String getHtmlFor()

This attribute links this label with another form control by
 id attribute. See the  for attribute definition in HTML
 4.0.

setHtmlFor

void setHtmlFor(String htmlFor)

Skip navigation links

Overview

Module

Package

Class

Use

Tree

Deprecated

Index

Help

Java SE 12 & JDK 12

Summary:

Nested |

Field |

Constr |

Method

Detail:

Field |

Constr |

Method

Report a bug or suggest an enhancement
 For further API reference and developer documentation see the Java SE Documentation, which contains more detailed, developer-targeted descriptions with conceptual overviews, definitions of terms, workarounds, and working code examples.
 Java is a trademark or registered trademark of Oracle and/or its affiliates in the US and other countries.
 Copyright © 1993, 2019, Oracle and/or its affiliates, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.
All rights reserved. Use is subject to license terms and the documentation redistribution policy.


// This file was procedurally generated from the following sources:
// - src/class-elements/rs-private-getter-alt.case
// - src/class-elements/productions/cls-decl-wrapped-in-sc.template
/*---
description: Valid PrivateName as private getter (fields definition wrapped in semicolons)
esid: prod-FieldDefinition
features: [class-methods-private, class-fields-private, class, class-fields-public]
flags: [generated]
info: |
    ClassElement :
      MethodDefinition
      ...
      ;

    MethodDefinition :
      ...
      get ClassElementName ( ){ FunctionBody }
      ...

    ClassElementName :
      PropertyName
      PrivateName

    PrivateName ::
      # IdentifierName

    IdentifierName ::
      IdentifierStart
      IdentifierName IdentifierPart

    IdentifierStart ::
      UnicodeIDStart
      $
      _
      \ UnicodeEscapeSequence

    IdentifierPart::
      UnicodeIDContinue
      $
      \ UnicodeEscapeSequence
      <ZWNJ> <ZWJ>

    UnicodeIDStart::
      any Unicode code point with the Unicode property "ID_Start"

    UnicodeIDContinue::
      any Unicode code point with the Unicode property "ID_Continue"

    NOTE 3
    The sets of code points with Unicode properties "ID_Start" and
    "ID_Continue" include, respectively, the code points with Unicode
    properties "Other_ID_Start" and "Other_ID_Continue".

---*/

class C {
  ;;;;
  ;;;;;;#$_; #__; #\u{6F}_; #℘_; #ZW__NJ_; #ZW__J_;
  get #$() {
    return this.#$_;
  }
  get #_() {
    return this.#__;
  }
  get #\u{6F}() {
    return this.#\u{6F}_;
  }
  get #℘() {
    return this.#℘_;
  }
  get #ZW__NJ() {
    return this.#ZW__NJ_;
  }
  get #ZW__J() {
    return this.#ZW__J_;
  }
;;;;;;;
  ;;;;
  $(value) {
    this.#$_ = value;
    return this.#$;
  }
  _(value) {
    this.#__ = value;
    return this.#_;
  }
  \u{6F}(value) {
    this.#\u{6F}_ = value;
    return this.#\u{6F};
  }
  ℘(value) {
    this.#℘_ = value;
    return this.#℘;
  }
  ZW__NJ(value) {
    this.#ZW__NJ_ = value;
    return this.#ZW__NJ;
  }
  ZW__J(value) {
    this.#ZW__J_ = value;
    return this.#ZW__J;
  }

}

var c = new C();

assert.sameValue(c.$(1), 1);
assert.sameValue(c._(1), 1);
assert.sameValue(c.\u{6F}(1), 1);
assert.sameValue(c.℘(1), 1);
assert.sameValue(c.ZW__NJ(1), 1);
assert.sameValue(c.ZW__J(1), 1);


/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) ST-Ericsson SA 2010
 *
 * Author: Bengt Jonsson <bengt.jonsson@stericsson.com> for ST-Ericsson,
 *	   Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
 */

#ifndef DBX500_REGULATOR_H
#define DBX500_REGULATOR_H

#include <linux/platform_device.h>

/**
 * struct dbx500_regulator_info - dbx500 regulator information
 * @desc: regulator description
 * @is_enabled: status of the regulator
 * @epod_id: id for EPOD (power domain)
 * @is_ramret: RAM retention switch for EPOD (power domain)
 *
 */
struct dbx500_regulator_info {
	struct regulator_desc desc;
	bool is_enabled;
	u16 epod_id;
	bool is_ramret;
	bool exclude_from_power_state;
};

void power_state_active_enable(void);
int power_state_active_disable(void);

#ifdef CONFIG_REGULATOR_DEBUG
int ux500_regulator_debug_init(struct platform_device *pdev,
			       struct dbx500_regulator_info *regulator_info,
			       int num_regulators);

int ux500_regulator_debug_exit(void);
#else

static inline int ux500_regulator_debug_init(struct platform_device *pdev,
			     struct dbx500_regulator_info *regulator_info,
			     int num_regulators)
{
	return 0;
}

static inline int ux500_regulator_debug_exit(void)
{
	return 0;
}

#endif
#endif


# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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

exclude:
  - "*.md"
  - "build_docs.sh"
  - "check_links.sh"
  - "content"
  - "content_en"
  - "content_zh"

include:
  - "*.zh.md"


<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>


<link rel="stylesheet" href="/css/main.css">

Previous
 Up
 Next

Module type Hashtbl.SeededHashedType

module type SeededHashedType = sig .. end

The input signature of the functor Hashtbl.MakeSeeded.

Since 4.00.0

type t;

The type of the hashtable keys.

let equal: (t, t) => bool;

The equality predicate used to compare keys.

let hash: (int, t) => int;

A seeded hashing function on keys.  The first argument is
          the seed.  It must be the case that if equal x y is true,
          then hash seed x = hash seed y for any value of seed.
          A suitable choice for hash is the function Hashtbl.seeded_hash
          below.


jokester

A Vue.js project

cross-env NODE_ENV=development webpack-dev-server --open --hot

cross-env NODE_ENV=production webpack --progress --hide-modules


export interface About {
  instance: {
    name: string
    shortDescription: string
    description: string
    terms: string

    codeOfConduct: string
    hardwareInformation: string

    creationReason: string
    moderationInformation: string
    administrator: string
    maintenanceLifetime: string
    businessModel: string

    languages: string[]
    categories: number[]
  }
}


.container,
#main {
    position: relative;
}

#menu-off {
    position: absolute;
    top: 0;
    left: 100%;
    .transition(.4s);
}

#menu {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 66;
    width: @menuWidth;
    min-height: 100%;
    background: #fff;
    box-shadow: @boxShadow;
    .transition(.4s, cubic-bezier(.18, .81, .3, .89));
    will-change: transform, -webkit-transform;

    &.hide {
        .transform(translateX(-100%));
        #menu-off {
            .transform(scale(0));
        }
        +#main {
            padding-left: 0;
        }
    }

    .inner {
        position: relative;
        height: 100%;
    }

    .brand-wrap {
        background-size: 100% 100%;
    }

    .brand {
        padding: 40px @menuPadding 2em;
        background: fade(@primaryColor, 50%);
    }

    .avatar {
        display: block;
        width: 80px;
        height: 80px;
        border: 2px solid #fff;
        border-radius: 50%;
        overflow: hidden;
        box-shadow: @boxShadow;
    }

    .introduce {
        margin: 1em 0 0;
        color: @textPrimaryColor;
    }

    .mail {
        display: inline-block;
        padding-top: 4px;
        color: @lightPrimaryColor;
        font-size: 13px;
    }

    .scroll-wrap {
        position: relative;
        overflow-y: auto;
    }

    .nav {
        margin: 0;
        padding: 12px 0;
        height: 300px;
        min-height: ~"calc(100% - 115px)";
        list-style: none;
        line-height: @navH;

        li {
            padding: 0 @menuPadding;

            .icon {
                position: absolute;
                top: 0;
                left: @menuPadding;
                line-height: inherit;
            }

            &:hover,
            &.active {
                background: rgba(0, 0, 0, .05);

                a,
                .icon {
                    color: @primaryColor;
                }
            }
        }

        a {
            display: block;
            padding-left: @menuPadding*2.4;
            height: @navH;
            line-height: @navH;
            font-weight: 500;
            color: @secondaryTextColor;
            text-decoration: none;
        }
    }
}

#main {
    padding-left: @menuWidth;
    min-height: 100%;
    .transition(.4s);
}

.body-wrap {
    padding: 30px 0 40px;
    min-height: ~'calc(100vh - 340px)';
}

.container {
    width: @contentWidth;
    margin: 0 auto;

    &:after {
        content: "";
        display: table;
        clear: both;
    }
}

.mask {
    visibility: hidden;
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 88;
    width: 100%;
    height: 100%;
    background: #000;
    opacity: 0;
    pointer-events: none;
    .transition(.3s);

    &.in {
        visibility: visible;
        pointer-events: auto;
        opacity: .3;
    }
}

.footer {
    color: rgba(255,255,255,.6);
    background: @darkPrimaryColor;
    p {
        margin: 0;
        line-height: 1.6;
        font-size: 13px;
        text-align: center;
        span {
            &:not(:first-child):before {
                content: "·";
                padding: 0 .5em;
            }
        }
        a {
            border-bottom: 1px dotted rgba(255,255,255,.5);
            &:hover {
                border-bottom: 1px solid rgba(255,255,255,.7);
            }
        }
    }

    .top {
        padding: 16px;
        background: @primaryColor;
    }
    a {
        color: inherit;
        opacity: .8;

        &:hover {
            color: #fff;
            text-decoration: none
        }
    }
    .bottom {
        padding: 16px;
    }
}

a[title="站长统计"] {
    display: none;
}

@media screen and (max-width:1240px) {
    #menu-off {
        display: none;
    }

    #menu {
        z-index: 99;
        box-shadow: none;
        .transform(translateX(-100%));

        &.show {
            .transform(translateX(0));
        }
    }

    #main {
        padding-left: 0;
    }
}

@media screen and (max-width:1040px) {
    .container {
        width: 100%;
        padding: 20px 16px;
    }
}

@media screen and (max-width:760px) {
    #main {
        width: 100%;
        overflow-x: hidden;
    }

    #menu {
        .brand {
            padding-top: 20px;
            padding-bottom: 1em;
        }

        .nav {
            line-height: @mNavH;

            a {
                height: @mNavH;
                line-height: @mNavH;
            }
        }
    }

    ::-webkit-scrollbar {
        display: none;
    }
}