text:
"""Parse AT&T-style x86 assembly.

The purpose of this parser is to get assembly instructions from large
binaries (such as kernel modules, vmlinux, etc.) and convert them into
a structural format that can be later manipulated.

Author:       Peter Goodman (peter.goodman@gmail.com)
Copyright:    Copyright 2012-2013 Peter Goodman, all rights reserved.
"""

import re
import collections

class Register(object):
  """Represents a system register.

  Note: Registers are considered a smaller unit than operands."""

  __slots__ = (
    'mnemonic',
    'size',
    'parent',
    'children',
    'kind',
  )

  # Different classes of registers.
  KIND_GENERAL_PURPOSE    = 1
  KIND_X87_FPU_STACK_REG  = 2
  KIND_MMX                = 3
  KIND_SIMD               = 4
  KIND_SEGMENT            = 5
  KIND_DEBUG              = 6
  KIND_CONTROL            = 7
  KIND_TEST               = 8
  KIND_INSTRUCTION        = 9
  KIND_STACK              = 10

  # Cache of register objects.
  CACHE = {}

  def __init__(self, mnemonic, size, kind, parent=None):
    global REGISTER_CACHE
    self.mnemonic = mnemonic
    self.size = size
    self.kind = kind
    self.parent = parent and self.CACHE[parent] or None
    self.children = set([self])

    parent = self.parent
    while parent:
      parent.children.add(self)
      parent = parent.parent

    self.CACHE[mnemonic] = self

  @classmethod
  def parse(cls, mnemonic):
    return cls.CACHE[mnemonic.strip("%*()").upper()]

  def __str__(self):
    return "%%%s" % self.mnemonic

Register("RIP",   8,  Register.KIND_INSTRUCTION)

Register("RAX",   8,  Register.KIND_GENERAL_PURPOSE)
Register("RCX",   8,  Register.KIND_GENERAL_PURPOSE)
Register("RDX",   8,  Register.KIND_GENERAL_PURPOSE)
Register("RBX",   8,  Register.KIND_GENERAL_PURPOSE)
Register("RSP",   8,  Register.KIND_STACK)
Register("RBP",   8,  Register.KIND_GENERAL_PURPOSE)
Register("RSI",   8,  Register.KIND_GENERAL_PURPOSE)
Register("RDI",   8,  Register.KIND_GENERAL_PURPOSE)
Register("R8",    8,  Register.KIND_GENERAL_PURPOSE)
Register("R9",    8,  Register.KIND_GENERAL_PURPOSE)
Register("R10",   8,  Register.KIND_GENERAL_PURPOSE)
Register("R11",   8,  Register.KIND_GENERAL_PURPOSE)
Register("R12",   8,  Register.KIND_GENERAL_PURPOSE)
Register("R13",   8,  Register.KIND_GENERAL_PURPOSE)
Register("R14",   8,  Register.KIND_GENERAL_PURPOSE)
Register("R15",   8,  Register.KIND_GENERAL_PURPOSE)

Register("EAX",   4,  Register.KIND_GENERAL_PURPOSE,   parent="RAX")
Register("ECX",   4,  Register.KIND_GENERAL_PURPOSE,   parent="RCX")
Register("EDX",   4,  Register.KIND_GENERAL_PURPOSE,   parent="RDX")
Register("EBX",   4,  Register.KIND_GENERAL_PURPOSE,   parent="RBX")
Register("ESP",   4,  Register.KIND_STACK,             parent="RSP")
Register("EBP",   4,  Register.KIND_GENERAL_PURPOSE,   parent="RBP")
Register("ESI",   4,  Register.KIND_GENERAL_PURPOSE,   parent="RSI")
Register("EDI",   4,  Register.KIND_GENERAL_PURPOSE,   parent="RDI")
Register("R8D",   4,  Register.KIND_GENERAL_PURPOSE,   parent="R8")
Register("R9D",   4,  Register.KIND_GENERAL_PURPOSE,   parent="R9")
Register("R10D",  4,  Register.KIND_GENERAL_PURPOSE,   parent="R10")
Register("R11D",  4,  Register.KIND_GENERAL_PURPOSE,   parent="R11")
Register("R12D",  4,  Register.KIND_GENERAL_PURPOSE,   parent="R12")
Register("R13D",  4,  Register.KIND_GENERAL_PURPOSE,   parent="R13")
Register("R14D",  4,  Register.KIND_GENERAL_PURPOSE,   parent="R14")
Register("R15D",  4,  Register.KIND_GENERAL_PURPOSE,   parent="R15")

Register("AX",    2,  Register.KIND_GENERAL_PURPOSE,   parent="EAX")
Register("CX",    2,  Register.KIND_GENERAL_PURPOSE,   parent="ECX")
Register("DX",    2,  Register.KIND_GENERAL_PURPOSE,   parent="EDX")
Register("BX",    2,  Register.KIND_GENERAL_PURPOSE,   parent="EBX")
Register("SP",    2,  Register.KIND_STACK,             parent="ESP")
Register("BP",    2,  Register.KIND_GENERAL_PURPOSE,   parent="EBP")
Register("SI",    2,  Register.KIND_GENERAL_PURPOSE,   parent="ESI")
Register("DI",    2,  Register.KIND_GENERAL_PURPOSE,   parent="EDI")
Register("R8W",   2,  Register.KIND_GENERAL_PURPOSE,   parent="R8D")
Register("R9W",   2,  Register.KIND_GENERAL_PURPOSE,   parent="R9D")
Register("R10W",  2,  Register.KIND_GENERAL_PURPOSE,   parent="R10D")
Register("R11W",  2,  Register.KIND_GENERAL_PURPOSE,   parent="R11D")
Register("R12W",  2,  Register.KIND_GENERAL_PURPOSE,   parent="R12D")
Register("R13W",  2,  Register.KIND_GENERAL_PURPOSE,   parent="R13D")
Register("R14W",  2,  Register.KIND_GENERAL_PURPOSE,   parent="R14D")
Register("R15W",  2,  Register.KIND_GENERAL_PURPOSE,   parent="R15D")

Register("AL",    1,  Register.KIND_GENERAL_PURPOSE,   parent="AX")
Register("CL",    1,  Register.KIND_GENERAL_PURPOSE,   parent="CX")
Register("DL",    1,  Register.KIND_GENERAL_PURPOSE,   parent="DX")
Register("BL",    1,  Register.KIND_GENERAL_PURPOSE,   parent="BX")
Register("AH",    1,  Register.KIND_GENERAL_PURPOSE,   parent="AX")
Register("CH",    1,  Register.KIND_GENERAL_PURPOSE,   parent="CX")
Register("DH",    1,  Register.KIND_GENERAL_PURPOSE,   parent="DX")
Register("BH",    1,  Register.KIND_GENERAL_PURPOSE,   parent="BX")
Register("R8B",   1,  Register.KIND_GENERAL_PURPOSE,   parent="R8W")
Register("R9B",   1,  Register.KIND_GENERAL_PURPOSE,   parent="R9W")
Register("R10B",  1,  Register.KIND_GENERAL_PURPOSE,   parent="R10W")
Register("R11B",  1,  Register.KIND_GENERAL_PURPOSE,   parent="R11W")
Register("R12B",  1,  Register.KIND_GENERAL_PURPOSE,   parent="R12W")
Register("R13B",  1,  Register.KIND_GENERAL_PURPOSE,   parent="R13W")
Register("R14B",  1,  Register.KIND_GENERAL_PURPOSE,   parent="R14W")
Register("R15B",  1,  Register.KIND_GENERAL_PURPOSE,   parent="R15W")
Register("SPL",   1,  Register.KIND_STACK,             parent="SP")
Register("BPL",   1,  Register.KIND_GENERAL_PURPOSE,   parent="BP")
Register("SIL",   1,  Register.KIND_GENERAL_PURPOSE,   parent="SI")
Register("DIL",   1,  Register.KIND_GENERAL_PURPOSE,   parent="DI")

Register("MM0",   8,  Register.KIND_MMX)
Register("MM1",   8,  Register.KIND_MMX)
Register("MM2",   8,  Register.KIND_MMX)
Register("MM3",   8,  Register.KIND_MMX)
Register("MM4",   8,  Register.KIND_MMX)
Register("MM5",   8,  Register.KIND_MMX)
Register("MM6",   8,  Register.KIND_MMX)
Register("MM7",   8,  Register.KIND_MMX)

Register("XMM0",  16, Register.KIND_SIMD)
Register("XMM1",  16, Register.KIND_SIMD)
Register("XMM2",  16, Register.KIND_SIMD)
Register("XMM3",  16, Register.KIND_SIMD)
Register("XMM4",  16, Register.KIND_SIMD)
Register("XMM5",  16, Register.KIND_SIMD)
Register("XMM6",  16, Register.KIND_SIMD)
Register("XMM7",  16, Register.KIND_SIMD)
Register("XMM8",  16, Register.KIND_SIMD)
Register("XMM9",  16, Register.KIND_SIMD)
Register("XMM10", 16, Register.KIND_SIMD)
Register("XMM11", 16, Register.KIND_SIMD)
Register("XMM12", 16, Register.KIND_SIMD)
Register("XMM13", 16, Register.KIND_SIMD)
Register("XMM14", 16, Register.KIND_SIMD)
Register("XMM15", 16, Register.KIND_SIMD)

Register("ST",    8,  Register.KIND_X87_FPU_STACK_REG)
Register("ST1",   8,  Register.KIND_X87_FPU_STACK_REG)
Register("ST2",   8,  Register.KIND_X87_FPU_STACK_REG)
Register("ST3",   8,  Register.KIND_X87_FPU_STACK_REG)
Register("ST4",   8,  Register.KIND_X87_FPU_STACK_REG)
Register("ST5",   8,  Register.KIND_X87_FPU_STACK_REG)
Register("ST6",   8,  Register.KIND_X87_FPU_STACK_REG)
Register("ST7",   8,  Register.KIND_X87_FPU_STACK_REG)

Register("ES",    8,  Register.KIND_SEGMENT)
Register("CS",    8,  Register.KIND_SEGMENT)
Register("SS",    8,  Register.KIND_SEGMENT)
Register("DS",    8,  Register.KIND_SEGMENT)
Register("FS",    8,  Register.KIND_SEGMENT)
Register("GS",    8,  Register.KIND_SEGMENT)

Register("DR0",   8,  Register.KIND_DEBUG)
Register("DR1",   8,  Register.KIND_DEBUG)
Register("DR2",   8,  Register.KIND_DEBUG)
Register("DR3",   8,  Register.KIND_DEBUG)
Register("DR4",   8,  Register.KIND_DEBUG)
Register("DR5",   8,  Register.KIND_DEBUG)
Register("DR6",   8,  Register.KIND_DEBUG)
Register("DR7",   8,  Register.KIND_DEBUG)
Register("DR8",   8,  Register.KIND_DEBUG)
Register("DR9",   8,  Register.KIND_DEBUG)
Register("DR10",  8,  Register.KIND_DEBUG)
Register("DR11",  8,  Register.KIND_DEBUG)
Register("DR12",  8,  Register.KIND_DEBUG)
Register("DR13",  8,  Register.KIND_DEBUG)
Register("DR14",  8,  Register.KIND_DEBUG)
Register("DR15",  8,  Register.KIND_DEBUG)

Register("CR0",   8,  Register.KIND_CONTROL)
Register("CR1",   8,  Register.KIND_CONTROL)
Register("CR2",   8,  Register.KIND_CONTROL)
Register("CR3",   8,  Register.KIND_CONTROL)
Register("CR4",   8,  Register.KIND_CONTROL)
Register("CR5",   8,  Register.KIND_CONTROL)
Register("CR6",   8,  Register.KIND_CONTROL)
Register("CR7",   8,  Register.KIND_CONTROL)
Register("CR8",   8,  Register.KIND_CONTROL)
Register("CR9",   8,  Register.KIND_CONTROL)
Register("CR10",  8,  Register.KIND_CONTROL)
Register("CR11",  8,  Register.KIND_CONTROL)
Register("CR12",  8,  Register.KIND_CONTROL)
Register("CR13",  8,  Register.KIND_CONTROL)
Register("CR14",  8,  Register.KIND_CONTROL)
Register("CR15",  8,  Register.KIND_CONTROL)

Register("YMM0",  32, Register.KIND_SIMD)
Register("YMM1",  32, Register.KIND_SIMD)
Register("YMM2",  32, Register.KIND_SIMD)
Register("YMM3",  32, Register.KIND_SIMD)
Register("YMM4",  32, Register.KIND_SIMD)
Register("YMM5",  32, Register.KIND_SIMD)
Register("YMM6",  32, Register.KIND_SIMD)
Register("YMM7",  32, Register.KIND_SIMD)
Register("YMM8",  32, Register.KIND_SIMD)
Register("YMM9",  32, Register.KIND_SIMD)
Register("YMM10", 32, Register.KIND_SIMD)
Register("YMM11", 32, Register.KIND_SIMD)
Register("YMM12", 32, Register.KIND_SIMD)
Register("YMM13", 32, Register.KIND_SIMD)
Register("YMM14", 32, Register.KIND_SIMD)
Register("YMM15", 32, Register.KIND_SIMD)

