text:
# This file contains code that is common to
# both the Python build system and the CMake
# build system.
#
# The code here generally is involved in
# generating files needed by Z3 at build time.
#
# You should **not** import ``mk_util`` here
# to avoid having this code depend on the
# of the Python build system.
import os
import pprint
import logging
import re
import sys

# Logger for this module
_logger = logging.getLogger(__name__)

###############################################################################
# Utility functions
###############################################################################
def check_dir_exists(output_dir):
    """
        Returns ``True`` if ``output_dir`` exists, otherwise
        returns ``False``.
    """
    if not os.path.isdir(output_dir):
        _logger.error('"{}" is not an existing directory'.format(output_dir))
        return False
    return True

def check_files_exist(files):
    assert isinstance(files, list)
    for f in files:
        if not os.path.exists(f):
            _logger.error('"{}" does not exist'.format(f))
            return False
    return True

def sorted_headers_by_component(l):
    """
      Take a list of header files and sort them by the
      path after ``src/``. E.g. for ``src/ast/fpa/fpa2bv_converter.h`` the sorting
      key is ``ast/fpa/fpa2bv_converter.h``.

      The sort is done this way because for the CMake build
      there are two directories for every component (e.g.
      ``<src_dir>/src/ast/fpa`` and ``<build_dir>/src/ast/fpa``).
      We don't want to sort based on different ``<src_dir>``
      and ``<build_dir>`` prefixes so that we can match the Python build
      system's behaviour.
    """
    assert isinstance(l, list)
    def get_key(path):
        _logger.debug("get_key({})".format(path))
        path_components = []
        stripped_path = path
        assert 'src' in stripped_path.split(os.path.sep) or 'src' in stripped_path.split('/')
        # Keep stripping off directory components until we hit ``src``
        while os.path.basename(stripped_path) != 'src':
            path_components.append(os.path.basename(stripped_path))
            stripped_path = os.path.dirname(stripped_path)
        assert len(path_components) > 0
        path_components.reverse()
        # For consistency across platforms use ``/`` rather than ``os.sep``.
        # This is a sorting key so it doesn't need to a platform suitable
        # path
        r = '/'.join(path_components)
        _logger.debug("return key:'{}'".format(r))
        return r
    sorted_headers = sorted(l, key=get_key)
    _logger.debug('sorted headers:{}'.format(pprint.pformat(sorted_headers)))
    return sorted_headers

###############################################################################
# Functions for generating constant declarations for language bindings
###############################################################################

def mk_z3consts_py_internal(api_files, output_dir):
    """
        Generate ``z3consts.py`` from the list of API header files
        in ``api_files`` and write the output file into
        the ``output_dir`` directory

        Returns the path to the generated file.
    """
    assert os.path.isdir(output_dir)
    assert isinstance(api_files, list)

    blank_pat      = re.compile("^ *\r?$")
    comment_pat    = re.compile("^ *//.*$")
    typedef_pat    = re.compile("typedef enum *")
    typedef2_pat   = re.compile("typedef enum { *")
    openbrace_pat  = re.compile("{ *")
    closebrace_pat = re.compile("}.*;")

    z3consts  = open(os.path.join(output_dir, 'z3consts.py'), 'w')
    z3consts_output_path = z3consts.name
    z3consts.write('# Automatically generated file\n\n')
    for api_file in api_files:
        api = open(api_file, 'r')

        SEARCHING  = 0
        FOUND_ENUM = 1
        IN_ENUM    = 2

        mode    = SEARCHING
        decls   = {}
        idx     = 0

        linenum = 1
        for line in api:
            m1 = blank_pat.match(line)
            m2 = comment_pat.match(line)
            if m1 or m2:
                # skip blank lines and comments
                linenum = linenum + 1
            elif mode == SEARCHING:
                m = typedef_pat.match(line)
                if m:
                    mode = FOUND_ENUM
                m = typedef2_pat.match(line)
                if m:
                    mode = IN_ENUM
                    decls = {}
                    idx   = 0
            elif mode == FOUND_ENUM:
                m = openbrace_pat.match(line)
                if m:
                    mode  = IN_ENUM
                    decls = {}
                    idx   = 0
                else:
                    assert False, "Invalid %s, line: %s" % (api_file, linenum)
            else:
                assert mode == IN_ENUM
                words = re.split('[^\-a-zA-Z0-9_]+', line)
                m = closebrace_pat.match(line)
                if m:
                    name = words[1]
                    z3consts.write('# enum %s\n' % name)
                    # Iterate over key-value pairs ordered by value
                    for k, v in sorted(decls.items(), key=lambda pair: pair[1]):
                        z3consts.write('%s = %s\n' % (k, v))
                    z3consts.write('\n')
                    mode = SEARCHING
                elif len(words) <= 2:
                    assert False, "Invalid %s, line: %s" % (api_file, linenum)
                else:
                    if words[2] != '':
                        if len(words[2]) > 1 and words[2][1] == 'x':
                            idx = int(words[2], 16)
                        else:
                            idx = int(words[2])
                    decls[words[1]] = idx
                    idx = idx + 1
            linenum = linenum + 1
        api.close()
    z3consts.close()
    return z3consts_output_path

###############################################################################
# Functions for generating a "module definition file" for MSVC
###############################################################################

def mk_def_file_internal(defname, dll_name, export_header_files):
    """
      Writes to a module definition file to a file named ``defname``.

      ``dll_name`` is the name of the dll (without the ``.dll`` suffix).
      ``export_header_file`` is a list of header files to scan for symbols
      to include in the module definition file.
    """
    assert isinstance(export_header_files, list)
    pat1 = re.compile(".*Z3_API.*")
    fout = open(defname, 'w')
    fout.write('LIBRARY "%s"\nEXPORTS\n' % dll_name)
    num = 1
    for export_header_file in export_header_files:
        api = open(export_header_file, 'r')
        for line in api:
            m = pat1.match(line)
            if m:
                words = re.split('\W+', line)
                i = 0
                for w in words:
                    if w == 'Z3_API':
                        f = words[i+1]
                        fout.write('\t%s @%s\n' % (f, num))
                    i = i + 1
                num = num + 1
        api.close()
    fout.close()

###############################################################################
# Functions for generating ``gparams_register_modules.cpp``
###############################################################################
def mk_gparams_register_modules_internal(component_src_dirs, path):
    """
        Generate a ``gparams_register_modules.cpp`` file in the directory ``path``.
        Returns the path to the generated file.

        This file implements the procedure

        ```
        void gparams_register_modules()
        ```

        This procedure is invoked by gparams::init()
    """
    assert isinstance(component_src_dirs, list)
    assert check_dir_exists(path)
    cmds = []
    mod_cmds = []
    mod_descrs = []
    fullname = os.path.join(path, 'gparams_register_modules.cpp')
    fout  = open(fullname, 'w')
    fout.write('// Automatically generated file.\n')
    fout.write('#include"gparams.h"\n')
    reg_pat = re.compile('[ \t]*REG_PARAMS\(\'([^\']*)\'\)')
    reg_mod_pat = re.compile('[ \t]*REG_MODULE_PARAMS\(\'([^\']*)\', *\'([^\']*)\'\)')
    reg_mod_descr_pat = re.compile('[ \t]*REG_MODULE_DESCRIPTION\(\'([^\']*)\', *\'([^\']*)\'\)')
    h_files_full_path = []
    for component_src_dir in component_src_dirs:
        h_files = filter(lambda f: f.endswith('.h') or f.endswith('.hpp'), os.listdir(component_src_dir))
        h_files = list(map(lambda p: os.path.join(component_src_dir, p), h_files))
        h_files_full_path.extend(h_files)
    for h_file in sorted_headers_by_component(h_files_full_path):
        added_include = False
        with open(h_file, 'r') as fin:
            for line in fin:
                m = reg_pat.match(line)
                if m:
                    if not added_include:
                        added_include = True
                        fout.write('#include"%s"\n' % os.path.basename(h_file))
                    cmds.append((m.group(1)))
                m = reg_mod_pat.match(line)
                if m:
                    if not added_include:
                        added_include = True
                        fout.write('#include"%s"\n' % os.path.basename(h_file))
                    mod_cmds.append((m.group(1), m.group(2)))
                m = reg_mod_descr_pat.match(line)
                if m:
                    mod_descrs.append((m.group(1), m.group(2)))
    fout.write('void gparams_register_modules() {\n')
    for code in cmds:
        fout.write('{ param_descrs d; %s(d); gparams::register_global(d); }\n' % code)
    for (mod, code) in mod_cmds:
        fout.write('{ param_descrs * d = alloc(param_descrs); %s(*d); gparams::register_module("%s", d); }\n' % (code, mod))
    for (mod, descr) in mod_descrs:
        fout.write('gparams::register_module_descr("%s", "%s");\n' % (mod, descr))
    fout.write('}\n')
    fout.close()
    return fullname

###############################################################################
# Functions/data structures for generating ``install_tactics.cpp``
###############################################################################

def mk_install_tactic_cpp_internal(component_src_dirs, path):
    """
        Generate a ``install_tactics.cpp`` file in the directory ``path``.
        Returns the path the generated file.

        This file implements the procedure

        ```
        void install_tactics(tactic_manager & ctx)
        ```

        It installs all tactics found in the given component directories
        ``component_src_dirs`` The procedure looks for ``ADD_TACTIC`` commands
        in the ``.h``  and ``.hpp`` files of these components.
    """
    ADD_TACTIC_DATA = []
    ADD_PROBE_DATA = []
    def ADD_TACTIC(name, descr, cmd):
        ADD_TACTIC_DATA.append((name, descr, cmd))

    def ADD_PROBE(name, descr, cmd):
        ADD_PROBE_DATA.append((name, descr, cmd))

    eval_globals = {
        'ADD_TACTIC': ADD_TACTIC,
        'ADD_PROBE': ADD_PROBE,
    }

    assert isinstance(component_src_dirs, list)
    assert check_dir_exists(path)
    fullname = os.path.join(path, 'install_tactic.cpp')
    fout  = open(fullname, 'w')
    fout.write('// Automatically generated file.\n')
    fout.write('#include"tactic.h"\n')
    fout.write('#include"tactic_cmds.h"\n')
    fout.write('#include"cmd_context.h"\n')
    tactic_pat   = re.compile('[ \t]*ADD_TACTIC\(.*\)')
    probe_pat    = re.compile('[ \t]*ADD_PROBE\(.*\)')
    h_files_full_path = []
    for component_src_dir in sorted(component_src_dirs):
        h_files = filter(lambda f: f.endswith('.h') or f.endswith('.hpp'), os.listdir(component_src_dir))
        h_files = list(map(lambda p: os.path.join(component_src_dir, p), h_files))
        h_files_full_path.extend(h_files)
    for h_file in sorted_headers_by_component(h_files_full_path):
        added_include = False
        with open(h_file, 'r') as fin:
            for line in fin:
                if tactic_pat.match(line):
                    if not added_include:
                        added_include = True
                        fout.write('#include"%s"\n' % os.path.basename(h_file))
                    try:
                        eval(line.strip('\n '), eval_globals, None)
                    except Exception as e:
                        _logger.error("Failed processing ADD_TACTIC command at '{}'\n{}".format(
                            fullname, line))
                        raise e
                if probe_pat.match(line):
                    if not added_include:
                        added_include = True
                        fout.write('#include"%s"\n' % os.path.basename(h_file))
                    try:
                        eval(line.strip('\n '), eval_globals, None)
                    except Exception as e:
                        _logger.error("Failed processing ADD_PROBE command at '{}'\n{}".format(
                            fullname, line))
                        raise e
    # First pass will just generate the tactic factories
    idx = 0
    for data in ADD_TACTIC_DATA:
        fout.write('MK_SIMPLE_TACTIC_FACTORY(__Z3_local_factory_%s, %s);\n' % (idx, data[2]))
        idx = idx + 1
    fout.write('#define ADD_TACTIC_CMD(NAME, DESCR, FACTORY) ctx.insert(alloc(tactic_cmd, symbol(NAME), DESCR, alloc(FACTORY)))\n')
    fout.write('#define ADD_PROBE(NAME, DESCR, PROBE) ctx.insert(alloc(probe_info, symbol(NAME), DESCR, PROBE))\n')
    fout.write('void install_tactics(tactic_manager & ctx) {\n')
    idx = 0
    for data in ADD_TACTIC_DATA:
        fout.write('  ADD_TACTIC_CMD("%s", "%s", __Z3_local_factory_%s);\n' % (data[0], data[1], idx))
        idx = idx + 1
    for data in ADD_PROBE_DATA:
        fout.write('  ADD_PROBE("%s", "%s", %s);\n' % data)
    fout.write('}\n')
    fout.close()
    return fullname

