text:
ABSL_FLAG(uint64_t, max_typing_correction_query_candidates, 40,
          "Maximum # of typing correction query temporary candidates.");
ABSL_FLAG(uint64_t, max_typing_correction_query_results, 8,
          "Maximum # of typing correction query results.");

namespace mozc {
namespace composer {
namespace {

using ::mozc::config::CharacterFormManager;

const Transliterators::Transliterator GetTransliterator(
    transliteration::TransliterationType comp_mode) {
  switch (comp_mode) {
    case transliteration::HALF_ASCII:
    case transliteration::HALF_ASCII_UPPER:
    case transliteration::HALF_ASCII_LOWER:
    case transliteration::HALF_ASCII_CAPITALIZED:
      return Transliterators::HALF_ASCII;

    case transliteration::FULL_ASCII:
    case transliteration::FULL_ASCII_UPPER:
    case transliteration::FULL_ASCII_LOWER:
    case transliteration::FULL_ASCII_CAPITALIZED:
      return Transliterators::FULL_ASCII;

    case transliteration::HALF_KATAKANA:
      return Transliterators::HALF_KATAKANA;

    case transliteration::FULL_KATAKANA:
      return Transliterators::FULL_KATAKANA;

    case transliteration::HIRAGANA:
      return Transliterators::HIRAGANA;

    default:
      LOG(ERROR) << "Unknown TransliterationType: " << comp_mode;
      return Transliterators::CONVERSION_STRING;
  }
}

transliteration::TransliterationType GetTransliterationType(
    Transliterators::Transliterator transliterator,
    const transliteration::TransliterationType default_type) {
  if (transliterator == Transliterators::HIRAGANA) {
    return transliteration::HIRAGANA;
  }
  if (transliterator == Transliterators::HALF_ASCII) {
    return transliteration::HALF_ASCII;
  }
  if (transliterator == Transliterators::FULL_ASCII) {
    return transliteration::FULL_ASCII;
  }
  if (transliterator == Transliterators::FULL_KATAKANA) {
    return transliteration::FULL_KATAKANA;
  }
  if (transliterator == Transliterators::HALF_KATAKANA) {
    return transliteration::HALF_KATAKANA;
  }
  return default_type;
}

void Transliterate(const transliteration::TransliterationType mode,
                   const std::string &input, std::string *output) {
  // When the mode is HALF_KATAKANA, Full width ASCII is also
  // transformed.
  if (mode == transliteration::HALF_KATAKANA) {
    std::string tmp_input;
    japanese_util::HiraganaToKatakana(input, &tmp_input);
    japanese_util::FullWidthToHalfWidth(tmp_input, output);
    return;
  }

  switch (mode) {
    case transliteration::HALF_ASCII:
      japanese_util::FullWidthAsciiToHalfWidthAscii(input, output);
      break;
    case transliteration::HALF_ASCII_UPPER:
      japanese_util::FullWidthAsciiToHalfWidthAscii(input, output);
      Util::UpperString(output);
      break;
    case transliteration::HALF_ASCII_LOWER:
      japanese_util::FullWidthAsciiToHalfWidthAscii(input, output);
      Util::LowerString(output);
      break;
    case transliteration::HALF_ASCII_CAPITALIZED:
      japanese_util::FullWidthAsciiToHalfWidthAscii(input, output);
      Util::CapitalizeString(output);
      break;

    case transliteration::FULL_ASCII:
      japanese_util::HalfWidthAsciiToFullWidthAscii(input, output);
      break;
    case transliteration::FULL_ASCII_UPPER:
      japanese_util::HalfWidthAsciiToFullWidthAscii(input, output);
      Util::UpperString(output);
      break;
    case transliteration::FULL_ASCII_LOWER:
      japanese_util::HalfWidthAsciiToFullWidthAscii(input, output);
      Util::LowerString(output);
      break;
    case transliteration::FULL_ASCII_CAPITALIZED:
      japanese_util::HalfWidthAsciiToFullWidthAscii(input, output);
      Util::CapitalizeString(output);
      break;

    case transliteration::FULL_KATAKANA:
      japanese_util::HiraganaToKatakana(input, output);
      break;
    case transliteration::HIRAGANA:
      *output = input;
      break;
    default:
      LOG(ERROR) << "Unknown TransliterationType: " << mode;
      *output = input;
      break;
  }
}

transliteration::TransliterationType GetTransliterationTypeFromCompositionMode(
    const commands::CompositionMode mode) {
  switch (mode) {
    case commands::HIRAGANA:
      return transliteration::HIRAGANA;
    case commands::FULL_KATAKANA:
      return transliteration::FULL_KATAKANA;
    case commands::HALF_ASCII:
      return transliteration::HALF_ASCII;
    case commands::FULL_ASCII:
      return transliteration::FULL_ASCII;
    case commands::HALF_KATAKANA:
      return transliteration::HALF_KATAKANA;
    default:
      // commands::DIRECT or invalid mode.
      LOG(ERROR) << "Invalid CompositionMode: " << mode;
      return transliteration::HIRAGANA;
  }
}

// A map used in `GetQueriesForPrediction()`. The key is a modified Hiragana
// and the values are its related Hiragana characters that can be cycled by
// hitting the modifier key. For instance, there's a modification cycle
// つ -> っ -> づ -> つ. For this cycle, the multimap contains:
//   っ: [つ, づ]
//   づ: [つ, っ]
// If the composition ends with a key in this map, its corresponding values
// are removed from the expansion produced by `GetQueryForPrediction()`,
// whereby we can suppress prediction from unmodified key when one modified a
// character explicitly (e.g., we don't want to suggest words starting with
// "さ" when one typed "ざ" with modified key).
using ModifierRemovalMap = std::unordered_multimap<std::string, std::string>;

const ModifierRemovalMap *GetModifierRemovalMap() {
  static const ModifierRemovalMap *const removal_map = new ModifierRemovalMap{
      {"ぁ", "あ"}, {"ぃ", "い"}, {"ぅ", "う"}, {"ぅ", "ゔ"}, {"ゔ", "う"},
      {"ゔ", "ぅ"}, {"ぇ", "え"}, {"ぉ", "お"}, {"が", "か"}, {"ぎ", "き"},
      {"ぐ", "く"}, {"げ", "け"}, {"ご", "こ"}, {"ざ", "さ"}, {"じ", "し"},
      {"ず", "す"}, {"ぜ", "せ"}, {"ぞ", "そ"}, {"だ", "た"}, {"ぢ", "ち"},
      {"づ", "つ"}, {"づ", "っ"}, {"っ", "つ"}, {"っ", "づ"}, {"で", "て"},
      {"ど", "と"}, {"ば", "は"}, {"ば", "ぱ"}, {"ぱ", "は"}, {"ぱ", "ば"},
      {"び", "ひ"}, {"び", "ぴ"}, {"ぴ", "ひ"}, {"ぴ", "び"}, {"ぶ", "ふ"},
      {"ぶ", "ぷ"}, {"ぷ", "ふ"}, {"ぷ", "ぶ"}, {"べ", "へ"}, {"べ", "ぺ"},
      {"ぺ", "へ"}, {"ぺ", "べ"}, {"ぼ", "ほ"}, {"ぼ", "ぽ"}, {"ぽ", "ほ"},
      {"ぽ", "ぼ"}, {"ゃ", "や"}, {"ゅ", "ゆ"}, {"ょ", "よ"}, {"ゎ", "わ"},
  };
  return removal_map;
}

constexpr size_t kMaxPreeditLength = 256;

}  // namespace

Composer::Composer()
    : Composer(&Table::GetDefaultTable(),
               &commands::Request::default_instance(),
               &config::ConfigHandler::DefaultConfig()) {}

Composer::Composer(const Table *table, const commands::Request *request,
                   const config::Config *config)
    : position_(0),
      input_mode_(transliteration::HIRAGANA),
      output_mode_(transliteration::HIRAGANA),
      comeback_input_mode_(transliteration::HIRAGANA),
      input_field_type_(commands::Context::NORMAL),
      shifted_sequence_count_(0),
      composition_(table),
      typing_corrector_(
          table, absl::GetFlag(FLAGS_max_typing_correction_query_candidates),
          absl::GetFlag(FLAGS_max_typing_correction_query_results)),
      max_length_(kMaxPreeditLength),
      request_(request),
      config_(config),
      is_new_input_(true) {
  SetInputMode(transliteration::HIRAGANA);
  if (config_ == nullptr) {
    config_ = &config::ConfigHandler::DefaultConfig();
  }
  typing_corrector_.SetConfig(config_);
  Reset();
}

Composer::Composer(const Composer &) = default;
Composer &Composer::operator=(const Composer &) = default;

Composer::~Composer() = default;

void Composer::Reset() {
  EditErase();
  ResetInputMode();
  SetOutputMode(transliteration::HIRAGANA);
  source_text_.assign("");
  typing_corrector_.Reset();
  timeout_threshold_msec_ = config_->composing_timeout_threshold_msec();
}

void Composer::ResetInputMode() { SetInputMode(comeback_input_mode_); }

void Composer::ReloadConfig() {
  // Do nothing at this moment.
}

bool Composer::Empty() const { return (GetLength() == 0); }

void Composer::SetTable(const Table *table) {
  composition_.SetTable(table);

  typing_corrector_.SetTable(table);
}

void Composer::SetRequest(const commands::Request *request) {
  request_ = request;
}

void Composer::SetConfig(const config::Config *config) {
  config_ = config;
  typing_corrector_.SetConfig(config);
}

void Composer::SetInputMode(transliteration::TransliterationType mode) {
  comeback_input_mode_ = mode;
  input_mode_ = mode;
  shifted_sequence_count_ = 0;
  is_new_input_ = true;
  composition_.SetInputMode(GetTransliterator(mode));
}

void Composer::SetTemporaryInputMode(
    transliteration::TransliterationType mode) {
  // Set comeback_input_mode_ to revert back the current input mode.
  comeback_input_mode_ = input_mode_;
  input_mode_ = mode;
  shifted_sequence_count_ = 0;
  is_new_input_ = true;
  composition_.SetInputMode(GetTransliterator(mode));
}

void Composer::UpdateInputMode() {
  if (position_ != 0 && request_->update_input_mode_from_surrounding_text()) {
    const Transliterators::Transliterator current_t12r =
        composition_.GetTransliterator(position_);
    if (position_ == composition_.GetLength() ||
        current_t12r == composition_.GetTransliterator(position_ + 1)) {
      // - The cursor is at the tail of composition.
      //   Use last character's transliterator as the input mode.
      // - If the current cursor is between the same character type like
      //   "A|B" and "あ|い", the input mode follows the character type.
      input_mode_ = GetTransliterationType(current_t12r, comeback_input_mode_);
      shifted_sequence_count_ = 0;
      is_new_input_ = true;
      composition_.SetInputMode(GetTransliterator(input_mode_));
      return;
    }
  }

  // Set the default input mode.
  SetInputMode(comeback_input_mode_);
}

transliteration::TransliterationType Composer::GetInputMode() const {
  return input_mode_;
}

transliteration::TransliterationType Composer::GetComebackInputMode() const {
  return comeback_input_mode_;
}

void Composer::ToggleInputMode() {
  if (input_mode_ == transliteration::HIRAGANA) {
    // TODO(komatsu): Refer user's perference.
    SetInputMode(transliteration::HALF_ASCII);
  } else {
    SetInputMode(transliteration::HIRAGANA);
  }
}

transliteration::TransliterationType Composer::GetOutputMode() const {
  return output_mode_;
}

void Composer::SetOutputMode(transliteration::TransliterationType mode) {
  output_mode_ = mode;
  composition_.SetTransliterator(0, composition_.GetLength(),
                                 GetTransliterator(mode));
  position_ = composition_.GetLength();
}

void Composer::ApplyTemporaryInputMode(const std::string &input,
                                       bool caps_locked) {
  DCHECK(!input.empty());

  const config::Config::ShiftKeyModeSwitch switch_mode =
      config_->shift_key_mode_switch();

  // When input is not an ASCII code, reset the input mode to the one before
  // temporary input mode.
  if (Util::OneCharLen(input.c_str()) != 1) {
    // Call SetInputMode() only when the current input mode is temporary, which
    // is detected by the if-condition below.  Without this check,
    // SetInputMode() is called always for multi-byte charactesrs.  This causes
    // a bug that multi-byte characters is inserted to a new chunk because
    // |is_new_input_| is set to true in SetInputMode(); see b/31444698.
    if (comeback_input_mode_ != input_mode_) {
      SetInputMode(comeback_input_mode_);
    }
    return;
  }

  // Input is an ASCII code.
  // we use first character to determin temporary input mode.
  const char key = input[0];
  const bool alpha_with_shift = (!caps_locked && ('A' <= key && key <= 'Z')) ||
                                (caps_locked && ('a' <= key && key <= 'z'));
  const bool alpha_without_shift =
      (caps_locked && ('A' <= key && key <= 'Z')) ||
      (!caps_locked && ('a' <= key && key <= 'z'));

  if (alpha_with_shift) {
    if (switch_mode == config::Config::ASCII_INPUT_MODE) {
      if (input_mode_ == transliteration::HALF_ASCII ||
          input_mode_ == transliteration::FULL_ASCII) {
        // Do nothing.
      } else {
        SetTemporaryInputMode(transliteration::HALF_ASCII);
      }
    } else if (switch_mode == config::Config::KATAKANA_INPUT_MODE) {
      if (input_mode_ == transliteration::HIRAGANA) {
        SetTemporaryInputMode(transliteration::FULL_KATAKANA);
      } else {
        // Do nothing.
      }
    }
    ++shifted_sequence_count_;
  } else if (alpha_without_shift) {
    // When shifted input continues, the next lower input is the end
    // of temporary half-width Ascii input.
    if (shifted_sequence_count_ > 1 &&
        switch_mode == config::Config::ASCII_INPUT_MODE) {
      SetInputMode(comeback_input_mode_);
    }
    if (switch_mode == config::Config::KATAKANA_INPUT_MODE) {
      SetInputMode(comeback_input_mode_);
    }
    shifted_sequence_count_ = 0;
  } else {
    // If the key is not an alphabet, reset shifted_sequence_count_
    // because "Continuous shifted input" feature should be reset
    // when the input meets non-alphabet character.
    shifted_sequence_count_ = 0;
  }
}

bool Composer::ProcessCompositionInput(const CompositionInput &input) {
  if (!EnableInsert()) {
    return false;
  }

  position_ = composition_.InsertInput(position_, input);
  is_new_input_ = false;
  typing_corrector_.InsertCharacter(input.raw(), input.probable_key_events());
  return true;
}

void Composer::InsertCharacter(const std::string &key) {
  CompositionInput input;
  input.InitFromRaw(key, is_new_input_);
  ProcessCompositionInput(input);
}

void Composer::InsertCommandCharacter(const InternalCommand internal_command) {
  switch (internal_command) {
    case REWIND:
      InsertCharacter(Table::ParseSpecialKey("{<}"));
      break;
    case STOP_KEY_TOGGLING:
      InsertCharacter(Table::ParseSpecialKey("{!}"));
      break;
    default:
      LOG(ERROR) << "Unknown command : " << internal_command;
  }
}

void Composer::InsertCharacterPreedit(const std::string &input) {
  size_t begin = 0;
  const size_t end = input.size();
  while (begin < end) {
    const size_t mblen = Util::OneCharLen(input.c_str() + begin);
    const std::string character(input, begin, mblen);
    if (!InsertCharacterKeyAndPreedit(character, character)) {
      return;
    }
    begin += mblen;
  }
  DCHECK_EQ(begin, end);
}

// Note: This method is only for test.
void Composer::SetPreeditTextForTestOnly(const std::string &input) {
  composition_.SetInputMode(Transliterators::RAW_STRING);
  size_t begin = 0;
  const size_t end = input.size();
  while (begin < end) {
    const size_t mblen = Util::OneCharLen(input.c_str() + begin);
    const std::string character(input, begin, mblen);
    CompositionInput input;
    input.set_raw(character);
    input.set_is_new_input(is_new_input_);
    position_ = composition_.InsertInput(position_, input);
    is_new_input_ = false;
    begin += mblen;
  }
  DCHECK_EQ(begin, end);

  std::string lower_input = input;
  Util::LowerString(&lower_input);
  if (Util::IsLowerAscii(lower_input)) {
    // Fake input mode.
    // This is useful to test the behavior of alphabet keyboard.
    SetTemporaryInputMode(transliteration::HALF_ASCII);
  }
}

bool Composer::InsertCharacterKeyAndPreedit(const std::string &key,
                                            const std::string &preedit) {
  CompositionInput input;
  input.InitFromRawAndConv(key, preedit, is_new_input_);
  return ProcessCompositionInput(input);
}

bool Composer::InsertCharacterKeyEvent(const commands::KeyEvent &key) {
  if (!EnableInsert()) {
    return false;
  }

  // Check timeout.
  // If the duration from the previous input is over than the threshold,
  // A STOP_KEY_TOGGLING command is sent before the key input.
  if (timeout_threshold_msec_ > 0) {
    int64_t current_msec = key.has_timestamp_msec()
                               ? key.timestamp_msec()
                               : absl::ToUnixMillis(Clock::GetAbslTime());
    if (timestamp_msec_ > 0 &&
        current_msec - timestamp_msec_ >= timeout_threshold_msec_) {
      InsertCommandCharacter(STOP_KEY_TOGGLING);
    }
    timestamp_msec_ = current_msec;
  }

  if (key.has_mode()) {
    const transliteration::TransliterationType new_input_mode =
        GetTransliterationTypeFromCompositionMode(key.mode());
    if (new_input_mode != input_mode_) {
      // Only when the new input mode is different from the current
      // input mode, SetInputMode is called.  Otherwise the value of
      // comeback_input_mode_ is lost.
      SetInputMode(new_input_mode);
    }
  }

  // If only SHIFT is pressed, this is used to revert back to the
  // previous input mode.
  if (!key.has_key_code()) {
    for (size_t i = 0; key.modifier_keys_size(); ++i) {
      if (key.modifier_keys(i) == commands::KeyEvent::SHIFT) {
        // TODO(komatsu): Enable to customize the behavior.
        SetInputMode(comeback_input_mode_);
        return true;
      }
    }
  }

  CompositionInput input;
  if (!input.Init(key, config_->use_typing_correction(), is_new_input_)) {
    return false;
  }

  if (key.has_key_string()) {
    if (key.input_style() == commands::KeyEvent::AS_IS ||
        key.input_style() == commands::KeyEvent::DIRECT_INPUT) {
      composition_.SetInputMode(Transliterators::CONVERSION_STRING);
      // Disable typing correction mainly for Android. b/258369101
      typing_corrector_.Invalidate();
      ProcessCompositionInput(input);
      SetInputMode(comeback_input_mode_);
    } else {
      // Kana input usually has key_string.  Note that, the existence of
      // key_string never determine if the input mode is Kana or Romaji.
      ProcessCompositionInput(input);
    }
  } else {
    // Romaji input usually does not has key_string.  Note that, the
    // existence of key_string never determines if the input mode is
    // Kana or Romaji.
    const uint32_t modifiers = KeyEventUtil::GetModifiers(key);
    ApplyTemporaryInputMode(input.raw(), KeyEventUtil::HasCaps(modifiers));
    ProcessCompositionInput(input);
  }

  if (comeback_input_mode_ == input_mode_) {
    AutoSwitchMode();
  }
  return true;
}

void Composer::DeleteAt(size_t pos) {
  composition_.DeleteAt(pos);
  // Adjust cursor position for composition mode.
  if (position_ > pos) {
    position_--;
  }
  // We do not call UpdateInputMode() here.
  // 1. In composition mode, UpdateInputMode finalizes pending chunk.
  // 2. In conversion mode, InputMode needs not to change.
  typing_corrector_.Invalidate();
}

void Composer::Delete() {
  position_ = composition_.DeleteAt(position_);
  UpdateInputMode();

  typing_corrector_.Invalidate();
}

void Composer::DeleteRange(size_t pos, size_t length) {
  for (int i = 0; i < length && pos < composition_.GetLength(); ++i) {
    DeleteAt(pos);
  }
  typing_corrector_.Invalidate();
}

void Composer::EditErase() {
  composition_.Erase();
  position_ = 0;
  SetInputMode(comeback_input_mode_);
  typing_corrector_.Reset();
}

void Composer::Backspace() {
  if (position_ == 0) {
    return;
  }

  // In the view point of updating input mode,
  // backspace is special case because new input mode is based on both
  // new current character and *character to be deleted*.

  // At first, move to left.
  // Now the cursor is between 'new current character'
  // and 'character to be deleted'.
  --position_;

  // Update input mode based on both 'new current character' and
  // 'character to be deleted'.
  UpdateInputMode();

  // Delete 'character to be deleted'
  position_ = composition_.DeleteAt(position_);

  typing_corrector_.Invalidate();
}

void Composer::MoveCursorLeft() {
  if (position_ > 0) {
    --position_;
  }
  UpdateInputMode();

  typing_corrector_.Invalidate();
}

void Composer::MoveCursorRight() {
  if (position_ < composition_.GetLength()) {
    ++position_;
  }
  UpdateInputMode();

  typing_corrector_.Invalidate();
}

void Composer::MoveCursorToBeginning() {
  position_ = 0;
  SetInputMode(comeback_input_mode_);

  typing_corrector_.Invalidate();
}

void Composer::MoveCursorToEnd() {
  position_ = composition_.GetLength();
  // Behavior between MoveCursorToEnd and MoveCursorToRight is different.
  // MoveCursorToEnd always makes current input mode default.
  SetInputMode(comeback_input_mode_);

  typing_corrector_.Invalidate();
}

void Composer::MoveCursorTo(uint32_t new_position) {
  if (new_position <= composition_.GetLength()) {
    position_ = new_position;
    UpdateInputMode();
  }
  typing_corrector_.Invalidate();
}

void Composer::GetPreedit(std::string *left, std::string *focused,
                          std::string *right) const {
  DCHECK(left);
  DCHECK(focused);
  DCHECK(right);
  composition_.GetPreedit(position_, left, focused, right);

  // TODO(komatsu): This function can be obsolete.
  std::string preedit = *left + *focused + *right;
  if (TransformCharactersForNumbers(&preedit)) {
    const size_t left_size = Util::CharsLen(*left);
    const size_t focused_size = Util::CharsLen(*focused);
    Util::Utf8SubString(preedit, 0, left_size, left);
    Util::Utf8SubString(preedit, left_size, focused_size, focused);
    Util::Utf8SubString(preedit, left_size + focused_size, std::string::npos,
                        right);
  }
}

void Composer::GetStringForPreedit(std::string *output) const {
  composition_.GetString(output);
  TransformCharactersForNumbers(output);
  // If the input field type needs half ascii characters,
  // perform conversion here.
  // Note that this purpose is also achieved by the client by setting
  // input type as "half ascii".
  // But the architecture of Mozc expects the server to handle such character
  // width management.
  // In addition, we also think about PASSWORD field type.
  // we can prepare NUMBER and TEL keyboard layout, which has
  // "half ascii" composition mode. This works.
  // But we will not have PASSWORD only keyboard. We will share the basic
  // keyboard on usual and password mode
  // so such hacky code cannot be applicable.
  // TODO(matsuzakit): Move this logic to another appopriate location.
  // SetOutputMode() is not currently applicable but ideally it is
  // better location than here.
  const commands::Context::InputFieldType field_type = GetInputFieldType();
  if (field_type == commands::Context::NUMBER ||
      field_type == commands::Context::PASSWORD ||
      field_type == commands::Context::TEL) {
    const std::string tmp = *output;
    japanese_util::FullWidthAsciiToHalfWidthAscii(tmp, output);
  }
}

void Composer::GetStringForSubmission(std::string *output) const {
  // TODO(komatsu): We should make sure if we can integrate this
  // function to GetStringForPreedit after a while.
  GetStringForPreedit(output);
}

void Composer::GetQueryForConversion(std::string *output) const {
  std::string base_output;
  composition_.GetStringWithTrimMode(FIX, &base_output);
  TransformCharactersForNumbers(&base_output);
  japanese_util::FullWidthAsciiToHalfWidthAscii(base_output, output);
}

namespace {
// Determine which query is suitable for a prediction query and return
// its pointer.
// Example:
// = Romanji Input =
// ("もz", "も") -> "も"  // a part of romanji should be trimed.
// ("もzky", "もz") -> "もzky"  // a user might intentionally typed them.
// ("z", "") -> "z"      // ditto.
// = Kana Input =
// ("か", "") -> "か"  // a part of kana (it can be "が") should not be trimed.
std::string *GetBaseQueryForPrediction(std::string *asis_query,
                                       std::string *trimed_query) {
  // If the sizes are equal, there is no matter.
  if (asis_query->size() == trimed_query->size()) {
    return asis_query;
  }

  // Get the different part between asis_query and trimed_query.  For
  // example, "ky" is the different part where asis_query is "もzky"
  // and trimed_query is "もz".
  DCHECK_GT(asis_query->size(), trimed_query->size());
  const std::string asis_tail(*asis_query, trimed_query->size());
  DCHECK(!asis_tail.empty());

  // If the different part is not an alphabet, asis_query is used.
  // This check is mainly used for Kana Input.
  const Util::ScriptType asis_tail_type = Util::GetScriptType(asis_tail);
  if (asis_tail_type != Util::ALPHABET) {
    return asis_query;
  }

  // If the trimed_query is empty and asis_query is alphabet, an asis
  // string is used because the query may be typed intentionally.
  if (trimed_query->empty()) {  // alphabet???
    const Util::ScriptType asis_type = Util::GetScriptType(*asis_query);
    if (asis_type == Util::ALPHABET) {
      return asis_query;
    } else {
      return trimed_query;
    }
  }

  // Now there are two patterns: ("もzk", "もz") and ("もずk", "もず").
  // We assume "もzk" is user's intentional query, but "もずk" is not.
  // So our results are:
  // ("もzk", "もz") => "もzk" and ("もずk", "もず") => "もず".
  const absl::string_view trimed_tail = Util::Utf8SubString(
      *trimed_query, Util::CharsLen(*trimed_query) - 1, std::string::npos);
  DCHECK(!trimed_tail.empty());
  const Util::ScriptType trimed_tail_type = Util::GetScriptType(trimed_tail);
  if (trimed_tail_type == Util::ALPHABET) {
    return asis_query;
  } else {
    return trimed_query;
  }
}
}  // namespace

void Composer::GetQueryForPrediction(std::string *output) const {
  std::string asis_query;
  composition_.GetStringWithTrimMode(ASIS, &asis_query);

  switch (input_mode_) {
    case transliteration::HALF_ASCII: {
      output->assign(asis_query);
      return;
    }
    case transliteration::FULL_ASCII: {
      japanese_util::FullWidthAsciiToHalfWidthAscii(asis_query, output);
      return;
    }
    default: {
    }
  }

  std::string trimed_query;
  composition_.GetStringWithTrimMode(TRIM, &trimed_query);

  // NOTE(komatsu): This is a hack to go around the difference
  // expectation between Romanji-Input and Kana-Input.  "かn" in
  // Romaji-Input should be "か" while "あか" in Kana-Input should be
  // "あか", although "かn" and "あか" have the same properties.  An
  // ideal solution is to expand the ambguity and pass all of them to
  // the converter. (e.g. "かn" -> ["かな",..."かの", "かん", ...] /
  // "あか" -> ["あか", "あが"])
  std::string *base_query =
      GetBaseQueryForPrediction(&asis_query, &trimed_query);
  TransformCharactersForNumbers(base_query);
  japanese_util::FullWidthAsciiToHalfWidthAscii(*base_query, output);
}

void Composer::GetQueriesForPrediction(std::string *base,
                                       std::set<std::string> *expanded) const {
  DCHECK(base);
  DCHECK(expanded);
  // In case of the Latin input modes, we don't perform expansion.
  switch (input_mode_) {
    case transliteration::HALF_ASCII:
    case transliteration::FULL_ASCII: {
      GetQueryForPrediction(base);
      expanded->clear();
      return;
    }
    default: {
    }
  }
  std::string base_query;
  composition_.GetExpandedStrings(&base_query, expanded);
  // The above `GetExpandedStrings` generates expansion for modifier key as
  // well, e.g., if the composition is "ざ", `expanded` contains "さ" too.
  // However, "ざ" is usually composed by explicitly hitting the modifier key.
  // So we don't want to generate prediction from "さ" in this case. The
  // following code removes such unnecessary expansion.
  std::string asis;
  composition_.GetStringWithTrimMode(ASIS, &asis);
  const std::string trailing = asis.substr(base_query.size());
  for (auto [iter, end] = GetModifierRemovalMap()->equal_range(trailing);
       iter != end; ++iter) {
    expanded->erase(iter->second);
  }

  japanese_util::FullWidthAsciiToHalfWidthAscii(base_query, base);
}

void Composer::GetTypeCorrectedQueriesForPrediction(
    std::vector<TypeCorrectedQuery> *queries) const {
  typing_corrector_.GetQueriesForPrediction(queries);
}

size_t Composer::GetLength() const { return composition_.GetLength(); }

size_t Composer::GetCursor() const { return position_; }

void Composer::GetTransliteratedText(Transliterators::Transliterator t12r,
                                     const size_t position, const size_t size,
                                     std::string *result) const {
  DCHECK(result);
  std::string full_base;
  composition_.GetStringWithTransliterator(t12r, &full_base);

  const size_t t13n_start =
      composition_.ConvertPosition(position, Transliterators::LOCAL, t12r);
  const size_t t13n_end = composition_.ConvertPosition(
      position + size, Transliterators::LOCAL, t12r);
  const size_t t13n_size = t13n_end - t13n_start;

  Util::Utf8SubString(full_base, t13n_start, t13n_size, result);
}

void Composer::GetRawString(std::string *raw_string) const {
  GetRawSubString(0, GetLength(), raw_string);
}

void Composer::GetRawSubString(const size_t position, const size_t size,
                               std::string *raw_sub_string) const {
  DCHECK(raw_sub_string);
  GetTransliteratedText(Transliterators::RAW_STRING, position, size,
                        raw_sub_string);
}

void Composer::GetTransliterations(
    transliteration::Transliterations *t13ns) const {
  GetSubTransliterations(0, GetLength(), t13ns);
}

void Composer::GetSubTransliteration(
    const transliteration::TransliterationType type, const size_t position,
    const size_t size, std::string *transliteration) const {
  const Transliterators::Transliterator t12r = GetTransliterator(type);
  std::string result;
  GetTransliteratedText(t12r, position, size, &result);
  transliteration->clear();
  Transliterate(type, result, transliteration);
}

void Composer::GetSubTransliterations(
    const size_t position, const size_t size,
    transliteration::Transliterations *transliterations) const {
  std::string t13n;
  for (size_t i = 0; i < transliteration::NUM_T13N_TYPES; ++i) {
    const transliteration::TransliterationType t13n_type =
        transliteration::TransliterationTypeArray[i];
    GetSubTransliteration(t13n_type, position, size, &t13n);
    transliterations->push_back(t13n);
  }
}

bool Composer::EnableInsert() const {
  if (GetLength() >= max_length_) {
    // do not accept long chars to prevent DOS attack.
    LOG(WARNING) << "The length is too long.";
    return false;
  }
  return true;
}

void Composer::AutoSwitchMode() {
  if (!config_->use_auto_ime_turn_off()) {
    return;
  }

  // AutoSwitchMode is only available on Roma input
  if (config_->preedit_method() != config::Config::ROMAN) {
    return;
  }

  std::string key;
  // Key should be in half-width alphanumeric.
  composition_.GetStringWithTransliterator(
      GetTransliterator(transliteration::HALF_ASCII), &key);

  ModeSwitchingHandler::ModeSwitching display_mode =
      ModeSwitchingHandler::NO_CHANGE;
  ModeSwitchingHandler::ModeSwitching input_mode =
      ModeSwitchingHandler::NO_CHANGE;
  if (!ModeSwitchingHandler::GetModeSwitchingHandler()->GetModeSwitchingRule(
          key, &display_mode, &input_mode)) {
    // If the key is not a pattern of mode switch rule, the procedure
    // stops here.
    return;
  }

  // |display_mode| affects the existing composition the user typed.
  switch (display_mode) {
    case ModeSwitchingHandler::NO_CHANGE:
      // Do nothing.
      break;
    case ModeSwitchingHandler::REVERT_TO_PREVIOUS_MODE:
      // Invalid value for display_mode
      LOG(ERROR) << "REVERT_TO_PREVIOUS_MODE is an invalid value "
                 << "for display_mode.";
      break;
    case ModeSwitchingHandler::PREFERRED_ALPHANUMERIC:
      if (input_mode_ == transliteration::FULL_ASCII) {
        SetOutputMode(transliteration::FULL_ASCII);
      } else {
        SetOutputMode(transliteration::HALF_ASCII);
      }
      break;
    case ModeSwitchingHandler::HALF_ALPHANUMERIC:
      SetOutputMode(transliteration::HALF_ASCII);
      break;
    case ModeSwitchingHandler::FULL_ALPHANUMERIC:
      SetOutputMode(transliteration::FULL_ASCII);
      break;
    default:
      LOG(ERROR) << "Unknown value: " << display_mode;
      break;
  }

  // |input_mode| affects the current input mode used for the user's
  // new typing.
  switch (input_mode) {
    case ModeSwitchingHandler::NO_CHANGE:
      // Do nothing.
      break;
    case ModeSwitchingHandler::REVERT_TO_PREVIOUS_MODE:
      SetInputMode(comeback_input_mode_);
      break;
    case ModeSwitchingHandler::PREFERRED_ALPHANUMERIC:
      if (input_mode_ != transliteration::HALF_ASCII &&
          input_mode_ != transliteration::FULL_ASCII) {
        SetTemporaryInputMode(transliteration::HALF_ASCII);
      }
      break;
    case ModeSwitchingHandler::HALF_ALPHANUMERIC:
      if (input_mode_ != transliteration::HALF_ASCII) {
        SetTemporaryInputMode(transliteration::HALF_ASCII);
      }
      break;
    case ModeSwitchingHandler::FULL_ALPHANUMERIC:
      if (input_mode_ != transliteration::FULL_ASCII) {
        SetTemporaryInputMode(transliteration::FULL_ASCII);
      }
      break;
    default:
      LOG(ERROR) << "Unknown value: " << display_mode;
      break;
  }
}

bool Composer::ShouldCommit() const { return composition_.ShouldCommit(); }

bool Composer::ShouldCommitHead(size_t *length_to_commit) const {
  size_t max_remaining_composition_length;
  switch (GetInputFieldType()) {
    case commands::Context::PASSWORD:
      max_remaining_composition_length = 1;
      break;
    case commands::Context::TEL:
    case commands::Context::NUMBER:
      max_remaining_composition_length = 0;
      break;
    default:
      // No need to commit. Return here.
      return false;
  }
  if (GetLength() > max_remaining_composition_length) {
    *length_to_commit = GetLength() - max_remaining_composition_length;
    return true;
  }
  return false;
}

namespace {
enum Script {
  ALPHABET,   // alphabet characters or symbols
  NUMBER,     // 0 - 9, "0" - "9"
  JA_HYPHEN,  // "ー"
  JA_COMMA,   // "、"
  JA_PERIOD,  // "。"
  OTHER,
};

bool IsAlphabetOrNumber(const Script script) {
  return (script == ALPHABET) || (script == NUMBER);
}
}  // namespace

// static
bool Composer::TransformCharactersForNumbers(std::string *query) {
  if (query == nullptr) {
    LOG(ERROR) << "query is nullptr";
    return false;
  }

  // Create a vector of scripts of query characters to avoid
  // processing query string many times.
  const size_t chars_len = Util::CharsLen(*query);
  std::vector<Script> char_scripts;
  char_scripts.reserve(chars_len);

  // flags to determine whether continue to the next step.
  bool has_symbols = false;
  bool has_alphanumerics = false;
  for (ConstChar32Iterator iter(*query); !iter.Done(); iter.Next()) {
    const char32_t one_char = iter.Get();
    switch (one_char) {
      case 0x30FC:  // "ー"
        has_symbols = true;
        char_scripts.push_back(JA_HYPHEN);
        break;
      case 0x3001:  // "、"
        has_symbols = true;
        char_scripts.push_back(JA_COMMA);
        break;
      case 0x3002:  // "。"
        has_symbols = true;
        char_scripts.push_back(JA_PERIOD);
        break;
      case '+':
      case '*':
      case '/':
      case '=':
      case '(':
      case ')':
      case '<':
      case '>':
      case 0xFF0B:  // "+"
      case 0xFF0A:  // "*"
      case 0xFF0F:  // "/"
      case 0xFF1D:  // "="
      case 0xFF08:  // "("
      case 0xFF09:  // ")"
      case 0xFF1C:  // "<"
      case 0xFF1E:  // ">"
        char_scripts.push_back(ALPHABET);
        break;
      default: {
        Util::ScriptType script_type = Util::GetScriptType(one_char);
        if (script_type == Util::NUMBER) {
          has_alphanumerics = true;
          char_scripts.push_back(NUMBER);
        } else if (script_type == Util::ALPHABET) {
          has_alphanumerics = true;
          char_scripts.push_back(ALPHABET);
        } else {
          char_scripts.push_back(OTHER);
        }
      }
    }
  }

  DCHECK_EQ(chars_len, char_scripts.size());
  if (!has_alphanumerics || !has_symbols) {
    VLOG(1) << "The query contains neither alphanumeric nor symbol.";
    return false;
  }

  std::string transformed_query;
  bool transformed = false;
  size_t i = 0;
  std::string append_char;
  for (ConstChar32Iterator iter(*query); !iter.Done(); iter.Next(), ++i) {
    append_char.clear();
    switch (char_scripts[i]) {
      case JA_HYPHEN: {
        // JA_HYPHEN(s) "ー" is/are transformed to "−" if:
        // (i) query has one and only one leading JA_HYPHEN followed by a
        //     number,
        // (ii) JA_HYPHEN(s) follow(s) after an alphanumeric (ex. 0-, 0----,
        //     etc).
        // Note that rule (i) implies that if query starts with more than
        // one JA_HYPHENs, those JA_HYPHENs are not transformed.
        bool check = false;
        if (i == 0 && chars_len > 1) {
          check = (char_scripts[1] == NUMBER);
        } else {
          for (size_t j = i; j > 0; --j) {
            if (char_scripts[j - 1] == JA_HYPHEN) {
              continue;
            }
            check = IsAlphabetOrNumber(char_scripts[j - 1]);
            break;
          }
        }

        // JA_HYPHEN should be transformed to MINUS.
        if (check) {
          CharacterFormManager::GetCharacterFormManager()->ConvertPreeditString(
              "−",  // U+2212
              &append_char);
          DCHECK(!append_char.empty());
        }
        break;
      }

      case JA_COMMA: {
        // "、" should be "," if the previous character is alphanumerics.
        // character are both alphanumerics.
        // Previous char should exist and be a number.
        const bool lhs_check =
            (i > 0 && IsAlphabetOrNumber(char_scripts[i - 1]));
        // JA_COMMA should be transformed to COMMA.
        if (lhs_check) {
          CharacterFormManager::GetCharacterFormManager()->ConvertPreeditString(
              ",", &append_char);
          DCHECK(!append_char.empty());
        }
        break;
      }

      case JA_PERIOD: {
        // "。" should be "." if the previous character and the next
        // character are both alphanumerics.
        // Previous char should exist and be a number.
        const bool lhs_check =
            (i > 0 && IsAlphabetOrNumber(char_scripts[i - 1]));
        // JA_PRERIOD should be transformed to PRERIOD.
        if (lhs_check) {
          CharacterFormManager::GetCharacterFormManager()->ConvertPreeditString(
              ".", &append_char);
          DCHECK(!append_char.empty());
        }
        break;
      }

      default: {
        // Do nothing.
      }
    }

    if (append_char.empty()) {
      // Append one character.
      Util::Ucs4ToUtf8Append(iter.Get(), &transformed_query);
    } else {
      // Append the transformed character.
      transformed_query.append(append_char);
      transformed = true;
    }
  }
  if (!transformed) {
    return false;
  }

  // It is possible that the query's size in byte differs from the
  // orig_query's size in byte.
  DCHECK_EQ(Util::CharsLen(*query), Util::CharsLen(transformed_query));
  *query = transformed_query;
  return true;
}

void Composer::SetNewInput() { is_new_input_ = true; }

bool Composer::IsToggleable() const {
  // When |is_new_input_| is true, a new chunk is always created and, hence, key
  // toggling never happens regardless of the composition state.
  return !is_new_input_ && composition_.IsToggleable(position_);
}

bool Composer::is_new_input() const { return is_new_input_; }

size_t Composer::shifted_sequence_count() const {
  return shifted_sequence_count_;
}

const std::string &Composer::source_text() const { return source_text_; }
std::string *Composer::mutable_source_text() { return &source_text_; }
void Composer::set_source_text(const std::string &source_text) {
  source_text_.assign(source_text);
}

size_t Composer::max_length() const { return max_length_; }
void Composer::set_max_length(size_t length) { max_length_ = length; }

int Composer::timeout_threshold_msec() const { return timeout_threshold_msec_; }

void Composer::set_timeout_threshold_msec(int threshold_msec) {
  timeout_threshold_msec_ = threshold_msec;
}

void Composer::SetInputFieldType(commands::Context::InputFieldType type) {
  input_field_type_ = type;
}

commands::Context::InputFieldType Composer::GetInputFieldType() const {
  return input_field_type_;
}
}  // namespace composer
}  // namespace mozc