class Operand(object):
  """Represents a parsed operand and common utilities that operate
  on operands in general."""

  # Operand sizes.
  SIZE_1              = 1
  SIZE_2              = 2
  SIZE_4              = 4
  SIZE_8              = 8
  SIZE_16             = 16
  SIZE_32             = 32

  @classmethod
  def parse(cls, instruction_mnemonic, op_str):
    op_str = op_str.strip(" \t\n") \
                   .replace(" ", "")

    # Operand is the target of a (non-RET) control-flow instruction.
    if instruction_mnemonic.startswith("J") \
    or "CALL" in instruction_mnemonic \
    or "LOOP" in instruction_mnemonic \
    or "JMP" in instruction_mnemonic:
      if op_str.startswith("*"):
        if "(" in op_str:
          return AddressOperand.parse(op_str[1:])
        elif "%" in op_str:
          return RegisterOperand.parse(op_str)
        else:
          return MemoryOperand.parse(op_str[1:])
      else:
        return AddressOperand.parse("0x" + op_str + "(%rip)")

    # Immediate integer operand.
    elif op_str.startswith("$"):
      return ImmediateOperand.parse(op_str)

    # Likely address operand of a base/displacement form.
    elif "(" in op_str:
      return AddressOperand.parse(op_str)

    # Register operand, or access of a displacement of a segment
    # register.
    elif "%" in op_str:
      if ":" in op_str and op_str[-1] in "0123456789abcdefABCDEF":
        return AddressOperand.parse(op_str)
      else:
        return RegisterOperand.parse(op_str)

    # Absolute memory address operand.
    elif op_str:
      return MemoryOperand.parse(op_str)

    # This is unusual.
    else:
      assert False

  # Returns True iff the current operand is an effective
  # address.
  def is_effective_address(self):
    if not isinstance(self, AddressOperand):
      return False

    if self.base_register:
      return Register.KIND_GENERAL_PURPOSE == self.base_register.kind
    elif self.index_register:
      return True
    return False

class ImmediateOperand(Operand):
  """Represents an immediate integer operand."""

  __slots__ = ('value',)

  KIND = 1

  def __init__(self, value):
    self.value = value

  @classmethod
  def parse(cls, op_str):
    if op_str.startswith("$"):
      op_str = op_str[1:]
    return ImmediateOperand(int(op_str, base=0))

  # Re-serialise this operand as a string in a way that can be
  # parsed again.
  def __str__(self):
    return "$%s0x%x" % (
      self.value < 0 and "-" or "", abs(self.value))

class RegisterOperand(Operand):
  """Represents a register operand."""

  __slots__ = (
    'segment_register',
    'base_register',
  )

  KIND = 2

  def __init__(self, seg, base):
    self.segment_register = seg
    self.base_register = base

  @classmethod
  def parse(cls, op_str):
    op_str = op_str.replace("*", "")
    parts = op_str.split(":")
    base_register = Register.parse(parts[-1])
    segment_register = None
    parts = parts[:-1]
    if parts:
      segment_register = Register.parse(parts[0])
    return RegisterOperand(segment_register, base_register)

  # Re-serialise this operand as a string in a way that can be
  # parsed again.
  def __str__(self):
    ret = ""
    if self.segment_register:
      ret = str(self.segment_register)
      if self.base_register:
        ret += ":"
    if self.base_register:
      ret += str(self.base_register)
    return ret

class MemoryOperand(Operand):
  """Represents an address operand."""

  CACHE = {}
  KIND = 3

  __slots__ = ('address',)

  def __init__(self, addr):
    self.address = addr

  # Parse a memory operand.
  #
  # Returns:
  #   A MemoryOperand instance or an AddressOperand instance.
  @classmethod
  def parse(cls, op_str):
    addr = int(op_str, base=0)
    if addr in cls.CACHE:
      return cls.CACHE[addr]

    op = MemoryOperand(addr)
    cls.CACHE[addr] = op
    return op

  # Re-serialise this operand as a string in a way that can be
  # parsed again.
  def __str__(self):
    return "%s0x%x" % (
      self.address < 0 and "-" or "", abs(self.address))

class AddressOperand(Operand):
  """Represents an effective address operand."""

  __slots__ = (
    'base_register',
    'index_register',
    'segment_register',
    'displacement',
    'scale',
  )

  KIND = 4

  def __init__(self):
    self.base_register = None
    self.index_register = None
    self.segment_register = None
    self.displacement = None
    self.scale = None

  @classmethod
  def parse(cls, op_str):
    orig_op_str = op_str
    op = AddressOperand()
    parts = op_str.split(":")
    if 2 == len(parts):
      op.segment_register = Register.parse(parts[0])
      op_str = parts[1]

    op_str = op_str.strip("()") \
                   .replace("(", ",") \
                   .replace(")", "")
    parts = op_str.split(",")

    # Parse the displacement.
    if parts[0][0] in "-0123456789abcdefABCDEF":
      op.displacement = int(parts[0], base=0)
      parts = parts[1:]

    # Parse or skip the base register.
    if parts:
      if parts[0]:
        op.base_register = Register.parse(parts[0])
      parts = parts[1:]

    # Parse the scale.
    if parts and parts[-1][-1] in "1248":
      op.scale = int(parts[-1], base=0)
      parts = parts[:-1]

    # Parse or skip the index register.
    if parts and parts[0]:
      op.index_register = Register.parse(parts[0])

    return op

  # Re-serialise this operand as a string in a way that can be
  # parsed again.
  def __str__(self):
    ret = ""
    if self.segment_register:
      ret += "%s:" % str(self.segment_register)
    if self.displacement is not None:
      ret += "%s0x%x" % (
        self.displacement < 0 and "-" or "", abs(self.displacement))
    ret += "("
    if self.base_register:
      ret += str(self.base_register)
    if self.index_register:
      ret += ",%s,%d" % (str(self.index_register), self.scale)
    ret += ")"
    return ret

class Instruction(object):
  """Represents an instruction."""

  __slots__ = (
    'mnemonic',
    'mnemonic_disambiguated', # Close to Intel syntax.
    'prefixes',
    'suffixes',
    'operands',
  )

  # Initialise an Instruction instance with default values.
  #
  # Note: Instruction objects should not be manually initialised.
  def __init__(self):
    self.mnemonic = None
    self.mnemonic_disambiguated = None
    self.prefixes = None
    self.suffixes = None
    self.operands = []

  # Re-serialise this instruction as a string in a way that can be
  # parsed again.
  def __str__(self):
    ret = ""
    if self.prefixes:
      ret = " ".join(self.prefixes)
    ret += " %s" % self.mnemonic
    if self.suffixes:
      ret += self.suffixes
    ret += " "
    if self.mnemonic in ("CALL", "JMP", "LCALL", "LJMP") \
    and self.operands:
      if isinstance(self.operands[0], RegisterOperand):
        ret += "*"
      elif isinstance(self.operands[0], AddressOperand) \
      and self.operands[0].is_effective_address():
        ret += "*"
    ret += ",".join(str(op) for op in self.operands)
    return ret.lower().strip()

  # Returns True iff this instruction is a control-flow instruction.
  def is_cti(self):
    if self.mnemonic.startswith("J"):
      return True
    return self.mnemonic in ("CALL", "LCALL", "RET", "LRET", "LJMP")

  # Returns True iff this instruction operates on memory.
  def accesses_memory(self):
    if self.mnemonic in ("LEA", "NOP"):
      return False
    for op in self.operands:
      if op.is_effective_address():
        return True
    return False

  # Set of instructions that implicitly change the stack pointer
  # and/or operate on stack memory.
  STACK_INSTRUCTIONS = set([
    "CALL", "LCALL",
    "RET", "LRET",
    "IRET",
    "PUSH", "POP",
    "PUSHA", "POPA",
    "PUSHF", "POPF",
  ])

  # Returns true iff an instruction operates on the stack. This
  # includes reading/writing the stack pointer, changing the stack
  # pointer, or reading/writing stack memory using the stack pointer.
  def operates_on_stack(self):
    if self.mnemonic in self.STACK_INSTRUCTIONS:
      return True
    for op in self.operands:
      if isinstance(op, RegisterOperand) \
      or isinstance(op, AddressOperand):
        if op.base_register \
        and Register.KIND_STACK == op.base_register.kind:
          return True
      if isinstance(op, AddressOperand):
        if op.index_register \
        and Register.KIND_STACK == op.index_register.kind:
          return True
    return False

  # Set of FPU register kinds.
  FPU_REGISTER_KINDS = (
    Register.KIND_X87_FPU_STACK_REG,
    Register.KIND_MMX,
    Register.KIND_SIMD,
  )

  # Returns True if this instruction uses floating point registers,
  # mmx registers, or xmm registers.
  def uses_fpu(self):
    if self.mnemonic.startswith("F"):
      return True
    for op in self.operands:
      if isinstance(op, RegisterOperand) \
      or isinstance(op, AddressOperand):
        if op.base_register \
        and op.base_register.kind in self.FPU_REGISTER_KINDS:
          return True
      if isinstance(op, AddressOperand):
        if op.index_register \
        and op.index_register.kind in self.FPU_REGISTER_KINDS:
          return True
    return False