###############################################################################
# Functions for generating ``mem_initializer.cpp``
###############################################################################

def mk_mem_initializer_cpp_internal(component_src_dirs, path):
    """
        Generate a ``mem_initializer.cpp`` file in the directory ``path``.
        Returns the path to the generated file.

        This file implements the procedures

        ```
        void mem_initialize()
        void mem_finalize()
        ```

       These procedures are invoked by the Z3 memory_manager
    """
    assert isinstance(component_src_dirs, list)
    assert check_dir_exists(path)
    initializer_cmds = []
    finalizer_cmds   = []
    fullname = os.path.join(path, 'mem_initializer.cpp')
    fout  = open(fullname, 'w')
    fout.write('// Automatically generated file.\n')
    initializer_pat      = re.compile('[ \t]*ADD_INITIALIZER\(\'([^\']*)\'\)')
    # ADD_INITIALIZER with priority
    initializer_prio_pat = re.compile('[ \t]*ADD_INITIALIZER\(\'([^\']*)\',[ \t]*(-?[0-9]*)\)')
    finalizer_pat        = re.compile('[ \t]*ADD_FINALIZER\(\'([^\']*)\'\)')
    h_files_full_path = []
    for component_src_dir in sorted(component_src_dirs):
        h_files = filter(lambda f: f.endswith('.h') or f.endswith('.hpp'), os.listdir(component_src_dir))
        h_files = list(map(lambda p: os.path.join(component_src_dir, p), h_files))
        h_files_full_path.extend(h_files)
    for h_file in sorted_headers_by_component(h_files_full_path):
        added_include = False
        with open(h_file, 'r') as fin:
            for line in fin:
                m = initializer_pat.match(line)
                if m:
                    if not added_include:
                        added_include = True
                        fout.write('#include"%s"\n' % os.path.basename(h_file))
                    initializer_cmds.append((m.group(1), 0))
                m = initializer_prio_pat.match(line)
                if m:
                    if not added_include:
                        added_include = True
                        fout.write('#include"%s"\n' % os.path.basename(h_file))
                    initializer_cmds.append((m.group(1), int(m.group(2))))
                m = finalizer_pat.match(line)
                if m:
                    if not added_include:
                        added_include = True
                        fout.write('#include"%s"\n' % os.path.basename(h_file))
                    finalizer_cmds.append(m.group(1))
    initializer_cmds.sort(key=lambda tup: tup[1])
    fout.write('void mem_initialize() {\n')
    for (cmd, prio) in initializer_cmds:
        fout.write(cmd)
        fout.write('\n')
    fout.write('}\n')
    fout.write('void mem_finalize() {\n')
    for cmd in finalizer_cmds:
        fout.write(cmd)
        fout.write('\n')
    fout.write('}\n')
    fout.close()
    return fullname

###############################################################################
# Functions for generating ``database.h``
###############################################################################

def mk_pat_db_internal(inputFilePath, outputFilePath):
    """
        Generate ``g_pattern_database[]`` declaration header file.
    """
    with open(inputFilePath, 'r') as fin:
        with open(outputFilePath, 'w') as fout:
            fout.write('static char const g_pattern_database[] =\n')
            for line in fin:
                fout.write('"%s\\n"\n' % line.strip('\n'))
            fout.write(';\n')

###############################################################################
# Functions and data structures for generating ``*_params.hpp`` files from
# ``*.pyg`` files
###############################################################################

UINT   = 0
BOOL   = 1
DOUBLE = 2
STRING = 3
SYMBOL = 4
UINT_MAX = 4294967295

TYPE2CPK = { UINT : 'CPK_UINT', BOOL : 'CPK_BOOL',  DOUBLE : 'CPK_DOUBLE',  STRING : 'CPK_STRING',  SYMBOL : 'CPK_SYMBOL' }
TYPE2CTYPE = { UINT : 'unsigned', BOOL : 'bool', DOUBLE : 'double', STRING : 'char const *', SYMBOL : 'symbol' }
TYPE2GETTER = { UINT : 'get_uint', BOOL : 'get_bool', DOUBLE : 'get_double', STRING : 'get_str',  SYMBOL : 'get_sym' }

def pyg_default(p):
    if p[1] == BOOL:
        if p[2]:
            return "true"
        else:
            return "false"
    return p[2]

def pyg_default_as_c_literal(p):
    if p[1] == BOOL:
        if p[2]:
            return "true"
        else:
            return "false"
    elif p[1] == STRING:
        return '"%s"' % p[2]
    elif p[1] == SYMBOL:
        return 'symbol("%s")' % p[2]
    elif p[1] == UINT:
        return '%su' % p[2]
    else:
        return p[2]

def to_c_method(s):
    return s.replace('.', '_')

def max_memory_param():
    return ('max_memory', UINT, UINT_MAX, 'maximum amount of memory in megabytes')

def max_steps_param():
    return ('max_steps', UINT, UINT_MAX, 'maximum number of steps')

def mk_hpp_from_pyg(pyg_file, output_dir):
    """
        Generates the corresponding header file for the input pyg file
        at the path ``pyg_file``. The file is emitted into the directory
        ``output_dir``.

        Returns the path to the generated file
    """
    CURRENT_PYG_HPP_DEST_DIR = output_dir
    # Note OUTPUT_HPP_FILE cannot be a string as we need a mutable variable
    # for the nested function to modify
    OUTPUT_HPP_FILE = [ ]
    # The function below has been nested so that it can use closure to capture
    # the above variables that aren't global but instead local to this
    # function. This avoids use of global state which makes this function safer.
    def def_module_params(module_name, export, params, class_name=None, description=None):
        dirname = CURRENT_PYG_HPP_DEST_DIR
        assert(os.path.exists(dirname))
        if class_name is None:
            class_name = '%s_params' % module_name
        hpp = os.path.join(dirname, '%s.hpp' % class_name)
        out = open(hpp, 'w')
        out.write('// Automatically generated file\n')
        out.write('#ifndef __%s_HPP_\n' % class_name.upper())
        out.write('#define __%s_HPP_\n' % class_name.upper())
        out.write('#include"params.h"\n')
        if export:
            out.write('#include"gparams.h"\n')
        out.write('struct %s {\n' % class_name)
        out.write('  params_ref const & p;\n')
        if export:
            out.write('  params_ref g;\n')
        out.write('  %s(params_ref const & _p = params_ref::get_empty()):\n' % class_name)
        out.write('     p(_p)')
        if export:
            out.write(', g(gparams::get_module("%s"))' % module_name)
        out.write(' {}\n')
        out.write('  static void collect_param_descrs(param_descrs & d) {\n')
        for param in params:
            out.write('    d.insert("%s", %s, "%s", "%s","%s");\n' % (param[0], TYPE2CPK[param[1]], param[3], pyg_default(param), module_name))
        out.write('  }\n')
        if export:
            out.write('  /*\n')
            out.write("     REG_MODULE_PARAMS('%s', '%s::collect_param_descrs')\n" % (module_name, class_name))
            if description is not None:
                out.write("     REG_MODULE_DESCRIPTION('%s', '%s')\n" % (module_name, description))
            out.write('  */\n')
        # Generated accessors
        for param in params:
            if export:
                out.write('  %s %s() const { return p.%s("%s", g, %s); }\n' %
                          (TYPE2CTYPE[param[1]], to_c_method(param[0]), TYPE2GETTER[param[1]], param[0], pyg_default_as_c_literal(param)))
            else:
                out.write('  %s %s() const { return p.%s("%s", %s); }\n' %
                          (TYPE2CTYPE[param[1]], to_c_method(param[0]), TYPE2GETTER[param[1]], param[0], pyg_default_as_c_literal(param)))
        out.write('};\n')
        out.write('#endif\n')
        out.close()
        OUTPUT_HPP_FILE.append(hpp)

    # Globals to use when executing the ``.pyg`` file.
    pyg_globals = {
        'UINT' : UINT,
        'BOOL' : BOOL,
        'DOUBLE' : DOUBLE,
        'STRING' : STRING,
        'SYMBOL' : SYMBOL,
        'UINT_MAX' : UINT_MAX,
        'max_memory_param' : max_memory_param,
        'max_steps_param' : max_steps_param,
        # Note that once this function is enterred that function
        # executes with respect to the globals of this module and
        # not the globals defined here
        'def_module_params' : def_module_params,
    }
    with open(pyg_file, 'r') as fh:
        eval(fh.read() + "\n", pyg_globals, None)
    assert len(OUTPUT_HPP_FILE) == 1
    return OUTPUT_HPP_FILE[0]


text:
require File.join(File.dirname(__FILE__), "../spec_helper")

