2014年2月28日金曜日

[scala] PlayFrameworkでJson文字列の取得で一瞬あせった

Play 使っててJsonの文字列取りたい時、
val jsonObj = ........ とかなんとかあった場合
ドキュメントとか世のブログとかでは、
Json.stringify(jsonObj)
とやれとのことなんだけど、何も考えずに
jsonObj.toString
ってやってて、後で、これでいいの?だめなの?
と疑問に思った。
ちょっと調べたらどうやらjavascriptでは違うらしいので、一瞬
{げっっ!!}
となったが、playのソース(JsValue)を見ると

override def toString = Json.stringify(this)

だってさ。取れるものは同じということで、安心したぜ。

2014年2月14日金曜日

[Java] マイナスの16進数文字列をLongに戻したい

javaで、マイナスの16進数文字列を数値に戻したい。ただそれだけなのに、はまってしまった。信じられん。ということで、運良く解決したのでメモ。
これ、絶対はまるやつ結構いると思うんだけどなぁ。javaめ。

まず、説明のため順序的にLong->16進数ね。
Long l = new Long(-1);
String s = Long.toHexString(l);
これ、当然sが"ffffffffffffffff"。 fが16個。これが欲しいのでOK。
で、今回のお題は、16進数->Longなので、とりあえずこうするわね。
Long rev = Long.parseLong(s, 16);
しかし、ここで実行時エラー。
{なぬーっ。そんなアホなーーっ。}
どうやら、parseLongは、sの中身を正の値だと決めてかかっているようで、"7fffffffffffffff"より大きい文字列を入れるとエラーになる仕様。
Long.decodeも試してみたが、同仕様。
{どうしよう。とほほ。}
ちなみに、
Long ll = Long.parseLong("-ff", 16);
とやると、-255になるんだそうな。誰が喜ぶんだそんな仕様・・・
で、なぜかいろいろググっても解決できなかったのだが、コードをごねごねいじってたらラッキーにも打開策を発見した。
答えは、
Long rev = (new java.math.BigInteger(s, 16)).longValue();
一度、BigIntegerにしてから、それをLongにする。見事revが-1になった。
ナイス、BigInteger.longValue()!!
こいつの仕様に助けられた。
あとは、勝手にlongValue()の仕様が変らないことを祈るだけだ。

2014年1月29日水曜日

L2TP over IPsec (UDP4500) のポート開放が効かなくて困った。解決メモ。

ローカルネットワーク内部に、SoftEther等のL2TP over IPsecを使用するVPNサーバーを置いて、iPhoneやmacやAndroidからVPN接続をしようとしていたのだが、どうもうまくいかなかった。

ルーターにポートフォーディングの設定を正しくして、ルーターを再起動すると「ちゃんと外部からVPN接続できる。」のだが、しばらくするとL2TP over IPsecのポートフォーディングが動かなくなる。
他のポートのポートフォーディングは、ちゃんと動いていて、ダメになるのはL2TP over IPsecのポートだけ。

ルーターを再起動すると復活するが、1日から1週間位運用していると、またダメになる。いつダメになるかは読めない。

という変な状況が続いていた。ルーターを再起動すると直るので、当初ルーターを疑ったのだが、真の原因が判明したので、メモっておく。

原因:ローカルネットワーク内部に存在するMacBookの「どこでもMy Mac」機能がUPnPを使って、ルーターのUDP4500を奪っていたので、VPNサーバーにUDP4500が転送されていなかった。

対処:ルーターのUPnP機能をOFFにした。

今まで知らなかったのだが、UPnPというのは、ルーターのポートフォワードテーブルを勝手に書き換える(詳しくはここ)という恐ろしいやつで、うちで使っているルーター(PR-S300SE)では、手動で設定したポートフォワードテーブルよりも優先度が高いため、ポートが奪われてしまっていたようだ。

ルーター再起動でVPNサーバーにつながるようになっていたのは、再起動でルーターのUPnPテーブルがクリアされるからだった。

PR-S300SEに限らず、UPnPがデフォルトでONになっているルーターはあるようなので、似たような症状の出ている人はチェックするといいかもしれません。

2013年12月10日火曜日

CentOS6.2にgcc4.8.2を入れた時のメモ

CentOS6.2のgcc4.7.2が入っている環境に、gcc4.8.2を入れた時、最後のgccのmakeではまったので記録。

まず、gcc4.8のコンパイルについては超親切で丁寧なページがあるので、それを参考に進めるのだが、最後のgccのmakeで少しはまったので、解決した時のconfigureオプションを残しておきます。

./configure --with-gmp=/usr/local --with-mpfr=/usr/local --with-mpc=/usr/local --with-ppl=/usr/local --with-cloog=/usr/local --program-suffix=-4.8 --enable-languages=c,c++ --disable-multilib

gccをc/c++しか使わない人用です。
なぜか、各コンポーネントを見つけてこないことがあるので全部ディレクトリ指定しました。
あと、64bit環境しかいらないので、--disable-multilib を指定しています。