text:
package org.wildfly.extras.creaper.commands.elytron.mapper;

import org.wildfly.extras.creaper.core.online.OnlineCommand;
import org.wildfly.extras.creaper.core.online.OnlineCommandContext;
import org.wildfly.extras.creaper.core.online.operations.Address;
import org.wildfly.extras.creaper.core.online.operations.Operations;
import org.wildfly.extras.creaper.core.online.operations.Values;
import org.wildfly.extras.creaper.core.online.operations.admin.Administration;

public final class AddRegexValidatingPrincipalTransformer implements OnlineCommand {

    private final String name;
    private final String pattern;
    private final Boolean match;
    private final boolean replaceExisting;

    private AddRegexValidatingPrincipalTransformer(Builder builder) {
        this.name = builder.name;
        this.pattern = builder.pattern;
        this.match = builder.match;
        this.replaceExisting = builder.replaceExisting;
    }

    @Override
    public void apply(OnlineCommandContext ctx) throws Exception {
        Operations ops = new Operations(ctx.client);
        Address regexPrincipalTransformerAddress = Address.subsystem("elytron").and("regex-validating-principal-transformer",
                name);
        if (replaceExisting) {
            ops.removeIfExists(regexPrincipalTransformerAddress);
            new Administration(ctx.client).reloadIfRequired();
        }

        ops.add(regexPrincipalTransformerAddress, Values.empty()
                .and("pattern", pattern)
                .and("match", match)
                .andOptional("replace-all", match));
    }