describe Flamethrower::Connection do
  before do
    @connection = Flamethrower::MockConnection.new
    @connection.stub!(:send_data)
    @user = Flamethrower::Irc::User.new :username => 'user', :nickname => 'nick', :hostname => 'host', :realname => 'realname'
    @connection.current_user = @user
  end

  describe "#send_message" do
    it "sends the message to the client" do
      message = "message"
      @connection.should_receive(:send_message).with("message")
      @connection.send_message(message)
    end

    it "should send the data across the wire" do
      message = "message"
      @connection.should_receive(:send_data).with("message\r\n")
      @connection.send_message(message)
    end
  end

  describe "#send_messages" do
    it "sends a list of messages to the client" do
      @connection.should_receive(:send_message).exactly(2).times
      @connection.send_messages("one", "two")
    end

    it "yields to the block to allow more messages" do
      @connection.should_receive(:send_message).exactly(3).times
      @connection.send_messages("one", "two") do |messages|
        messages << "three"
      end
    end
  end

  describe "#receive_data" do
    it "calls the dispatcher with a new Message" do
      incoming = "COMMAND params"
      msg = Flamethrower::Irc::Message.new(incoming)
      Flamethrower::Irc::Message.should_receive(:new).with(incoming).and_return(msg)
      @connection.dispatcher.should_receive(:handle_message).with(msg)
      @connection.receive_data("#{incoming}\r\n")
    end
  end

  context "#after_connect" do
    before do
      stub_request(:get, "https://mydomain.campfirenow.com/rooms.json").
        with(:headers => {'Authorization'=>['mytoken', 'x']}).
        to_return(:status => 200, :body => json_fixture("rooms"))
    end

    it "sends welcome" do
      @connection.stub(:populate_irc_channels)
      @connection.stub(:populate_my_user)
      @connection.should_receive(:send_welcome)
      @connection.after_connect
    end

    it "sends motd" do
      @connection.stub(:populate_irc_channels)
      @connection.stub(:populate_my_user)
      @connection.should_receive(:send_motd)
      @connection.after_connect
    end

    it "populates the channel list" do
      @connection.stub(:populate_my_user)
      @connection.should_receive(:populate_irc_channels)
      @connection.after_connect
    end

    it "populates the currently logged in user" do
      @connection.stub(:populate_irc_channels)
      @connection.should_receive(:populate_my_user)
      @connection.after_connect
    end
  end

  describe "irc_channels" do
    it "stores the list of irc_channels on the connection" do
      channel = Flamethrower::Irc::Channel.new("#flamethrower")
      @connection.irc_channels << channel
      @connection.irc_channels.should include(channel)
    end
  end

  describe "IRCcommands" do
    it "should have a first message" do
      @connection.send_welcome.should == ":host 001 nick :Welcome to Flamethrower"
    end

    it "should have the correct MOTD format" do
      @connection.send_motd.should == [
        ":host 375 nick :MOTD",
        ":host 372 nick :Fetching channel list from campfire..."
      ]
    end

    it "should send the channel mode" do
      channel = Flamethrower::Irc::Channel.new("#flamethrower")
      @connection.send_channel_mode(channel).should == ":host 324 nick #flamethrower +t"
    end

    it "should send the current user mode" do
      @connection.send_user_mode.should == ":host 221 nick +i"
    end

    it "should have the correct TOPIC format" do
      room = Flamethrower::Campfire::Room.new("mydomain", "mytoken", "id" => 347348, "name" => "room 1")
      channel = Flamethrower::Irc::Channel.new("#flamethrower", room)
      channel.topic = "A topic"
      @connection.send_topic(channel).should == ":host 332 nick #flamethrower :A topic"
    end

    it "should have the correct USERLIST format" do
      room = Flamethrower::Campfire::Room.new('mydomain', 'mytoken')
      channel = Flamethrower::Irc::Channel.new("#flamethrower", room)
      channel.users << Flamethrower::Irc::User.new(:nickname => 'bob', :username => 'bob')
      @connection.send_userlist(channel).should == [
        ":host 353 nick = #flamethrower :@nick bob",
        ":host 366 nick #flamethrower :/End of /NAMES list"
      ]
    end

    describe "#send_who" do
      it "sends the campfire users in the userlist" do
        room = Flamethrower::Campfire::Room.new('mydomain', 'mytoken')
        channel = Flamethrower::Irc::Channel.new("#flamethrower", room)
        user1 = Flamethrower::Campfire::User.new('id' => 1234, 'name' => 'Bob Jones')
        user2 = Flamethrower::Campfire::User.new('id' => 4321, 'name' => 'Bill Myer')
        room.users = [user1, user2]
        @connection.send_who(channel).should == [
          ":host 352 nick #flamethrower Bob_Jones campfirenow.com localhost Bob_Jones H :0 Bob_Jones",
          ":host 352 nick #flamethrower Bill_Myer campfirenow.com localhost Bill_Myer H :0 Bill_Myer",
          ":host 315 nick #flamethrower :/End of /WHO list"
        ]
      end
    end

    describe "#send_channel_list" do
      it "sends the right motd message with the channel list" do
        room = Flamethrower::Campfire::Room.new("mydomain", "mytoken", "id" => 347348, "name" => "room 1")
        room2 = Flamethrower::Campfire::Room.new("mydomain", "mytoken", "id" => 347349, "name" => "room 2")
        channel = Flamethrower::Irc::Channel.new("#flamethrower", room)
        channel.topic = "Flamethrower topic"
        channel2 = Flamethrower::Irc::Channel.new("#room_1", room2)
        channel2.topic = "Room 1 topic"
        @connection.irc_channels = [channel, channel2]
        @connection.send_channel_list.should == [
          ":host 372 nick :Active channels:",
          ":host 372 nick :#flamethrower - Flamethrower topic",
          ":host 372 nick :#room_1 - Room 1 topic",
          ":host 376 nick :End of channel list /MOTD"
        ]
      end

      it "shows 'No topic' in the channel list if there's no room topic" do
        room = Flamethrower::Campfire::Room.new("mydomain", "mytoken", "id" => 347348, "name" => "room 1")
        room2 = Flamethrower::Campfire::Room.new("mydomain", "mytoken", "id" => 347349, "name" => "room 2")
        channel = Flamethrower::Irc::Channel.new("#flamethrower", room)
        channel2 = Flamethrower::Irc::Channel.new("#room_1", room2)
        channel.topic = channel2.topic = ""
        @connection.irc_channels = [channel, channel2]
        @connection.send_channel_list.should == [
          ":host 372 nick :Active channels:",
          ":host 372 nick :#flamethrower - No topic",
          ":host 372 nick :#room_1 - No topic",
          ":host 376 nick :End of channel list /MOTD"
        ]
      end
    end

    describe "#populate_irc_channels" do
      it "populates the server irc_channels from the associated campfire channels" do
        stub_request(:get, "https://mydomain.campfirenow.com/rooms.json").
          with(:headers => {'Authorization'=>['mytoken', 'x']}).
          to_return(:status => 200, :body => json_fixture("rooms"))

        EM.run_block { @connection.populate_irc_channels }
        @connection.irc_channels.count.should == 1
        @connection.irc_channels.first.name.should == "#room_1"
      end
    end
  end

end

redpajama_set_name: RedPajamaGithub


text:
BEGIN { push(@INC, ".."); };
eval "use WebminCore;";
&init_config();
&foreign_require("software", "software-lib.pl");
&foreign_require("cron", "cron-lib.pl");
&foreign_require("webmin", "webmin-lib.pl");
use Data::Dumper;

$available_cache_file = "$module_config_directory/available.cache";
$current_cache_file = "$module_config_directory/current.cache";
$updates_cache_file = "$module_config_directory/updates.cache";
$cron_cmd = "$module_config_directory/update.pl";

$yum_cache_file = "$module_config_directory/yumcache";
$apt_cache_file = "$module_config_directory/aptcache";
$yum_changelog_cache_dir = "$module_config_directory/yumchangelog";

# get_software_packages()
# Fills in software::packages with list of installed packages (if missing),
# returns count.
sub get_software_packages
{
if (!$get_software_packages_cache) {
        %software::packages = ( );
        $get_software_packages_cache = &software::list_packages();
        }
return $get_software_packages_cache;
}

