@blog.justoneplanet.info

日々勉強

iOSでOpenSSLを使って大きな数値計算をする

桁あふれしそうな数の計算をする。

■OpenSSLをiOS用にビルド

git clone https://github.com/x2on/OpenSSL-for-iPhone.git
cd OpenSSL-for-iPhone/
./build-libssl.sh

ビルドされたライブラリとヘッダーファイルをプロジェクトに追加する。

mkdir ../MyProject/Library/OpenSSL
cp -r include/ ../MyProject/Library/OpenSSL/include
cp -r lib/ ../MyProject/Library/OpenSSL/lib

Build Settings

Header Search Path

以下を追加する。

$(SRCROOT)/MyProject/Library/OpenSSL/include
Library Search Path

以下を追加する。

"$(SRCROOT)/MyProject/Library/OpenSSL/lib"

Build Phases

Link Binary With Libraries

libcrypto.aとlibssl.aを追加する。

■実装

#import <openssl/bn.h>

unsigned int rand = arc4random() % 100000000;
BIGNUM *random = BN_new();BN_set_word(random, rand);
BIGNUM *base = BN_new();BN_set_word(base, BASE);
BIGNUM *prime = BN_new();BN_set_word(prime, PRIME);
BIGNUM *remainder = BN_new();
BN_CTX *ctx;
ctx = BN_CTX_new();
BN_mod_exp(remainder, base, random, prime, ctx);
BN_CTX_free(ctx);

iOSでPythonが動けばいいのに。

参考

mozc for Androidにトグルが一定時間で確定される機能を追加する

mozc本体のコメントに将来的にそういった機能をつけるような事が書かれていて、その時コンフリクトする事が予想される。

■クライアント側

以下のように定義し、ViewManager.javaでタイマーでコマンドが実行されるようにする。

ViewManager.java

  private final int keycodeKaomojiToggleCommit;
    keycodeKaomojiToggleCommit = res.getInteger(R.integer.key_kaomoji_toggle_commit);

とりあえず定義だけ上述のようにする。タイマー部分はよきに計らってやる。

KeycodeConverter.java

  public static final ProtoCommands.KeyEvent KAOMOJI_TOGGLE_COMMIT =
      ProtoCommands.KeyEvent.newBuilder().setSpecialKey(SpecialKey.KAOMOJI_TOGGLE_COMMIT).build();

keycode.xml

  <integer name="key_kaomoji_toggle_commit">-10025</integer>

ProtoCommands.java

サーバー側をビルドすると生成される。

■サーバー側

composer/composer.cc

実装しようとしている機能はカーソルを右に動かす動作と非常に似ている。そしてカーソルを動かす処理はこのファイルの以下のメソッドである。

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

  typing_corrector_.Invalidate();
}

そこでpositionを移動させない関数を追加する。引き数で条件分岐してもいいのだが右に移動させる機能とトグルをコミットさせる機能は本質的に別物であるので別にする。コンフリクトすると面倒なだけでもある。

void Composer::KaomojiToggleCommit() {
  UpdateInputMode();
  typing_corrector_.Invalidate();
}

composer/composer.h

  void KaomojiToggleCommit();

次に上述を呼び出す処理を実装する。

session/session.h

  bool KaomojiToggleCommit(mozc::commands::Command *command);

session/session.cc

bool Session::KaomojiToggleCommit(commands::Command *command) {
  if (context_->GetRequest().crossing_edge_behavior() == commands::Request::COMMIT_WITHOUT_CONSUMING && context_->composer().GetLength() == context_->composer().GetCursor()) {
    Commit(command);

    // Do not consume.
    command->mutable_output()->set_consumed(false);
    return true;
  }

  command->mutable_output()->set_consumed(true);
  if (CommitIfPassword(command)) {
    return true;
  }
  context_->mutable_composer()->KaomojiToggleCommit();
  if (Suggest(command->input())) {
    Output(command);
    return true;
  }
  OutputComposition(command);
  return true;
}

コピペで申し訳ない限りである。このメソッドは同ファイルの以下の部分から呼び出される。

    case keymap::CompositionState::MOVE_CURSOR_RIGHT:
      return MoveCursorRight(command);

    case keymap::CompositionState::KAOMOJI_TOGGLE_COMMIT:
      return KaomojiToggleCommit(command);

    case keymap::CompositionState::MOVE_CURSOR_TO_BEGINNING:
      return MoveCursorToBeginning(command);