class ASMParser(object):
  """Parses an AT&T-style x86-64 instruction as output by the `objdump`
  command-line program.

  This expects `objdump` to be invoked with the following command-line
  options:
      --disassemble
      --no-show-raw-insn
      --disassembler-options=no-aliases,att-mnemonic,addr64,suffix
      --section=.text
  """

  ADJACENT_SPACES = re.compile(r"([ \t\r\n]+)")

  PREFIXES = set([
    "REP",
    "REPE",
    "REPZ",
    "REPNE",
    "REPNZ",
    "LOCK",
    "DATA16",
    "DATA32",
    "ADDR16",
    "ADDR32",
    "REX",
    "REX.W",
    "REX.R",
    "REX.X",
    "REX.B",
    "CS",
    "SS",
    "DS",
    "ES",
    "FS",
    "GS",
  ])

  # GAS/AT&T instruction size suffixes.
  SIZE_SUFFIX = "BWLQSDT"

  # Instructions that look like that have a size suffix but don't.
  #
  # Note: This is an incomplete list.
  NO_SUFFIX = set([
    "SWAPGS", "SYSEXIT", "FWAIT", "MOVABS",
    "JB", "JNB", "JL", "JNL", "JS", "JNS",
    "CMOVB", "CMOVNB", "CMOVL", "CMOVNL", "CMOVS", "CMOVNS",

    "SETB", "SETNB", "SETL", "SETNL", "SETS", "SETNS",
    "NOT", "SHL", "SAL", "ADD", "MUL", "IMUL", "BTS", "AND", "TEST", "BT",
    "MOVZ", "MOVSS",
    "INS", "MOVS", "OUTS", "LODS", "STOS", "CMPS", "SCAS",
    "LIDT", "SIDT", "LGDT", "SGDT", "HLT", "RDRAND",
    "MWAIT",

    "STD", "CLD", "SBB",

    "FCOS", "FMUL", "FXTRACT",
  ])

  # String instructions.
  STRING_OPS = set([
    "INS", "MOVS", "OUTS", "LODS", "STOS", "CMPS", "SCAS",
  ])

  # Valid registers that can appear in a string instruction.
  STRING_REGS = set(
      Register.parse("%rdi").children \
    | Register.parse("%rsi").children \
    | Register.parse("%rax").children
  )

  # Sign- and zero-extension MOV.
  MULTI_SIZED_INSTRUCTIONS = re.compile(r"^(MOVS|MOVZ)")

  # Regular expressions for matching split points in operand strings.
  COMMA_BEFORE_BASE_DISP = re.compile(
      r",(([%][a-zA-Z]+[:])*[0-9a-fA-FxX-]*[(])")
  COMMA_AFTER_BASE_DISP = re.compile(r"[)],")
  COMMA_AFTER_IMMED_OR_ADDR = re.compile(
      r"^(([%][a-zA-Z]+[:])?[$-]?[0-9a-fA-FxX]+),")
  COMMA_BEFORE_REG = re.compile(r",([%][a-zA-Z0-9]+)$")
  COMMA_AFTER_REG = re.compile(r"^([%][a-zA-Z0-9]+),")

  # Translate debug registers to a canonical naming scheme.
  DEBUG_REG = re.compile(r"[%]db")

  # Translate FPU stack registers to a canonical naming scheme.
  ST_REG = re.compile(r"[%]st\(([0-9]+)\)")

  # A "useless" encoding where a scale is used with a known zero index.
  ZERO_INDEX_REG = re.compile(r",[%](riz|RIZ),[01248]\)")

  # Initialise an ASM Parser.
  #
  # Args:
  #   instruction_visitor: A function that is called for each parsed
  #                        instruction.
  def __init__(self, instruction_visitor):
    self.instruction_visitor = instruction_visitor

  # Parse an iterable of lines, where some lines potentially contain
  # instructions in the AT&T syntax.
  #
  # Args:
  #   lines:          An iterable of strings, where each string represents
  #                   a line with no more than one instruction.
  def parse(self, lines):
    i = 1
    for line in lines:
      self._parse_line(i, line)
      i += 1

  # Returns True if this instruction is an invalid string instruction.
  # This can come up in some binaries where invalid registers are used
  # in some of the string instructions.
  def _uses_invalid_regs(self, mnemonic, ops):
    valid_regs = None
    if mnemonic in self.STRING_OPS:
      valid_regs = self.STRING_REGS
    elif "XLAT" == mnemonic:
      valid_regs = Register.parse("%rbx").children
    else:
      return False

    for op in ops:
      if isinstance(op, AddressOperand) \
      or isinstance(op, RegisterOperand):
        if op.base_register and op.base_register not in valid_regs:
          return True

      if isinstance(op, AddressOperand):
        if op.index_register and op.index_register not in valid_regs:
          return True
    return False

  # Parse a single line of output from `objdump` and try to extract a
  # single instruction.
  #
  # Args:
  #   line:           A string containing zero or one instructions.
  def _parse_line(self, line_num, line):
    orig_line = line

    if "<internal disassembler error>" in line:
      return

    line = line + " "
    line = line[:line.find("<")]
    line = line + " "
    line = line[:line.find("#")]
    line = line.strip(" \t\r\n;")

    # Try to root out disassembly errors or function names.
    if not line \
    or line.endswith(":") \
    or ":" not in line \
    or line.startswith("/") \
    or line.startswith(".") \
    or "file format" in line \
    or "(bad)" in line \
    or ",pt" in line \
    or "%?" in line:
      return

    # Drop the leading binary offset, and deal with spaces.
    line = ":".join(line.split(":")[1:])
    line = line.lstrip(" \r\n\t")
    line = self.ADJACENT_SPACES.sub(" ", line)

    # Split the instruction into its constituent parts.
    ins = Instruction()
    line = line.replace(", ", ",")
    parts = line.split(" ")

    # Extract the instruction prefixes.
    i = 0
    prefixes = []
    for part in map(str.upper, parts):
      if "REX." in part or part in self.PREFIXES:
        prefixes.append(part)
        i += 1
      else:
        break

    # Prefixes or empty.
    if i >= len(parts):
      return

    mnemonic = parts[i].upper()
    op_strs = "".join(parts[i+1:]).lower()

    # Extract the instruction suffixes.
    suffixes = ""
    if "." in mnemonic:
      mnemonic, suffix = mnemonic.split(".")
      if suffix:
        suffixes = ".%s" % suffix

    # Get the mnemonic and the operand size suffix.
    #
    # Note: Some operands have two size suffixes; however, we won't
    #       deal with those just yet.
    while mnemonic not in self.NO_SUFFIX \
    and mnemonic[-1] in self.SIZE_SUFFIX:
      suffixes = "%s%s" % (mnemonic[-1], suffixes)
      mnemonic = mnemonic[:-1]
      if not self.MULTI_SIZED_INSTRUCTIONS.match(mnemonic):
        break

    ins.mnemonic = mnemonic
    ins.prefixes = tuple(prefixes)
    if suffixes:
      ins.suffixes = suffixes

    # Uses Intel mnemonics for disambiguating some instructions.
    ins.mnemonic_disambiguated = ins.mnemonic
    if ins.mnemonic == "MOVS" and suffixes and 2 <= len(suffixes):
      ins.mnemonic_disambiguated = "MOVSX"
    elif ins.mnemonic == "MOVZ":
      ins.mnemonic_disambiguated = "MOVZX"

    # Parse the operands. First they need to be reasonably split up.
    op_strs = self.ST_REG.sub(r"%st\1", op_strs)
    op_strs = op_strs.replace("st0", "st")
    op_strs = self.DEBUG_REG.sub("%dr", op_strs)
    op_strs = self.ZERO_INDEX_REG.sub(")", op_strs)
    op_strs = self.COMMA_BEFORE_BASE_DISP.sub(r"|\1", op_strs)
    op_strs = self.COMMA_AFTER_BASE_DISP.sub(r")|", op_strs)
    op_strs = self.COMMA_AFTER_IMMED_OR_ADDR.sub(r"\1|", op_strs)
    op_strs = self.COMMA_BEFORE_REG.sub(r"|\1", op_strs)
    op_strs = self.COMMA_AFTER_REG.sub(r"\1|", op_strs)

    if op_strs:
      ins.operands = tuple(map(
          lambda s: Operand.parse(mnemonic, s),
          op_strs.split("|")))

    # Detect some invalid instructions by their use of the improper
    # registers.
    if self._uses_invalid_regs(mnemonic, ins.operands):
      return

    # Visit the parsed instruction.
    self.instruction_visitor(ins)

if __name__ == "__main__":
  import sys

  parser = ASMParser(lambda ins: None)
  with open(sys.argv[1], "r") as lines:
    parser.parse(lines)


text:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Historial_movimientos extends CI_Controller {

  public function __construct() {
    parent::__construct();
    if($this->session->userdata('logged_in') == FALSE){
      redirect('login/index/error_no_autenticado');
    }
    $this->load->helper(array('form', 'paginacion'));
    $this->load->library('table');
    $this->load->model(array('ActivoFijo/Movimiento_Model'));
  }

  public function index(){
    $data['title'] = "Detalle Movimiento";
    $msg = array('alert' => $this->uri->segment(5),'controller'=>'Historial_movimientos');
		$data['body'] = $this->load->view('mensajes', $msg, TRUE) . $this->load->view('ActivoFijo/Reportes/Historial_movimientos_view',$msg,TRUE) .
                    "

" .
                    "
Historial Movimientos
".
                    "
" . $this->mostrarTabla()."
";
    $data['menu'] = $this->menu_dinamico->menus($this->session->userdata('logged_in'),$this->uri->segment(1));
    $this->load->view('base', $data);
	}

  public function mostrarTabla(){
    /*
    * Configuracion de la tabla
    */

    $template = array(
        'table_open' => '
'
    );
    $this->table->set_template($template);
    $this->table->set_heading('Id movimiento','Almacen','Sección', 'Oficina','Empleado','Fecha','Tipo de movimiento');

    /*
    * Filtro a la BD
    */

    /*Obtiene el numero de registros a mostrar por pagina */
    $num = '10';
    $pagination = '';
    $registros;
    if ($this->input->is_ajax_request()) {
          $registros = $this->Movimiento_Model->obtenerMovimientosLimitId($num, $this->uri->segment(6),$this->uri->segment(5));
          $pagination = paginacion('index.php/ActivoFijo/Reportes/Historial_movimientos/index/'.$this->uri->segment(5), $this->Movimiento_Model->totalMovimientosDetalle($this->uri->segment(5)),
                        $num, '6');
    } else {
          $registros = $this->Movimiento_Model->obtenerMovimientosLimitId($num, $this->uri->segment(6),$this->uri->segment(5));
          $pagination = paginacion('index.php/ActivoFijo/Reportes/Historial_movimientos/index/'.$this->uri->segment(5), $this->Movimiento_Model->totalMovimientosDetalle($this->uri->segment(5)),
                        $num, '6');
    }
    /*
    * llena la tabla con los datos consultados
    */

    if (!($registros == FALSE)) {
      foreach($registros as $det) {
          $this->table->add_row($det->id_movimiento, $det->nombre_almacen,$det->nombre_seccion,$det->nombre_oficina,
          $det->primer_nombre.' '.$det->segundo_nombre.' '.$det->primer_apellido.' '.$det->segundo_apellido,
          $det->fecha_guarda,$det->nombre_movimiento);
      }
    } else {
      $msg = array('data' => "Texto no encontrado", 'colspan' => "7");
      $this->table->add_row($msg);
    }
    /*
    * vuelve a verificar para mostrar los datos
    */
    if ($this->input->is_ajax_request()) {
      echo $this->table->generate() . $pagination;
    } else {
      return $this->table->generate() . $pagination;
    }
  }
}
?>

redpajama_set_name: RedPajamaGithub


text:
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/image_decoder/image_decoder.h"

#include "base/macros.h"
#include "base/run_loop.h"
#include "build/build_config.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "content/public/browser/browser_child_process_observer.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_utils.h"
#include "ui/base/l10n/l10n_util.h"

using content::BrowserThread;

namespace {

std::vector<uint8_t> GetValidPngData() {
  // 1x1 PNG. Does not get much smaller than this.
  static const char kPngData[] =
      "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52"
      "\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90\x77\x53"
      "\xde\x00\x00\x00\x0c\x49\x44\x41\x54\x08\xd7\x63\xf8\xff\xff\x3f"
      "\x00\x05\xfe\x02\xfe\xdc\xcc\x59\xe7\x00\x00\x00\x00\x49\x45\x4e"
      "\x44\xae\x42\x60\x82";
  // Need to specify the buffer size because it contains NULs.
  return std::vector<uint8_t>(kPngData, kPngData + sizeof(kPngData) - 1);
}

std::vector<uint8_t> GetValidJpgData() {
  // 1x1 JPG created from the 1x1 PNG above.
  static const char kJpgData[] =
      "\xFF\xD8\xFF\xE0\x00\x10\x4A\x46\x49\x46\x00\x01\x01\x01\x00\x48"
      "\x00\x48\x00\x00\xFF\xDB\x00\x43\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
      "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
      "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
      "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
      "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xDB\x00\x43\x01\xFF\xFF"
      "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
      "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
      "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
      "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC0"
      "\x00\x11\x08\x00\x01\x00\x01\x03\x01\x22\x00\x02\x11\x01\x03\x11"
      "\x01\xFF\xC4\x00\x15\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00"
      "\x00\x00\x00\x00\x00\x00\x00\x03\xFF\xC4\x00\x14\x10\x01\x00\x00"
      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xC4"
      "\x00\x14\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
      "\x00\x00\x00\x00\xFF\xC4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00"
      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xDA\x00\x0C\x03\x01"
      "\x00\x02\x11\x03\x11\x00\x3F\x00\xA0\x00\xFF\xD9";
  // Need to specify the buffer size because it contains NULs.
  return std::vector<uint8_t>(kJpgData, kJpgData + sizeof(kJpgData) - 1);
}

class TestImageRequest : public ImageDecoder::ImageRequest {
 public:
  explicit TestImageRequest(base::OnceClosure quit_closure)
      : decode_succeeded_(false),
        quit_closure_(std::move(quit_closure)),
        quit_called_(false) {}

  ~TestImageRequest() override {
    if (!quit_called_) {
      std::move(quit_closure_).Run();
    }
  }

  bool decode_succeeded() const { return decode_succeeded_; }

  const SkBitmap& get_bitmap() const { return bitmap_; }

 private:
  void OnImageDecoded(const SkBitmap& decoded_image) override {
    decode_succeeded_ = true;
    bitmap_ = decoded_image;
    Quit();
  }

  void OnDecodeImageFailed() override { Quit(); }

  void Quit() {
    EXPECT_FALSE(quit_called_);
    quit_called_ = true;
    std::move(quit_closure_).Run();
  }

  bool decode_succeeded_;

  base::OnceClosure quit_closure_;
  bool quit_called_;
  SkBitmap bitmap_;

  DISALLOW_COPY_AND_ASSIGN(TestImageRequest);
};

}  // namespace

class ImageDecoderBrowserTest : public InProcessBrowserTest {};

IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, Basic) {
  base::RunLoop run_loop;
  TestImageRequest test_request(run_loop.QuitClosure());
  ImageDecoder::Start(&test_request, std::vector<uint8_t>());
  run_loop.Run();
  EXPECT_FALSE(test_request.decode_succeeded());
}

#if defined(OS_CHROMEOS)

IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, BasicDecodeWithOptionsString) {
  base::RunLoop run_loop;
  TestImageRequest test_request(run_loop.QuitClosure());
  const std::vector<uint8_t> data = GetValidPngData();
  ImageDecoder::StartWithOptions(&test_request,
                                 std::string(data.begin(), data.end()),
                                 ImageDecoder::ROBUST_PNG_CODEC,
                                 /*shrink_to_fit=*/false);
  run_loop.Run();
  EXPECT_TRUE(test_request.decode_succeeded());
}

IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, RobustJpegCodecWithJpegData) {
  base::RunLoop run_loop;
  TestImageRequest test_request(run_loop.QuitClosure());
  ImageDecoder::StartWithOptions(
      &test_request, GetValidJpgData(), ImageDecoder::DEFAULT_CODEC,
      /*shrink_to_fit=*/false, /*desired_image_frame_size=*/gfx::Size());
  run_loop.Run();
  EXPECT_TRUE(test_request.decode_succeeded());
}

IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, RobustPngCodecWithPngData) {
  base::RunLoop run_loop;
  TestImageRequest test_request(run_loop.QuitClosure());
  ImageDecoder::StartWithOptions(
      &test_request, GetValidPngData(), ImageDecoder::ROBUST_PNG_CODEC,
      /*shrink_to_fit=*/false, /*desired_image_frame_size=*/gfx::Size());
  run_loop.Run();
  EXPECT_TRUE(test_request.decode_succeeded());
}

IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, RobustPngCodecWithJpegData) {
  base::RunLoop run_loop;
  TestImageRequest test_request(run_loop.QuitClosure());
  ImageDecoder::StartWithOptions(
      &test_request, GetValidJpgData(), ImageDecoder::ROBUST_PNG_CODEC,
      /*shrink_to_fit=*/false, /*desired_image_frame_size=*/gfx::Size());
  run_loop.Run();
  // Should fail with JPEG data because only PNG data is allowed.
  EXPECT_FALSE(test_request.decode_succeeded());
}

#endif  // defined(OS_CHROMEOS)

IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, BasicDecode) {
  base::RunLoop run_loop;
  TestImageRequest test_request(run_loop.QuitClosure());
  ImageDecoder::Start(&test_request, GetValidPngData());
  run_loop.Run();
  EXPECT_TRUE(test_request.decode_succeeded());
}

IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, BasicDecodeString) {
  base::RunLoop run_loop;
  TestImageRequest test_request(run_loop.QuitClosure());
  const std::vector<uint8_t> data = GetValidPngData();
  ImageDecoder::Start(&test_request, std::string(data.begin(), data.end()));
  run_loop.Run();
  EXPECT_TRUE(test_request.decode_succeeded());
  EXPECT_EQ(test_request.get_bitmap().height(), 1);
  EXPECT_EQ(test_request.get_bitmap().width(), 1);
  EXPECT_EQ(test_request.get_bitmap().getColor(0, 0), 0xffffffffUL);
}

IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, BasicDecodeStringJpeg) {
  base::RunLoop run_loop;
  TestImageRequest test_request(run_loop.QuitClosure());
  const std::vector<uint8_t> data = GetValidJpgData();
  ImageDecoder::Start(&test_request, std::string(data.begin(), data.end()));
  run_loop.Run();
  EXPECT_TRUE(test_request.decode_succeeded());
  EXPECT_EQ(test_request.get_bitmap().height(), 1);
  EXPECT_EQ(test_request.get_bitmap().width(), 1);
  EXPECT_EQ(test_request.get_bitmap().getColor(0, 0), 0xffffffffUL);
}

IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, StartAndDestroy) {
  base::RunLoop run_loop;
  std::unique_ptr<TestImageRequest> test_request(
      new TestImageRequest(run_loop.QuitClosure()));
  ImageDecoder::Start(test_request.get(), std::vector<uint8_t>());
  test_request.reset();
  run_loop.Run();
}


text:
package dev.jeka.core.tool;

import dev.jeka.core.api.depmanagement.resolution.JkDependencyResolver;
import dev.jeka.core.api.file.JkPathSequence;
import dev.jeka.core.api.system.JkLog;
import dev.jeka.core.api.utils.JkUtilsAssert;
import dev.jeka.core.api.utils.JkUtilsIterable;
import dev.jeka.core.api.utils.JkUtilsReflect;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Container where is registered the KBeans for a given project.
 * In multi-project builds, there is one JkRuntime per project.
 */
public final class JkRuntime {

    private static final ThreadLocal<Path> BASE_DIR_CONTEXT = new ThreadLocal<>();   //NOSONAR

    private static final Map<Path, JkRuntime> RUNTIMES = new LinkedHashMap<>();

    private final Path projectBaseDir;

    private JkDependencyResolver dependencyResolver;

    private JkPathSequence classpath;

    private JkPathSequence importedProjects;

    private List<EngineCommand> fieldInjections = Collections.emptyList();

    private final Map<Class<? extends JkBean>, JkBean> beans = new LinkedHashMap<>();

    private JkRuntime(Path projectBaseDir) {
        this.projectBaseDir = projectBaseDir;
    }

    public static JkRuntime get(Path projectBaseDir) {
        return RUNTIMES.computeIfAbsent(projectBaseDir, path -> new JkRuntime(path));
    }

    static JkRuntime getCurrentContextBaseDir() {
        return get(getBaseDirContext());
    }

    static void setBaseDirContext(Path baseDir) {
        JkUtilsAssert.argument(baseDir == null || Files.exists(baseDir),"Project " + baseDir + " not found.");
        BASE_DIR_CONTEXT.set(baseDir);
    }

    private static Path getBaseDirContext() {
        return Optional.ofNullable(BASE_DIR_CONTEXT.get()).orElseGet(() -> {
            setBaseDirContext(Paths.get(""));
            return BASE_DIR_CONTEXT.get();
        });
    }

    Path getProjectBaseDir() {
        return projectBaseDir;
    }

    /**
     * Returns the dependency resolver used to fetch 3rd party build dependencies.
     */
    public JkDependencyResolver getDependencyResolver() {
        return dependencyResolver;
    }

    /**
     * Returns the classpath used to compile def classes.
     */
    public JkPathSequence getClasspath() {
        return classpath;
    }

    /**
     * Returns root path of imported projects.
     */
    public JkPathSequence getImportedProjects() {
        return importedProjects;
    }

    /**
     * Returns the plugin instance of the specified class loaded in the holding JkClass instance. If it does not hold
     * a plugin of the specified class at call time, the plugin is loaded then returned.
     */
    public <T extends JkBean> T getBean(Class<T> jkBeanClass) {
        JkUtilsAssert.argument(jkBeanClass != null, "KBean class cannot be null.");
        JkBean result = beans.get(jkBeanClass);
        if (result == null) {
            JkLog.startTask("Instantiate KBean " + jkBeanClass + " in project '" + projectBaseDir + "'");
            Path previousProject = BASE_DIR_CONTEXT.get();
            BASE_DIR_CONTEXT.set(projectBaseDir);  // without this, projects nested with more than 1 level failed to get proper base dir
            result = this.instantiate(jkBeanClass);
            BASE_DIR_CONTEXT.set(previousProject);
            JkLog.endTask();
            beans.put(jkBeanClass, result);
        }
        return (T) result;
    }

    public <T extends JkBean> Optional<T> getBeanOptional(Class<T> jkBeanClass) {
        return (Optional<T>) Optional.ofNullable(beans.get(jkBeanClass));
    }

    /**
     * Returns the list of registered KBeans. A KBean is registered when it has been identified as the default KBean or
     * when {@link #getBean(Class)} is invoked.
     */
    public List<JkBean> getBeans() {
        return new LinkedList<>(beans.values());
    }

    void setDependencyResolver(JkDependencyResolver resolverArg) {
        dependencyResolver = resolverArg;
    }

    void setClasspath(JkPathSequence pathSequence) {
        this.classpath = pathSequence;
    }

    void setImportedProjects(JkPathSequence importedProjects) {
        this.importedProjects = importedProjects;
    }

    void init(List<EngineCommand> commands) {
        JkLog.trace("Initialize JkRuntime with " + commands);
        this.fieldInjections = commands.stream()
                .filter(engineCommand -> engineCommand.getAction() == EngineCommand.Action.PROPERTY_INJECT)
                .collect(Collectors.toList());

        // Instantiate & register beans
        JkLog.startTask("Register KBeans");
        List<? extends JkBean> beans = commands.stream()
                //.filter(engineCommand -> engineCommand.getAction() != EngineCommand.Action.PROPERTY_INJECT)
                .map(EngineCommand::getBeanClass)
                .distinct()
                .map(this::getBean)
                .collect(Collectors.toList());
        JkLog.endTask();
    }

    void run(List<EngineCommand> commands) {
        for (EngineCommand engineCommand : commands) {
            JkBean bean = getBean(engineCommand.getBeanClass());
            if (engineCommand.getAction() == EngineCommand.Action.METHOD_INVOKE) {
                Method method;
                try {
                    method = bean.getClass().getMethod(engineCommand.getMember());
                } catch (NoSuchMethodException e) {
                    throw new JkException("No public no-args method '" + engineCommand.getMember() + "' found on KBean "
                            + bean.getClass());
                }
                JkUtilsReflect.invoke(bean, method);
            }
        }
    }

    private JkBean instantiate(Class<? extends JkBean> beanClass) {
        if (Modifier.isAbstract(beanClass.getModifiers())) {
            throw new JkException("KBean class " + beanClass + " in " + this.projectBaseDir
                    + " is abstract and therefore cannot be instantiated. Please, use a concrete type to declare imported KBeans.");
        }
        JkBean bean = JkUtilsReflect.newInstance(beanClass);
        fieldInjections.stream()
                .filter(engineCommand -> engineCommand.getAction() == EngineCommand.Action.PROPERTY_INJECT)
                .filter(engineCommand -> engineCommand.getBeanClass().equals(bean.getClass()))
                .forEach(action -> {
                    Set<String> injectedProp =
                            FieldInjector.inject(bean, JkUtilsIterable.mapOf(action.getMember(), action.getValue()));
                    if (injectedProp.isEmpty()) {
                        throw new JkException("Field %s does not exist in KBean %s", injectedProp, bean);
                    }
                });
        FieldInjector.injectAnnotatedProperties(bean);
        return bean;
    }

    @Override
    public String toString() {
        return "JkRuntime{" +
                "projectBaseDir=" + projectBaseDir +
                ", beans=" + beans.keySet() +
                '}';
    }

}


text:
//
// FastTemplate
//
// The MIT License (MIT)
//
// Copyright (c) 2014 Jeff Panici

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

using System;
using System.IO;
using System.Reflection;
using System.Text;

namespace PaniciSoftware.FastTemplate.Compiler
{
    public abstract class Instruction
    {
        public abstract byte Type { get; }

        public abstract void Emit(AssemblyContext c);

        public abstract void WriteTo(BinaryWriter s);

        public abstract void ReadFrom(BinaryReader s);

        protected static void WriteType(Type t, BinaryWriter w)
        {
            var name = t.AssemblyQualifiedName;
            WriteString(name, w);
        }

        protected static void WriteString(string s, BinaryWriter w)
        {
            var buffer = Encoding.UTF8.GetBytes(s);
            w.Write(buffer.Length);
            w.Write(buffer);
        }

        protected static void WriteCtorInfo(ConstructorInfo i, BinaryWriter w)
        {
            var type = i.DeclaringType;
            var parameters = i.GetParameters();
            WriteType(type, w);
            var count = parameters.Length;
            w.Write(count);
            foreach (var p in parameters)
                WriteType(p.ParameterType, w);
        }

        protected static void WriteFieldInfo(FieldInfo i, BinaryWriter w)
        {
            var type = i.DeclaringType;
            var name = i.Name;
            WriteType(type, w);
            WriteString(name, w);
        }

        protected static void WriteMethodInfo(MethodInfo i, BinaryWriter w)
        {
            var type = i.DeclaringType;
            var name = i.Name;
            WriteType(type, w);
            WriteString(name, w);
        }

        protected static Type ReadType(BinaryReader w)
        {
            var name = ReadString(w);
            return System.Type.GetType(name);
        }

        protected static string ReadString(BinaryReader w)
        {
            var size = w.ReadInt32();
            var buffer = new byte[size];
            w.Read(buffer, 0, size);
            return Encoding.UTF8.GetString(buffer);
        }

        protected static ConstructorInfo ReadCtorInfo(BinaryReader w)
        {
            var type = ReadType(w);
            var count = w.ReadInt32();
            var args = new Type[count];
            for (var i = 0; i < count; i++)
            {
                args[i] = ReadType(w);
            }
            var ctor = type.GetConstructor(args);
            return ctor;
        }

        protected static FieldInfo ReadFieldInfo(BinaryReader w)
        {
            var type = ReadType(w);
            var name = ReadString(w);
            return type.GetField(name, BindingFlags.NonPublic | BindingFlags.Instance);
        }

        protected static MethodInfo ReadMethodInfo(BinaryReader w, uint flags)
        {
            var type = ReadType(w);
            var name = ReadString(w);
            return type.GetMethod(name, (BindingFlags) flags);
        }
    }
}


text:
void ResolveTypes( dab_Function & fun )
{
	fun.node->updateType();
}

void BuildFunctions( dab_Function & fun )
{
	fun.node->func = new qneu_Function(fun.node);
}


text:
using Ebboy.Core.Domain.OAuths;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration;