# list_current(nocache)
# Returns a list of packages and versions for installed software. Keys are :
#  name - The my package name (ie. CSWapache2)
#  update - Name used to refer to it by the updates system (ie. apache2)
#  version - Version number
#  epoch - Epoch part of the version
#  desc - Human-readable description
sub list_current
{
my ($nocache) = @_;
if ($nocache || &cache_expired($current_cache_file)) {
	my $n = &get_software_packages();
	my @rv;
	for(my $i=0; $i<$n; $i++) {
		push(@rv, { 'name' => $software::packages{$i,'name'},
			    'update' => $software::packages{$i,'name'},
			    'version' =>
			      $software::packages{$i,'version'},
			    'epoch' =>
			      $software::packages{$i,'epoch'},
			    'desc' =>
			      $software::packages{$i,'desc'},
			    'system' => $software::update_system,
			});
		&fix_pkgadd_version($rv[$#rv]);
		}

	# Filter out dupes and sort by name
	@rv = &filter_duplicates(\@rv);

	&write_cache_file($current_cache_file, \@rv);
	return @rv;
	}
else {
	return &read_cache_file($current_cache_file);
	}
}

# list_available(nocache)
# Returns the names and versions of packages available from the update system
sub list_available
{
my ($nocache) = @_;
my $expired = &cache_expired($available_cache_file);
if ($nocache || $expired == 2 ||
    $expired == 1 && !&check_available_lock()) {
	# Get from update system
	my @rv;
	my @avail = &packages_available();
	foreach my $avail (@avail) {
		$avail->{'update'} = $avail->{'name'};
		$avail->{'name'} = &csw_to_pkgadd($avail->{'name'});
		push(@rv, $avail);
		}

	# Filter out dupes and sort by name
	@rv = &filter_duplicates(\@rv);

	if (!@rv) {
		# Failed .. fall back to cache
		@rv = &read_cache_file($available_cache_file);
		}
	&write_cache_file($available_cache_file, \@rv);
	return @rv;
	}
else {
	return &read_cache_file($available_cache_file);
	}
}

# check_available_lock()
# Returns 1 if the package update system is currently locked
sub check_available_lock
{
if ($software::update_system eq "yum") {
        return &check_pid_file("/var/run/yum.pid");
        }
return 0;
}

# filter_duplicates(&packages)
# Given a list of package structures, orders them by name and version number,
# and removes dupes with the same name
sub filter_duplicates
{
my ($pkgs) = @_;
my @rv = sort { $a->{'name'} cmp $b->{'name'} ||
	         &compare_versions($b, $a) } @$pkgs;
my %done;
return grep { !$done{$_->{'name'},$_->{'system'}}++ } @rv;
}

# cache_expired(file)
# Checks if some cache has expired. Returns 0 if OK, 1 if expired, 2 if
# totally missing.
sub cache_expired
{
my ($file) = @_;
my @st = stat($file);
return 2 if (!@st);
if (!$config{'cache_time'} || time()-$st[9] > $config{'cache_time'}*60*60) {
        return 1;
        }
return 0;
}

sub write_cache_file
{
my ($file, $arr) = @_;
&open_tempfile(FILE, ">$file");
&print_tempfile(FILE, Dumper($arr));
&close_tempfile(FILE);
$read_cache_file_cache{$file} = $arr;
}

# read_cache_file(file)
# Returns the contents of some cache file, as an array ref
sub read_cache_file
{
my ($file) = @_;
if (defined($read_cache_file_cache{$file})) {
	return @{$read_cache_file_cache{$file}};
	}
if (-r $file) {
	do $file;
	$read_cache_file_cache{$file} = $VAR1;
	return @$VAR1;
	}
return ( );
}

# compare_versions(&pkg1, &pk2)
# Returns -1 if the version of pkg1 is older than pkg2, 1 if newer, 0 if same.
sub compare_versions
{
my ($pkg1, $pkg2) = @_;
if ($pkg1->{'system'} eq 'webmin' && $pkg2->{'system'} eq 'webmin') {
	# Webmin module version compares are always numeric
	return $pkg1->{'version'} <=> $pkg2->{'version'};
	}
my $ec = $pkg1->{'epoch'} <=> $pkg2->{'epoch'};
if ($ec && ($pkg1->{'epoch'} eq '' || $pkg2->{'epoch'} eq '') &&
    $pkg1->{'system'} eq 'apt') {
	# On some Debian systems, we don't have a my epoch
	$ec = undef;
	}
return $ec ||
       &software::compare_versions($pkg1->{'version'}, $pkg2->{'version'});
}

sub find_cron_job
{
my @jobs = &cron::list_cron_jobs();
my ($job) = grep { $_->{'user'} eq 'root' &&
		      $_->{'command'} eq $cron_cmd } @jobs;
return $job;
}

# packages_available()
# Returns a list of all available packages, as hash references with name and
# version keys. These come from the APT, YUM or CSW update system, if available.
# If not, nothing is returned.
sub packages_available
{
if (@packages_available_cache) {
        return @packages_available_cache;
        }
if (defined(&software::update_system_available)) {
	# From a decent package system
	my @rv = software::update_system_available();
	my %done;
	foreach my $p (@rv) {
		$p->{'system'} = $software::update_system;
		$p->{'version'} =~ s/,REV=.*//i;		# For CSW
		if ($p->{'system'} eq 'apt' && !$p->{'source'}) {
			$p->{'source'} =
			    $p->{'file'} =~ /virtualmin/i ? 'virtualmin' :
			    $p->{'file'} =~ /debian/i ? 'debian' :
			    $p->{'file'} =~ /ubuntu/i ? 'ubuntu' : undef;
			}
		$done{$p->{'name'}} = $p;
		}
	if ($software::update_system eq "yum" &&
	    &has_command("up2date")) {
		# YUM is the package system select, but up2date is installed
		# too (ie. RHEL). Fetch its packages too..
		if (!$done_rhn_lib++) {
			do "../software/rhn-lib.pl";
			}
		my @rhnrv = &update_system_available();
		foreach my $p (@rhnrv) {
			$p->{'system'} = "rhn";
			my $d = $done{$p->{'name'}};
			if ($d) {
				# Seen already .. but is this better?
				if (&compare_versions($p, $d) > 0) {
					# Yes .. replace
					@rv = grep { $_ ne $d } @rv;
					push(@rv, $p);
					$done{$p->{'name'}} = $p;
					}
				}
			else {
				push(@rv, $p);
				$done{$p->{'name'}} = $p;
				}
			}
		}
	@packages_available_cache = @rv;
	return @rv;
	}
return ( );
}

sub supports_updates_available
{
return defined(&software::update_system_updates);
}

# updates_available(no-cache)
# Returns an array of hash refs of package updates available, according to
# the update system, with caching.
sub updates_available
{
my ($nocache) = @_;
if (!scalar(@updates_available_cache)) {
	if ($nocache || &cache_expired($updates_cache_file)) {
		# Get from original source
		@updates_available_cache = &software::update_system_updates();
		foreach my $a (@updates_available_cache) {
			$a->{'update'} = $a->{'name'};
			$a->{'system'} = $software::update_system;
			}
		&write_cache_file($updates_cache_file,
				  \@updates_available_cache);
		}
	else {
		# Use on-disk cache
		@updates_available_cache =
			&read_cache_file($updates_cache_file);
		}
	}
return @updates_available_cache;
}

# package_install(package-name, [system])
# Install some package, either from an update system or from Webmin. Returns
# a list of updated package names.
sub package_install
{
my ($name, $system) = @_;
my @rv;
my $pkg;

# First get from list of updates
($pkg) = grep { $_->{'update'} eq $name &&
		($_->{'system'} eq $system || !$system) }
	      sort { &compare_versions($b, $a) }
		   &list_possible_updates(0);
if (!$pkg) {
	# Then try list of all available packages
	($pkg) = grep { $_->{'update'} eq $name &&
			($_->{'system'} eq $system || !$system) }
		      sort { &compare_versions($b, $a) }
			   &list_available(0);
	}
if (!$pkg) {
	print &text('update_efindpkg', $name),"<p>\n";
	return ( );
	}
if (defined(&software::update_system_install)) {
	# Using some update system, like YUM or APT
	&clean_environment();
	if ($software::update_system eq $pkg->{'system'}) {
		# Can use the default system
		@rv = &software::update_system_install($name, undef, 1);
		}
	else {
		# Another update system exists!! Use it..
		if (!$done_rhn_lib++) {
			do "../software/$pkg->{'system'}-lib.pl";
			}
		if (!$done_rhn_text++) {
			%text = ( %text, %software::text );
			}
		@rv = &update_system_install($name, undef, 1);
		}
	&reset_environment();
	}
else {
	&error("Don't know how to install package $pkg->{'name'} with type $pkg->{'type'}");
	}
# Flush installed cache
unlink($current_cache_file);
return @rv;
}

# package_install_multiple(&package-names, system)
# Install multiple packages, either from an update system or from Webmin.
# Returns a list of updated package names.
sub package_install_multiple
{
my ($names, $system) = @_;
my @rv;
my $pkg;

if (defined(&software::update_system_install)) {
	# Using some update system, like YUM or APT
	&clean_environment();
	if ($software::update_system eq $system) {
		# Can use the default system
		@rv = &software::update_system_install(
			join(" ", @$names), undef, 1);
		}
	else {
		# Another update system exists!! Use it..
		if (!$done_rhn_lib++) {
			do "../software/$pkg->{'system'}-lib.pl";
			}
		if (!$done_rhn_text++) {
			%text = ( %text, %software::text );
			}
		@rv = &update_system_install(join(" ", @$names), undef, 1);
		}
	&reset_environment();
	}
else {
	&error("Don't know how to install packages");
	}
# Flush installed cache
unlink($current_cache_file);
return @rv;
}

# list_package_operations(package|packages, system)
# Given a package (or space-separate package list), returns a list of all
# dependencies that will be installed
sub list_package_operations
{
my ($name, $system) = @_;
if (defined(&software::update_system_operations)) {
	my @rv = &software::update_system_operations($name);
	foreach my $p (@rv) {
		$p->{'system'} = $system;
		}
	return @rv;
	}
return ( );
}

# list_possible_updates([nocache])
# Returns a list of updates that are available. Each element in the array
# is a hash ref containing a name, version, description and severity flag.
# Intended for calling from themes. Nocache 0=cache everything, 1=flush all
# caches, 2=flush only current
sub list_possible_updates
{
my ($nocache) = @_;
my @rv;
my @current = &list_current($nocache);
if (&supports_updates_available()) {
	# Software module supplies a function that can list just packages
	# that need updating
	my %currentmap;
	foreach my $c (@current) {
		$currentmap{$c->{'name'},$c->{'system'}} ||= $c;
		}
	foreach my $a (&updates_available($nocache == 1)) {
		my $c = $currentmap{$a->{'name'},$a->{'system'}};
		next if (!$c);
		next if ($a->{'version'} eq $c->{'version'});
		push(@rv, { 'name' => $a->{'name'},
			    'update' => $a->{'update'},
			    'system' => $a->{'system'},
			    'version' => $a->{'version'},
			    'oldversion' => $c->{'version'},
			    'epoch' => $a->{'epoch'},
			    'oldepoch' => $c->{'epoch'},
			    'security' => $a->{'security'},
			    'source' => $a->{'source'},
			    'desc' => $c->{'desc'} || $a->{'desc'} });
		}
	}
else {
	# Compute from current and available list
	my @avail = &list_available($nocache == 1);
	my %availmap;
	foreach my $a (@avail) {
		my $oa = $availmap{$a->{'name'},$a->{'system'}};
		if (!$oa || &compare_versions($a, $oa) > 0) {
			$availmap{$a->{'name'},$a->{'system'}} = $a;
			}
		}
	foreach my $c (sort { $a->{'name'} cmp $b->{'name'} } @current) {
		# Work out the status
		my $a = $availmap{$c->{'name'},$c->{'system'}};
		if ($a->{'version'} && &compare_versions($a, $c) > 0) {
			# A regular update is available
			push(@rv, { 'name' => $a->{'name'},
				    'update' => $a->{'update'},
				    'system' => $a->{'system'},
				    'version' => $a->{'version'},
				    'oldversion' => $c->{'version'},
				    'epoch' => $a->{'epoch'},
				    'oldepoch' => $c->{'epoch'},
				    'security' => $a->{'security'},
				    'source' => $a->{'source'},
				    'desc' => $c->{'desc'} || $a->{'desc'},
				    'severity' => 0 });
			}
		}
	}
return @rv;
}

# list_possible_installs([nocache])
# Returns a list of packages that could be installed, but are not yet
sub list_possible_installs
{
my ($nocache) = @_;
my @rv;
my @current = &list_current($nocache);
my @avail = &list_available($nocache == 1);
foreach my $a (sort { $a->{'name'} cmp $b->{'name'} } @avail) {
	($c) = grep { $_->{'name'} eq $a->{'name'} &&
		      $_->{'system'} eq $a->{'system'} } @current;
	if (!$c && &installation_candiate($a)) {
		push(@rv, { 'name' => $a->{'name'},
			    'update' => $a->{'update'},
			    'system' => $a->{'system'},
			    'version' => $a->{'version'},
			    'epoch' => $a->{'epoch'},
			    'desc' => $a->{'desc'},
			    'severity' => 0 });
		}
	}
return @rv;
}

# csw_to_pkgadd(package)
# On Solaris systems, convert a CSW package name like ap2_modphp5 to a
# real package name like CSWap2modphp5
sub csw_to_pkgadd
{
my ($pn) = @_;
if ($gconfig{'os_type'} eq 'solaris') {
	$pn =~ s/[_\-]//g;
	$pn = "CSW$pn";
	}
return $pn;
}

# fix_pkgadd_version(&package)
# If this is Solaris and the package version is missing, we need to make
# a separate pkginfo call to get it.
sub fix_pkgadd_version
{
my ($pkg) = @_;
if ($gconfig{'os_type'} eq 'solaris') {
	if (!$pkg->{'version'}) {
		# Make an extra call to get the version
		my @pinfo = &software::package_info($pkg->{'name'});
		$pinfo[4] =~ s/,REV=.*//i;
		$pkg->{'version'} = $pinfo[4];
		}
	else {
		# Trip off the REV=
		$pkg->{'version'} =~ s/,REV=.*//i;
		}
	}
$pkg->{'desc'} =~ s/^\Q$pkg->{'update'}\E\s+\-\s+//;
}

# installation_candiate(&package)
# Returns 1 if some package can be installed, even when it currently isn't.
# Always true for now.
sub installation_candiate
{
my ($p) = @_;
return 1;
}

# clear_repository_cache()
# Clear any YUM or APT caches
sub clear_repository_cache
{
if ($software::update_system eq "yum") {
	&execute_command("yum clean all");
	}
elsif ($software::update_system eq "apt") {
	&execute_command("apt-get update");
	}
}

# split_epoch(version)
# Splits a version formatted like 5:x.yy into an epoch and real version
sub split_epoch
{
my ($ver) = @_;
if ($ver =~ /^(\d+):(\S+)$/) {
	return ($1, $2);
	}
return (undef, $ver);
}

# get_changelog(&pacakge)
# If possible, returns information about what has changed in some update
sub get_changelog
{
my ($pkg) = @_;
if ($pkg->{'system'} eq 'yum') {
	# See if yum supports changelog
	if (!defined($supports_yum_changelog)) {
		my $out = &backquote_command("yum -h 2>&1 </dev/null");
		$supports_yum_changelog = $out =~ /changelog/ ? 1 : 0;
		}
	return undef if (!$supports_yum_changelog);

	# Check if we have this info cached
	my $cfile = $yum_changelog_cache_dir."/".
		       $pkg->{'name'}."-".$pkg->{'version'};
	my $cl = &read_file_contents($cfile);
	if (!$cl) {
		# Run it for this package and version
		my $started = 0;
		&open_execute_command(YUMCL, "yum changelog all ".
					     quotemeta($pkg->{'name'}), 1, 1);
		while(<YUMCL>) {
			s/\r|\n//g;
			if (/^\Q$pkg->{'name'}-$pkg->{'version'}\E/) {
				$started = 1;
				}
			elsif (/^==========/ || /^changelog stats/) {
				$started = 0;
				}
			elsif ($started) {
				$cl .= $_."\n";
				}
			}
		close(YUMCL);

		# Save the cache
		if (!-d $yum_changelog_cache_dir) {
			&make_dir($yum_changelog_cache_dir, 0700);
			}
		&open_tempfile(CACHE, ">$cfile");
		&print_tempfile(CACHE, $cl);
		&close_tempfile(CACHE);
		}
	return $cl;
	}
return undef;
}

sub flush_package_caches
{
unlink($current_cache_file);
unlink($updates_cache_file);
unlink($available_cache_file);
unlink($available_cache_file.'0');
unlink($available_cache_file.'1');
@packages_available_cache = ( );
%read_cache_file_cache = ( );
}

# list_for_mode(mode, nocache)
# If not is 'updates' or 'security', return just updates. Othewise, return
# all available packages.
sub list_for_mode
{
my ($mode, $nocache) = @_;
return $mode eq 'updates' || $mode eq 'security' ?
	&list_possible_updates($nocache) : &list_available($nocache);
}

# check_reboot_required(after-flag)
# Returns 1 if the package system thinks a reboot is needed
sub check_reboot_required
{
if ($gconfig{'os_type'} eq 'debian-linux') {
        return -e "/var/run/reboot-required" ? 1 : 0;
        }
return 0;
}

1;


text:
var semver = require('semver');
var UAParser = require('ua-parser-js');

// semver-compliant version must be x.y.z
var toSemVer = function (version) {
    var splitDots = version.split(".");
    var nbDots = splitDots.length - 1;
    if (nbDots === 0) {
        return version + ".0.0";
    } else if (nbDots === 1) {
        return version + ".0";
    } else if (nbDots === 2) {
        return version;
    } else {
        return splitDots.slice(0, 3).join(".") + "-" + splitDots.slice(3).join(".");
    }
};

exports.detectBrowser = function (data) {
    var parser = new UAParser(data.userAgent);
    var browser = parser.getBrowser();
    var browserName = browser.name || "Unknown browser";
    var browserVersion = browser.version;

    if (browserName == "IE") {
        // always something specific for IE!
        // documentMode is what really matters in IE, not the userAgent

        var documentMode = data.documentMode;
        if (documentMode) {
            browserVersion = String(documentMode);
        }
    }

    var os = parser.getOS();
    var osName = os.name || "Unknown OS";

    var res = {
        displayName: browserName + (browserVersion ? " " + browserVersion : ""),
        semverString: toSemVer(browserVersion || "0"),
        family: browserName,
        os: {
            displayName: osName + (os.version ? " " + os.version : ""),
            family: osName
        },
        flags: data.flags
    };
    return res;
};

exports.browserMatch = function (config, browserInfo) {
    var match = true;
    if (config.browserName != null) {
        match = match && (config.browserName == browserInfo.family);
    }
    if (match && config.browserVersion != null) {
        // user may pass version as a number, hence using String()
        match = semver.satisfies(browserInfo.semverString, String(config.browserVersion));
    }
    if (match && config.os != null) {
        match = (config.os == browserInfo.os.family) || (config.os == browserInfo.os.displayName);
    }
    if (match) {
        // flags must match exactly:
        match = (config.flags || "") === (browserInfo.flags || "");
    }
    return match;
};


text:
require 'mittsu/renderers/shaders/uniforms_utils'
require 'mittsu/renderers/shaders/uniforms_lib'
require 'mittsu/renderers/shaders/shader_chunk'
require 'mittsu/renderers/shaders/rbsl_loader'

module Mittsu
  class ShaderLib_Instance
    attr_accessor :uniforms, :vertex_shader, :fragment_shader
    def initialize(options = {})
      @uniforms = options.fetch(:uniforms)
      @vertex_shader = options.fetch(:vertex_shader)
      @fragment_shader = options.fetch(:fragment_shader)
    end

    def self.load_from_file(name)
      ShaderLib_Instance.new(
        uniforms: RBSLLoader.load_uniforms(File.read(File.join(__dir__, 'shader_lib', name, "#{name}_uniforms.rbslu")), UniformsLib),
        vertex_shader: RBSLLoader.load_shader(File.read(File.join(__dir__, 'shader_lib', name, "#{name}_vertex.rbsl")), ShaderChunk),
        fragment_shader: RBSLLoader.load_shader(File.read(File.join(__dir__, 'shader_lib', name, "#{name}_fragment.rbsl")), ShaderChunk)
      )
    end
  end
  private_constant :ShaderLib_Instance

  SHADER_LIB_HASH = Hash.new { |h, k|
    h[k] = ShaderLib_Instance.load_from_file(k.to_s)
  }

  class ShaderLib
    def self.create_shader(id, options={})
      shader = self[id]
      {
        uniforms: UniformsUtils.clone(shader.uniforms),
        vertex_shader: shader.vertex_shader,
        fragment_shader: shader.fragment_shader
      }.merge(options)
    end

    def self.[](id)
      SHADER_LIB_HASH[id]
    end
  end
end


text:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using SKM.V3;
using SKM.V3.Methods;
using SKM.V3.Models;

namespace SKM_Test
{
    [TestClass]
    public class MethodSpecificTests
    {
        [TestMethod]
        public void TestMethod1()
        {
            var a = Helpers.GetMachineCodePI();
            System.Diagnostics.Debug.WriteLine(Helpers.GetMachineCodePI());
            System.Diagnostics.Debug.WriteLine(Helpers.GetMachineCodePI());

            System.Diagnostics.Debug.WriteLine(Helpers.GetMachineCodePI());

        }

        [TestMethod]
        public void MyTestMethod()
        {
            System.Diagnostics.Debug.WriteLine(Environment.OSVersion.Platform.ToString());

            AI.RegisterEvent("", new RegisterEventModel { Metadata = Helpers.GetOSStats() });

        }

        [TestMethod]
        public void CheckVM()
        {
            Helpers.IsVM();
        }

        [TestMethod]
        public void CheckGetMachineCodeNormal()
        {
            Helpers.GetMachineCode(platformIndependent: false);
        }

        [TestMethod]
        public void TestHasFeature()
        {
            var features = "[\"f1\", [\"f2\",[[\"voice\",[\"all\"]], \"image\"]]]";

            var lc = new LicenseKey();
            lc.DataObjects = new System.Collections.Generic.List<DataObject>();
            lc.DataObjects.Add(new DataObject() { Name = "cryptolens_features", StringValue = features });

            Assert.IsTrue(Helpers.HasFeature(lc, "f2.voice.all"));
            Assert.IsTrue(Helpers.HasFeature(lc, "f2.voice"));
            Assert.IsTrue(Helpers.HasFeature(lc, "f2"));
            Assert.IsFalse(Helpers.HasFeature(lc, "f1.voice"));
        }

        [TestMethod]
        public void Test2()
        {
            //var features = "[[\"ModuleB\",[\"Submodule 1\"]],\"ModuleC\",[\"ModuleD\",[\"ModuleD1\",[\"Submodule D1\",\"Submodule D2\"]]]]";
            var features = "[[\"ModuleB\",[\"Submodule 2\"]],[\"ModuleD\",[[\"ModuleD1\",[\"Submodule D4\"]]]]]";

            var lc = new LicenseKey();
            lc.DataObjects = new System.Collections.Generic.List<DataObject>();
            lc.DataObjects.Add(new DataObject() { Name = "cryptolens_features", StringValue = features });

            Assert.IsTrue(Helpers.HasFeature(lc, "ModuleD.ModuleD1.Submodule D4"));
            //Assert.IsTrue(Helpers.HasFeature(lc, "ModuleD.ModuleD1.Submodule D2"));

        }
    }
}


text:
"use strict"

var assert = require('assert');
var getHighestBitrate = require('../lib/getHighestBitrate');
var fixture = require('./fixtures/getHighestBitrateFixture.js');

describe('getHighestBitrate should', () => {
	it('return the format object with the highest bitrate', () => {
		assert.deepEqual({ audioEncoding: 'aac', audioBitrate: 256 },  getHighestBitrate(fixture.withBitrates.formats))
	});
	it('return the a format object when fields are null', () => {
		assert.deepEqual({ audioEncoding: null, audioBitrate: null },  getHighestBitrate(fixture.withoutBitrates.formats))
	});
})


text:
package org.apache.flink.table.runtime.window.grouping;

import org.apache.flink.table.dataformat.BinaryRow;
import org.apache.flink.table.runtime.util.RowIterator;

import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;

/**
 * A jvm heap implementation of {@link WindowsGrouping}, which uses a linked list to buffer
 * all the inputs of a keyed group belonging to the same window.
 * It is designed to have a capacity limit to avoid JVM OOM and reduce GC pauses.
 */
public class HeapWindowsGrouping extends WindowsGrouping {

	private LinkedList<BinaryRow> buffer;

	private final int maxSizeLimit;

	private int evictLimitIndex;

	private Iterator<BinaryRow> iterator;

	public HeapWindowsGrouping(int maxSizeLimit, long windowSize, long slideSize, int timeIndex, boolean isDate) {
		this(maxSizeLimit, 0L, windowSize, slideSize, timeIndex, isDate);
	}

	public HeapWindowsGrouping(
			int maxSizeLimit, long offset, long windowSize, long slideSize, int timeIndex, boolean isDate) {
		super(offset, windowSize, slideSize, timeIndex, isDate);
		this.maxSizeLimit = maxSizeLimit;
		this.evictLimitIndex = 0;
		this.buffer = new LinkedList<>();
	}

	@Override
	protected void resetBuffer() {
		buffer.clear();
		evictLimitIndex = 0;
		iterator = null;
	}

	@Override
	protected void onBufferEvict(int limitIndex) {
		while (evictLimitIndex < limitIndex) {
			buffer.removeFirst();
			evictLimitIndex++;
		}
	}

	@Override
	protected void addIntoBuffer(BinaryRow input) throws IOException {
		if (buffer.size() >= maxSizeLimit) {
			throw new IOException("HeapWindowsGrouping out of memory, element size limit " + maxSizeLimit);
		}
		buffer.add(input);
	}

	@Override
	protected RowIterator<BinaryRow> newBufferIterator(int startIndex) {
		iterator = buffer.subList(startIndex - evictLimitIndex, buffer.size()).iterator();
		return new BufferIterator(iterator);
	}

	@Override
	public void close() throws IOException {
		buffer = null;
	}

	private final class BufferIterator implements RowIterator<BinaryRow> {
		private final Iterator<BinaryRow> iterator;
		private BinaryRow next;

		BufferIterator(Iterator<BinaryRow> iterator) {
			this.iterator = iterator;
		}

		@Override
		public boolean advanceNext() {
			if (iterator.hasNext()) {
				next = iterator.next();
				return true;
			} else {
				next = null;
				return false;
			}
		}

		@Override
		public BinaryRow getRow() {
			return next;
		}
	}
}


text:
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

-- -----------------------------------------------------
-- Schema controleacesso
-- -----------------------------------------------------
DROP SCHEMA IF EXISTS `controleacesso` ;

-- -----------------------------------------------------
-- Schema controleacesso
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `controleacesso` DEFAULT CHARACTER SET utf8 ;
USE `controleacesso` ;

-- -----------------------------------------------------
-- Table `controleacesso`.`clientes`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `controleacesso`.`clientes` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `nome` VARCHAR(255) NOT NULL,
  `cpf` VARCHAR(255) NOT NULL,
  `telefone` VARCHAR(255) NOT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `controleacesso`.`tipos`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `controleacesso`.`tipos` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `nome` VARCHAR(255) NOT NULL,
  `valorporhora` DECIMAL(10,2) NOT NULL,
  `valorpormes` DECIMAL(10,2) NOT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `controleacesso`.`veiculos`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `controleacesso`.`veiculos` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `tipo` INT NOT NULL,
  `placa` VARCHAR(45) NOT NULL,
  `modelo` VARCHAR(255) NOT NULL,
  `cor` VARCHAR(255) NOT NULL,
  `ismensal` TINYINT(1) NOT NULL,
  PRIMARY KEY (`id`, `tipo`),
  INDEX `fk_veiculos_tipos1_idx` (`tipo` ASC),
  UNIQUE INDEX `placa_UNIQUE` (`placa` ASC),
  CONSTRAINT `fk_veiculos_tipos1`
    FOREIGN KEY (`tipo`)
    REFERENCES `controleacesso`.`tipos` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `controleacesso`.`usuarios`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `controleacesso`.`usuarios` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `nome` VARCHAR(255) NOT NULL,
  `usuario` VARCHAR(255) NOT NULL,
  `senha` VARCHAR(255) NOT NULL,
  `status` TINYINT(1) NOT NULL,
  `admin` TINYINT(1) NOT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `controleacesso`.`caixadiarios`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `controleacesso`.`caixadiarios` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `usuario` INT NOT NULL,
  `abertura` TIMESTAMP NULL,
  `fechamento` TIMESTAMP NULL,
  `valortotal` DECIMAL(10,2) NULL,
  `data` DATE NOT NULL,
  `isfechado` TINYINT(1) NOT NULL,
  PRIMARY KEY (`id`, `usuario`),
  INDEX `fk_caixadiarios_usuarios1_idx` (`usuario` ASC),
  CONSTRAINT `fk_caixadiarios_usuarios1`
    FOREIGN KEY (`usuario`)
    REFERENCES `controleacesso`.`usuarios` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `controleacesso`.`clientes_veiculos`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `controleacesso`.`clientes_veiculos` (
  `cliente` INT NOT NULL AUTO_INCREMENT,
  `veiculo` INT NOT NULL,
  PRIMARY KEY (`cliente`, `veiculo`),
  INDEX `fk_clientes_has_veiculos_veiculos1_idx` (`veiculo` ASC),
  INDEX `fk_clientes_has_veiculos_clientes1_idx` (`cliente` ASC),
  CONSTRAINT `fk_clientes_has_veiculos_clientes1`
    FOREIGN KEY (`cliente`)
    REFERENCES `controleacesso`.`clientes` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_clientes_has_veiculos_veiculos1`
    FOREIGN KEY (`veiculo`)
    REFERENCES `controleacesso`.`veiculos` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `controleacesso`.`entradas_veiculos`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `controleacesso`.`entradas_veiculos` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `usuario` INT NOT NULL,
  `veiculo` INT NOT NULL,
  `data` TIMESTAMP NULL,
  `jasaiu` TINYINT(1) NOT NULL,
  PRIMARY KEY (`id`, `usuario`, `veiculo`),
  INDEX `fk_entradas_veiculos_usuarios1_idx` (`usuario` ASC),
  INDEX `fk_entradas_veiculos_veiculos1_idx` (`veiculo` ASC),
  CONSTRAINT `fk_entradas_veiculos_usuarios1`
    FOREIGN KEY (`usuario`)
    REFERENCES `controleacesso`.`usuarios` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_entradas_veiculos_veiculos1`
    FOREIGN KEY (`veiculo`)
    REFERENCES `controleacesso`.`veiculos` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `controleacesso`.`saidas_veiculos`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `controleacesso`.`saidas_veiculos` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `entrada_veiculo` INT NOT NULL,
  `usuario` INT NOT NULL,
  `data` TIMESTAMP NULL,
  `valor` DECIMAL(10,2) NOT NULL,
  `iscortesia` TINYINT(1) NOT NULL,
  PRIMARY KEY (`id`, `entrada_veiculo`, `usuario`),
  INDEX `fk_saidas_usuarios1_idx` (`usuario` ASC),
  INDEX `fk_saidas_veiculos_entradas_veiculos1_idx` (`entrada_veiculo` ASC),
  CONSTRAINT `fk_saidas_usuarios1`
    FOREIGN KEY (`usuario`)
    REFERENCES `controleacesso`.`usuarios` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_saidas_veiculos_entradas_veiculos1`
    FOREIGN KEY (`entrada_veiculo`)
    REFERENCES `controleacesso`.`entradas_veiculos` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `controleacesso`.`mensalidades`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `controleacesso`.`mensalidades` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `cliente` INT NOT NULL,
  `veiculo` INT NOT NULL,
  `datavencimento` DATE NOT NULL,
  PRIMARY KEY (`id`, `cliente`, `veiculo`),
  INDEX `fk_mensalidade_veiculos1_idx` (`veiculo` ASC),
  INDEX `fk_mensalidade_clientes1_idx` (`cliente` ASC),
  CONSTRAINT `fk_mensalidade_veiculos1`
    FOREIGN KEY (`veiculo`)
    REFERENCES `controleacesso`.`veiculos` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_mensalidade_clientes1`
    FOREIGN KEY (`cliente`)
    REFERENCES `controleacesso`.`clientes` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `controleacesso`.`movimentacao_caixadiario`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `controleacesso`.`movimentacao_caixadiario` (
  `saida_veiculo` INT NOT NULL,
  `caixadiario` INT NOT NULL,
  PRIMARY KEY (`saida_veiculo`, `caixadiario`),
  INDEX `fk_saida_veiculos_has_caixadiario_caixadiario1_idx` (`caixadiario` ASC),
  INDEX `fk_saida_veiculos_has_caixadiario_saida_veiculos1_idx` (`saida_veiculo` ASC),
  CONSTRAINT `fk_saida_veiculos_has_caixadiario_saida_veiculos1`
    FOREIGN KEY (`saida_veiculo`)
    REFERENCES `controleacesso`.`saidas_veiculos` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_saida_veiculos_has_caixadiario_caixadiario1`
    FOREIGN KEY (`caixadiario`)
    REFERENCES `controleacesso`.`caixadiarios` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;


text:
<!--
  ~  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.
  -->

<project default="build-service">

    <property name="synapse.home" value="../../../.."/>
    <property name="temp.dir" value="temp"/>
    <property name="classes" value="${temp.dir}/classes"/>
    <property name="src" value="src"/>
    <property name="services" value="../../repository/services"/>

    <path id="synapse.class.path">
        <pathelement path="${java.class.path}"/>
        <fileset dir="${synapse.home}">
            <include name="lib/*.jar"/>
            <include name="webapp/WEB-INF/lib/*.jar"/>
        </fileset>
    </path>

    <target name="init" depends="clean">
        <mkdir dir="${temp.dir}"/>
        <mkdir dir="${classes}"/>
        <mkdir dir="${services}"/>
    </target>

    <target name="clean">
        <delete dir="${temp.dir}"/>
    </target>

    <target name="compile-all" depends="init">
        <javac debug="on" destdir="${classes}">
            <src path="${src}"/>
            <classpath refid="synapse.class.path"/>
        </javac>
    </target>

    <target name="build-service" depends="compile-all">
        <property name="SSQ.dir" value="${temp.dir}/SecureStockQuoteService"/>
        <mkdir dir="${SSQ.dir}"/>

        <mkdir dir="${SSQ.dir}/META-INF"/>
        <copy file="conf/services.xml" tofile="${SSQ.dir}/META-INF/services.xml"/>
        <!--<copy file="wsdl/SimpleStockQuoteService.wsdl" tofile="${SSQ.dir}/META-INF/service.wsdl"/>        -->
        <copy file="store.jks" tofile="${SSQ.dir}/store.jks"/>
        <copy toDir="${SSQ.dir}">
            <fileset dir="${classes}">
                <include name="**/*.class"/>
            </fileset>
        </copy>

        <jar destfile="${services}/SecureStockQuoteService.aar">
            <fileset dir="${SSQ.dir}"/>
        </jar>
    </target>

</project>


text:
<?php
/**
 * @author Alexandr Medvedev <medvedevav@niissu.ru>
 */

namespace Lexty\AuthManager\Exception;

use Lexty\AuthManager\Token\TokenInterface;

class AuthenticationException extends \RuntimeException implements \Serializable
{
    private $token;

    public function getToken()
    {
        return $this->token;
    }

    public function setToken(TokenInterface $token)
    {
        $this->token = $token;
    }

    public function serialize()
    {
        return serialize([
            $this->token,
            $this->code,
            $this->message,
            $this->file,
            $this->line,
        ]);
    }

    public function unserialize($serialized)
    {
        list(
            $this->token,
            $this->code,
            $this->message,
            $this->file,
            $this->line
        ) = unserialize($serialized);
    }
}


text:
<?php

namespace Grav\Common\Markdown;

use Grav\Common\Page\Interfaces\PageInterface;
use Grav\Common\Page\Markdown\Excerpts;

/**
 * Class Parsedown
 * @package Grav\Common\Markdown
 */
class Parsedown extends \Parsedown
{
    use ParsedownGravTrait;

    /**
     * Parsedown constructor.
     *
     * @param Excerpts|PageInterface|null $excerpts
     * @param array|null $defaults
     */
    public function __construct($excerpts = null, $defaults = null)
    {
        if (!$excerpts || $excerpts instanceof PageInterface || null !== $defaults) {
            // Deprecated in Grav 1.6.10
            if ($defaults) {
                $defaults = ['markdown' => $defaults];
            }
            $excerpts = new Excerpts($excerpts, $defaults);
            user_error(__CLASS__ . '::' . __FUNCTION__ . '($page, $defaults) is deprecated since Grav 1.6.10, use new ' . __CLASS__ . '(new ' . Excerpts::class . '($page, [\'markdown\' => $defaults])) instead.', E_USER_DEPRECATED);
        }

        $this->init($excerpts, $defaults);
    }
}


text:
Controllers (Controladores)
===========

Os controllers (controladores) fazem parte da arquitetura [MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller).
São objetos de classes que estendem de [[yii\base\Controller]] e são responsáveis
pelo processamento das requisições e por gerar respostas. Em particular, após
assumir o controle de [applications](structure-applications.md), controllers
analisarão os dados de entradas obtidos pela requisição, passarão estes dados
para os [models](structure-models.md) (modelos), incluirão os resultados dos models
(modelos) nas [views](structure-views.md) (visões) e finalmente gerarão as respostas
de saída.

## Actions (Ações)

Os controllers são compostos por unidades básicas chamadas de *ações* que podem
ser tratados pelos usuários finais a fim de realizar a sua execução.

No exemplo a seguir mostra um controller `post` com duas ações: `view` e `create`:

```php
namespace app\controllers;

use Yii;
use app\models\Post;
use yii\web\Controller;
use yii\web\NotFoundHttpException;

class PostController extends Controller
{
    public function actionView($id)
    {
        $model = Post::findOne($id);
        if ($model === null) {
            throw new NotFoundHttpException;
        }

        return $this->render('view', [
            'model' => $model,
        ]);
    }

    public function actionCreate()
    {
        $model = new Post;

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['view', 'id' => $model->id]);
        } else {
            return $this->render('create', [
                'model' => $model,
            ]);
        }
    }
}
```

Na ação `view` (definido pelo método `actionView()`), o primeiro código carrega o
[model](structure-models.md) conforme o ID solicitado; Se o model for devidamente
carregado, a ação irá exibi-lo utilizado a [view](structure-views.md) chamada de `view`.
Caso contrário, a ação lançará uma exceção.

Na ação `create` (definido pelo método `actionCreate()`), o código é parecido.
Primeiro ele tenta popular o [model](structure-models.md) usando os dados da requisição
em seguida os salva. Se ambos forem bem sucedidos, a ação redirecionará o navegador
para a ação `view` com o novo ID criado pelo model. Caso contrário, a ação exibirá
a view `create` na qual os usuário poderão fornecer os dados necessários.

## Routes (Rotas)

Os usuários finais abordarão as ações por meio de *rotas*. Uma rota é uma string composta
pelas seguintes partes:

* um ID do módulo: serve apenas se o controller pertencer a um [módulo](structure-modules.md) que não seja da aplicação;
* um ID do controller: uma string que identifica exclusivamente o controller dentre todos os controllers da mesma aplicação (ou do mesmo módulo, caso o controller pertença a um módulo);
* um ID da ação: uma string que identifica exclusivamente uma ação dentre todas as ações de um mesmo controller.

As rotas seguem o seguinte formato:

```
IDdoController/IDdoAction
```

ou o seguinte formato se o controller estiver em um módulo:

```php
IDdoModule/IDdoController/IDdoAction
```

Portanto, se um usuário fizer uma requisição com a URL `https://hostname/index.php?r=site/index`,
a ação `index` do controller `site` será executada. Para mais detalhes sobre como
as ações são resolvidas pelas rotas, por favor consulte a seção [Roteamento e Criação de URL](runtime-routing.md).

## Criando Controllers

Em [[yii\web\Application|aplicações Web]], os controllers devem estender de [[yii\web\Controller]]
ou de suas classes filhas. De forma semelhante, em [[yii\console\Application|aplicaçoes console]],
os controllers devem estender de [[yii\console\Controller]] ou de suas classes filhos. O código a seguir define um controller `site`:

```php
namespace app\controllers;

use yii\web\Controller;

class SiteController extends Controller
{
}
```

### IDs de Controllers

Normalmente, um controller é projetado para tratar as requisições relativos a
um determinado tipo de recurso. Por esta razão, os IDs dos controllers geralmente
são substantivos que referenciam-se ao tipo de recurso que será tratado.
Por exemplo, você pode usar o `article` como o ID do um controller para tratar
dados de artigos.

Por padrão, os IDs dos controllers devem conter apenas esses caracteres:
letras inglesas em caixa baixa, números, underscores (underline), hífens e barras.
Por exemplo, `article` e `post-comment` são ambos IDs de controllers válidos,
enquanto `article?`, `PostComment`, `admin\post` não são.

Um ID de controller também pode conter um prefixo para o subdiretório. Por exemplo,
`admin/article` representa um controller `article` em um subdiretório `admin` sob
o [[yii\base\Application::controllerNamespace|namespace do controller]]
Os caracteres válidos para os prefixos de subdiretórios incluem: letras inglesas
em caixa alto ou caixa baixa, números, underscores (underline) e barras, onde as
barras são usadas para separar os níveis dos subdiretórios (por exemplo, `panels/admin`).

### Nomenclatura da Classe do Controller

Os nomes da classes dos controllers podem ser derivadas dos IDs dos controllers
de acordo com as seguintes procedimentos:

1. Colocar em caixa alta a primeira letra de cada palavra separadas por traço.
   Observe que se o ID do controller possuir barras, a regra é aplicada apenas na
   parte após a última barra no ID.
2. Remover os traços e substituir todas as barras por barras invertidas.
3. Adicionar `Controller` como sufixo.
4. Preceder ao [[yii\base\Application::controllerNamespace|namespace do controller]].

Segue alguns exemplos, assumindo que o [[yii\base\Application::controllerNamespace|namespace do controller]]
tenha por padrão o valor `app\controllers`:

* `article` torna-se `app\controllers\ArticleController`;
* `post-comment` torna-se `app\controllers\PostCommentController`;
* `admin/post-comment` torna-se `app\controllers\admin\PostCommentController`;
* `adminPanels/post-comment` torna-se `app\controllers\adminPanels\PostCommentController`.

As classes dos controllers devem ser [autoloadable](concept-autoloading.md).
Por esta razão, nos exemplos anteriores, o controller `article` deve ser salvo
no arquivo cuja [alias](concept-aliases.md) é `@app/controllers/ArticleController.php`;
enquanto o controller `admin/post-comment` deve ser salvo no `@app/controllers/admin/PostCommentController.php`.

> Informação: No último exemplo `admin/post-comment`, mostra como você pode colocar
um controller em um subdiretório do [[yii\base\Application::controllerNamespace|namespace controller]]. Isto é útil quando você quiser organizar seus controllers em diversas
categorias e não quiser usar [módulos](structure-modules.md).

### Mapeando Controllers

Você pode configurar um [[yii\base\Application::controllerMap|mapeamento de controllers]]
para superar as barreiras impostas pelos IDs de controllers e pelos nomes de classes
descritos acima. Isto é útil principalmente quando quiser esconder controllers
de terceiros na qual você não tem controle sobre seus nomes de classes.

Você pode configurar o [[yii\base\Application::controllerMap|mapeamento de controllers]]
na [configuração da aplicação](structure-applications.md#application-configurations). Por exemplo:

```php
[
    'controllerMap' => [
        // declara o controller "account" usando um nome de classe
        'account' => 'app\controllers\UserController',

        // declara o controller "article" usando uma configuração em array
        'article' => [
            'class' => 'app\controllers\PostController',
            'enableCsrfValidation' => false,
        ],
    ],
]
```

### Controller Padrão

Cada aplicação tem um controller padrão que é especificado pela propriedade [[yii\base\Application::defaultRoute]].
Quando uma requisição não especificar uma [rota](#id-da-rota), será utilizada a
rota especificada pela propriedade.
Para as [[yii\web\Application|aplicações Web]], este valor é `'site'`, enquanto
para as [[yii\console\Application|aplicações console]] é `help`. Portanto, se uma
URL for `https://hostname/index.php`, o controller `site` será utilizado nesta requisição.

Você pode alterar o controller padrão como a seguinte [configuração da aplicação](structure-applications.md#application-configurations):

```php
[
    'defaultRoute' => 'main',
]
```

## Criando Ações

Criar ações pode ser tão simples como a definição dos chamados *métodos de ação*
em uma classe controller. Um método de ação é um método *público* cujo nome inicia
com a palavra `action`. O valor de retorno representa os dados de resposta a serem
enviados aos usuário finais. O código a seguir define duas ações, `index` e `hello-world`:

```php
namespace app\controllers;

use yii\web\Controller;

class SiteController extends Controller
{
    public function actionIndex()
    {
        return $this->render('index');
    }

    public function actionHelloWorld()
    {
        return 'Hello World';
    }
}
```

### IDs de Actions

Uma ação muitas vezes é projetada para realizar uma manipulação em particular sobre
um recurso. Por esta razão, os IDs das ações geralmente são verbos, tais como `view`, `update`, etc.

Por padrão, os IDs das ações devem conter apenas esses caracteres: letras inglesas
em caixa baixa, números, underscores (underline) e traços. Os traços em um ID da
ação são usados para separar palavras. Por exemplo, `view`, `update2` e `comment-post`
são IDs válidos, enquanto `view?` e `Update` não são.

Você pode criar ações de duas maneiras: ações inline (em sequência) e
ações standalone (autônomas). Uma ação inline é definida pelo método
de uma classe controller, enquanto uma ação standalone é uma classe que estende de
[[yii\base\Action]] ou de uma classe-filha. As ações inline exigem menos esforço
para serem criadas e muitas vezes as preferidas quando não se tem a intenção de
reutilizar estas ações. Ações standalone, por outro lado, são criados principalmente
para serem utilizados em diferentes controllers ou para serem distribuídos como
[extensions](structure-extensions.md).

### Ações Inline

As ações inline referem-se a os chamados métodos de ação, que foram descritos anteriormente.

Os nomes dos métodos de ações são derivadas dos IDs das ações de acordo com os
seguintes procedimentos:

1. Colocar em caixa alta a primeira letra de cada palavra do ID da ação;
2. Remover os traços;
3. Adicionar o prefixo `action`.

Por exemplo, `index` torna-se `actionIndex` e `hello-world` torna-se `actionHelloWorld`.

> Observação: Os nomes dos métodos de ações são *case-sensitive*. Se você tiver
  um método chamado `ActionIndex`, não será considerado como um método de ação e
  como resultado, o pedido para a ação `index` lançará uma exceção. Observe também
  que os métodos de ações devem ser públicas. Um método privado ou protegido NÃO
  será definido como ação inline.

As ações inline normalmente são as mais utilizadas pois demandam pouco esforço
para serem criadas. No entanto, se você deseja reutilizar algumas ações em diferentes
lugares ou se deseja distribuir uma ação, deve considerar defini-la como uma *ação standalone*.

### Ações Standalone

Ações standalone são definidas por classes de ações que estendem de [[yii\base\Action]]
ou de uma classe-filha.
Por example, nas versões do Yii, existe a [[yii\web\ViewAction]] e a [[yii\web\ErrorAction]], ambas são ações standalone.

Para usar uma ação standalone, você deve *mapear as ações* sobrescrevendo o método
[[yii\base\Controller::actions()]] em suas classes controllers como o seguinte:

```php
public function actions()
{
    return [
        // declara a ação "error" usando um nome de classe
        'error' => 'yii\web\ErrorAction',

        // declara a ação "view" usando uma configuração em array
        'view' => [
            'class' => 'yii\web\ViewAction',
            'viewPrefix' => '',
        ],
    ];
}
```

Como pode ver, o método `actions()` deve retornar um array cujas chaves são os IDs
das ações e os valores correspondentes ao nome da classe da ação ou [configurações](concept-configurations.md). Ao contrário das ações inline, os IDs das ações standalone
podem conter caracteres arbitrários desde que sejam mapeados no método `actions()`.

Para criar uma classe de ação standalone, você deve estender de [[yii\base\Action]] ou de duas classes filhas e implementar um método público chamado `run()`. A regra para o método `run()`
é semelhante ao de um método de ação. Por exemplo,

```php
<?php
namespace app\components;

use yii\base\Action;

class HelloWorldAction extends Action
{
    public function run()
    {
        return "Hello World";
    }
}
```

### Resultados da Ação

O valor de retorno do método de ação ou do método `run()` de uma ação standalone
são importantes. Eles representam o resultado da ação correspondente.

O valor de retorno pode ser um objeto de [resposta](runtime-responses.md) que
será enviado como resposta aos usuários finais.

* Para [[yii\web\Application|aplicações Web]], o valor de retorno também poder
  ser algum dado arbitrário que será atribuído à propriedade [[yii\web\Response::data]]
  e ainda ser convertido em uma string para representar o corpo da resposta.
* Para [[yii\console\Application|aplicações console]], o valor de retorno também
  poder ser um inteiro representando o [[yii\console\Response::exitStatus|exit status]]
  (status de saída) da execução do comando.

Nos exemplos acima, todos os resultados são strings que serão tratados como o
corpo das respostas para serem enviados aos usuários finais. No exemplo a seguir,
mostra como uma ação pode redirecionar o navegador do usuário para uma nova URL
retornando um objeto de resposta (o método [[yii\web\Controller::redirect()|redirect()]]
retorna um objeto de resposta):

```php
public function actionForward()
{
    // redireciona o navegador do usuário para https://example.com
    return $this->redirect('https://example.com');
}
```

### Parâmetros da Ação

Os métodos de ações para as ações inline e os métodos `run()` para as ações
standalone podem receber parâmetros, chamados *parâmetros da ação*.
Seus valores são obtidos a partir das requisições. Para
[[yii\web\Application|aplicações Web]], o valor de cada parâmetro da ação são
obtidos pelo `$_GET` usando o nome do parâmetro como chave; para
[[yii\console\Application|aplicações console]], eles correspondem aos argumentos
da linha de comando.

No exemplo a seguir, a ação `view` (uma ação inline) possui dois parâmetros declarados:
`$id` e `$version`.

```php
namespace app\controllers;

use yii\web\Controller;

class PostController extends Controller
{
    public function actionView($id, $version = null)
    {
        // ...
    }
}
```

A seguir, os parâmetros da ação serão populados em diferentes requisições:

* `https://hostname/index.php?r=post/view&id=123`: o parâmetro `$id` receberá
  o valor `'123'`, enquanto o `$version` continuará com o valor nulo porque não
  existe o parâmetro `version` na URL.
* `https://hostname/index.php?r=post/view&id=123&version=2`: os parâmetros `$id`
  e `$version` serão receberão os valores `'123'` e `'2'`, respectivamente.
* `https://hostname/index.php?r=post/view`: uma exceção [[yii\web\BadRequestHttpException]]
  será lançada porque o parâmetro obrigatório `$id` não foi informado na requisição.
* `https://hostname/index.php?r=post/view&id[]=123`: uma exceção [[yii\web\BadRequestHttpException]]
  será lançada porque o parâmetro `$id` foi informado com um valor array `['123']`
  na qual não era esperado.

Se você quiser que um parâmetro da ação aceite valores arrays, deverá declara-lo
explicitamente com `array`, como mostro a seguir:

```php
public function actionView(array $id, $version = null)
{
    // ...
}
```

Agora, se a requisição for `https://hostname/index.php?r=post/view&id[]=123`, o
parâmetro `$id` receberá o valor `['123']`. Se a requisição for
`https://hostname/index.php?r=post/view&id=123`, o parâmetro `$id` ainda receberá
um array como valor pois o valor escalar `'123'` será convertido automaticamente
em um array.

Os exemplo acima mostram, principalmente, como os parâmetros da ação trabalham em
aplicações Web. Para aplicações console, por favor, consulte a seção
[Comandos de Console](tutorial-console.md) para mais detalhes.

### Default Action

Cada controller tem uma ação padrão especificado pela propriedade
[[yii\base\Controller::defaultAction]].
Quando uma [rota](#id-da-rota) contém apenas o ID do controller, implica que a
ação padrão do controller seja solicitada.

Por padrão, a ação padrão é definida como `index`. Se quiser alterar o valor padrão,
simplesmente sobrescreva esta propriedade na classe controller, como o seguinte:

```php
namespace app\controllers;

use yii\web\Controller;

class SiteController extends Controller
{
    public $defaultAction = 'home';

    public function actionHome()
    {
        return $this->render('home');
    }
}
```

## Ciclo de Vida do Controller

Ao processar uma requisição, a [aplicação](structure-applications.md) criará
um controller baseada na [rota](#routes) solicitada. O controller, então, se submeterá
ao seguinte ciclo de vida para concluir a requisição:

1. O método [[yii\base\Controller::init()]] é chamado após o controller ser criado e configurado.
2. O controller cria um objeto da ação baseada no ID da ação solicitada:
   * Se o ID da ação não for especificado, o [[yii\base\Controller::defaultAction|ID da ação padrão]] será utilizada.
   * Se o ID da ação for encontrada no [[yii\base\Controller::actions()|mapeamento das ações]], uma ação standalone será criada;
   * Se o ID da ação for encontrada para corresponder a um método de ação, uma ação inline será criada;
   * Caso contrário, uma exceção [[yii\base\InvalidRouteException]] será lançada.
3. De forma sequencial, o controller chama o método `beforeAction()` da aplicação, o módulo (se o controller pertencer a um módulo) e o controller.
   * Se uma das chamadas retornar `false`, o restante dos métodos subsequentes `beforeAction()` serão ignoradas e a execução da ação será cancelada.
   * Por padrão, cada método `beforeAction()` desencadeia a execução de um evento chamado `beforeAction` na qual você pode associar a uma função (handler).
4. O controller executa a ação:
   * Os parâmetros da ação serão analizados e populados a partir dos dados obtidos pela requisição;
5. De forma sequencial, o controller chama o método `afterAction()` do controller, o módulo (se o controller pertencer a um módulo) e a aplicação.
   * Por padrão, cada método `afterAction()` desencadeia a execução de um evento chamado `afterAction` na qual você pode associar a uma função (handler).
6. A aplicação obterá o resultado da ação e irá associá-lo na [resposta](runtime-responses.md).

## Boas Práticas

Em uma aplicação bem projetada, frequentemente os controllers são bem pequenos na
qual cada ação possui poucas linhas de códigos.
Se o controller for um pouco complicado, geralmente indica que terá que refaze-lo
e passar algum código para outro classe.

Segue algumas boas práticas em destaque. Os controllers:

* podem acessar os dados de uma [requisição](runtime-requests.md);
* podem chamar os métodos dos [models](structure-models.md) e outros componentes
  de serviço com dados da requisição;
* podem usar as [views](structure-views.md) para compor as respostas;
* NÃO devem processar os dados da requisição - isto deve ser feito na [camada model (modelo)](structure-models.md);
* devem evitar inserir códigos HTML ou outro código de apresentação - é melhor
  que sejam feitos nas [views](structure-views.md).


text:
local M = { }
local name = "test_path"
local me = ...
local FX = require("FunctionalX")
local TK = require("PackageToolkit")
local case = TK.test.case
M[name] = function()
  local fn = FX.os.path
  print(fn("HOME"))
  print("---------------------")
  print("path separator: " .. FX.os.pathsep())
  print("---------------------")
  return true
end
return M


text: version 1.0 pre-alpha


text:
package org.mortbay.cometd.jms;

import java.util.Enumeration;

import javax.jms.Destination;
import javax.jms.JMSException;

public class CometdMessage implements javax.jms.Message
{

    public void acknowledge() throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void clearBody() throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void clearProperties() throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public boolean getBooleanProperty(String name) throws JMSException
    {
        // TODO Auto-generated method stub
        return false;
    }

    public byte getByteProperty(String name) throws JMSException
    {
        // TODO Auto-generated method stub
        return 0;
    }

    public double getDoubleProperty(String name) throws JMSException
    {
        // TODO Auto-generated method stub
        return 0;
    }

    public float getFloatProperty(String name) throws JMSException
    {
        // TODO Auto-generated method stub
        return 0;
    }

    public int getIntProperty(String name) throws JMSException
    {
        // TODO Auto-generated method stub
        return 0;
    }

    public String getJMSCorrelationID() throws JMSException
    {
        // TODO Auto-generated method stub
        return null;
    }

    public byte[] getJMSCorrelationIDAsBytes() throws JMSException
    {
        // TODO Auto-generated method stub
        return null;
    }

    public int getJMSDeliveryMode() throws JMSException
    {
        // TODO Auto-generated method stub
        return 0;
    }

    public Destination getJMSDestination() throws JMSException
    {
        // TODO Auto-generated method stub
        return null;
    }

    public long getJMSExpiration() throws JMSException
    {
        // TODO Auto-generated method stub
        return 0;
    }

    public String getJMSMessageID() throws JMSException
    {
        // TODO Auto-generated method stub
        return null;
    }

    public int getJMSPriority() throws JMSException
    {
        // TODO Auto-generated method stub
        return 0;
    }

    public boolean getJMSRedelivered() throws JMSException
    {
        // TODO Auto-generated method stub
        return false;
    }

    public Destination getJMSReplyTo() throws JMSException
    {
        // TODO Auto-generated method stub
        return null;
    }

    public long getJMSTimestamp() throws JMSException
    {
        // TODO Auto-generated method stub
        return 0;
    }

    public String getJMSType() throws JMSException
    {
        // TODO Auto-generated method stub
        return null;
    }

    public long getLongProperty(String name) throws JMSException
    {
        // TODO Auto-generated method stub
        return 0;
    }

    public Object getObjectProperty(String name) throws JMSException
    {
        // TODO Auto-generated method stub
        return null;
    }

    public Enumeration getPropertyNames() throws JMSException
    {
        // TODO Auto-generated method stub
        return null;
    }

    public short getShortProperty(String name) throws JMSException
    {
        // TODO Auto-generated method stub
        return 0;
    }

    public String getStringProperty(String name) throws JMSException
    {
        // TODO Auto-generated method stub
        return null;
    }

    public boolean propertyExists(String name) throws JMSException
    {
        // TODO Auto-generated method stub
        return false;
    }

    public void setBooleanProperty(String name, boolean value) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setByteProperty(String name, byte value) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setDoubleProperty(String name, double value) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setFloatProperty(String name, float value) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setIntProperty(String name, int value) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setJMSCorrelationID(String correlationID) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setJMSCorrelationIDAsBytes(byte[] correlationID) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setJMSDeliveryMode(int deliveryMode) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setJMSDestination(Destination destination) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setJMSExpiration(long expiration) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setJMSMessageID(String id) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setJMSPriority(int priority) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setJMSRedelivered(boolean redelivered) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setJMSReplyTo(Destination replyTo) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setJMSTimestamp(long timestamp) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setJMSType(String type) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setLongProperty(String name, long value) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setObjectProperty(String name, Object value) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setShortProperty(String name, short value) throws JMSException
    {
        // TODO Auto-generated method stub

    }

    public void setStringProperty(String name, String value) throws JMSException
    {
        // TODO Auto-generated method stub

    }

}


text:
package de.uni_freiburg.informatik.dbis.sempala.translator;

import java.util.HashMap;

/**
 *
 * @author ALKA2008
 */
public final class Tags {

	// Global Constants
	public static final String IMPALA_PROPERTYTABLE_TABLENAME = "bigtable_parquet";
	public static final String IMPALA_SINGLETABLE_TABLENAME = "singletable";
	public static final String IMPALA_TABLENAME_TRIPLESTORE = "triplestore_parquet";

	// tables produced by the complex property table loading process
	public static final String COMPLEX_TRIPLETABLE_TABLENAME = "tripletable";
	public static final String COMPLEX_PROPERTYTABLE_TABLENAME = "complex_property_table";
	// spark caches the complex_property_table under this table
	public static final String CACHED_COMPLEX_PROPERTYTABLE_TABLENAME = "cached_complex_property_table";
	public static final String COMPLEX_PROPERTIES_TABLENAME = "properties";

	//tables produced by the ExtVP loading process
	public static final String TABLENAME_TRIPLE_TABLE = "tripletable";

	public static final String SEMPALA_RESULTS_DB_NAME = "sempala_results";

	public static final String BGP = "BGP";
	public static final String FILTER = "FILTER";
	public static final String JOIN = "JOIN";
	public static final String SEQUENCE = "SEQUENCE_JOIN";
	public static final String LEFT_JOIN = "OPTIONAL";
	public static final String CONDITIONAL = "OPTIONAL";
	public static final String UNION = "UNION";
	public static final String PROJECT = "PROJECTION ";
	public static final String DISTINCT = "SM_Distinct";
	public static final String ORDER = "SM_Order";
	public static final String SLICE = "SM_Slice";
	public static final String REDUCED = "SM_Reduced";

	public static final String GREATER_THAN = " > ";
	public static final String GREATER_THAN_OR_EQUAL = " >= ";
	public static final String LESS_THAN = " < ";
	public static final String LESS_THAN_OR_EQUAL = " <= ";
	public static final String EQUALS = " = ";
	public static final String NOT_EQUALS = " != ";
	public static final String LOGICAL_AND = " AND ";
	public static final String LOGICAL_OR = " OR ";
	public static final String LOGICAL_NOT = "NOT ";
	public static final String BOUND = " IS NOT NULL";
	public static final String NOT_BOUND = " IS NULL";

	public static final String NO_VAR = "#noVar";
	public static final String NO_SUPPORT = "#noSupport";

	public static final String OFFSETCHAR = "\t";
	public static final String SUBJECT_COLUMN_NAME   = "s";
	public static final String PREDICATE_COLUMN_NAME = "p";
	public static final String OBJECT_COLUMN_NAME    = "o";

	public static final int LIMIT_LARGE_NUMBER = 100000000;
	public static final String ADD = "+";
	public static final String SUBTRACT = "-";
	public static final String LIKE = " LIKE ";
	public static final String LANG_MATCHES = " LIKE ";

	// names which cannot be used for columns and their replacements
	public static HashMap<String, String> restrictedNames = new HashMap<String, String>();
	static {
		restrictedNames.put("comment", "comme");
		restrictedNames.put("date", "dat");
		restrictedNames.put("?comment", "comme");
		restrictedNames.put("?date", "dat");
	}

	// Suppress default constructor for noninstantiability
	private Tags() {
	}

}


text:
<nb-card>
  <nb-card-body>
    <nb-button-group multiple>
      <button nbButtonToggle pressed>A</button>
      <button nbButtonToggle pressed>B</button>
      <button nbButtonToggle>C</button>
    </nb-button-group>
  </nb-card-body>
</nb-card>