定義したメソッドがクライアントからのコマンドで呼び出されるようにする。

■CompositionState

以下のようにCompositionStateで実行されるコマンドの定義と登録をする。

session/internal/keymap_interface.h

  MOVE_CURSOR_RIGHT,
  KAOMOJI_TOGGLE_COMMIT,
  MOVE_CURSOR_TO_BEGINNING,

session/internal/keymap.cc

以下のようにして、コマンド名KaomojiToggleCommitで、CompositionState::KAOMOJI_TOGGLE_COMMITが実行されるようになる。

RegisterCompositionCommand("KaomojiToggleCommit", CompositionState::KAOMOJI_TOGGLE_COMMIT);

data/keymap/mobile.tsv

以下のようにして、KaomojiToggleCommitキーでKaomojiToggleCommitコマンドが実行される。

Composition	Right	MoveCursorRight
Composition	KaomojiToggleCommit	KaomojiToggleCommit
Composition	Space	Convert

一番左の列はstatusなのだがIME全体で入力の状態というものが存在するという事を理解しておく必要がある。

■Specialキーの追加とKeyEvent

強引ではあるがトグルをコミットさせる(実際には視認できない)KaomojiToggleCommitキーを追加する。

session/commands.proto

下のように記述して定義する。ビルドした時にKAOMOJI_TOGGLE_COMMITが追加されたProtoCommands.javaが生成され、クライアント側からSpecialKeyのKAOMOJI_TOGGLE_COMMITを叩ける。

COMMA = 70;  // Numpad [,]
KAOMOJI_TOGGLE_COMMIT = 71;
NUM_SPECIALKEYS = 72;

data/usage_stats/stats.def

追加したSpecialKeyなどがusage stats用のリストに存在せず、Debugビルドするとトグルがコミットされた時に落ちるので、以下のように追加する。

Performed_Composition_KaomojiToggleCommit
# Virtual Key for software keyboard
KAOMOJI_TOGGLE_COMMIT

この定義により、今回のキーとコマンドがusage_stats_list.hに追加される。

commands.protoから、commands.pb.hとcommands.pb.ccが生成されるが、キー操作がフックされるために以下の2ファイルの書き換えが必要となる。

session/random_keyevents_generator.cc

commands.pb.hがincludeされ以下のようにkSpecialKeysの配列ができる。

  commands::KeyEvent::RIGHT,
  commands::KeyEvent::KAOMOJI_TOGGLE_COMMIT,
  commands::KeyEvent::UP,

session/key_parser.cc

    keycode_map_["right"] = KeyEvent::RIGHT;
    keycode_map_["kaomojitogglecommit"] = KeyEvent::KAOMOJI_TOGGLE_COMMIT;
    keycode_map_["enter"] = KeyEvent::ENTER;

SessionCommandの追加

都合によりSpecialKeyを追加したが本来ならばSessionCommandの追加で特に問題はない。

data/usage_stats/stats.def
SendCommand_KaomojiToggleCommit
session/commands.proto

以下のようにしてSessionCommandを追加できる。

    KAOMOJI_TOGGLE_COMMIT = 24;

    // Number of commands.
    // When new command is added, the command should use below number
    // and NUM_OF_COMMANDS should be incremented.
    NUM_OF_COMMANDS = 25;
session/session.cc

以下のようにしてSessionCommandをフックする。

    case commands::SessionCommand::KAOMOJI_TOGGLE_COMMIT:
      result = KaomojiToggleCommit(command);
      break;  

上述のようにするとSessionExecutorから以下のように呼び出せる。

  public void toggleCommit(int candidateId, EvaluationCallback callback) {
    Input.Builder inputBuilder = Input.newBuilder()
        .setType(CommandType.SEND_COMMAND)
        .setCommand(SessionCommand.newBuilder()
            .setType(SessionCommand.CommandType.KAOMOJI_TOGGLE_COMMIT)
            .setId(candidateId));
    evaluateAsynchronously(inputBuilder, null, callback);
  }

■ダウンロード

みんなの顔文字キーボード