    public static final class Builder {

        private final String name;
        private String pattern;
        private Boolean match;
        private boolean replaceExisting;

        public Builder(String name) {
            if (name == null) {
                throw new IllegalArgumentException("Name of the regex-validating-principal-transformer must be specified as non null value");
            }
            if (name.isEmpty()) {
                throw new IllegalArgumentException("Name of the regex-validating-principal-transformer must not be empty value");
            }
            this.name = name;
        }

        public Builder pattern(String pattern) {
            this.pattern = pattern;
            return this;
        }

        public Builder match(boolean match) {
            this.match = match;
            return this;
        }

        public Builder replaceExisting() {
            this.replaceExisting = true;
            return this;
        }

        public AddRegexValidatingPrincipalTransformer build() {
            if (pattern == null || pattern.isEmpty()) {
                throw new IllegalArgumentException("Pattern must not be null and must have a minimum length of 1 character");
            }
            if (match == null) {
                throw new IllegalArgumentException("Match must not be null");
            }
            return new AddRegexValidatingPrincipalTransformer(this);
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
//
//  YTAVPlayerCtrlView.h
//  YTAVPlayer
//
//  Created by songyutao on 16/9/9.
//  Copyright © 2016年 Creditease. All rights reserved.
//

#import <UIKit/UIKit.h>

typedef NS_ENUM(NSUInteger, GestureMoveDirection)
{
    kGestureMoveDirectionNone,
    kGestureMoveDirectionUp,
    kGestureMoveDirectionDown,
    kGestureMoveDirectionRight,
    kGestureMoveDirectionLeft
};

@class YTAVPlayerView;
@interface YTAVPlayerCtrlView : UIControl

@property(nonatomic, weak  )YTAVPlayerView          *container;

@property(nonatomic, strong)UIButton                *ctrlButton;
@property(nonatomic, strong)UIButton                *backButton;

@property(nonatomic, strong)UILabel                 *currentTimeLabel;
@property(nonatomic, strong)UILabel                 *totalTimeLabel;
@property(nonatomic, strong)UILabel                 *titleLabel;

@property(nonatomic, strong)UIView                  *totalView;
@property(nonatomic, strong)UIView                  *bufferView;
@property(nonatomic, strong)UIView                  *currentView;
@property(nonatomic, strong)UIImageView             *dragView;
@property(nonatomic, strong)UIButton                *ctrlScreenButton;

@property(atomic, assign)UInt16                     current;       //当前秒
@property(atomic, assign)UInt16                     total;         //总秒
@property(atomic, assign)CGFloat                    bufferPercent; //缓冲百分比
@property(nonatomic, assign)BOOL                    seeking;       //手势定位中

@property(nonatomic, assign)BOOL                    liveMode;

@property(nonatomic, strong)UIPanGestureRecognizer  *panRecognizer;

/**
 *  更新播放时间、进度及缓冲
 *
 *  @param current 当前播放秒数时间
 *  @param total   总秒数时间
 *  @param bufferPercent  缓冲百分比
 */
- (void)updateProgress:(UInt16)current total:(UInt16)total bufferPercent:(CGFloat)bufferPercent;

/**
 *  只用于滑动屏幕seek时做动画使用
 *
 *  @param seekDistance 定位位置
 */
- (void)updateProgressAni:(CGFloat)seekDistance;

@end


text:
'use strict';

//Events service used for communicating with the events REST endpoints
angular.module('events').factory('Events', ['$resource',
  function ($resource) {
    return $resource('api/events/:eventId', {
      eventId: '@_id'
    }, {
      update: {
        method: 'PUT'
      }
    });
  }
]);


text:
#include "config.h"
#include "FrameTestHelpers.h"

#include "URLTestHelpers.h"
#include "wtf/StdLibExtras.h"
#include "WebFrame.h"
#include "WebFrameClient.h"
#include "WebSettings.h"
#include "WebView.h"
#include "WebViewClient.h"
#include "public/platform/Platform.h"
#include "public/platform/WebString.h"
#include "public/platform/WebThread.h"
#include "public/platform/WebURLRequest.h"
#include "public/platform/WebURLResponse.h"
#include "public/platform/WebUnitTestSupport.h"

namespace WebKit {
namespace FrameTestHelpers {

void loadFrame(WebFrame* frame, const std::string& url)
{
    WebURLRequest urlRequest;
    urlRequest.initialize();
    urlRequest.setURL(URLTestHelpers::toKURL(url));
    frame->loadRequest(urlRequest);
}

class TestWebFrameClient : public WebFrameClient {
};

static WebFrameClient* defaultWebFrameClient()
{
    DEFINE_STATIC_LOCAL(TestWebFrameClient, client, ());
    return &client;
}

class TestWebViewClient : public WebViewClient {
};

static WebViewClient* defaultWebViewClient()
{
    DEFINE_STATIC_LOCAL(TestWebViewClient,  client, ());
    return &client;
}

WebView* createWebView(bool enableJavascript, WebFrameClient* webFrameClient, WebViewClient* webViewClient)
{
    if (!webFrameClient)
        webFrameClient = defaultWebFrameClient();
    if (!webViewClient)
        webViewClient = defaultWebViewClient();
    WebView* webView = WebView::create(webViewClient);
    webView->settings()->setJavaScriptEnabled(enableJavascript);
    webView->settings()->setDeviceSupportsMouse(false);
    webView->settings()->setForceCompositingMode(true);
    webView->initializeMainFrame(webFrameClient);

    return webView;
}

WebView* createWebViewAndLoad(const std::string& url, bool enableJavascript, WebFrameClient* webFrameClient, WebViewClient* webViewClient)
{
    WebView* webView = createWebView(enableJavascript, webFrameClient, webViewClient);

    loadFrame(webView->mainFrame(), url);
    Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();

    return webView;
}

class QuitTask : public WebThread::Task {
public:
    virtual void run()
    {
        Platform::current()->currentThread()->exitRunLoop();
    }
};

void runPendingTasks()
{
    Platform::current()->currentThread()->postTask(new QuitTask);
    Platform::current()->currentThread()->enterRunLoop();
}

} // namespace FrameTestHelpers
} // namespace WebKit


text:
<?php

namespace Flarum\Debug\Console;

use Flarum\Admin\WebApp as AdminWebApp;
use Flarum\Console\Command\AbstractCommand;
use Flarum\Forum\WebApp as ForumWebApp;
use Illuminate\Contracts\Cache\Store;

class CacheClearCommand extends AbstractCommand
{
    /**
     * @var \Illuminate\Contracts\Cache\Store
     */
    protected $cache;

    /**
     * @var \Flarum\Forum\WebApp
     */
    protected $forum;

    /**
     * @var \Flarum\Admin\WebApp
     */
    protected $admin;

    /**
     * @param Store $cache
     * @param ForumWebApp $forum
     * @param AdminWebApp $admin
     */
    public function __construct(Store $cache, ForumWebApp $forum, AdminWebApp $admin)
    {
        $this->cache = $cache;
        $this->forum = $forum;
        $this->admin = $admin;

        parent::__construct();
    }

    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this
            ->setName('cache:clear')
            ->setDescription('Remove all temporary and generated files');
    }

    /**
     * {@inheritdoc}
     */
    protected function fire()
    {
        $this->info('Clearing the cache...');

        $this->forum->getAssets()->flush();
        $this->admin->getAssets()->flush();

        $this->cache->flush();
    }
}


text:
<!DOCTYPE html>

