仕事上いろいとな場所でパソコンを使うので、その先でよくUSBハブとかマウスとかHDMIケーブルとかがなくて困ります。
ケーブルのストックを持ってたり電気屋さんに行って買ってもよいんだけど、USBハブとかマウスとかHDMIケーブルとかって2000円くらいする上、何個かストックを持とうとするとすぐに一万円くらいいってしまうのでので、なかなか買う気がしません。
というか、大型量販店って在庫リスクがかさんで利益が出ないからなのか、2000円以下のものを明らかに安く売る気がないのです。
みんなどうしているのか調べたところ、amazonで買えばよいとのこと。とくにケーブル類はamazonベーシックっていうものがあって安いらしい。
USBハブ だいたい500円
HDMIケーブル だいたい600円
無線マウス だいたい800円
HDMI-DVIアダプター だいたい300円
ヨドバシカメラやヤマダ電気で売っている価格の1/3くらいで買えて、しかも送料込み。
大部分が送料を占めている気がしますが、どうやってこの価格でうれるのか不思議でたまりません。
電車とかで秋葉原に買いに行くよりはるかに時間と手間と価格がお得な気がします。
韓国製だけれどプライベートブランドの第三のビールも88円でスーパーで売られているし。
恐るべし価格破壊。
百円のものって、原料を買って工場で作って、海外から輸送して、配送センターから自宅まで届けてるのを一万個全部1人でやったとしても、売上百万円しかないし。
24時間無人で作らない限りこんなに安くできない気がします。どうやって作るとこんなに安くできるのかなぞが深まるばかりです。
2013年9月27日金曜日
2013年9月20日金曜日
37才にして字が書けるようになりました。
うちの二歳八か月の子供が最近お勉強ごっこあそびというものをしていて、僕はそれをまいにちひたすら見させられる。
パパは見てるだけといわれ、見てないとみててといわれ、なにか手を出したり見本を見せてもダメと言われる。
文字の形は全然合っていないんだけれど、どうやらABCを書いているらしい。
うまくかけなくて、ママに書いてもらってそれをよーくみて自分のと比べているよう。
不思議なことに毎日ママの文字を書く姿を見てるだけで、
文字は左から右または上から下に書くこと、
文字と文字の隙間を空けること、
文字は全部同じくらいの大きさに書くこと、
文字に対応する音があること。
字は読める、
字は書ける、
文字がいくつか集まって何かのものを表すこと、
文字がたくさん集まるとなにか意味のあることがかいてあること、
文字は相手に何かを伝えるときに書くもの
自分はママと違ってうまくかけない。
ママは字が書ける。
字を覚えて書くことを勉強というらしい
などいろいろなことを子供は分析して覚えているらしい。
文字を書くアルゴリズムを見るという行為をして導き出しているのである。
これらから分析するに、僕は子供の前で字を書いたことがないので、子供にいろいろ聞いてみた。
Q 保育園の先生は字が書けると思う人
先生は字がかける。
Q パパは字が読めると思う人
パパは字がよめる。
Q パパは字が書けると思う人
パパは字がかけない。
なんかわかったぞ!
どうやらうちの子供はパパが字を書けないと思っていて、私がママに教わった文字を書いてパパに字を教えあげているのである。
そう、勉強をしているのは子供ではなくてパパなのです。
真似をすることとごっこ遊びをすることが、真似をすることを真似することになる。
この単なる欲求行動の組み合わせの中に自然と再帰性がうまれることが人類が文字や文化を獲得し伝承できた仕組みなんだと1人で感動。
そういえば保育園ごっこもいつも僕が赤ちゃん役だし、おうたも僕が歌うとダメといわれるんだよね。
明日朝、子供に言おうと思う、パパに字を教えてくれたらパパ字が書けるようになったよって。
2013年9月11日水曜日
AndroidのActivityはどのように書くのがよいのか
AndroidのアプリケーションをJavaで書くと、いろいろなコールバックのメソッドがいろいろなクラスに散らばってしまいます。
このため、いろいろなクラスがActivityのコンテキストを持ってしまい、メモリ使用量が増えるという欠点があります。
特に、Activityは専用のクラスを作らないといけなかったりひとつのクラスで二つのActivityを管理できないとかいろいろ不便。
そこで他の人はどうしているのかを調べてみました。
GoogleのChromeブラウザのソースをみると、いろいろなイベントはインナークラスで受けて、アウタークラスに処理を委譲しています。
Activitをインナークラスで作ってデリゲートのように使えば、一つのクラスで複数のActivityを管理できるますし、他のイベントも同じような仕組みでいろいろ受けられます。
インナークラスに処理を書くのか、アウタークラスに処理を書くのかは好みの問題ですが、コンテキストもいろいろなクラスに渡さなくてすむので、全体としてきれいにかけそうな気がします。
------------------------------
SomeMain.java
------------------------------
package com.yomei;
import java.io.*;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
public class SomeMain {
static Handler handler = new Handler();
static Activity activity = null;
public static void onCreate()
{
}
public static void onDestroy()
{
}
//Activityのイベントを受け取るデリゲート
public static class MainActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState){
activity=this; super.onCreate(savedInstanceState);
SomeMain.onCreate();//Outerクラスに委譲
}
@Override
protected void onDestroy() {
SomeMain.onDestroy();//Outerクラスに委譲
activity=null;
}
}
------------------------------
AndroidManifest.xml
------------------------------
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yomei"
android:versionCode="1"
android:versionName="1.0">
<application >
<activity android:name="com.yomeiSomeMain$MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
このため、いろいろなクラスがActivityのコンテキストを持ってしまい、メモリ使用量が増えるという欠点があります。
特に、Activityは専用のクラスを作らないといけなかったりひとつのクラスで二つのActivityを管理できないとかいろいろ不便。
そこで他の人はどうしているのかを調べてみました。
GoogleのChromeブラウザのソースをみると、いろいろなイベントはインナークラスで受けて、アウタークラスに処理を委譲しています。
Activitをインナークラスで作ってデリゲートのように使えば、一つのクラスで複数のActivityを管理できるますし、他のイベントも同じような仕組みでいろいろ受けられます。
インナークラスに処理を書くのか、アウタークラスに処理を書くのかは好みの問題ですが、コンテキストもいろいろなクラスに渡さなくてすむので、全体としてきれいにかけそうな気がします。
------------------------------
SomeMain.java
------------------------------
package com.yomei;
import java.io.*;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
public class SomeMain {
static Handler handler = new Handler();
static Activity activity = null;
public static void onCreate()
{
}
public static void onDestroy()
{
}
//Activityのイベントを受け取るデリゲート
public static class MainActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState){
activity=this; super.onCreate(savedInstanceState);
SomeMain.onCreate();//Outerクラスに委譲
}
@Override
protected void onDestroy() {
SomeMain.onDestroy();//Outerクラスに委譲
activity=null;
}
}
------------------------------
AndroidManifest.xml
------------------------------
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yomei"
android:versionCode="1"
android:versionName="1.0">
<application >
<activity android:name="com.yomeiSomeMain$MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
2013年9月8日日曜日
Emscriptenを動かしてみた。
GoogleのJavascriptエンジンV8のコードを読んでいると、実行速度の高速化へのしたたかかつはてしない追及、コードの美しさに感動します。
オリンピックの開催候補地が決まるまで起きているつもりなので、最近、いろいろな面白いJavascriptの高速化技術があるので一通り動かしてみました。
Emscripten
C/C++などの言語で書かれたコードをマシン語にして、それをJSでエミュレーションするんですが、最適化をコンパイラーとクロージャーライブラリで行うのが面白いですね。あとコンソールアプリやOpenGLのプログラムを簡単にJSにできるので、昔のゲームとかをWebに移植できそうな気がする。
asm.js
これも計算しか早くならないけど、Javascriptでシュミレーションとか音声合成とかできそうな気がする。
2013年9月7日土曜日
囲碁のルールを勉強してみた
今日、教育テレビの「こども囲碁名人」という番組で小学生が囲碁をしていました。
囲碁のルールは囲んだら取れるしか知らなかったのですが、小学生でも囲碁のルールがわかるのだから僕もわかるはずと思い、長年わからなかった囲んだら取れる以外の囲碁のルールを夕方からずっと勉強してます。
囲碁のルールはもう一つ囲んでいる中には入れられないしかないらしい。
このため、目の形を作ると相手は目の中を取れないこともわかった。
長年の疑問であった、なんであんなとびとびに石を置くのかとか、相手の石のすぐ横に石を置くのか意味はわかってきた。
生き死にを現在勉強中
囲碁のルールは極めて簡単ななんだけど、宇宙を支配する物理法則のようなすごい多様性があっることがわかった。理系のコンピュータ好きの人はみんなきっとはまる。
囲碁のルールは囲んだら取れるしか知らなかったのですが、小学生でも囲碁のルールがわかるのだから僕もわかるはずと思い、長年わからなかった囲んだら取れる以外の囲碁のルールを夕方からずっと勉強してます。
囲碁のルールはもう一つ囲んでいる中には入れられないしかないらしい。
このため、目の形を作ると相手は目の中を取れないこともわかった。
長年の疑問であった、なんであんなとびとびに石を置くのかとか、相手の石のすぐ横に石を置くのか意味はわかってきた。
生き死にを現在勉強中
囲碁のルールは極めて簡単ななんだけど、宇宙を支配する物理法則のようなすごい多様性があっることがわかった。理系のコンピュータ好きの人はみんなきっとはまる。
2013年9月6日金曜日
C++でvar型変数を作ってみた。 その2
以前作ったC++のvar型変数ですが、よくがんがえたら配列の長さとかクリアとか列挙ができず、操作性が悪いことに気づきました。そこで配列の操作関数を追加してみました。
これで、ひとつの変数で、int,文字列、配列、多次元配列、連想配列、ができます。
これに伴い、配列と連想配列の明確な区別をしました。
配列は要素識別子に0から始まり最大要素数-1をとる連続したデータ列。
連想配列は任意の文字列や数値をとる配列
==や!=でnullと0と""と空配列を同じに扱うかどうか悩みます。
var変数の値の設定取得、サイズ取得、同値判定、初期化、破棄、要素選択など基本動作はすべてできます。
あとは+や-など、演算子をオーバーロードすれば完成。
だんだん複雑になってきたのでテストコードを追加しました。
------------------------------
varient.cpp
------------------------------
#include <stdio.h>
#include "variant.h"
#if defined(_WIN32) && !defined(__GNUC__)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
static var var_null;
var::var()
{
clear();
type=0;
m_val=0;
}
var::var(int v)
{
clear();
type=VAR_TYPE_INT;
m_val=v;
}
var::var(const char*str)
{
var((std::string)str);
}
var::var(std::string str)
{
clear();
type=VAR_TYPE_STRING;
m_str=str;
}
var::var(var& val)
{
(*this)=val;
}
var::~var()
{
clear();
}
void var::clear()
{
var* ret;
std::map<std::string,var*>::iterator ite;
ite=m_map.begin();
while( ite != m_map.end() )
{
ret=(*ite).second;
delete ret;
ite++;
}
type=0;
m_val=0;
m_str.clear();
m_map.clear();
//m_min_array=0;
m_max_array=0;
m_is_array=false;
}
var& var::operator[](const char* str)
{
if(str==NULL){
return var_null;
}
return operator[]((std::string)str);
}
var& var::operator[](std::string str)
{
var* ret=&var_null;
if(type!=0 && type!=VAR_TYPE_MAP){
return *ret;
}
switch(type){
case 0:
type=VAR_TYPE_MAP;
m_is_array=false;
case VAR_TYPE_MAP:
m_is_array=false;
ret=m_map[str];
if(ret==NULL){
ret=new var();
m_map[str]=ret;
}
break;
}
return *ret;
}
var& var::operator[](int v)
{
var* ret=&var_null;
char tmp[64];
tmp[0]=0;
sprintf(tmp,"%d",v);
std::string str=tmp;
if(type!=0 && type!=VAR_TYPE_MAP){
return *ret;
}
switch(type){
case 0:
type=VAR_TYPE_MAP;
m_is_array=true;
case VAR_TYPE_MAP:
ret=m_map[str];
if(ret==NULL){
ret=new var();
m_map[str]=ret;
}
if(m_is_array){
if(v<0)m_is_array=false;
if(m_max_array<v+1)m_max_array=v+1;
}
break;
}
return *ret;
}
void var::tumeru()
{
if(type!=VAR_TYPE_MAP)return;
std::map<std::string,var*>::iterator ite;
std::map<std::string,var*>::iterator old_ite;
bool f_del=false;
type=VAR_TYPE_MAP;
ite=m_map.begin();
while( ite != m_map.end() )
{
var* v;
v=(*ite).second;
if(v->type==0){
f_del=true;
}
old_ite=ite;
ite++;
if(f_del){
m_map.erase(old_ite);
}
f_del=false;
}
}
var& var::at(int n)
{
if(type!=VAR_TYPE_MAP || n<0){
return var_null;
}
tumeru();
std::map<std::string,var*>::iterator ite;
int ct=0;
ite=m_map.begin();
while( ite != m_map.end() )
{
if(ct==n)return *(*ite).second;
ite++;
ct++;
}
return var_null;
}
var& var::operator =(std::string str)
{
clear();
type=VAR_TYPE_STRING;
m_str=str;
return *this;
}
var& var::operator =(int val)
{
clear();
type=VAR_TYPE_INT;
m_val=val;
// 0 is as same as null
//if(val==0){
// type=VAR_TYPE_NULL;
// m_val=0;
//}
return *this;
}
var& var::operator =(var& val)
{
var* ret;
std::map<std::string,var*>::iterator ite;
//clear all
clear();
switch(val.type){
case VAR_TYPE_NULL:
break;
case VAR_TYPE_INT:
type=VAR_TYPE_INT;
m_val=val.m_val;
if(m_val==0){
type=0;
}
break;
case VAR_TYPE_STRING:
type=VAR_TYPE_STRING;
m_str=val.m_str;
break;
case VAR_TYPE_MAP:
std::map<std::string,var*>::iterator ite;
type=VAR_TYPE_MAP;
ite=val.m_map.begin();
while( ite != val.m_map.end() )
{
m_map[(*ite).first]=new var();
*(m_map[(*ite).first])=*(*ite).second;
ite++;
}
break;
}
return *this;
}
var::operator std::string()
{
switch(type){
case 0:
return "null";
case VAR_TYPE_STRING:
return m_str;
case VAR_TYPE_INT:
return toString();
case VAR_TYPE_MAP:
return "objrct";
}
return "broken";
}
var::operator int()
{
switch(type){
case 0:
return 0;
case VAR_TYPE_INT:
return m_val;
case VAR_TYPE_STRING:
return toInt();
}
return -1;
}
const char* var::pchar()
{
switch(type){
case 0:
return "null";
case VAR_TYPE_STRING:
return m_str.c_str();
case VAR_TYPE_INT:
return toString().c_str();
case VAR_TYPE_MAP:
return "objrct";
}
return "broken";
}
int var::toInt()
{
int ret=0;
switch(type){
case 0:
return 0;
case VAR_TYPE_INT:
return m_val;
case VAR_TYPE_STRING:
ret=-1;
sscanf(m_str.c_str(),"%d",&ret);
return ret;
}
return ret;
}
std::string var::toString()
{
std::string ret;
switch(type){
case 0:
return "0";
case VAR_TYPE_INT:
char tmp[64];
tmp[0]=0;
sprintf(tmp,"%d",m_val);
ret=tmp;
return ret;
case VAR_TYPE_STRING:
return m_str;
}
return ret;
}
bool var::operator ==(int v)
{
switch(type){
case 0:
if(v==0)return true;
return false;
}
return false;
}
bool var::operator !=(int v)
{
switch(type){
case 0:
if(v==0)return false;
return true;
}
return true;
}
bool var::operator ==(var& val)
{
switch(type){
case 0:
if(val.type==0)return true;
if(val.type==VAR_TYPE_INT && val.m_val==0)return true;
return false;
case VAR_TYPE_INT:
if(val.type==VAR_TYPE_INT && m_val==val.m_val)return true;
return false;
case VAR_TYPE_STRING:
if(val.type==VAR_TYPE_STRING && m_str==val.m_str)return true;
return false;
case VAR_TYPE_MAP:
//no implement
return false;
}
return false;
}
bool var::operator !=(var& val)
{
switch(type){
case 0:
if(val.type==0)return false;
if(val.type==VAR_TYPE_INT && val.m_val==0)return false;
return true;
case VAR_TYPE_INT:
if(val.type==VAR_TYPE_INT && m_val==val.m_val)return false;
return true;
case VAR_TYPE_STRING:
if(val.type==VAR_TYPE_STRING && m_str==val.m_str)return false;
return true;
case VAR_TYPE_MAP:
//no implement
return true;
}
return true;
}
int var::length()
{
int ret=0;
switch(type){
case 0:
return 0;
case VAR_TYPE_STRING:
return m_str.length();
case VAR_TYPE_INT:
if(m_val>=0)return m_val;
return -m_val;
case VAR_TYPE_MAP:
if(m_is_array){
return m_max_array;
}
tumeru();
ret=m_map.size();
return ret;
}
return ret;
}
------------------------------
varient.h
------------------------------
#include <string>
#include <map>
#define VAR_TYPE_NULL 0
#define VAR_TYPE_INT 1
#define VAR_TYPE_STRING 2
#define VAR_TYPE_MAP 3
#define VAR_TYPE_LIST 4
class var{
public:
var();
var(int v);
var(const char* str);
var(std::string str);
var(var& val);
void clear();
virtual ~var();
var& operator[](std::string str);
var& operator[](const char* str);
var& operator[](int);
var& at(int);
var& operator =(std::string str);
var& operator =(int val);
var& operator =(var& val);
bool operator ==(int);
bool operator !=(int);
bool operator ==(var& val);
bool operator !=(var& val);
// you should implement
//var& operator +=(std::string str);
//var& operator +=(const char* str);
//var& operator +=(int val);
//var& operator +=(var& val);
// you should implement
//var operator +(std::string str);
//var operator +(const char* str);
//var operator +(int val);
//var operator +(var& val);
operator std::string();
operator int();
int toInt();
std::string toString();
int length();
const char* pchar();
private:
void tumeru();
private:
int type;
std::map<std::string,var*> m_map;
std::string m_str;
int m_val;
int m_max_array;
bool m_is_array;
};
------------------------------
varient.cpp
------------------------------
#include <stdio.h>
#include "variant.h"
#if defined(_WIN32) && !defined(__GNUC__)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
int main(int argc,char* argv[])
{
#if defined(_WIN32) && !defined(__GNUC__)
// _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_WNDW);
// _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
// _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_WNDW);
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
#endif
var a,b,c,d,e,f;
var g=5;
var h="hoge";
var j=(std::string)"hoge";
var k=j;
std::string str;
int i=-1;
//null testing
if(a==NULL)printf("a is null #### OK ####\n");
else printf("a is NOT null#### NG ####\n");
if(a!=NULL)printf("a is NOT null #### NG ####\n");
else printf("a is null#### OK ####\n");
a["key"]="value";
a[5]=10;
if(a==NULL)printf("a is null #### NG ####\n");
else printf("a is NOT null#### OK ####\n");
if(a!=NULL)printf("a is NOT null#### OK ####\n");
else printf("a is null#### NG ####\n");
//int testing
i=a[5];
printf("i=%d\n",i);
if(i==10)printf("#### OK ####\n");
else printf("#### NG ####\n");
// redbrack testing
b["hoge"]=a;
c=b;
d=c["hoge"];
if(a["key"]==e)printf("a[key]is e #### NG ####\n");
else printf("a[key]is NOT e #### OK ####\n");
if(a["key"]!=e)printf("a[key]is NOT e #### OK ####\n");
else printf("a[key]is e #### NG ####\n");
if(a[5]==f)printf("a[key]is f #### NG ####\n");
else printf("a[key]is NOT f #### OK ####\n");
if(a[5]!=f)printf("a[key]is NOT f #### OK ####\n");
else printf("a[key]is f #### NG ####\n");
e="value";
f=10;
printf("str=>>%s<<\n",((std::string)e).c_str());
if((std::string)e=="value")printf("#### OK ####\n");
else printf("#### NG ####\n");
printf("str=>>%s<<\n",e.pchar());
if((std::string)e.pchar()=="value")printf("#### OK ####\n");
else printf("#### NG ####\n");
if(a["key"]==e)printf("a[key]is e #### OK ####\n");
else printf("a[key]is NOT e #### NG ####\n");
if(a[5]==f)printf("a[key]is f #### OK ####\n");
else printf("a[key]is NOT f #### NG ####\n");
str=a["key"];
a["key"]="hoge!!!!";
printf("str=>>%s<<\n",str.c_str());
if(str=="value")printf("#### OK ####\n");
else printf("#### NG ####\n");
str=d["key"];
printf("str=>>%s<<\n",str.c_str());
if(str=="value")printf("#### OK ####\n");
else printf("#### NG ####\n");
str=a["key"];
printf("str=>>%s<<\n",str.c_str());
if(str=="hoge!!!!")printf("#### OK ####\n");
else printf("#### NG ####\n");
str=a[5];
printf("str=>>%s<<\n",str.c_str());
if(str=="10")printf("#### OK ####\n");
else printf("#### NG ####\n");
a["key"]="123";
i=a["key"];
printf("i=%d\n",i);
if(i=123)printf("#### OK ####\n");
else printf("#### NG ####\n");
a["key"]=0;
i=a["key"];
printf("i=%d\n",i);
if(i==0)printf("#### OK ####\n");
else printf("#### NG ####\n");
// clear testing
a["key"]=100;
a["key"].clear();
i=a["key"];
printf("i=%d\n",i);
if(i==0)printf("#### OK ####\n");
else printf("#### NG ####\n");
// length tesintg
a.clear();
if(a==NULL)printf("#### OK ####\n");
else printf("#### NG ####\n");
i=a.length();
printf("a.length()=%d\n",i);
if(i==0)printf("#### OK ####\n");
else printf("#### NG ####\n");
a=-5;
i=a.length();
printf("a.length()=%d\n",i);
if(i==5)printf("#### OK ####\n");
else printf("#### NG ####\n");
a="";
i=a.length();
printf("a.length()=%d\n",i);
if(i==0)printf("#### OK ####\n");
else printf("#### NG ####\n");
a="abcdefg";
i=a.length();
printf("a.length()=%d\n",i);
if(i==7)printf("#### OK ####\n");
else printf("#### NG ####\n");
a.clear();
a[7]=70;
a[100]=123;
i=a.length();
printf("a.length()=%d\n",i);
if(i==101)printf("#### OK ####\n");
else printf("#### NG ####\n");
a[-1]=123;
i=a.length();
printf("a.length()=%d\n",i);
if(i==3)printf("#### OK ####\n");
else printf("#### NG ####\n");
// multidimensional array testing
a.clear();
a[15][5]=55;
i=a[15].length();
printf("a[15].length()=%d\n",i);
if(i==6)printf("#### OK ####\n");
else printf("#### NG ####\n");
i=a[15][5];
printf("i=%d\n",i);
if(i==55)printf("#### OK ####\n");
else printf("#### NG ####\n");
//erase test
a.clear();
a["sss"]=5;
a["ttt"]=10;
a["uuu"]=20;
a["ttt"].clear();
i=a.length();
printf("i=%d\n",i);
if(i==2)printf("#### OK ####\n");
else printf("#### NG ####\n");
// at() testing
i=a.at(0);
printf("a.at(0)=%d\n",i);
if(i==5 || i==20)printf("#### OK ####\n");
else printf("#### NG ####\n");
i=a.at(1);
printf("a.at(1)=%d\n",i);
if(i==5 || i==20)printf("#### OK ####\n");
else printf("#### NG ####\n");
i=a.at(2);
printf("a.at(2)=%d\n",i);
if(i==0)printf("#### OK ####\n");
else printf("#### NG ####\n");
i=a.length();
printf("i=%d\n",i);
if(i==2)printf("#### OK ####\n");
else printf("#### NG ####\n");
return 0;
}
これで、ひとつの変数で、int,文字列、配列、多次元配列、連想配列、ができます。
これに伴い、配列と連想配列の明確な区別をしました。
配列は要素識別子に0から始まり最大要素数-1をとる連続したデータ列。
連想配列は任意の文字列や数値をとる配列
==や!=でnullと0と""と空配列を同じに扱うかどうか悩みます。
var変数の値の設定取得、サイズ取得、同値判定、初期化、破棄、要素選択など基本動作はすべてできます。
あとは+や-など、演算子をオーバーロードすれば完成。
だんだん複雑になってきたのでテストコードを追加しました。
------------------------------
varient.cpp
------------------------------
#include <stdio.h>
#include "variant.h"
#if defined(_WIN32) && !defined(__GNUC__)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
static var var_null;
var::var()
{
clear();
type=0;
m_val=0;
}
var::var(int v)
{
clear();
type=VAR_TYPE_INT;
m_val=v;
}
var::var(const char*str)
{
var((std::string)str);
}
var::var(std::string str)
{
clear();
type=VAR_TYPE_STRING;
m_str=str;
}
var::var(var& val)
{
(*this)=val;
}
var::~var()
{
clear();
}
void var::clear()
{
var* ret;
std::map<std::string,var*>::iterator ite;
ite=m_map.begin();
while( ite != m_map.end() )
{
ret=(*ite).second;
delete ret;
ite++;
}
type=0;
m_val=0;
m_str.clear();
m_map.clear();
//m_min_array=0;
m_max_array=0;
m_is_array=false;
}
var& var::operator[](const char* str)
{
if(str==NULL){
return var_null;
}
return operator[]((std::string)str);
}
var& var::operator[](std::string str)
{
var* ret=&var_null;
if(type!=0 && type!=VAR_TYPE_MAP){
return *ret;
}
switch(type){
case 0:
type=VAR_TYPE_MAP;
m_is_array=false;
case VAR_TYPE_MAP:
m_is_array=false;
ret=m_map[str];
if(ret==NULL){
ret=new var();
m_map[str]=ret;
}
break;
}
return *ret;
}
var& var::operator[](int v)
{
var* ret=&var_null;
char tmp[64];
tmp[0]=0;
sprintf(tmp,"%d",v);
std::string str=tmp;
if(type!=0 && type!=VAR_TYPE_MAP){
return *ret;
}
switch(type){
case 0:
type=VAR_TYPE_MAP;
m_is_array=true;
case VAR_TYPE_MAP:
ret=m_map[str];
if(ret==NULL){
ret=new var();
m_map[str]=ret;
}
if(m_is_array){
if(v<0)m_is_array=false;
if(m_max_array<v+1)m_max_array=v+1;
}
break;
}
return *ret;
}
void var::tumeru()
{
if(type!=VAR_TYPE_MAP)return;
std::map<std::string,var*>::iterator ite;
std::map<std::string,var*>::iterator old_ite;
bool f_del=false;
type=VAR_TYPE_MAP;
ite=m_map.begin();
while( ite != m_map.end() )
{
var* v;
v=(*ite).second;
if(v->type==0){
f_del=true;
}
old_ite=ite;
ite++;
if(f_del){
m_map.erase(old_ite);
}
f_del=false;
}
}
var& var::at(int n)
{
if(type!=VAR_TYPE_MAP || n<0){
return var_null;
}
tumeru();
std::map<std::string,var*>::iterator ite;
int ct=0;
ite=m_map.begin();
while( ite != m_map.end() )
{
if(ct==n)return *(*ite).second;
ite++;
ct++;
}
return var_null;
}
var& var::operator =(std::string str)
{
clear();
type=VAR_TYPE_STRING;
m_str=str;
return *this;
}
var& var::operator =(int val)
{
clear();
type=VAR_TYPE_INT;
m_val=val;
// 0 is as same as null
//if(val==0){
// type=VAR_TYPE_NULL;
// m_val=0;
//}
return *this;
}
var& var::operator =(var& val)
{
var* ret;
std::map<std::string,var*>::iterator ite;
//clear all
clear();
switch(val.type){
case VAR_TYPE_NULL:
break;
case VAR_TYPE_INT:
type=VAR_TYPE_INT;
m_val=val.m_val;
if(m_val==0){
type=0;
}
break;
case VAR_TYPE_STRING:
type=VAR_TYPE_STRING;
m_str=val.m_str;
break;
case VAR_TYPE_MAP:
std::map<std::string,var*>::iterator ite;
type=VAR_TYPE_MAP;
ite=val.m_map.begin();
while( ite != val.m_map.end() )
{
m_map[(*ite).first]=new var();
*(m_map[(*ite).first])=*(*ite).second;
ite++;
}
break;
}
return *this;
}
var::operator std::string()
{
switch(type){
case 0:
return "null";
case VAR_TYPE_STRING:
return m_str;
case VAR_TYPE_INT:
return toString();
case VAR_TYPE_MAP:
return "objrct";
}
return "broken";
}
var::operator int()
{
switch(type){
case 0:
return 0;
case VAR_TYPE_INT:
return m_val;
case VAR_TYPE_STRING:
return toInt();
}
return -1;
}
const char* var::pchar()
{
switch(type){
case 0:
return "null";
case VAR_TYPE_STRING:
return m_str.c_str();
case VAR_TYPE_INT:
return toString().c_str();
case VAR_TYPE_MAP:
return "objrct";
}
return "broken";
}
int var::toInt()
{
int ret=0;
switch(type){
case 0:
return 0;
case VAR_TYPE_INT:
return m_val;
case VAR_TYPE_STRING:
ret=-1;
sscanf(m_str.c_str(),"%d",&ret);
return ret;
}
return ret;
}
std::string var::toString()
{
std::string ret;
switch(type){
case 0:
return "0";
case VAR_TYPE_INT:
char tmp[64];
tmp[0]=0;
sprintf(tmp,"%d",m_val);
ret=tmp;
return ret;
case VAR_TYPE_STRING:
return m_str;
}
return ret;
}
bool var::operator ==(int v)
{
switch(type){
case 0:
if(v==0)return true;
return false;
}
return false;
}
bool var::operator !=(int v)
{
switch(type){
case 0:
if(v==0)return false;
return true;
}
return true;
}
bool var::operator ==(var& val)
{
switch(type){
case 0:
if(val.type==0)return true;
if(val.type==VAR_TYPE_INT && val.m_val==0)return true;
return false;
case VAR_TYPE_INT:
if(val.type==VAR_TYPE_INT && m_val==val.m_val)return true;
return false;
case VAR_TYPE_STRING:
if(val.type==VAR_TYPE_STRING && m_str==val.m_str)return true;
return false;
case VAR_TYPE_MAP:
//no implement
return false;
}
return false;
}
bool var::operator !=(var& val)
{
switch(type){
case 0:
if(val.type==0)return false;
if(val.type==VAR_TYPE_INT && val.m_val==0)return false;
return true;
case VAR_TYPE_INT:
if(val.type==VAR_TYPE_INT && m_val==val.m_val)return false;
return true;
case VAR_TYPE_STRING:
if(val.type==VAR_TYPE_STRING && m_str==val.m_str)return false;
return true;
case VAR_TYPE_MAP:
//no implement
return true;
}
return true;
}
int var::length()
{
int ret=0;
switch(type){
case 0:
return 0;
case VAR_TYPE_STRING:
return m_str.length();
case VAR_TYPE_INT:
if(m_val>=0)return m_val;
return -m_val;
case VAR_TYPE_MAP:
if(m_is_array){
return m_max_array;
}
tumeru();
ret=m_map.size();
return ret;
}
return ret;
}
------------------------------
varient.h
------------------------------
#include <string>
#include <map>
#define VAR_TYPE_NULL 0
#define VAR_TYPE_INT 1
#define VAR_TYPE_STRING 2
#define VAR_TYPE_MAP 3
#define VAR_TYPE_LIST 4
class var{
public:
var();
var(int v);
var(const char* str);
var(std::string str);
var(var& val);
void clear();
virtual ~var();
var& operator[](std::string str);
var& operator[](const char* str);
var& operator[](int);
var& at(int);
var& operator =(std::string str);
var& operator =(int val);
var& operator =(var& val);
bool operator ==(int);
bool operator !=(int);
bool operator ==(var& val);
bool operator !=(var& val);
// you should implement
//var& operator +=(std::string str);
//var& operator +=(const char* str);
//var& operator +=(int val);
//var& operator +=(var& val);
// you should implement
//var operator +(std::string str);
//var operator +(const char* str);
//var operator +(int val);
//var operator +(var& val);
operator std::string();
operator int();
int toInt();
std::string toString();
int length();
const char* pchar();
private:
void tumeru();
private:
int type;
std::map<std::string,var*> m_map;
std::string m_str;
int m_val;
int m_max_array;
bool m_is_array;
};
------------------------------
varient.cpp
------------------------------
#include <stdio.h>
#include "variant.h"
#if defined(_WIN32) && !defined(__GNUC__)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
int main(int argc,char* argv[])
{
#if defined(_WIN32) && !defined(__GNUC__)
// _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_WNDW);
// _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
// _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_WNDW);
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
#endif
var a,b,c,d,e,f;
var g=5;
var h="hoge";
var j=(std::string)"hoge";
var k=j;
std::string str;
int i=-1;
//null testing
if(a==NULL)printf("a is null #### OK ####\n");
else printf("a is NOT null#### NG ####\n");
if(a!=NULL)printf("a is NOT null #### NG ####\n");
else printf("a is null#### OK ####\n");
a["key"]="value";
a[5]=10;
if(a==NULL)printf("a is null #### NG ####\n");
else printf("a is NOT null#### OK ####\n");
if(a!=NULL)printf("a is NOT null#### OK ####\n");
else printf("a is null#### NG ####\n");
//int testing
i=a[5];
printf("i=%d\n",i);
if(i==10)printf("#### OK ####\n");
else printf("#### NG ####\n");
// redbrack testing
b["hoge"]=a;
c=b;
d=c["hoge"];
if(a["key"]==e)printf("a[key]is e #### NG ####\n");
else printf("a[key]is NOT e #### OK ####\n");
if(a["key"]!=e)printf("a[key]is NOT e #### OK ####\n");
else printf("a[key]is e #### NG ####\n");
if(a[5]==f)printf("a[key]is f #### NG ####\n");
else printf("a[key]is NOT f #### OK ####\n");
if(a[5]!=f)printf("a[key]is NOT f #### OK ####\n");
else printf("a[key]is f #### NG ####\n");
e="value";
f=10;
printf("str=>>%s<<\n",((std::string)e).c_str());
if((std::string)e=="value")printf("#### OK ####\n");
else printf("#### NG ####\n");
printf("str=>>%s<<\n",e.pchar());
if((std::string)e.pchar()=="value")printf("#### OK ####\n");
else printf("#### NG ####\n");
if(a["key"]==e)printf("a[key]is e #### OK ####\n");
else printf("a[key]is NOT e #### NG ####\n");
if(a[5]==f)printf("a[key]is f #### OK ####\n");
else printf("a[key]is NOT f #### NG ####\n");
str=a["key"];
a["key"]="hoge!!!!";
printf("str=>>%s<<\n",str.c_str());
if(str=="value")printf("#### OK ####\n");
else printf("#### NG ####\n");
str=d["key"];
printf("str=>>%s<<\n",str.c_str());
if(str=="value")printf("#### OK ####\n");
else printf("#### NG ####\n");
str=a["key"];
printf("str=>>%s<<\n",str.c_str());
if(str=="hoge!!!!")printf("#### OK ####\n");
else printf("#### NG ####\n");
str=a[5];
printf("str=>>%s<<\n",str.c_str());
if(str=="10")printf("#### OK ####\n");
else printf("#### NG ####\n");
a["key"]="123";
i=a["key"];
printf("i=%d\n",i);
if(i=123)printf("#### OK ####\n");
else printf("#### NG ####\n");
a["key"]=0;
i=a["key"];
printf("i=%d\n",i);
if(i==0)printf("#### OK ####\n");
else printf("#### NG ####\n");
// clear testing
a["key"]=100;
a["key"].clear();
i=a["key"];
printf("i=%d\n",i);
if(i==0)printf("#### OK ####\n");
else printf("#### NG ####\n");
// length tesintg
a.clear();
if(a==NULL)printf("#### OK ####\n");
else printf("#### NG ####\n");
i=a.length();
printf("a.length()=%d\n",i);
if(i==0)printf("#### OK ####\n");
else printf("#### NG ####\n");
a=-5;
i=a.length();
printf("a.length()=%d\n",i);
if(i==5)printf("#### OK ####\n");
else printf("#### NG ####\n");
a="";
i=a.length();
printf("a.length()=%d\n",i);
if(i==0)printf("#### OK ####\n");
else printf("#### NG ####\n");
a="abcdefg";
i=a.length();
printf("a.length()=%d\n",i);
if(i==7)printf("#### OK ####\n");
else printf("#### NG ####\n");
a.clear();
a[7]=70;
a[100]=123;
i=a.length();
printf("a.length()=%d\n",i);
if(i==101)printf("#### OK ####\n");
else printf("#### NG ####\n");
a[-1]=123;
i=a.length();
printf("a.length()=%d\n",i);
if(i==3)printf("#### OK ####\n");
else printf("#### NG ####\n");
// multidimensional array testing
a.clear();
a[15][5]=55;
i=a[15].length();
printf("a[15].length()=%d\n",i);
if(i==6)printf("#### OK ####\n");
else printf("#### NG ####\n");
i=a[15][5];
printf("i=%d\n",i);
if(i==55)printf("#### OK ####\n");
else printf("#### NG ####\n");
//erase test
a.clear();
a["sss"]=5;
a["ttt"]=10;
a["uuu"]=20;
a["ttt"].clear();
i=a.length();
printf("i=%d\n",i);
if(i==2)printf("#### OK ####\n");
else printf("#### NG ####\n");
// at() testing
i=a.at(0);
printf("a.at(0)=%d\n",i);
if(i==5 || i==20)printf("#### OK ####\n");
else printf("#### NG ####\n");
i=a.at(1);
printf("a.at(1)=%d\n",i);
if(i==5 || i==20)printf("#### OK ####\n");
else printf("#### NG ####\n");
i=a.at(2);
printf("a.at(2)=%d\n",i);
if(i==0)printf("#### OK ####\n");
else printf("#### NG ####\n");
i=a.length();
printf("i=%d\n",i);
if(i==2)printf("#### OK ####\n");
else printf("#### NG ####\n");
return 0;
}
2013年9月5日木曜日
AndroidのWebViewにキーイベントを送る
AndroidのWebViewはタブレットやスマートフォン用にカスタマイズされているため、キーイベントがほとんどきません。
このため、キーボードやゲームパッドで操作するWebViewベースのAndroidアプリを作ることができません。
せっかくいろいろなUSBデバイスやBluetoothデバイスがつながるのに、これらをWebViewで利用できないなんてとても不便です。
ネットで調べても答えが見つからなかったのでいろいろ考えてキーイベントをきっちっと受け取れるWebViewを作ってみました。
ActivityのdispatchKeyEvent()にはイベントがくるので、webview.loadUrl()でJavaScriptを実行させます。
javaScript側ではcreateEvent()でイベントを作って、initEvent()でキーボードイベントを作成、最後にdispatchEvent()でイベントを送信します。
とりあえず方向キーのキーイベントを送るサンプルを作ってみました。
これでどんなキーイベントもWebViewに送れます。
------------------------------------------------------------------------
public class SomeMain extends Activity{
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
webview.getSettings().setJavaScriptEnabled(true);
webview.loadUrl("file:///android_asset/index.html");
setContentView(webview);
}
public boolean dispatchKeyEvent(KeyEvent e) {
int keyCode=e.getKeyCode();
if (e.getAction() == KeyEvent.ACTION_UP) {
switch(keyCode){
case 19:
webview.loadUrl("javascript: "
+"try{"
+"var evt = document.createEvent('Events');"
+"evt.initEvent('keydown', true, true);"
+"evt.keyCode = 38;"
+"window.dispatchEvent(evt);"
+"}catch(e){}"
);
return true;
case 20:
webview.loadUrl("javascript: "
+"try{"
+"var evt = document.createEvent('Events');"
+"evt.initEvent('keydown', true, true);"
+"evt.keyCode = 40;"
+"window.dispatchEvent(evt);"
+"}catch(e){}"
);
return true;
case 21:
webview.loadUrl("javascript: "
+"try{"
+"var evt = document.createEvent('Events');"
+"evt.initEvent('keydown', true, true);"
+"evt.keyCode = 37;"
+"window.dispatchEvent(evt);"
+"}catch(e){}"
);
return true;
case 22:
webview.loadUrl("javascript: "
+"try{"
+"var evt = document.createEvent('Events');"
+"evt.initEvent('keydown', true, true);"
+"evt.keyCode = 39;"
+"window.dispatchEvent(evt);"
+"}catch(e){}"
);
return true;
}
}
if (e.getAction() == KeyEvent.ACTION_DOWN) {
switch(keyCode){
case 19:
webview.loadUrl("javascript: "
+"try{"
+"var evt = document.createEvent('Events');"
+"evt.initEvent('keyup', true, true);"
+"evt.keyCode = 38;"
+"window.dispatchEvent(evt);"
+"}catch(e){}"
);
return true;
case 20:
webview.loadUrl("javascript: "
+"try{"
+"var evt = document.createEvent('Events');"
+"evt.initEvent('keyup', true, true);"
+"evt.keyCode = 40;"
+"window.dispatchEvent(evt);"
+"}catch(e){}"
);
return true;
case 21:
webview.loadUrl("javascript: "
+"try{"
+"var evt = document.createEvent('Events');"
+"evt.initEvent('keyup', true, true);"
+"evt.keyCode = 37;"
+"window.dispatchEvent(evt);"
+"}catch(e){}"
);
return true;
case 22:
webview.loadUrl("javascript: "
+"try{"
+"var evt = document.createEvent('Events');"
+"evt.initEvent('keyup', true, true);"
+"evt.keyCode = 39;"
+"window.dispatchEvent(evt);"
+"}catch(e){}"
);
return true;
}
}
return super.dispatchKeyEvent(e);
}
}
このため、キーボードやゲームパッドで操作するWebViewベースのAndroidアプリを作ることができません。
せっかくいろいろなUSBデバイスやBluetoothデバイスがつながるのに、これらをWebViewで利用できないなんてとても不便です。
ネットで調べても答えが見つからなかったのでいろいろ考えてキーイベントをきっちっと受け取れるWebViewを作ってみました。
ActivityのdispatchKeyEvent()にはイベントがくるので、webview.loadUrl()でJavaScriptを実行させます。
javaScript側ではcreateEvent()でイベントを作って、initEvent()でキーボードイベントを作成、最後にdispatchEvent()でイベントを送信します。
とりあえず方向キーのキーイベントを送るサンプルを作ってみました。
これでどんなキーイベントもWebViewに送れます。
------------------------------------------------------------------------
public class SomeMain extends Activity{
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
webview.getSettings().setJavaScriptEnabled(true);
webview.loadUrl("file:///android_asset/index.html");
setContentView(webview);
}
public boolean dispatchKeyEvent(KeyEvent e) {
int keyCode=e.getKeyCode();
if (e.getAction() == KeyEvent.ACTION_UP) {
switch(keyCode){
case 19:
webview.loadUrl("javascript: "
+"try{"
+"var evt = document.createEvent('Events');"
+"evt.initEvent('keydown', true, true);"
+"evt.keyCode = 38;"
+"window.dispatchEvent(evt);"
+"}catch(e){}"
);
return true;
case 20:
webview.loadUrl("javascript: "
+"try{"
+"var evt = document.createEvent('Events');"
+"evt.initEvent('keydown', true, true);"
+"evt.keyCode = 40;"
+"window.dispatchEvent(evt);"
+"}catch(e){}"
);
return true;
case 21:
webview.loadUrl("javascript: "
+"try{"
+"var evt = document.createEvent('Events');"
+"evt.initEvent('keydown', true, true);"
+"evt.keyCode = 37;"
+"window.dispatchEvent(evt);"
+"}catch(e){}"
);
return true;
case 22:
webview.loadUrl("javascript: "
+"try{"
+"var evt = document.createEvent('Events');"
+"evt.initEvent('keydown', true, true);"
+"evt.keyCode = 39;"
+"window.dispatchEvent(evt);"
+"}catch(e){}"
);
return true;
}
}
if (e.getAction() == KeyEvent.ACTION_DOWN) {
switch(keyCode){
case 19:
webview.loadUrl("javascript: "
+"try{"
+"var evt = document.createEvent('Events');"
+"evt.initEvent('keyup', true, true);"
+"evt.keyCode = 38;"
+"window.dispatchEvent(evt);"
+"}catch(e){}"
);
return true;
case 20:
webview.loadUrl("javascript: "
+"try{"
+"var evt = document.createEvent('Events');"
+"evt.initEvent('keyup', true, true);"
+"evt.keyCode = 40;"
+"window.dispatchEvent(evt);"
+"}catch(e){}"
);
return true;
case 21:
webview.loadUrl("javascript: "
+"try{"
+"var evt = document.createEvent('Events');"
+"evt.initEvent('keyup', true, true);"
+"evt.keyCode = 37;"
+"window.dispatchEvent(evt);"
+"}catch(e){}"
);
return true;
case 22:
webview.loadUrl("javascript: "
+"try{"
+"var evt = document.createEvent('Events');"
+"evt.initEvent('keyup', true, true);"
+"evt.keyCode = 39;"
+"window.dispatchEvent(evt);"
+"}catch(e){}"
);
return true;
}
}
return super.dispatchKeyEvent(e);
}
}
2013年9月3日火曜日
C++でvar型変数を作ってみた。
C++言語にはJavaScriptやPythonのようなインタープリタ言語で使われているvariant型のvar変数がありません。
boost::variantというライブラリがありますが、他の言語と比べるとあまり似ていません。
なので頭の体操を兼ねて、C++のvar型を作ってみました。
var型の「+」と「+=」がまだありませんが、必要になったらそのうち作ります。
------------------------------
variant.cpp
------------------------------
------------------------------
variant.h
------------------------------
boost::variantというライブラリがありますが、他の言語と比べるとあまり似ていません。
なので頭の体操を兼ねて、C++のvar型を作ってみました。
var型の「+」と「+=」がまだありませんが、必要になったらそのうち作ります。
------------------------------
variant.cpp
------------------------------
#include <stdio.h>
#include "variant.h"
#if defined(_WIN32) && !defined(__GNUC__)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
static var var_null;
var::var()
{
type=0;
m_val=0;
}
var::var(int v)
{
type=VAR_TYPE_INT;
m_val=v;
}
var::var(const char*str)
{
var((std::string)str);
}
var::var(std::string str)
{
type=VAR_TYPE_STRING;
m_str=str;
}
var::var(var& val)
{
(*this)=val;
}
var::~var()
{
var* ret;
std::map<std::string,var*>::iterator ite;
ite=m_map.begin();
while( ite != m_map.end() )
{
ret=(*ite).second;
delete ret;
ite++;
}
}
var& var::operator[](const char* str)
{
if(str==NULL){
return var_null;
}
return operator[]((std::string)str);
}
var& var::operator[](std::string str)
{
var* ret=&var_null;
if(type!=0 && type!=VAR_TYPE_MAP){
return *ret;
}
switch(type){
case 0:
type=VAR_TYPE_MAP;
case VAR_TYPE_MAP:
ret=m_map[str];
if(ret==NULL){
ret=new var();
m_map[str]=ret;
}
break;
}
return *ret;
}
var& var::operator[](int v)
{
var* ret=&var_null;
char tmp[64];
tmp[0]=0;
sprintf(tmp,"%d",v);
std::string str=tmp;
if(type!=0 && type!=VAR_TYPE_MAP){
return *ret;
}
switch(type){
case 0:
type=VAR_TYPE_MAP;
case VAR_TYPE_MAP:
ret=m_map[str];
if(ret==NULL){
ret=new var();
m_map[str]=ret;
}
break;
}
return *ret;
}
var& var::operator =(std::string str)
{
if(type!=0 && type!=VAR_TYPE_STRING){
return var_null;
}
type=VAR_TYPE_STRING;
m_str=str;
return *this;
}
var& var::operator =(int val)
{
if(type!=0 && type!=VAR_TYPE_INT){
return var_null;
}
type=VAR_TYPE_INT;
m_val=val;
return *this;
}
var& var::operator =(var& val)
{
var* ret;
std::map<std::string,var*>::iterator ite;
//clear all
ite=m_map.begin();
while( ite != m_map.end() )
{
ret=(*ite).second;
delete ret;
ite++;
}
m_map.clear();
type=0;
switch(val.type){
case VAR_TYPE_INT:
type=VAR_TYPE_INT;
m_val=val.m_val;
break;
case VAR_TYPE_STRING:
type=VAR_TYPE_STRING;
m_str=val.m_str;
break;
case VAR_TYPE_MAP:
std::map<std::string,var*>::iterator ite;
type=VAR_TYPE_MAP;
ite=val.m_map.begin();
while( ite != val.m_map.end() ) // 先頭まで
{
m_map[(*ite).first]=new var();
*(m_map[(*ite).first])=*(*ite).second;
ite++;
}
break;
}
return *this;
}
var::operator std::string()
{
if(type==0){
return "null";
}
if(type==VAR_TYPE_STRING){
return m_str;
}
if(type==VAR_TYPE_INT){
return toString();
}
if(type==VAR_TYPE_MAP){
return "objrct";
}
return "broken";
}
var::operator int()
{
if(type==VAR_TYPE_INT){
return m_val;
}
if(type==VAR_TYPE_STRING){
return toInt();
}
return -1;
}
const char* var::pchar()
{
if(type==0){
return "null";
}
if(type==VAR_TYPE_STRING){
return m_str.c_str();
}
if(type==VAR_TYPE_INT){
return toString().c_str();
}
if(type==VAR_TYPE_MAP){
return "objrct";
}
return "broken";
}
int var::toInt()
{
int ret=0;
if(type==VAR_TYPE_STRING){
sscanf(m_str.c_str(),"%d",&ret);
}
return ret;
}
std::string var::toString()
{
std::string ret;
if(type==VAR_TYPE_INT){
char tmp[64];
tmp[0]=0;
sprintf(tmp,"%d",m_val);
ret=tmp;
}
return ret;
}
bool var::operator ==(int v)
{
if(v==0 && type==0)return true;
return false;
}
bool var::operator !=(int v)
{
if(v==0 && type==0)return false;
return true;
}
bool var::operator ==(var& val)
{
switch(type){
case 0:
if(val.type==0)return true;
return false;
case VAR_TYPE_INT:
if(val.type==VAR_TYPE_INT && m_val==val.m_val)return true;
return false;
case VAR_TYPE_STRING:
if(val.type==VAR_TYPE_STRING && m_str==val.m_str)return true;
return false;
case VAR_TYPE_MAP:
//no implement
return false;
}
return false;
}
bool var::operator !=(var& val)
{
switch(type){
case 0:
if(val.type==0)return false;
return true;
case VAR_TYPE_INT:
if(val.type==VAR_TYPE_INT && m_val==val.m_val)return false;
return true;
case VAR_TYPE_STRING:
if(val.type==VAR_TYPE_STRING && m_str==val.m_str)return false;
return true;
case VAR_TYPE_MAP:
//no implement
return true;
}
return true;
}
#if 1
int main(int argc,char* argv[])
{
#if defined(_WIN32) && !defined(__GNUC__)
// _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_WNDW);
// _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
// _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_WNDW);
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
#endif
var a,b,c,d,e,f;
var g=5;
var h="hoge";
var j=(std::string)"hoge";
var k=j;
std::string str;
int i=-1;
if(a==NULL)printf("a is null\n");
else printf("a is NOT null\n");
if(a!=NULL)printf("a is NOT null\n");
else printf("a is null\n");
a["key"]="value";
a[5]=10;
if(a==NULL)printf("a is null\n");
else printf("a is NOT null\n");
if(a!=NULL)printf("a is NOT null\n");
else printf("a is null\n");
i=a[5];
b["hoge"]=a;
c=b;
d=c["hoge"];
if(a["key"]==e)printf("a[key]is e\n");
else printf("a[key]is NOT e\n");
if(a["key"]!=e)printf("a[key]is NOT e\n");
else printf("a[key]is e\n");
if(a[5]==f)printf("a[key]is f\n");
else printf("a[key]is NOT f\n");
if(a[5]!=f)printf("a[key]is NOT f\n");
else printf("a[key]is f\n");
e="value";
f=10;
printf("str=>>%s<<\n",((std::string)e).c_str());
printf("str=>>%s<<\n",e.pchar());
if(a["key"]==e)printf("a[key]is e\n");
else printf("a[key]is NOT e\n");
if(a[5]==f)printf("a[key]is f\n");
else printf("a[key]is NOT f\n");
str=a["key"];
a["key"]="hoge!!!!";
printf("i=%d\n",i);
printf("str=>>%s<<\n",str.c_str());
str=d["key"];
printf("str=>>%s<<\n",str.c_str());
str=a["key"];
printf("str=>>%s<<\n",str.c_str());
str=a[5];
printf("str=>>%s<<\n",str.c_str());
a["key"]="123";
i=a["key"];
printf("i=%d\n",i);
return 0;
}
#endif
variant.h
------------------------------
#include <string>
#include <map>
#define VAR_TYPE_NULL 0
#define VAR_TYPE_INT 1
#define VAR_TYPE_STRING 2
#define VAR_TYPE_MAP 3
#define VAR_TYPE_LIST 4
class var{
public:
var();
var(int v);
var(const char* str);
var(std::string str);
var(var& val);
virtual ~var();
var& operator[](std::string str);
var& operator[](const char* str);
var& operator[](int);
var& operator =(std::string str);
var& operator =(int val);
var& operator =(var& val);
bool operator ==(int);
bool operator !=(int);
bool operator ==(var& val);
bool operator !=(var& val);
// you should implement
//var& operator +=(std::string str);
//var& operator +=(const char* str);
//var& operator +=(int val);
//var& operator +=(var& val);
// you should implement
//var operator +(std::string str);
//var operator +(const char* str);
//var operator +(int val);
//var operator +(var& val);
operator std::string();
operator int();
int toInt();
std::string toString();
// you should implement
//std::string typeOf();
//int length();
const char* pchar();
private:
int type;
std::map<std::string,var*> m_map;
std::string m_str;
int m_val;
};
登録:
投稿 (Atom)