2013年11月25日月曜日

[c++11] えっc++って__METHOD__ないの?

プログラム書いてて、エラーメッセージのところで発生箇所のメソッド名を付けたかったんだけど、よくわからんから何となく __METHOD__ とか書いてみたら当然エラーになった。
__func__じゃ短いし、__PRETTY_FUNCTION__じゃ長いので、
// class::method みたいな文字列を取るマクロ
#define __METHOD__ [](std::string s){int sp=s.find(' ')+1;int pa=s.find('(');if(sp>pa)sp=0;return s.substr(sp,pa-sp);}(__PRETTY_FUNCTION__)
ってやったら欲しいのができた。
type_info::name()を使ってもよかったんだけど、デマングルとか面倒くさそうだったので、上の形にした。
自分でよく使いそうなのでメモ。

2013年11月21日木曜日

[linux] mozcで、かな入力。入力できない文字への対処。

mozcのかな入力で、はまった。

実際は、mozcの問題というよりもキーボード設定の問題だと思うんだけど、入力できない文字があって困った。
例えば、自分の場合、macbookからvncを通して、Ubuntu12.04のmozcでかな入力しようとするとどうしても小さい「ゃ」が打てなくて大きい「や」になってしまう。「ゅ」「ょ」はOKなのにである。
ちなみにシングルクォーテーションはちゃんと入力できる。

{むむぅ。随分、微妙な症状だなぁ・・・}
もちろん、ぐぐっても微妙すぎて解決法どころか同じ症状すら出てこない。

キーボードの設定を調べたが、すぐにわからなかったのと、
 ・ ディストリとかが違うとどうせ設定も違う。
 ・ vncを通すので問題がややこしい。
 ・ macからもwindowsからも操作したりするのでややこしい。
ので、
{追いかけるのも面倒だぞ、これは。}
と思い、頭に来たので、禁断の
ローマ字テーブル「かな」化作戦!!
を決行することにした。ダメ作戦と思いきや、意外に快適になったので、ローマ字テーブルをmozc設定画面からexportしたファイルをリンクしておきます。
そのままmozc設定画面からimportして使用できます。

使用時に注意するところは、
・ aを叩くと「ち」ではなく「a」と表示されるが変換するとちゃんと「ち」で変換できるので気にしないこと。(他のキーも同様)
・ 「0」のshiftは登録できないので、「を」を出すのは「ほ」のshiftになっている。
・ 自分の環境だと漢字入力モードでも、¥キーだけ押すと直接¥になってしまったので、「ー」は、shift+¥になっている。
・ 「」をshiftなし、『』をshift付きで出したいのだが「む」とバッティングするので、「」とセットで打ち込んだ時に「」が表示されるようになっている。
くらいかなー。

これを元に、好きにカスタマイズするといいかもしれません。

この方法で結構良かったのは、キーボードの微妙なカスタマイズが、ローマ字変換テーブルの調整でできちゃうところで、自分の環境にあわせて作れます。
また、ローマ字変換テーブルには、かなり複雑な入力パターンも登録できるので、IMEのカスタマイズとしても変な使い方が出来そうです。

2013年10月24日木曜日

[c++11] finallyみたいなことしたいけど、専用のRAIIクラス作るの嫌なんだけど・・・

c++には、javaみたいなfinallyがないんだけど、あーゆーの欲しいなーとおもって調べてみると、結局、

RAII用のクラス作れよ
boost/scope_exit使えよ

ということのようだ、前者はそれ用のクラス毎回作るのもなんだかなーだし、後者はちょっとぐじゃぐじゃしてて嫌だった。

頭に来たので、RAII用にshared_ptrを流用することにしたので、以下にメモっておく。
あ、c++11必須ね。
#include <iostream>
#include <string>
#include <memory>
#include <stdexcept>

using namespace std;
#define FINALLY(CLAUSE) shared_ptr<void> f_i_n_a_l_l_y(nullptr, [&](void*){CLAUSE});

class SomeResource {
public:
 void open() {cout << "some resource open." << endl;}
 void close() {cout << "some resource close." << endl;}
};

int main() {
 try {
  SomeResource res;
  FINALLY(
    res.close();
  )

  res.open();
  cout << "before throw exception." << endl;
  throw runtime_error("xxx error.");
  cout << "end of try block." << endl;
 } catch (runtime_error &e) {
  cout << "Error: " << e.what() << endl;
 }
 cout << "out of try block." << endl;
}
実行した結果は、
some resource open.
before throw exception.
some resource close.
Error: xxx error.
out of try block.
マクロ使って少し見やすくしました。
注意点は、FINALLYを解放したいリソースの宣言と例外が出る可能性のある場所の「間」に入れるところです。

こう見ると、shared_ptrのカスタムデリーターって、いろんなことに流用できそうですね。ちゃんとカウント取ってるからそこの一部のスコープだけに限らず使えるし。
後処理という発想だけでなく、なんかのトリガー的なことに使うと面白そう。