	  {% seo %}
    {% include meta.html %}

    <link rel="stylesheet" type="text/css" href="{{ site.baseurl }}/style.css" />
    <link rel="alternate" type="application/rss+xml" title="{{ site.name }} - {{ site.description }}" href="{{ site.baseurl }}/feed.xml" />
    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?">

{{ site.name }}

{{ site.description }}

            Blog
            About

      {{ content }}

          〈 Back
          {% include svg-icons.html %}
          Top ↑

    {% include analytics.html %}


text:
<?xml version="1.0" encoding="utf-8"?>

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_enabled="false" android:drawable="@color/float_label_disabled" />

    <item android:drawable="@color/float_label"/>

</selector>


text:
from __future__ import print_function
# Time:  O(n)
# Space: O(1)
#
# Two elements of a binary search tree (BST) are swapped by mistake.
#
# Recover the tree without changing its structure.
#
# Note:
# A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?
#

# Definition for a  binary tree node
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

    def __repr__(self):
        if self:
            serial = []
            queue = [self]

            while queue:
                cur = queue[0]

                if cur:
                    serial.append(cur.val)
                    queue.append(cur.left)
                    queue.append(cur.right)
                else:
                    serial.append("#")

                queue = queue[1:]

            while serial[-1] == "#":
                serial.pop()