namespace Ebboy.Data.Models.Mapping
{
    public class OAuthNonceMap : EntityTypeConfiguration<OAuthNonce>
    {
        public OAuthNonceMap()
        {
            // Primary Key
            this.HasKey(t => t.Id);

            // Properties
            this.Property(t => t.Context)
                .IsRequired()
                .HasMaxLength(50);

            this.Property(t => t.Code)
                .IsRequired()
                .HasMaxLength(128);

            // Table & Column Mappings
            this.ToTable("OAuthNonces");
            this.Property(t => t.Id).HasColumnName("Id");
            this.Property(t => t.Context).HasColumnName("Context");
            this.Property(t => t.Code).HasColumnName("Code");
            this.Property(t => t.Timestamp).HasColumnName("Timestamp");
        }
    }
}


text:
"""85. Maximal Rectangle
https://leetcode.com/problems/maximal-rectangle/

Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle
containing only 1's and return its area.

Example:

Input:
[
 ["1","0","1","0","0"],
 ["1","0","1","1","1"],
 ["1","1","1","1","1"],
 ["1","0","0","1","0"]
]
Output: 6
"""
from typing import List

class Solution:
    def maximal_rectangle(self, matrix: List[List[str]]) -> int:
        """
        Time complexity O(N^2)
        """
        if not matrix or not matrix[0]:
            return 0
        rows, cols = len(matrix), len(matrix[0])
        heights = [0] * (cols + 1)
        max_area = 0
        for row in range(rows):
            stack = []
            for col in range(cols + 1):
                if col < cols and matrix[row][col] == "1":
                    heights[col] += 1
                else:
                    heights[col] = 0
                while stack and heights[stack[-1]] >= heights[col]:
                    height = heights[stack.pop()]
                    width = col - stack[-1] - 1 if stack else col
                    cur_area = height * width
                    max_area = max(max_area, cur_area)
                stack.append(col)
        return max_area


text:
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>

<title>TEST_STDC</title>
<meta name='robots' content='noindex,nofollow' />
<meta name='generator' content='GLOBAL-6.5.2' />
<meta http-equiv='Content-Style-Type' content='text/css' />
<link rel='stylesheet' type='text/css' href='../style.css' />

TEST_STDC          20 test/test.c    #ifdef TEST_STDC
TEST_STDC         234 test/test.c    #ifdef TEST_STDC
TEST_STDC         348 test/test.h    #ifdef TEST_STDC


text:
using System;
using System.Collections.Generic;

namespace MicrosoftGraph.Model
{
    /// <summary>
    /// Person Search Response
    /// </summary>
    [Serializable]
    public class PersonSearchResponse
    {
        /// <summary>
        /// List of users
        /// </summary>
        public  List<Person> Value { get; set; }

    }
}


text:
"use strict";

var helpers = require("app/client/views/helpers");
var presenter = require("app/client/views/presenter");
var BaseView = require("app/client/views/base_view");

var agg_is = helpers.agg_is;