            return repr(serial)

        else:
            return None

class Solution:
    # @param root, a tree node
    # @return a tree node
    def recoverTree(self, root):
        return self.MorrisTraversal(root)

    def MorrisTraversal(self, root):
        if root is None:
            return
        broken = [None, None]
        pre, cur = None, root

        while cur:
            if cur.left is None:
                self.detectBroken(broken, pre, cur)
                pre = cur
                cur = cur.right
            else:
                node = cur.left
                while node.right and node.right != cur:
                    node = node.right

                if node.right is None:
                    node.right =cur
                    cur = cur.left
                else:
                    self.detectBroken(broken, pre, cur)
                    node.right = None
                    pre = cur
                    cur = cur.right

        broken[0].val, broken[1].val = broken[1].val, broken[0].val

        return root

    def detectBroken(self, broken, pre, cur):
        if pre and pre.val > cur.val:
            if broken[0] is None:
                broken[0] = pre
            broken[1] = cur

if __name__ == "__main__":
    root = TreeNode(0)
    root.left = TreeNode(1)
    print(root)
    print(Solution().recoverTree(root))


text:
<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="chrome=1">
    <title>R4S11 » {{ page.title }}</title>
    {% if page.description %}<meta name="description" content="{{ page.description }}">{% endif %}
    <meta name="author" content="{{ site.author.name }}">

    <link href="{{ ASSET_PATH }}/styles.css?body=1" rel="stylesheet" type="text/css" media="all">
    <link href="{{ ASSET_PATH }}/pygment_trac.css?body=1" rel="stylesheet" type="text/css" media="all">

    <link rel="alternate" type="application/atom+xml" href="{{ BASE_PATH }}/atom.xml"/>

    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">

          {{ site.title }}

Programmer, Snowboarder, Dota-er.

        {{site.author.github}}

        {{site.author.stackoverflow.name}}

        {{site.author.linkedin.name}}

          {% assign pages_list = site.pages %}
          {% assign group = 'navigation' %}
          {% include JB/pages_list %}

> Resume

          {{ content }}

© {{ site.author.name }} 2016

          Directly forked from Rahul's github page.

          Based on Jekyll Bootstrap and theme Minimal.

          Hosted on GitHub Pages.

    {% include JB/analytics %}


text:
package org.wso2.siddhi.extension.math;

import org.wso2.siddhi.core.config.ExecutionPlanContext;
import org.wso2.siddhi.core.executor.ConstantExpressionExecutor;
import org.wso2.siddhi.core.executor.ExpressionExecutor;
import org.wso2.siddhi.core.executor.function.FunctionExecutor;
import org.wso2.siddhi.query.api.definition.Attribute;
import org.wso2.siddhi.query.api.exception.ExecutionPlanValidationException;

import java.util.Random;

/*
* rand() or rand(seed);
* A sequence of calls to rand(seed) generates a stream of pseudo-random numbers.
* Accept Type(s): INT/LONG
* Return Type(s): DOUBLE
*/
public class RandomFunctionExtension extends FunctionExecutor {