var DrillView = BaseView.extend({
  baseview: helpers.VIEWS.TABLE,
  render: function() {

    var tabEl = this.$el;
    var tableEl = this.render_table();
    var chartEl = $("
");
    var tabs = {
      Overview: chartEl,
      Details: tableEl
    };

    var self = this;
    var not_rendered = true;
    $C("tabs", { tabs: tabs, active: "Overview" } , function(cmp) {
      tabEl.prepend(cmp.$el);

      var graphEl = self.render_charts();
      cmp.getTab("Overview").append(graphEl);
    });
  },

  render_charts: function() {
    var chartEl = $("
");
    var categories = [];
    var series = [];
    var chart_values = [];
    var compare_values = [];
    var delta_values = [];
    var movements = this.movements;

    var self = this;
    var dataset = self.table;
    var samplesEl = $("
");
    var first_col = _.first(_.keys(self.data));
    samplesEl.html("samples: " + self.data[first_col].count);
    if (this.compare_data) {
      samplesEl.html("samples: " +
        this.compare_data[first_col].count + " -> " +
        this.data[first_col].count);
    }

    var avgEl = $("
");
    var col_aggs = presenter.get_col_aggs(this.table, this.parsed);
    _.each(col_aggs, function(col) {
      var field = presenter.extract_field(col) || col;
      var curAvgEl = $("
");
      var formatter = presenter.get_field_formatter(dataset, field);
      curAvgEl.html(col + ": "  + formatter(self.data[col].avg));
      if (self.compare_data) {
        curAvgEl.html(col + ": " +
          formatter(self.compare_data[col].greater).html() + " -> " +
          formatter(self.data[col].greater).html());
      }

      avgEl.append(curAvgEl);
    });

    chartEl.append(samplesEl);
    chartEl.append(avgEl);

    var ordered_groups;
    if (!_.isEmpty(movements)) {
      ordered_groups = _.sortBy(_.keys(this.movements), function(key) {
        return -Math.abs(movements[key]);
      });
    }

    _.each(this.data, function(stats, col) {
      ordered_groups = ordered_groups || _.keys(stats.diffs);

      _.each(ordered_groups, function(group) {
        chart_values.push({
          name: group,
          y: (stats.diffs[group] * 100)
        });
      });

    });

    _.each(this.compare_data, function(stats, col) {
      _.each(ordered_groups, function(group) {
        compare_values.push({
          name: group,
          y: (stats.diffs[group] * 100)
        });
      });
    });

    _.each(ordered_groups, function(group) {
      delta_values.push({
        name : group,
        y : movements[group]
      });
    });

    function make_chart(values, title) {
      _.each(values, function(f) {
        f.y = parseInt((f.y||0) * 100, 10) / 100;
        f.color = f.y >= 0 ? helpers.get_color("positive") : helpers.get_color("negative");
      });

      var only_values = _.map(values, function(f) { return f.y || 0; });
      var el = $("
");
      el.css('height', 400);
      var options = {
        height: "400px",
        chart: {
          type: 'bar'
        },
        xAxis: {
          categories: _.map(values, function(f) { return f.name; })
        },
        yAxis: {
          gridLineWidth: 1,
          min: _.min(only_values) - 5,
          max: _.max(only_values) + 5
        },
        tooltip: {
          valueSuffix: '%',
          shared: true
        },

        series: [{
          data: values,
          type: 'column',
          name: title
        }]
      };

      $C(self.graph_component, {skip_client_init: true}, function(cmp) {
        el
          .append(cmp.$el)
          .show();

        // There's a little setup cost to highcharts, maybe?
        cmp.client(options);

      });

      return el;
    }

    if (compare_values.length) {
      chartEl.append($("
").html("Delta Impact breakdown"));
      chartEl.append(make_chart(delta_values, 'impact'));

      chartEl.append($("
").html("After Query breakdown"));
      chartEl.append(make_chart(compare_values, 'impact'));
    }

    chartEl.append($("
").html("Before Query breakdown"));
    chartEl.append(make_chart(chart_values, 'impact'));

    return chartEl;
  },

  render_table: function() {
    var headers = ["", "samples"];
    var rows = {
      "total" : ["total"]
    };
    var compare_rows = {
      "total" : ["total"]
    };
    var dataset = this.table;
    var data = this.data;
    var compare_data = this.compare_data;
    var $el = $("
");
    var self = this;
    var agg = self.query.parsed.agg;

    _.each(data, function(stats, col) {
      var agg = presenter.extract_agg(col);
      headers = headers.concat(
        _.map([ col + " AGG", "AGG without row", "delta", "delta / AGG"],
          function(r) { return r.replace("AGG", agg); })
        );

      var formatter = presenter.get_field_formatter(dataset, col);

      var compare_stats;
      if (compare_data) {
        compare_stats = compare_data[col];
      }

      function gen_el(rows, stats, diff, group) {
        var el = "";
        if (rows.total.length === 1) {
          rows.total.push(helpers.count_format(stats.count));
        }

        if (!rows[group]) {
          rows[group] = [group, helpers.count_format(stats.counts[group])];
        }

        if (agg_is(agg, "avg")) {
          rows[group].push(formatter(stats.values[group]));
        } else if (agg_is(agg, "count")) {
          rows[group].push(formatter(stats.counts[group]));
        } else if (agg_is(agg, "sum")) {
          rows[group].push(formatter(stats.values[group]));
        }

        rows[group].push(stats.deltas[group].toFixed(2));
        rows[group].push((stats.greater - stats.deltas[group]).toFixed(2));
        rows[group].push(diff.toFixed(4));
      }

      _.each(stats.diffs, function(diff, group) {
        gen_el(rows, stats, diff, group);

      });

      if (compare_data) {
        _.each(compare_stats.diffs, function(diff, group) {
          gen_el(compare_rows, compare_stats, diff, group);

        });
        compare_rows.total.push(compare_stats.greater.toFixed(2));

        compare_rows.total.push("");
        compare_rows.total.push("");
        compare_rows.total.push("");
      }

      rows.total.push(stats.greater.toFixed(2));

      rows.total.push("");
      rows.total.push("");
      rows.total.push("");
    });

    rows = _.sortBy(_.values(rows), function(row) {
      return -Math.abs(parseFloat(row[4]));
    });
    compare_rows = _.sortBy(_.values(compare_rows), function(row) {
      return -Math.abs(parseFloat(row[4]));
    });
    var table = helpers.build_table(dataset, headers, rows);
    var compare_table = helpers.build_table(dataset, headers, compare_rows);

    $el.append($("
after
"));
    $el.append(table);

    var movements = {};
    this.movements = movements;

    if (compare_data) {
      $el.append($("
before
"));
      $el.append(compare_table);

      var delta_rows = {};

      var delta_headers = ["", "samples"];
      _.each(compare_data, function(stats, col) {
        var agg = presenter.extract_agg(col);

        delta_headers = delta_headers.concat(
          _.map([ "change in " + col, "new AGG with old row", "delta from real AGG", "impact"],
            function(r) { return r.replace("AGG", agg); })
          );

        _.each(_.keys(self.groups), function(group) {
          var new_data = data[col];

          var subtracted, addtracted, delta, frac;
          var old_val, new_val;

          if (agg_is(agg, "avg")) {
            subtracted = new_data.total - ((new_data.counts[group] || 0) * (new_data.values[group] || 0));
            addtracted = subtracted + ((stats.counts[group] || 0) * (stats.values[group]||0));
            new_val = addtracted / ((new_data.minus_counts[group] || new_data.count) + (stats.counts[group] || 0));

            old_val = new_data.avg;
          } else if (agg_is(agg, "sum")) {
            subtracted = new_data.total - (new_data.values[group] || 0);
            new_val = subtracted + (stats.values[group]||0);
            old_val = new_data.total;

          } else {
            subtracted = new_data.count - (new_data.counts[group] || 0);
            old_val = new_data.count;
            new_val = subtracted + (stats.counts[group] || 0);
          }

          delta = old_val- new_val;
          frac = delta / old_val * 100;

          if (!delta_rows[group]) {
            delta_rows[group] = [ group, helpers.count_format((stats.counts[group] || 0)) + "->" +
              helpers.count_format((new_data.counts[group] || 0))];
          }

          delta_rows[group].push((stats.values[group]||0).toFixed(2) + "->" +
            (new_data.values[group] || 0).toFixed(2));

          delta_rows[group].push(new_val.toFixed(2));
          delta_rows[group].push((old_val - new_val).toFixed(2));
          delta_rows[group].push(frac.toFixed(2) + "%");

          movements[group] = frac;
        });

      });

      delta_rows = _.sortBy(_.values(delta_rows), function(row) {
        return -Math.abs(parseFloat(row[4]));
      });

      var other_table = helpers.build_table(dataset, delta_headers, _.values(delta_rows));
      $el.prepend(other_table);
      $el.prepend($("
delta & impact
"));
    }

    return $el;
  },

  prepare: function(data) {
    var ret = {};
    var self = this;
    self.groups = self.groups || {};
    self.parsed = data.parsed;
    var custom_fields = data.parsed.custom_fields;

    var agg = data.parsed.agg;
    var cols = data.parsed.cols;
    var col_aggs = presenter.get_col_aggs(this.table, data.parsed);
    if (agg == "$count" && !cols.length && !custom_fields.length) {
      col_aggs = [ "count" ];
    }

    _.each(col_aggs, function(col) {
      var agg = presenter.extract_agg(col);
      ret[col] = {};
      var sums = {};
      var counts = {};
      var minus_counts = {};
      var deltas = {};
      var values = {};
      var diffs = {};
      var avgs = {};

      var col_total = _.reduce(data.results, function(memo, res) {
        if (agg_is(agg, "avg")) {
          return memo + ((res.weighted_count  || res.count) * res[col]);
        } else if (agg_is(agg, "sum")) {
          return memo + res[col];
        } else {
          return memo + (res.weighted_count  || res.count);

        }
      }, 0);

      var col_count = _.reduce(data.results, function(memo, res) {
        return memo + (res.weighted_count || res.count);
      }, 0);

      var col_avg = col_total / col_count;

      _.each(data.results, function(row) {
        var group = _.keys(row._id);
        group.sort();
        group = _.map(group, function(g) { return row._id[g]; }).join(',');
        self.groups[group] = true;
        sums[group] = col_total - ((row.weighted_count || row.count) * row[col]);
        minus_counts[group] = col_count - (row.weighted_count || row.count);
        counts[group] = row.weighted_count || row.count;
        values[group] = row[col];
      });

      var greater;
      if (agg_is(agg, "avg")) {
        greater = col_avg;
      } else if (agg_is(agg, "sum")) {
        greater = col_total;
      } else if (agg_is(agg, "count")) {
        greater = col_count;
      }

      // Maybe compare how different it is to the real average.
      _.each(sums, function(sum, group) {
        var col_val, group_val;
        avgs[group] = sum / minus_counts[group];
        if (agg_is(agg, "avg")) {
          col_val = col_avg;
          group_val = avgs[group];
        } else if (agg_is(agg, "sum")) {
          col_val = col_total;
          group_val = values[group];
        } else if (agg_is(agg, "count")) {
          col_val = col_count;
          group_val = counts[group];
        }

        deltas[group] = col_val - group_val;
        diffs[group] = deltas[group] / col_val;
      });

      ret[col].deltas = deltas;
      ret[col].diffs = diffs;
      ret[col].sums = sums;
      ret[col].counts = counts;
      ret[col].minus_counts = minus_counts;
      ret[col].avg = col_avg;
      ret[col].count = col_count;
      ret[col].total = col_total;
      ret[col].avgs = avgs;
      ret[col].values = values;

      ret[col].greater = greater;
    });

    return ret;
  }
});

SF.trigger("view:add", "drill", {
  include: helpers.STD_INPUTS
    .concat(helpers.inputs.COMPARE),
  icon: "noun/table.svg"
}, DrillView);

module.exports = DrillView;


text:
* Will now notice !important declarations
* Added a zeroed rule for if offsets need to be cancelled at certain breakpoints (e.g. `.offset--3/12 .offset--md-0/12`)

# 0.2.1

* Remove pointless try/catch

# 0.2.0

* Allow column values to be passed in the css file (e.g `ri-columns(16)`)
* Default value can still be set in options

# 0.1.0

* Initial release.


text:
# SmileTouchID

[![GitHub Issues](http://img.shields.io/github/issues/liu044100/SmileTouchID.svg?style=flat)](https://github.com/liu044100/SmileTouchID/issues)
[![Version](https://img.shields.io/cocoapods/v/SmileTouchID.svg?style=flat)](http://cocoadocs.org/docsets/SmileTouchID)
[![License](https://img.shields.io/cocoapods/l/SmileTouchID.svg?style=flat)](http://cocoadocs.org/docsets/SmileTouchID)
[![Platform](https://img.shields.io/cocoapods/p/SmileTouchID.svg?style=flat)](http://cocoadocs.org/docsets/SmileTouchID)

A library for integrate Touch ID & Passcode to iOS App conveniently.

![](https://raw.githubusercontent.com/liu044100/SmileTouchID/master/Example/demo_gif/promo_banner_s.png)

#What can it do for you?

##### 1. Handle all complicated things about Touch ID & Passcode. You just need to write a few simple code to integrate Touch ID & Passcode to your app.

For example, handle the device that not support Touch ID, instead of Touch ID, use Passcode for authentication.

handle the whole process about securing the app (the user change passcode or turn passcode off),

```Objective-c
if ([SmileAuthenticator hasPassword]) {
        [SmileAuthenticator sharedInstance].securityType = INPUT_TOUCHID;
        [[SmileAuthenticator sharedInstance] presentAuthViewController];
    }
```

##### 2. Get elegant animation and adaptive UI automatically.

![](https://raw.githubusercontent.com/liu044100/SmileTouchID/master/Example/demo_gif/demo1.gif)
![](https://raw.githubusercontent.com/liu044100/SmileTouchID/master/Example/demo_gif/demo2.gif)
![](https://raw.githubusercontent.com/liu044100/SmileTouchID/master/Example/demo_gif/rotate.gif)

##### 3. Can customize the color,Touch ID icon and background image to fit your app style. For example, you can customize like the below image.

```Objective-c
[SmileAuthenticator sharedInstance].tintColor = [UIColor purpleColor];
[SmileAuthenticator sharedInstance].touchIDIconName = @"my_Touch_ID";
[SmileAuthenticator sharedInstance].appLogoName = @"my_Logo";
[SmileAuthenticator sharedInstance].navibarTranslucent = YES;
[SmileAuthenticator sharedInstance].backgroundImage = [UIImage imageNamed:@"backgroundImage"];

```

![](https://raw.githubusercontent.com/liu044100/SmileTouchID/master/Example/demo_gif/customize1.png)

You can use the property `nightMode` to change all the UI element to black style, like the below image.

```Objective-c
[SmileAuthenticator sharedInstance].nightMode = YES;
[SmileAuthenticator sharedInstance].backgroundImage = [UIImage imageNamed:@"nightMode_BG"];

```

![](https://raw.githubusercontent.com/liu044100/SmileTouchID/master/Example/demo_gif/night_mode1.png)

##### 4. Can customize the passcode digit to 6 or 10, or any number, automatically handle other things for you.

```Objective-c
[SmileAuthenticator sharedInstance].passcodeDigit = 6;
```

If you want to try this feature in the demo app, before you try to change `passcodeDigit` to new number, make sure turn off the passcode switch, because the keychain will save your old passcode even you delete the app, so you have to clear the old passcode in keychain, and then change new digit for test.

![](https://raw.githubusercontent.com/liu044100/SmileTouchID/master/Example/demo_gif/passlength.png)

##### 5. Support iOS7 and later.

In iOS7, because Apple had not given the TouchID API to developers, only use Passcode for authentication.

#Theoretical Introduction

The main class is the `SmileAuthenticator`. It has a property `SecurityType` that has four types: `INPUT_ONCE`, `INPUT_TWICE`, `INPUT_THREE`, `INPUT_TOUCHID`. The reason for this name is that show the user input times.

**`INPUT_ONCE`:** For the user turn the passcode switch off, user need input their passcode only one time for turn the password off.

**`INPUT_TWICE`:** For the user turn the password switch on, user need input their password once and re-enter their password one more time for confirm it to match each other.

**`INPUT_THREE`:** For the user change the password, user need input their old passcode one time, then input their new passcode one time and re-enter one time for confirm, a total of three times.

**`INPUT_TOUCHID`:** For the user open the app, user can use touch ID or input passcode to unlock.

Use `[[SmileAuthenticator sharedInstance] presentAuthViewController]` to present view for authentication.

#How to use it for your project?

**Step 1.** SmileTouchID is available through use [CocoaPods](http://cocoapods.org). To install
it, simply add the following line to your Podfile:

```Ruby
pod 'SmileTouchID'

```
Or you can drag the `SmileAuth` fold to your project.

**Step 2.** Import `SmileAuthenticator.h` to your `AppDelegate.m`, and add below line to `didFinishLaunchingWithOptions`.

```Objective-c
[SmileAuthenticator sharedInstance].rootVC = self.window.rootViewController;
```

![](https://raw.githubusercontent.com/liu044100/SmileTouchID/master/Example/demo_gif/step2.png)

**Step 3.** In your project root view controller,  add below line to `viewDidAppear:`.

```Objective-c
if ([SmileAuthenticator hasPassword]) {
        [SmileAuthenticator sharedInstance].securityType = INPUT_TOUCHID;
        [[SmileAuthenticator sharedInstance] presentAuthViewController];
    }
```

![](https://raw.githubusercontent.com/liu044100/SmileTouchID/master/Example/demo_gif/step3.png)

**Step 4.** Configure with your interactive UI parts,  set appropriate `securityType`, then call `presentAuthViewController`.

For example below image show a switch to turn the passcode on/off, when the switch turn on, the `securityType` is `INPUT_TWICE`, when turn off, the `securityType` is `INPUT_ONCE`. A button for change passcode, the `securityType` is `INPUT_THREE`.

```Objective-c
- (IBAction)changePassword:(id)sender {
    [SmileAuthenticator sharedInstance].securityType = INPUT_THREE;
    [[SmileAuthenticator sharedInstance] presentAuthViewController];
}

- (IBAction)passwordSwitch:(UISwitch*)passwordSwitch {
    if (passwordSwitch.on) {
        [SmileAuthenticator sharedInstance].securityType = INPUT_TWICE;
    } else {
        [SmileAuthenticator sharedInstance].securityType = INPUT_ONCE;
    }

    [[SmileAuthenticator sharedInstance] presentAuthViewController];
}

```

![](https://raw.githubusercontent.com/liu044100/SmileTouchID/master/Example/demo_gif/step4.png)

Update your interactive UI parts in `viewWillAppear`.

For example, below code show update the switch and button based on `[SmileAuthenticator hasPassword]`.

```Objective-c
-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];

    if ([SmileAuthenticator hasPassword]) {
        self.mySwitch.on = YES;
        self.changePasswordButton.hidden = NO;
    } else {
        self.mySwitch.on = NO;
        self.changePasswordButton.hidden = YES;
    }
}
```

**Step 5.** Build your project, very simple :)

#About Delegate callback

`SmileAuthenticator` has a delegate that can get more information about the process of authentication.

The delegate name is `SmileAuthenticatorDelegate`. It has four optional method.

```Objective-c
@protocol SmileAuthenticatorDelegate <NSObject>
@optional
/*!The method is called when AuthViewController be presented*/
-(void)AuthViewControllerPresented;
@optional
/*!The method is called when AuthViewController be dismissed*/
-(void)AuthViewControllerDismssed;
@optional
/*!The method is called when user success authentication by using Touch ID & Passcode*/
-(void)userSuccessAuthentication;
@optional
/*!The method is called when authentication failed*/
-(void)userFailAuthenticationWithCount:(NSInteger)failCount;
@optional
/*!The method is called when user turn password on.*/
-(void)userTurnPasswordOn;
@optional
/*!The method is called when user turn password off.*/
-(void)userTurnPasswordOff;
@optional
/*!The method is called when user change password.*/
-(void)userChangePassword;
```
# Localization
Sorry about it, but you have to do it yourself. Add below line to your `Localizable.strings`. For detail please see the example demo app.

```Objective-c
/*
 UNIVERSAL PARTS
 */
"SMILE_REASON" = "Are you device owner?";
"SMILE_INPUT_FAILED" = "%ld Failed Passcode Attempt. Try again.";
"SMILE_INPUT_DESCRIPTION" = "Enter %ld digit passcode";
"SMILE_INPUT_NOT_MATCH" = "Passcode not match. Try again.";
"SMILE_INPUT_RE-ENTER" = "Re-enter your %ld digit Passcode";

/*
 INPUT_TOUCHID
 */
"SMILE_INPUT_TOUCHID_TITLE" = "Enter Passcode";

/*
 INPUT_ONCE
 */
"SMILE_INPUT_ONCE_TITLE" = "Turn off Passcode";

/*
 INPUT_TWICE
 */
"SMILE_INPUT_TWICE_TITLE" = "Set Passcode";

/*
 INPUT_THREE
 */
"SMILE_INPUT_THREE_TITLE" = "Change Passcode";
"SMILE_INPUT_THREE_STEP_1_DESCRIPTION" = "Enter your old %ld digit Passcode";
"SMILE_INPUT_THREE_STEP_2_DESCRIPTION" = "Enter your new %ld digit Passcode";

```

# Contributions

* Warmly welcome to submit a pull request.

# Contact

* If you have some advice or find some issue, please contact me.
* Email [me](liu044100@gmail.com)

# Thanks
Thanks for raywenderlich's tutorial about [securing iOS User Data](http://www.raywenderlich.com/92667/securing-ios-data-keychain-touch-id-1password), I am inspired by this tutorial.

# License

SmileTouchID is available under the MIT license. See the LICENSE file for more info.


text:
<!DOCTYPE html>

		<title>Ajax Tutorial</title>
		<link rel="stylesheet" type="text/css" href="public/css/main.css">

		<link href="https://fonts.googleapis.com/css?family=Hind|Lemonada" rel="stylesheet">

jQuery Ajax Tutorial

Add a Friend

Name: <input type="text" id="name">

Age: <input type="text" id="age">

Friendship  Longevity: <input type="text" name=" longevity">

Friendship Quality: <input type="text" name="quality">

<button id="add-friend">Add!</button>


text:
package pilot

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strings"
	"sync"
	"text/template"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/events"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/api/types/mount"
	k8s "github.com/docker/docker/client"
	"golang.org/x/net/context"
)

/**
Label:
aliyun.log: /var/log/hello.log[:json][;/var/log/abc/def.log[:txt]]
*/

// Global variables
const (
	ENV_PILOT_LOG_PREFIX     = "PILOT_LOG_PREFIX"
	ENV_PILOT_CREATE_SYMLINK = "PILOT_CREATE_SYMLINK"
	ENV_LOGGING_OUTPUT       = "LOGGING_OUTPUT"

	ENV_SERVICE_LOGS_TEMPL                  = "%s_logs_"
	ENV_SERVICE_LOGS_CUSTOME_CONFIG_TEMPL   = "%s_logs_custom_config"
	LABEL_SERVICE_LOGS_TEMPL                = "%s.logs."
	LABEL_SERVICE_LOGS_CUSTOME_CONFIG_TEMPL = "%s.logs.custom.config"
	LABEL_PROJECT_SWARM_MODE                = "com.docker.stack.namespace"
	LABEL_PROJECT                           = "com.docker.compose.project"
	LABEL_SERVICE                           = "com.docker.compose.service"
	LABEL_SERVICE_SWARM_MODE                = "com.docker.swarm.service.name"
	LABEL_K8S_POD_NAMESPACE                 = "io.kubernetes.pod.namespace"
	LABEL_K8S_CONTAINER_NAME                = "io.kubernetes.container.name"
	LABEL_POD                               = "io.kubernetes.pod.name"
	SYMLINK_LOGS_BASE                       = "/acs/log/"

	ERR_ALREADY_STARTED = "already started"
)

// Pilot entry point
type Pilot struct {
	piloter       Piloter
	mutex         sync.Mutex
	templ         *template.Template
	client        *k8s.Client
	lastReload    time.Time
	reloadChan    chan bool
	stopChan      chan bool
	baseDir       string
	logPrefix     []string
	createSymlink bool
}

// Run start log pilot
func Run(templ string, baseDir string) error {
	p, err := New(templ, baseDir)
	if err != nil {
		panic(err)
	}
	return p.watch()
}

// New returns a log pilot instance
func New(tplStr string, baseDir string) (*Pilot, error) {
	templ, err := template.New("pilot").Parse(tplStr)
	if err != nil {
		return nil, err
	}

	if os.Getenv("DOCKER_API_VERSION") == "" {
		os.Setenv("DOCKER_API_VERSION", "1.23")
	}

	client, err := k8s.NewEnvClient()
	if err != nil {
		return nil, err
	}

	piloter, err := NewPiloter(baseDir)
	if err != nil {
		return nil, err
	}

	logPrefix := []string{"aliyun"}
	if os.Getenv(ENV_PILOT_LOG_PREFIX) != "" {
		envLogPrefix := os.Getenv(ENV_PILOT_LOG_PREFIX)
		logPrefix = strings.Split(envLogPrefix, ",")
	}

	createSymlink := os.Getenv(ENV_PILOT_CREATE_SYMLINK) == "true"
	return &Pilot{
		client:        client,
		templ:         templ,
		baseDir:       baseDir,
		reloadChan:    make(chan bool),
		stopChan:      make(chan bool),
		piloter:       piloter,
		logPrefix:     logPrefix,
		createSymlink: createSymlink,
	}, nil
}

func (p *Pilot) watch() error {
	if err := p.cleanConfigs(); err != nil {
		return err
	}

	err := p.piloter.Start()
	if err != nil && ERR_ALREADY_STARTED != err.Error() {
		return err
	}

	p.lastReload = time.Now()
	go p.doReload()

	ctx := context.Background()
	filter := filters.NewArgs()
	filter.Add("type", "container")
	options := types.EventsOptions{
		Filters: filter,
	}

	msgs, errs := p.client.Events(ctx, options)

	go func() {
		defer func() {
			log.Warn("finish to watch event")
			p.stopChan <- true
		}()

		log.Info("begin to watch event")

		for {
			select {
			case msg := <-msgs:
				if err := p.processEvent(msg); err != nil {
					log.Errorf("fail to process event: %v,  %v", msg, err)
				}
			case err := <-errs:
				log.Warnf("error: %v", err)
				if err == io.EOF || err == io.ErrUnexpectedEOF {
					return
				}
				msgs, errs = p.client.Events(ctx, options)
			}
		}
	}()

	time.Sleep(time.Second * 1)
	if err := p.processAllContainers(); err != nil {
		return err
	}

	<-p.stopChan
	close(p.reloadChan)
	close(p.stopChan)
	return nil
}

// LogConfig log configuration
type LogConfig struct {
	Name         string
	HostDir      string
	ContainerDir string
	Format       string
	FormatConfig map[string]string
	File         string
	Tags         map[string]string
	Target       string
	EstimateTime bool
	Stdout       bool

	CustomFields  map[string]string
	CustomConfigs map[string]string
}

func (p *Pilot) cleanConfigs() error {
	p.mutex.Lock()
	defer p.mutex.Unlock()

	confDir := fmt.Sprintf(p.piloter.GetConfHome())
	d, err := os.Open(confDir)
	if err != nil {
		return err
	}
	defer d.Close()

	names, err := d.Readdirnames(-1)
	if err != nil {
		return err
	}

	for _, name := range names {
		conf := filepath.Join(confDir, name)
		stat, err := os.Stat(filepath.Join(confDir, name))
		if err != nil {
			return err
		}
		if stat.Mode().IsRegular() {
			if err := os.Remove(conf); err != nil {
				return err
			}
		}
	}
	return nil
}

func (p *Pilot) processAllContainers() error {
	p.mutex.Lock()
	defer p.mutex.Unlock()

	log.Debug("process all container log config")

	opts := types.ContainerListOptions{}
	containers, err := p.client.ContainerList(context.Background(), opts)
	if err != nil {
		log.Errorf("fail to list container: %v", err)
		return nil
	}

	containerIDs := make(map[string]string, 0)
	for _, c := range containers {
		if _, ok := containerIDs[c.ID]; !ok {
			containerIDs[c.ID] = c.ID
		}

		if c.State == "removing" {
			continue
		}

		if p.exists(c.ID) {
			log.Debugf("%s is already exists", c.ID)
			continue
		}

		containerJSON, err := p.client.ContainerInspect(context.Background(), c.ID)
		if err != nil {
			log.Errorf("fail to inspect container %s: %v", c.ID, err)
			continue
		}

		if err = p.newContainer(&containerJSON); err != nil {
			log.Errorf("fail to process container %s: %v", containerJSON.Name, err)
		}
	}

	return p.processSymlink(containerIDs)
}

func (p *Pilot) processSymlink(existingContainerIDs map[string]string) error {
	symlinkContainerIDs := p.listAllSymlinkContainer()
	for containerID := range symlinkContainerIDs {
		if _, ok := existingContainerIDs[containerID]; !ok {
			p.removeVolumeSymlink(containerID)
		}
	}
	return nil
}

func (p *Pilot) listAllSymlinkContainer() map[string]string {
	containerIDs := make(map[string]string, 0)
	linkBaseDir := path.Join(p.baseDir, SYMLINK_LOGS_BASE)
	if _, err := os.Stat(linkBaseDir); err != nil && os.IsNotExist(err) {
		return containerIDs
	}

	projects := listSubDirectory(linkBaseDir)
	for _, project := range projects {
		projectPath := path.Join(linkBaseDir, project)
		services := listSubDirectory(projectPath)
		for _, service := range services {
			servicePath := path.Join(projectPath, service)
			containers := listSubDirectory(servicePath)
			for _, containerID := range containers {
				if _, ok := containerIDs[containerID]; !ok {
					containerIDs[containerID] = containerID
				}
			}
		}
	}
	return containerIDs
}

func listSubDirectory(path string) []string {
	subdirs := make([]string, 0)
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return subdirs
	}

	files, err := ioutil.ReadDir(path)
	if err != nil {
		log.Warnf("read %s error: %v", path, err)
		return subdirs
	}

	for _, file := range files {
		if file.IsDir() {
			subdirs = append(subdirs, file.Name())
		}
	}
	return subdirs
}

func putIfNotEmpty(store map[string]string, key, value string) {
	if key == "" || value == "" {
		return
	}
	store[key] = value
}

func container(containerJSON *types.ContainerJSON) map[string]string {
	labels := containerJSON.Config.Labels
	c := make(map[string]string)
	putIfNotEmpty(c, "docker_app", labels[LABEL_PROJECT])
	putIfNotEmpty(c, "docker_app", labels[LABEL_PROJECT_SWARM_MODE])
	putIfNotEmpty(c, "docker_service", labels[LABEL_SERVICE])
	putIfNotEmpty(c, "docker_service", labels[LABEL_SERVICE_SWARM_MODE])
	putIfNotEmpty(c, "k8s_pod", labels[LABEL_POD])
	putIfNotEmpty(c, "k8s_pod_namespace", labels[LABEL_K8S_POD_NAMESPACE])
	putIfNotEmpty(c, "k8s_container_name", labels[LABEL_K8S_CONTAINER_NAME])
	putIfNotEmpty(c, "k8s_node_name", os.Getenv("NODE_NAME"))
	putIfNotEmpty(c, "docker_container", strings.TrimPrefix(containerJSON.Name, "/"))
	extension(c, containerJSON)
	return c
}

func (p *Pilot) newContainer(containerJSON *types.ContainerJSON) error {
	id := containerJSON.ID
	env := containerJSON.Config.Env
	mounts := containerJSON.Mounts
	labels := containerJSON.Config.Labels
	jsonLogPath := containerJSON.LogPath

	//logConfig.containerDir match types.mountPoint
	/**
	  场景:
	  1. 容器一个路径,中间有多级目录对应宿主机不同的目录
	  2. containerdir对应的目录不是直接挂载的,挂载的是它上级的目录

	  查找:从containerdir开始查找最近的一层挂载
	*/

	container := container(containerJSON)

	for _, e := range env {
		for _, prefix := range p.logPrefix {
			customConfig := fmt.Sprintf(ENV_SERVICE_LOGS_CUSTOME_CONFIG_TEMPL, prefix)
			if strings.HasPrefix(e, customConfig) {
				labels[customConfig] = e[len(customConfig)+1:]
				log.Infof("Get customConfig key = %s, value = %s", customConfig, labels[customConfig])
				continue
			}

			serviceLogs := fmt.Sprintf(ENV_SERVICE_LOGS_TEMPL, prefix)
			if !strings.HasPrefix(e, serviceLogs) {
				continue
			}

			envLabel := strings.SplitN(e, "=", 2)
			if len(envLabel) == 2 {
				labelKey := strings.Replace(envLabel[0], "_", ".", -1)
				labels[labelKey] = envLabel[1]
			}
		}
	}

	logConfigs, err := p.getLogConfigs(jsonLogPath, mounts, labels)
	if err != nil {
		return err
	}

	if len(logConfigs) == 0 {
		log.Debugf("%s has not log config, skip", id)
		return nil
	}

	// create symlink
	p.createVolumeSymlink(containerJSON)

	//pilot.findMounts(logConfigs, jsonLogPath, mounts)
	//生成配置
	logConfig, err := p.render(id, container, logConfigs)
	if err != nil {
		return err
	}
	//TODO validate config before save
	//log.Debugf("container %s log config: %s", id, logConfig)
	if err = ioutil.WriteFile(p.piloter.GetConfPath(id), []byte(logConfig), os.FileMode(0644)); err != nil {
		return err
	}

	p.tryReload()
	return nil
}

func (p *Pilot) tryReload() {
	select {
	case p.reloadChan <- true:
	default:
		log.Info("Another load is pending")
	}
}

func (p *Pilot) doReload() {
	log.Info("Reload goroutine is ready")
	for {
		<-p.reloadChan
		p.reload()
	}
}

func (p *Pilot) delContainer(id string) error {
	p.removeVolumeSymlink(id)

	//fixme refactor in the future
	if p.piloter.Name() == PILOT_FLUENTD {
		clean := func() {
			log.Infof("Try removing log config %s", id)
			if err := os.Remove(p.piloter.GetConfPath(id)); err != nil {
				log.Warnf("removing %s log config failure", id)
				return
			}
			p.tryReload()
		}
		time.AfterFunc(15*time.Minute, clean)
		return nil
	}

	return p.piloter.OnDestroyEvent(id)
}

func (p *Pilot) processEvent(msg events.Message) error {
	containerId := msg.Actor.ID
	ctx := context.Background()

	switch msg.Action {
	case "start", "restart":
		log.Debugf("Process container start event: %s", containerId)

		if p.exists(containerId) {
			log.Debugf("%s is already exists", containerId)
			return nil
		}

		containerJSON, err := p.client.ContainerInspect(ctx, containerId)
		if err != nil {
			return err
		}

		return p.newContainer(&containerJSON)
	//Increase the monitoring of container Exit events and repair the log duplicate collection caused by the failure to delete the exited container in time
	case "destroy", "die":
		log.Debugf("Process container destroy event: %s", containerId)

		err := p.delContainer(containerId)
		if err != nil {
			log.Warnf("Process container destroy event error: %s, %s",
				containerId, err.Error())
		}
	}
	return nil
}

func (p *Pilot) hostDirOf(path string, mounts map[string]types.MountPoint) string {
	confPath := path
	for {
		if point, ok := mounts[path]; ok {
			if confPath == path {
				return point.Source
			}

			relPath, err := filepath.Rel(path, confPath)
			if err != nil {
				panic(err)
			}
			return fmt.Sprintf("%s/%s", point.Source, relPath)
		}
		path = filepath.Dir(path)
		if path == "/" || path == "." {
			break
		}
	}
	return ""
}

func (p *Pilot) parseTags(tags string) (map[string]string, error) {
	tagMap := make(map[string]string)
	if tags == "" {
		return tagMap, nil
	}

	kvArray := strings.Split(tags, ",")
	for _, kv := range kvArray {
		arr := strings.Split(kv, "=")
		if len(arr) != 2 {
			return nil, fmt.Errorf("%s is not a valid k=v format", kv)
		}
		key := strings.TrimSpace(arr[0])
		value := strings.TrimSpace(arr[1])
		if key == "" || value == "" {
			return nil, fmt.Errorf("%s is not a valid k=v format", kv)
		}
		tagMap[key] = value
	}
	return tagMap, nil
}

func (p *Pilot) tryCheckKafkaTopic(topic string) error {
	output := os.Getenv(ENV_LOGGING_OUTPUT)
	if output != "kafka" {
		return nil
	}

	topicPath := filepath.Join(p.piloter.GetBaseConf(), "config", "kafka_topics")
	if _, err := os.Stat(topicPath); os.IsNotExist(err) {
		log.Info("ignore checking the validity of kafka topic")
		return nil
	}

	topics, err := ReadFile(topicPath, ",")
	if err != nil {
		return err
	}

	for _, t := range topics {
		if t == topic {
			return nil
		}
	}

	return fmt.Errorf("invalid topic: %s, supported topics: %v", topic, topics)
}

func (p *Pilot) parseLogConfig(name string, info *LogInfoNode, jsonLogPath string, mounts map[string]types.MountPoint) (*LogConfig, error) {
	path := strings.TrimSpace(info.value)
	if path == "" {
		return nil, fmt.Errorf("path for %s is empty", name)
	}

	tags := info.get("tags")
	tagMap, err := p.parseTags(tags)
	if err != nil {
		return nil, fmt.Errorf("parse tags for %s error: %v", name, err)
	}

	target := info.get("target")
	// add default index or topic
	if _, ok := tagMap["index"]; !ok {
		if target != "" {
			tagMap["index"] = target
		} else {
			tagMap["index"] = name
		}
	}

	if _, ok := tagMap["topic"]; !ok {
		if target != "" {
			tagMap["topic"] = target
		} else {
			tagMap["topic"] = name
		}
	}

	// try to check the validity of the target topic for kafka
	if err := p.tryCheckKafkaTopic(tagMap["topic"]); err != nil {
		return nil, err
	}

	format := info.children["format"]
	if format == nil || format.value == "none" {
		format = newLogInfoNode("nonex")
	}

	formatConfig, err := Convert(format)
	if err != nil {
		return nil, fmt.Errorf("in log %s: format error: %v", name, err)
	}

	//特殊处理regex
	if format.value == "regexp" {
		format.value = fmt.Sprintf("/%s/", formatConfig["pattern"])
		delete(formatConfig, "pattern")
	}

	if path == "stdout" {
		logFile := filepath.Base(jsonLogPath)
		if p.piloter.Name() == PILOT_FILEBEAT {
			logFile = logFile + "*"
		}

		return &LogConfig{
			Name:         name,
			HostDir:      filepath.Join(p.baseDir, filepath.Dir(jsonLogPath)),
			File:         logFile,
			Format:       format.value,
			Tags:         tagMap,
			FormatConfig: map[string]string{"time_format": "%Y-%m-%dT%H:%M:%S.%NZ"},
			Target:       target,
			EstimateTime: false,
			Stdout:       true,
		}, nil
	}

	if !filepath.IsAbs(path) {
		return nil, fmt.Errorf("%s must be absolute path, for %s", path, name)
	}

	containerDir := filepath.Dir(path)
	file := filepath.Base(path)
	if file == "" {
		return nil, fmt.Errorf("%s must be a file path, not directory, for %s", path, name)
	}

	hostDir := p.hostDirOf(containerDir, mounts)
	if hostDir == "" {
		return nil, fmt.Errorf("in log %s: %s is not mount on host", name, path)
	}

	cfg := &LogConfig{
		Name:         name,
		ContainerDir: containerDir,
		Format:       format.value,
		File:         file,
		Tags:         tagMap,
		HostDir:      filepath.Join(p.baseDir, hostDir),
		FormatConfig: formatConfig,
		Target:       target,
	}

	if formatConfig["time_key"] == "" {
		cfg.EstimateTime = true
		cfg.FormatConfig["time_key"] = "time"
	}
	return cfg, nil
}

// LogInfoNode node info
type LogInfoNode struct {
	value    string
	children map[string]*LogInfoNode
}

func newLogInfoNode(value string) *LogInfoNode {
	return &LogInfoNode{
		value:    value,
		children: make(map[string]*LogInfoNode),
	}
}

func (node *LogInfoNode) insert(keys []string, value string) error {
	if len(keys) == 0 {
		return nil
	}
	key := keys[0]
	if len(keys) > 1 {
		if child, ok := node.children[key]; ok {
			child.insert(keys[1:], value)
		} else {
			return fmt.Errorf("%s has no parent node", key)
		}
	} else {
		child := newLogInfoNode(value)
		node.children[key] = child
	}
	return nil
}

func (node *LogInfoNode) get(key string) string {
	if child, ok := node.children[key]; ok {
		return child.value
	}
	return ""
}

func (p *Pilot) getLogConfigs(jsonLogPath string, mounts []types.MountPoint, labels map[string]string) ([]*LogConfig, error) {
	var ret []*LogConfig

	mountsMap := make(map[string]types.MountPoint)
	for _, mount := range mounts {
		mountsMap[mount.Destination] = mount
	}

	var labelNames []string
	//sort keys
	for k := range labels {
		labelNames = append(labelNames, k)
	}

	customConfigs := make(map[string]string)

	sort.Strings(labelNames)
	root := newLogInfoNode("")
	for _, k := range labelNames {
		for _, prefix := range p.logPrefix {
			customConfig := fmt.Sprintf(ENV_SERVICE_LOGS_CUSTOME_CONFIG_TEMPL, prefix)
			if customConfig == k {
				configs := strings.Split(labels[k], "\n")
				for _, c := range configs {
					if c == "" {
						continue
					}
					customLabel := strings.SplitN(c, "=", 2)
					customConfigs[customLabel[0]] = customLabel[1]
				}
				continue
			}

			serviceLogs := fmt.Sprintf(LABEL_SERVICE_LOGS_TEMPL, prefix)
			if !strings.HasPrefix(k, serviceLogs) || strings.Count(k, ".") == 1 {
				continue
			}

			logLabel := strings.TrimPrefix(k, serviceLogs)
			if err := root.insert(strings.Split(logLabel, "."), labels[k]); err != nil {
				return nil, err
			}
		}
	}

	for name, node := range root.children {
		logConfig, err := p.parseLogConfig(name, node, jsonLogPath, mountsMap)
		if err != nil {
			return nil, err
		}
		CustomConfig(name, customConfigs, logConfig)
		ret = append(ret, logConfig)
	}
	return ret, nil
}

func (p *Pilot) exists(containId string) bool {
	if _, err := os.Stat(p.piloter.GetConfPath(containId)); os.IsNotExist(err) {
		return false
	}
	return true
}

func (p *Pilot) render(containerId string, container map[string]string, configList []*LogConfig) (string, error) {
	for _, config := range configList {
		log.Infof("logs: %s = %v", containerId, config)
	}

	output := os.Getenv(ENV_FLUENTD_OUTPUT)
	if p.piloter.Name() == PILOT_FILEBEAT {
		output = os.Getenv(ENV_FILEBEAT_OUTPUT)
	}
	if output == "" {
		output = os.Getenv(ENV_LOGGING_OUTPUT)
	}

	var buf bytes.Buffer
	context := map[string]interface{}{
		"containerId": containerId,
		"configList":  configList,
		"container":   container,
		"output":      output,
	}
	if err := p.templ.Execute(&buf, context); err != nil {
		return "", err
	}
	return buf.String(), nil
}

func (p *Pilot) reload() error {
	p.mutex.Lock()
	defer p.mutex.Unlock()

	log.Infof("Reload %s", p.piloter.Name())
	interval := time.Now().Sub(p.lastReload)
	time.Sleep(30*time.Second - interval)

	log.Info("Start reloading")
	err := p.piloter.Reload()
	p.lastReload = time.Now()
	return err
}

func (p *Pilot) createVolumeSymlink(containerJSON *types.ContainerJSON) error {
	if !p.createSymlink {
		return nil
	}

	linkBaseDir := path.Join(p.baseDir, SYMLINK_LOGS_BASE)
	if _, err := os.Stat(linkBaseDir); err != nil && os.IsNotExist(err) {
		if err := os.MkdirAll(linkBaseDir, 0777); err != nil {
			log.Errorf("create %s error: %v", linkBaseDir, err)
		}
	}

	applicationInfo := container(containerJSON)
	containerLinkBaseDir := path.Join(linkBaseDir, applicationInfo["docker_app"],
		applicationInfo["docker_service"], containerJSON.ID)
	symlinks := make(map[string]string, 0)
	for _, mountPoint := range containerJSON.Mounts {
		if mountPoint.Type != mount.TypeVolume {
			continue
		}

		volume, err := p.client.VolumeInspect(context.Background(), mountPoint.Name)
		if err != nil {
			log.Errorf("inspect volume %s error: %v", mountPoint.Name, err)
			continue
		}

		symlink := path.Join(containerLinkBaseDir, volume.Name)
		if _, ok := symlinks[volume.Mountpoint]; !ok {
			symlinks[volume.Mountpoint] = symlink
		}
	}

	if len(symlinks) == 0 {
		return nil
	}

	if _, err := os.Stat(containerLinkBaseDir); err != nil && os.IsNotExist(err) {
		if err := os.MkdirAll(containerLinkBaseDir, 0777); err != nil {
			log.Errorf("create %s error: %v", containerLinkBaseDir, err)
			return err
		}
	}

	for mountPoint, symlink := range symlinks {
		err := os.Symlink(mountPoint, symlink)
		if err != nil && !os.IsExist(err) {
			log.Errorf("create symlink %s error: %v", symlink, err)
		}
	}
	return nil
}

func (p *Pilot) removeVolumeSymlink(containerId string) error {
	if !p.createSymlink {
		return nil
	}

	linkBaseDir := path.Join(p.baseDir, SYMLINK_LOGS_BASE)
	containerLinkDirs, _ := filepath.Glob(path.Join(linkBaseDir, "*", "*", containerId))
	if containerLinkDirs == nil {
		return nil
	}
	for _, containerLinkDir := range containerLinkDirs {
		if err := os.RemoveAll(containerLinkDir); err != nil {
			log.Warnf("remove error: %v", err)
		}
	}
	return nil
}


text:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace Cake.Common.Tools.NUnit
{
    /// <summary>
    /// The /domain option controls of the creation of AppDomains for running tests.
    /// </summary>
    public enum NUnit3AppDomainUsage
    {
        /// <summary>
        /// Create a separate AppDomain for each assembly if more than one is listed on the command
        /// line, otherwise creates a single AppDomain.
        /// </summary>
        Default = 0,

        /// <summary>
        /// No AppDomain is created - the tests are run in the primary domain.
        /// This normally requires copying the NUnit assemblies into the same directory as your tests.
        /// </summary>
        None,

        /// <summary>
        /// A single test AppDomain is created for all test assemblies
        /// This is how NUnit worked prior to version 2.4.
        /// </summary>
        Single,

        /// <summary>
        /// An AppDomain is created for each assembly specified on the command line.
        /// </summary>
        Multiple
    }
}


text:
"""
The :mod:`sklearn.cluster` module gathers popular unsupervised clustering
algorithms.
"""

from .spectral import spectral_clustering, SpectralClustering
from .mean_shift_ import mean_shift, MeanShift, estimate_bandwidth, \
    get_bin_seeds
from .affinity_propagation_ import affinity_propagation, AffinityPropagation
from .hierarchical import (ward_tree, Ward, WardAgglomeration,
    AgglomerativeClustering, linkage_tree, FeatureAgglomeration)
from .k_means_ import k_means, KMeans, MiniBatchKMeans
from .dbscan_ import dbscan, DBSCAN
from .bicluster import SpectralBiclustering, SpectralCoclustering

__all__ = ['AffinityPropagation',
           'AgglomerativeClustering',
           'DBSCAN',
           'KMeans',
           'FeatureAgglomeration',
           'MeanShift',
           'MiniBatchKMeans',
           'SpectralClustering',
           'Ward',
           'WardAgglomeration',
           'affinity_propagation',
           'dbscan',
           'estimate_bandwidth',
           'get_bin_seeds',
           'k_means',
           'linkage_tree',
           'mean_shift',
           'spectral_clustering',
           'ward_tree',
           'SpectralBiclustering',
           'SpectralCoclustering']