    //state-variables
    Random random;

    @Override
    protected void init(ExpressionExecutor[] attributeExpressionExecutors, ExecutionPlanContext executionPlanContext) {
        if (attributeExpressionExecutors.length > 1) {
            throw new ExecutionPlanValidationException("Invalid no of Arguments Passed. Required 0 or 1. Found " + attributeExpressionExecutors.length);
        }
        if(attributeExpressionExecutors.length == 1){
            if(attributeExpressionExecutors[0] == null){
                throw new ExecutionPlanValidationException("Invalid input given to math:rand() function. The 'seed' argument cannot be null");
            }
            Attribute.Type type = attributeExpressionExecutors[0].getReturnType();
            if(type != Attribute.Type.INT && type != Attribute.Type.LONG){
                throw new ExecutionPlanValidationException("Invalid parameter type found for the argument of math:rand() function, " +
                        "required "+Attribute.Type.INT+" or "+Attribute.Type.LONG+", but found "+type.toString());
            }
            long seed;
            if(attributeExpressionExecutors[0] instanceof ConstantExpressionExecutor){
                Object constantObj = ((ConstantExpressionExecutor) attributeExpressionExecutors[0]).getValue();
                if (type == Attribute.Type.INT) {
                    int intSeed;
                    intSeed = (Integer) constantObj;
                    seed = (long) intSeed;
                } else {
                    seed = (Long) constantObj;
                }
            } else {
                throw new ExecutionPlanValidationException("The seed argument of math:rand() function should be a constant," +
                        " but found "+attributeExpressionExecutors[0].getClass().toString());
                        //This should be a constant because the instantiation of java.util.Random should be done in the init() method.
            }
            random = new Random(seed);
        } else {
            random = new Random();
        }

    }

    @Override
    protected Object execute(Object[] data) {
        return null;  //Since the rand function takes in 0 or 1 parameter, this method does not get called. Hence, not implemented.
    }

    @Override
    protected Object execute(Object data) {
        return random.nextDouble();
    }

    @Override
    public void start() {
        //Nothing to start.
    }

    @Override
    public void stop() {
        //Nothing to stop.
    }

    @Override
    public Attribute.Type getReturnType() {
        return Attribute.Type.DOUBLE;
    }

    @Override
    public Object[] currentState() {
        return new Object[]{random};
    }

    @Override
    public void restoreState(Object[] state) {
        random = (Random) state[0];
    }
}


text:
This project contains .Net CLR code for a simple client/server .NET remoting test application.

# Links

- MSDN: [.NET Remoting](http://msdn.microsoft.com/en-us/library/72x4h507\(v=vs.80\))

- MSDN: [Asynchronous Remoting](http://msdn.microsoft.com/en-us/library/0sa925ka\(v=vs.80\).aspx)


text:
from django.conf.urls import patterns, include, url
from .views import SweepEntryDetail, SweepEntrySubmitted

urlpatterns = patterns('vodkamartinisweeps.views',
    url(r'^(?P<slug>[-\w]+)/thank-you/$', SweepEntrySubmitted.as_view(), name='vodkamartinisweeps_sweepentry_submitted'),
    url(r'^(?P<slug>[-\w]+)/$', SweepEntryDetail.as_view(), name='vodkamartinisweeps_sweepentry_detail'),
    # if we need to do something with the entry data
    #url(r'^(?P<slug>[-\w]+)/entry/(?P<sweepentry_pk>\d+)/$', SweepEntrySubmitted.as_view(), name='vodkamartinisweeps_sweepentry_submitted'),
)


text:
<?xml version="1.0" encoding="utf-8"?>

<info><title>Динамическая загрузка файлов и классов</title></info>

    <para>
        Класс <classname>Zend_Loader</classname> включает в себя методы,
        помогающие производить динамическую загрузку файлов.
    </para>

    <tip><info><title>Zend_Loader vs. require_once()</title></info>

        <para>
            Методы <classname>Zend_Loader</classname> лучше всего использовать,
            когда имя файла для загрузки является переменным - например,
            если оно базируется на данных, введенных пользователем,
            или аргументе метода.
            Если вы загружаете файл или класс, чье имя является постоянным,
            то использование <classname>Zend_Loader</classname>
            не дает каких-либо преимуществ по сравнению использованием обычных
            функций PHP, таких, как
            <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://php.net/require_once">require_once()</link>.
        </para>
    </tip>

<info><title>Загрузка файлов</title></info>

        <para>
            Статический метод Zend_Loader::loadFile() загружает
            файл PHP. Загружаемый файл должен содержать код PHP. Метод является
            оберткой к PHP-функции
            <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://php.net/include">include()</link>.
            Этот метод возвращает <constant>FALSE</constant> в случае
            неуспеха - например, если требуемый файл не существует.
        </para>

        <example xml:id="zend.loader.load.file.example"><info><title>Пример использования метода loadFile()</title></info>

            <programlisting language="php"><![CDATA[
Zend_Loader::loadFile($filename, $dirs=null, $once=false);
]]></programlisting>
    </example>

        <para>
            Аргумент <varname>$filename</varname> задает имя файла для загрузки, он
            не должен содержать путь к файлу. В целях безопасности производится
            проверка <varname>$filename</varname>. <varname>$filename</varname> должен
            содержать только алфавитно-цифровые символы, тире ("-"), знак
            подчеркивания ("_") и точку ("."). На аргумент <varname>$dirs</varname>
            эти ограничения не распространяются.
        </para>

        <para>
            Аргумент <varname>$dirs</varname> задает директории, в которых должен
            производиться поиск файла. Если его значение равно
            <constant>NULL</constant>, то для поиска используется только
            include_path. Если его значение является строкой или
            массивом, то файл сначала ищется в данной директории (директориях),
            а затем в include_path.
        </para>

        <para>
            Аргумент <varname>$once</varname> является значением булевого типа. Если
            равен <constant>TRUE</constant>, то Zend_Loader::loadFile() для
            загрузки файла использует PHP-функцию
            <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://php.net/include">include_once()</link>,
            иначе используется функция <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://php.net/include_once">include()</link>.
        </para>

<info><title>Загрузка классов</title></info>

        <para>
            Статический метод Zend_Loader::loadClass($class, $dirs)
            загружает файл PHP и затем проверяет наличие требуемого класса.
        </para>

        <example xml:id="zend.loader.load.class.example"><info><title>Пример использования метода loadClass()</title></info>

            <programlisting language="php"><![CDATA[
Zend_Loader::loadClass('Container_Tree',
    array(
        '/home/production/mylib',
        '/home/production/myapp'
    )
);
]]></programlisting>
        </example>

        <para>
            Строка, задающая класс, преобразуется в относительный путь
            посредством замены знаков подчеркивания разделителями директорий,
            используемыми в вашей ОС, и добавления расширения '.php'. В примере
            выше на Windows будет использоваться путь 'Container\\Tree.php'.
        </para>

        <para>
            Если <varname>$dirs</varname> является строкой или массивом, то
            Zend_Loader::loadClass() ищет в директориях в
            том порядке, в котором они были определены. Загружается первый
            найденный файл. Если файл не найден в директориях
            <varname>$dirs</varname>, то производится поиск в include_path.
        </para>

        <para>
            Если файл не найден, или класс не существует после загрузки, то
            Zend_Loader::loadClass() бросает
            исключение Zend_Exception.
        </para>

        <para>
            Для загрузки используется метод
            Zend_Loader::loadFile(), поэтому имя класса должно
            содержать только алфавитно-цпфровые символы, тире ('-'), знак
            подчеркивания ('_') и точку ('.').
        </para>

<info><title>Проверка на возможность чтения из файла</title></info>

        <para>
            Статический метод Zend_Loader::isReadable($pathname)
            возвращает <constant>TRUE</constant>, если по заданному пути существует файл
            и он доступен для чтения, иначе возвращается <constant>FALSE</constant>.
        </para>

        <example xml:id="zend.loader.load.isreadable.example"><info><title>Пример использования метода isReadable()</title></info>

            <programlisting language="php"><![CDATA[
if (Zend_Loader::isReadable($filename)) {
    // делаем что-либо с файлом $filename
}
]]></programlisting>
        </example>

        <para>
            Аргумент <varname>$filename</varname> задает имя файла для проверки. Он
            может содержать путь к файлу. Этот метод является оберкой к
            PHP-функции
            <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://php.net/is_readable">is_readable()</link>.
            Метод Zend_Loader::isReadable() производит поиск в
            include_path, в то время как is_readable()
            этого не делает.
        </para>

<info><title>Использование автозагрузчика</title></info>

        <para>
            Класс <classname>Zend_Loader</classname> содержит метод, который
            можно регистрировать
            через автозагрузчик PHP SPL. Zend_Loader::autoload()
            является методом обратного вызова. Для удобства
            <classname>Zend_Loader</classname> предоставляет метод
            registerAutoload() для регистрации
            его метода autoload(). Если в используемой среде
            PHP отсутствует расширение spl_autoload, то метод
            registerAutoload() бросает исключение
            <classname>Zend_Exception</classname>.
        </para>

        <example xml:id="zend.loader.load.autoload.example"><info><title>Пример регистрации метода автозагрузки</title></info>

            <programlisting language="php"><![CDATA[
Zend_Loader::registerAutoload();
]]></programlisting>
        </example>

        <para>
            После регистрации метода автозагрузки вы можете
            ссылаться на классы из Zend Framework без их явной загрузки.
            Метод autoload() автоматически запускает метод
            Zend_Loader::loadClass(), когда вы ссылаетесь на класс.
        </para>

        <para>
            Если вы расширили класс <classname>Zend_Loader</classname>, то
            можете передавать методу registerAutoload()
            опциональный аргумент для указания
            класса, из которого следует регистрировать метод
            autoload().
        </para>

        <example xml:id="zend.loader.load.autoload.example-extended"><info><title>Пример регистрации метода автозагрузки из расширенного класса</title></info>

            <para>
                В силу особенностей семантики статических функций в PHP
                вы должны реализовать код для обоих методов
                loadClass() и autoload(), при этом
                autoload() должен вызывать
                self::loadClass(). Если ваш метод
                autoload() делегирует родительскому классу вызов
                self::loadClass() то будет вызван метод
                родительского класса, не подкласса.
            </para>
            <programlisting language="php"><![CDATA[
class My_Loader extends Zend_Loader
{
    public static function loadClass($class, $dirs = null)
    {
        parent::loadClass($class, $dirs);
    }

    public static function autoload($class)
    {
        try {
            self::loadClass($class);
            return $class;
        } catch (Exception $e) {
            return false;
        }
    }
}

Zend_Loader::registerAutoload('My_Loader');
]]></programlisting>
        </example>

        <para>
            Регистрацию метода автозагрузки можно отменить.
            Метод registerAutoload() имеет опциональный
            второй аргумент, его значением по умолчанию является
            <constant>TRUE</constant>. Если этот аргумент равен <constant>FALSE</constant>,
            то данный метод автозагрузки удаляется из стека SPL.
        </para>