目次
- SophiaFramework UNIVERSE の効用
- GUIフレームワーク
- ユーティリティー
- BREW C++ ラッパー
SophiaFramework UNIVERSE の効用
GUI 環境が使えます。 GUI フレームワーク
BREW アプリ開発に便利な C++ クラスライブラリが使えます。 ユーティリティー
- Web サービスへの SOAP / WSDL 通信処理がわずか10行で済みます。SSL に対応したセキュアな Web サービスの実装が簡単です。
Mobile SOAP / XML - HTTP / HTTPS、POP3 / SMTP、SSL、TCP / IP、UDP を扱うクラスが使えます。
ネットワーク - ファイル、ディレクトリの操作やファイルパスの演算が直感的に記述できます。
ファイル - ネットワークやファイルを利用した、効率の良いデータの送受信が記述できます。
ストリーム - メモリの確保と解放が自動化されます。
バッファ - 文字列の処理が直感的に記述できます。
文字列 - 図形の処理が直感的に記述できます。
図形 - 色演算が簡単です。
カラー - 可変個のデータの管理を直感的に記述できます。
コレクション - 浮動小数点演算や三角関数や指数関数などの数学関数が使えます。
数学演算 - 日付クラスやエンディアン変換などのクラスが使えます。
汎用ユーティリティー - メモリリークを自動検出できます。
デバッグ
BREW インターフェースに対応した C++ ラッパーが使えます。 BREW C++ ラッパー
GUIフレームワーク
GUI 環境
【 BREW の問題】
GUI のイベント処理や画面描画の実装は大変です。
【 SophiaFramework UNIVERSE による解決】
GUI フレームワークを使えば、GUI が簡単にすばやく実現できます。
SophiaFramework UNIVERSE の GUI 環境:
- イベントの配信
- 描画処理の最適化
- フォーカス移動やスクロールの自動化
- UI コンポーネントのフォーカス・操作可能・活性・可視・有効状態の管理
イベント処理のカプセル化
【 BREW の問題】
GUI ではイベント処理が欠かせません。イベントによって分岐するプログラムは保守が大変です。
【 SophiaFramework UNIVERSE による解決】
イベントハンドラにイベントとその処理を登録するだけです。煩雑なイベント分岐処理の実装は不要です。
GUI コンポーネント
【 BREW の問題】
UI コンポーネントの開発が必要です。
【 SophiaFramework UNIVERSE による解決】
カスタマイズ可能なウィンドウ、メニュー、ダイアログ、タブなどの UI コンポーネントが使えます。
【例】ウインドウにボタンを貼り付けるコード
SophiaFramework UNIVERSE :
// カスタムウィンドウの定義 SFMTYPEDEFRESPONDER(USRWindow) class USRWindow : public SFZWindow { SFMSEALRESPONDER(USRWindow) SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder) private: SFZTextButtonControlSmp _button; ... private: SFCError Make(Void); // ボタン操作時の結果イベントを処理するハンドラ XANDLER_DECLARE_VOIDRESULT(OnResult) }; // テキストボタンコントロールをウィンドウに貼り付ける処理の実装 SFCError USRWindow::Make(Void) { SFCError error(SFERR_NO_ERROR); if ((_button = SFZTextButtonControl::NewInstance(&error)) != null) { error = _button->SetParent(GetThis()); if (error == SFERR_NO_ERROR) { // ボタン操作時の結果イベントを処理するハンドラを登録する error = _button->RegisterHandler( SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END), XANDLER_INTERNAL(OnResult) ); if (error == SFERR_NO_ERROR) { // 表示するテキストを設定する error = _button->SetText("hello world"); if (error == SFERR_NO_ERROR) { _button->SetRealBound( _button->GetSuitableBound().SetOrigin(10, 10) ); _button->SetState(true, true, true, true); } } } } return error; } // ボタン操作時の結果イベントを処理するハンドラ XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result) { // reason は常に SFP16_RESULT_OK、result は GetCurrentValue 関数の戻り値となる return; }
ユーティリティー
Mobile SOAP / XML
SOAP / XML
【 BREW の問題】
SOAP 通信のミドルウェアを使用しても、BREW から Web サービスへアクセスするには 1000 行程度のプログラミングが必要です。
【 SophiaFramework UNIVERSE による解決】
SOAP-RPC サポートにより、プログラミングの生産性が大幅に向上します。
SophiaFramework UNIVERSE XML for BREW
SFXSOAPRPC _rpc // メソッド名を設定する _rpc.SetMethodName("ItemSearch"); // ターゲットとなるURIを設定する _rpc.SetTargetObjectURI("http://webservices.amazon.com/"); // Web サービスのパラメータを設定する _rpc.AddParameter("AWSAccessKeyId", SFXBuffer(SFXAnsiString("0FV0D3E595H0FH4P1VR2"))); _rpc.AddParameter("Keywords", SFXBuffer(SFXAnsiString("caviar"))); _rpc.AddParameter("MerchantId", SFXBuffer(SFXAnsiString("Amazon"))); _rpc.AddParameter("SearchIndex", SFXBuffer(SFXAnsiString("GourmetFood"))); // Web サービスを呼び出す _rpc.Invoke("http://soap.amazon.com/onca/soap?Service=AWSECommerceService", "http://soap.amazon.com", OnResultSHP_SOAP, this);
HTTPS 対応 セキュア Web サービス
SOAP-RPC プロトコルを扱うクラス(SFXSOAPRPC)は HTTPS に対応しています。
関連情報 : SSL ソケット通信プログラミング ( SFXSSLSocket )
SFXSOAPRPC を HTTPS で使う場合
SFXSOAPRPC _rpc // メソッド名を設定する _rpc.SetMethodName("ItemSearch"); // ターゲットとなるURIを設定する _rpc.SetTargetObjectURI("https://webservices.amazon.com/"); // Web サービスのパラメータを設定する _rpc.AddParameter("AWSAccessKeyId", SFXBuffer(SFXAnsiString("0FV0D3E595H0FH4P1VR2"))); _rpc.AddParameter("Keywords", SFXBuffer(SFXAnsiString("caviar"))); _rpc.AddParameter("MerchantId", SFXBuffer(SFXAnsiString("Amazon"))); _rpc.AddParameter("SearchIndex", SFXBuffer(SFXAnsiString("GourmetFood"))); // SSL の検証モードを設定する _wsdl.SetTrustMode(SSL_TRUST_MODE_IGNORE); // Web サービスを呼び出す _rpc.Invoke("https://soap.amazon.com/onca/soap?Service=AWSECommerceService", "https://soap.amazon.com", OnResultSHP_SOAP, this);
ネットワーク
ホスト名、ポート番号管理クラス ( SFXSocketAddress )
【 BREW の問題】
ソケットに渡すアドレスは IP アドレスを渡す必要があり、ホスト名から IP アドレスへの変換は開発者が行わなければいけません。
【 SophiaFramework UNIVERSE による解決】
ホスト名から IP アドレスへの変換処理を自動化できます。ホスト名の解決に必要なコンテキストの管理も気にする必要がありません。
// SFXTCPSocket を使う場合、ホスト解決は自動で行われるので、 // 以下のコードを書く必要はありません。 SFXSocketAddress _socket; CHelloWorld::CHelloWorld(Void) static_throws { // ホストを設定する _socket.Set("www.s-cradle.com:8080"); // 解決済みの IP アドレスの個数を取得する TRACE("ip count = %d", _socket.GetCount()); // ホストを表示する TRACE(" host = %s", _socket.Get().GetCString()); // ホスト名から IP アドレスを解決 _socket.Resolve(XALLBACK_INTERNAL(OnResolve)); return; } XALLBACK_IMPLEMENT_SFXSOCKETADDRESS(CHelloWorld, OnResolve, error) { // 解決済みの IP アドレスの個数を取得する TRACE("ip count = %d", _socket.GetCount()); // ホストを表示する TRACE("host = %s:%d", _socket.GetIP(0).GetCString(), _socket.GetPort()); return; }
TCP ソケットクラス ( SFXTCPSocket )
【 BREW の問題】
TCP / IP 通信を実現するには INetMgr, ISocket インターフェースを利用し、コールバックで非同期的に送受信されるデータを開発者が管理しなければいけません。データを断片的に生成し、元の形に復元するプログラミングは複雑で、バグが多発する傾向にあります。
【 SophiaFramework UNIVERSE による解決】
SFXTCPSocket クラスを利用すると INetMgr, ISocket インターフェースの管理は自動化され、バッファリングされたストリームクラスを通してデータの送受信が行われるために、データの送受信処理のプログラミングが簡潔になります。また、ホスト名から IP アドレスへの変換処理も自動化されます。
// クラス変数 SFXTCPSocket _socket; SFXAnsiStringStreamWriter _writer; SFXAnsiStringStreamReader _reader; CHelloWorld::CHelloWorld(Void) static_throws { SFXSocketAddress host("www.s-cradle.com:80"); // ソケットをオープンする _socket.Open(); // www.s-cradle.com:80 に接続する // ホスト名は自動的に解決される _socket.Connect(host, XALLBACK_INTERNAL(OnConnect)); return; } XALLBACK_IMPLEMENT_SFXTCPSOCKET(CHelloWorld, OnConnect, error) { // SFXAnsiStringStreamWriter を取得する _socket.GetStreamWriter(&_writer); // ストリーム バッファにデータを書き込む _writer << "GET / HTTP/1.0\r\n"; // データを送信する _writer.Flush(XALLBACK_INTERNAL(OnFlush)); return; } XALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMWRITER(CHelloWorld, OnFlush, error) { // 送信が終わったので SFXAnsiStringStreamWriter を解放する _writer.Release(); // SFXAnsiStringStreamReader を取得する _socket.GetStreamReader(&_reader); // データを受信する _reader.Fetch(XALLBACK_INTERNAL(OnFetch)); return; } XALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(CHelloWorld, OnFetch, error) { SFXAnsiString str; // ストリーム バッファからデータを読み込む _reader >> str; // 応答を表示する TRACE("%s", str.GetCString()); // 受信が終わったので SFXAnsiStringStreamReader を解放する _reader.Release(); // ソケットをクローズする _socket.Close(); return; }
UDP ソケット通信プログラミング ( SFXUDPSocket )
【 BREW の問題】
TCP / IP 通信と同様に、UDP 通信を実現するには、INetMgr, ISocket インターフェースを利用し、コールバックで非同期的に送受信されるデータを開発者が管理しなければいけません。この管理はとても手間がかかります。
【 SophiaFramework UNIVERSE による解決】
SFXUDPSocket クラスを利用すると、複雑な INetMgr, ISocket インターフェースの管理は自動化され、通信時のコンテキスト管理が簡潔になります。また、ホスト名から IP アドレスへの変換処理も自動化されます。
// クラス変数 SFXUDPSocket _socket; Void SFXStorageExplainer::_SFXUDPSocket(Void) { // ソケットを開く _socket.Open(); // ソケットを IP アドレスとポート番号にバインドする _SFXUDPSocket_OnBind(SFERR_NO_ERROR); return; } XALLBACK_IMPLEMENT_SFXUDPSOCKET(SFXStorageExplainer, _SFXUDPSocket_OnBind, error) { switch (_socket.Bind(SFXSocketAddress( SFXInetAddress::LoopbackInetAddress(), 1024))) { case SFERR_NO_ERROR: // データを非同期に書き込む _SFXUDPSocket_OnSend(SFERR_NO_ERROR); break; case AEE_NET_WOULDBLOCK: // コールバックを登録する _socket.ScheduleBind(XALLBACK_INTERNAL(_SFXUDPSocket_OnBind)); break; } return; } XALLBACK_IMPLEMENT_SFXUDPSOCKET(SFXStorageExplainer, _SFXUDPSocket_OnSend, error) { static ACharConst data[] = "udp!"; UInt32 size; size = sizeof(data) - 1; switch (_socket.Send(SFXSocketAddress( SFXInetAddress::LoopbackInetAddress(), 1024), data, &size)) { case SFERR_NO_ERROR: // 指定したサイズのデータが書き込まれたかチェックする if (size == sizeof(data) - 1) { // データを非同期に読み込む _SFXUDPSocket_OnReceive(SFERR_NO_ERROR); } else { TRACE("...send failed..."); } break; case AEE_NET_WOULDBLOCK: // コールバックを登録する _socket.ScheduleSend(XALLBACK_INTERNAL(_SFXUDPSocket_OnSend)); break; } return; } XALLBACK_IMPLEMENT_SFXUDPSOCKET(SFXStorageExplainer, _SFXUDPSocket_OnReceive, error) { SFXSocketAddress socket; SFXBuffer buffer; UInt32 size; buffer.SetSize(4); size = static_cast<UInt16>(buffer.GetSize()); switch (_socket.Receive(&socket, buffer.GetBuffer(), &size)) { case SFERR_NO_ERROR: // 指定したサイズのデータが読み込まれたかチェックする if (size == buffer.GetSize()) { // 読み込んだデータを表示する buffer.SetSize(buffer.GetSize() + 1); buffer[buffer.GetSize() - 1] = '\0'; TRACE(":%s", SFXAnsiString(buffer).GetCString()); // ソケットを閉じる _socket.Close(); } else { TRACE("...receive failed..."); } break; case AEE_NET_WOULDBLOCK: // コールバックを登録する _socket.ScheduleReceive(XALLBACK_INTERNAL(_SFXUDPSocket_OnReceive)); break; } return; }
SSL ソケット通信プログラミング ( SFXSSLSocket )
【 BREW の問題】
SSL 通信を実装するには、INetMgr, ISocket, ISSL, ISSLRootCerts など、たくさんのインターフェースを協調させ、煩雑な SSL 通信に関するコンテキストも明示的に管理しなければいけません。
【 SophiaFramework UNIVERSE による解決】
SFXTCPSocket クラスとほぼ同じ利用方法で SSL 通信が簡単に実装できます。SSL 通信に関するコンテキストは自動的に管理され、プログラミングは不要です。
※ SSL : Secure Socket Layer の略。情報を暗号化して送受信するためのインターネットプロトコル。
SFXSSLSocket の場合
// クラス変数 SFXSSLSocket _socket; SFXAnsiStringStreamWriter _writer; SFXAnsiStringStreamReader _reader; CHelloWorld::CHelloWorld(Void) static_throws { SFXSocketAddress host("rollovertest2.verisign.co.jp:443"); // ソケットをオープンする _socket.Open(); // rollovertest2.verisign.co.jp:443 に接続する // ホスト名は自動的に解決される _socket.Connect(host, XALLBACK_INTERNAL(OnConnect)); return; } XALLBACK_IMPLEMENT_SFXSSLSOCKET(CHelloWorld, OnConnect, error) { _socket.Negotiate(XALLBACK_INTERNAL(OnNegotiate)); return; } XALLBACK_IMPLEMENT_SFXSSLSOCKET(CHelloWorld, OnNegotiate, error) { // SFXAnsiStringStreamWriter を取得する _socket.GetStreamWriter(&_writer); // ストリーム バッファにデータを書き込む _writer << "GET / HTTP/1.0\r\n\r\n"; // データを送信する _writer.Flush(XALLBACK_INTERNAL(OnFlush)); return; } XALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMWRITER(CHelloWorld, OnFlush, error) { // 送信が終わったので SFXAnsiStringStreamWriter を解放する _writer.Release(); // SFXAnsiStringStreamReader を取得する _socket.GetStreamReader(&_reader); // データを受信する _reader.Fetch(XALLBACK_INTERNAL(OnFetch)); return; } XALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(CHelloWorld, OnFetch, error) { SFXAnsiString str; // ストリーム バッファからデータを読み込む _reader >> str; // 応答を表示する TRACE("%s", str.GetCString()); // 受信が終わったので SFXAnsiStringStreamReader を解放する _reader.Release(); // ソケットをクローズする _socket.Close(); return; }
SFXTCPSocket の場合
SFXTCPSocket _socket; SFXAnsiStringStreamWriter _writer; SFXAnsiStringStreamReader _reader; CHelloWorld::CHelloWorld(Void) static_throws { SFXSocketAddress host("www.verisign.co.jp:80"); // ソケットをオープンする _socket.Open(); // www.verisign.co.jp:80 に接続する // ホスト名は自動的に解決される _socket.Connect(host, XALLBACK_INTERNAL(OnConnect)); return; } XALLBACK_IMPLEMENT_SFXTCPSOCKET(CHelloWorld, OnConnect, error) { // SFXAnsiStringStreamWriter を取得する _socket.GetStreamWriter(&_writer); // ストリーム バッファにデータを書き込む _writer << "GET / HTTP/1.0\r\n\r\n"; // データを送信する _writer.Flush(XALLBACK_INTERNAL(OnFlush)); return; } XALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMWRITER(CHelloWorld, OnFlush, error) { // 送信が終わったので SFXAnsiStringStreamWriter を解放する _writer.Release(); // SFXAnsiStringStreamReader を取得する _socket.GetStreamReader(&_reader); // データを受信する _reader.Fetch(XALLBACK_INTERNAL(OnFetch)); return; } XALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(CHelloWorld, OnFetch, error) { SFXAnsiString str; // ストリーム バッファからデータを読み込む _reader >> str; // 応答を表示する TRACE("%s", str.GetCString()); // 受信が終わったので SFXAnsiStringStreamReader を解放する _reader.Release(); // ソケットをクローズする _socket.Close(); return; }
HTTP / HTTPS 通信クラス ( SFXHTTPConnection )
【 BREW の問題】
HTTP / HTTPS 通信を実現するには、IWeb, IWebResp, ISSLRootCerts, ISource インターフェースなどを利用し、送受信するデータを通信が完了するまで明示的に保持する必要があります。この管理はとても手間がかかります。
【 SophiaFramework UNIVERSE による解決】
各インターフェースの管理は自動化され、送受信するデータの管理も完全に自動化されます。開発者は、JAVA の HttpURLConnection クラスなどを利用する感覚で HTTP / HTTPS 通信を簡単に実現できます。
// クラス変数 SFXHTTPConnection _http; SFXAnsiStringStreamReader _reader; CHelloWorld::CHelloWorld(Void) static_throws { // http 接続をオープンする _http.Open(); // User-Agent フィールドを設定する _http.SetUserAgent("SophiaFramework UNIVERSE 5.0"); // サイトに接続する _http.Connect("/index.html", XALLBACK_INTERNAL(OnConnect)); return; } XALLBACK_IMPLEMENT_SFXHTTPCONNECTION(CHelloWorld, OnConnect, error) { SFXPropertyConstPtr header; SInt16 i; // リザルトコードを取得する TRACE("result = %d", _http.GetResultCode()); // Content-Length フィールドを取得する TRACE("length = %d", _http.GetLength()); // Date フィールドを取得する TRACE("date = %s", _http.GetDate().Format("YYYY/MM/DD hh:mm:ss (Wek)").GetCString()); // 受信された全てのヘッダをダンプして表示する TRACE("---header dump---"); header = &_http.GetResponseHeader(); for (i = 0; i < header->GetSize(); ++i) { TRACE("%s: %s", header->GetKey(i).GetCString(), header->GetValue(i).GetCString()); } TRACE("---header dump---"); // SFXAnsiStringStreamReader を取得する _http.GetStreamReader(&_reader); // ボディ部分のデータを受信する _reader.Fetch(XALLBACK_INTERNAL(OnFetch)); return; } XALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(CHelloWorld, OnFetch, error) { SFXAnsiString str; // ストリーム バッファから受信データを読み込む _reader >> str; TRACE("%s", str.GetCString()); // 受信が完了したので解放する _reader.Release(); // http 接続をクローズする _http.Close(); return; }
POP3 / SMTP メール送受信処理 ( SFXPOP3Receiver / SFXSMTPSender )
【 BREW の問題】
POP3 や SMTP プロトコルを処理するインターフェースは存在しません。サーバとのデータの送受信処理やメールデータの管理など、すべての処理を開発者がプログラミングしなければいけません。
【 SophiaFramework UNIVERSE による解決】
POP3 受信クラスや SMTP 送信クラスを利用すると、わずか数行のプログラミングでメールの送受信が完成します。メールデータを管理するクラスや、エンコーディング変換を行う便利なクラスなども用意されています。
メールの送信 ( SFXSMTPSender )
class MyClass { private: SFXSMTPSender _sender; XALLBACK_DECLARE_SFXSMTPSENDER(SMTPCallback) public: Void Function(Void); }; Void MyClass::Function(Void) { SFXMailMessage message; // From アドレスを設定する message.SetFromField("fromaddress@example.com"); // To アドレスを設定する message.AddToField("toaddress1@example.com"); message.AddToField("toaddress2@example.com"); // タイトルを設定する message.SetSubjectField("Mail Subject"); // 本文を設定する message.SetBody("Mail test\r\nThis mail is sent by SFXSMTPSender.\r\n"); // 送信用メールサーバとポート番号を指定する (ドメインは自動解決される) _sender.SetServer(SFXSocketAddress("smtpserver.example.com:25")); // メールを送信する (コールバックを登録する) _sender.SendMessage(&message, XALLBACK_INTERNAL(SMTPCallback)); } // メールの送信に成功 or 失敗した場合のコールバック関数 XALLBACK_IMPLEMENT_SFXSMTPSENDER(MyClass, SMTPCallback, error) { TRACE("メールを送信しました。"); }
メールの受信 ( SFXPOP3Receiver )
class MyClass { private: SFXPOP3Receiver _receiver; XALLBACK_DECLARE_SFXPOP3RECEIVER(POP3Callback) public: Void Function(Void); }; Void MyClass::Function(Void) { // アカウントを設定する _receiver.SetAccount("user", "password"); // 受信用メールサーバとポート番号を指定する (ドメインは自動解決) _receiver.SetServer(SFXSocketAddress("pop3server.example.com:110")); // メールを受信する (コールバックを登録する) _receiver.Receive(XALLBACK_INTERNAL(POP3Callback)); } // メールの受信に成功 or 失敗した場合のコールバック関数 XALLBACK_IMPLEMENT_SFXPOP3RECEIVER(MyClass, POP3Callback, error) { SInt32 i; if (error == SFERR_NO_ERROR) { //受信に成功した場合 const SFXArray<SFXPOP3Receiver::MailInfoPtr>& mailArray = receiver.GetReceivedMailArray(); TRACE("received %d mails", mailArray.GetSize()); //数を表示する for (i = 0; i < mailArray.GetSize() ; i++) { SFXPOP3Receiver::MailInfoPtr minfo = mailArray[i]; //左から順に、メールサイズ、UIDL、メール本体(ヘッダ含む)を取得する TRACE("%d, %s, %s", minfo->size, minfo->uidl.GetCString(), minfo->mail.GetCString()); } } }
ファイル
ファイルパスクラス ( SFXPath )
【 BREW の問題】
ファイルパスを扱うクラスは存在しません。親ディレクトリの取得や、拡張子の変更などはプログラミングが必要です。
【 SophiaFramework UNIVERSE による解決】
SFXPath クラスを利用することにより、文字列演算に伴うメモリの確保や解放処理を考える必要がありません。親ディレクトリの取得や拡張子の変更などは関数を呼び出すだけです。
SFXPath path; SFXPath temp; // 絶対パスの取得 path.Set("/user/admin/log.txt"); TRACE("path = %s", path.GetAbsolute().GetCString()); // 親ディレクトリの取得 temp = path.GetParentPath(); TRACE("parent = %s", temp.GetAbsolute().GetCString()); // 拡張子が ".txt" かどうか調べて ".html" に変更する if (path.GetExtension("txt")) { path.SetExtension("html"); TRACE("path = %s", path.GetAbsolute().GetCString()); } // 複雑なパスの設定 path.Set("/user/admin/log/../../guest/./log.txt"); TRACE("path = %s", path.GetAbsolute().GetCString()); // 複雑なパスを正規化する temp = path.NormalizePath(); TRACE("normalize = %s", temp.GetAbsolute().GetCString());
ディレクトリクラス ( SFXDirectory )
【 BREW の問題】
ファイルパスを扱うインターフェースは存在しません。ファイルパスの演算は煩雑なプログラミングが必要です。また、空ではないディレクトリを削除するにはディレクトリ内のファイルを再帰的に削除しておかなければいけません。
【 SophiaFramework UNIVERSE による解決】
SFXPath クラスを使うと、ファイルパスの演算がとても簡単です。ディレクトリの強制削除機能があります。また、イテレータを利用してファイルやディレクトリを列挙できます。
SFXPath path("/user/admin/apps/"); SFXDirectory::Enumerator en; // "/user/admin/" が存在する場合に限り apps ディレクトリ作成 SFXDirectory::Create(path, false); // ディレクトリイテレータの取得 SFXDirectory::GetDirectoryEnumerator(SFXPath::HomeDirectoryPath(), &en); // イテレータを用いたディレクトリの列挙 while (en.HasNext()) { path = en.GetNext(); TRACE("dir = %s", path.Get().GetCString()); } // ファイルイテレータの取得 SFXDirectory::GetFileEnumerator(SFXPath::HomeDirectoryPath(), &en); // イテレータを用いたファイルの列挙 while (en.HasNext()) { path = en.GetNext(); TRACE("file = %s", path.Get().GetCString()); } // ディレクトリを再帰的に強制削除する SFXDirectory::Remove(path, true);
ファイルクラス ( SFXFile )
【 BREW の問題】
ファイルパスを扱うクラスは存在しません。パスの演算は開発者が行う必要があります。TCP / IP ソケットと同様に、データを断片的に生成し、元の形に復元するプログラミングは複雑で、バグが発生しやすい傾向にあります。
【 SophiaFramework UNIVERSE による解決】
SFXPath クラスを使うと、ファイルパスの演算が簡単です。バッファリングされたストリームクラスを通してデータの読み書きが行われるために、プログラミングはとても簡潔になります。
SFXPath path("/sample.txt"); SFXFile file; SFXAnsiStringStreamWriter writer; SFXDate date(0); // ファイル作成日の取得 SFXFile::GetCreateDate(path, &date); // 日時の書式出力 TRACE("create = %s", date.Format("YYYY/MM/DD hh:mm:ss (Wek)").GetCString()); // ファイルの削除 SFXFile::Remove(path); // ファイルの新規作成と書き込み file.OpenReadWrite(path); file.GetStreamWriter(&writer); writer << "sophiaframework"; writer.Flush(); file.Close();
ストリーム
バイナリデータ入出力クラス ( SFXBinaryStreamReader / SFXBinaryStreamWriter )
【 BREW の問題】
IFile インターフェースや ISocket インターフェースを利用してデータの入出力を行う場合、一度に希望したサイズのデータを入出力できない可能性があります。断片化されたデータの復元は開発者が明示的に記述しなければいけません。
【 SophiaFramework UNIVERSE による解決】
自動拡張されるバッファを用いてデータの入出力を可能にします。また、自動的にバッファリングされるためにデータの入出力が効率化されます。
SFXFile file; SFXBinaryStreamReader reader; UInt16 index; SFXAnsiString str; // ファイルをオープンする file.OpenReadOnly(SFXPath("/sample.txt")); // SFXBinaryStreamReader を取得する file.GetStreamReader(&reader); // ファイルからデータを読み込む reader.Fetch(); // ストリーム バッファからデータを読み込む reader >> index >> str; // データを表示する TRACE("index = %d", index); TRACE("str = %s", str.GetCString());
文字列データ入出力クラス ( SFXAnsiStringStreamReader / SFXAnsiStringStreamWriter / SFXWideStringStreamReader / SFXWideStringStreamWriter)
【 BREW の問題】
IFile インターフェースや ISocket インターフェースを利用してデータの入出力を行う場合、一度にリクエストしたサイズのデータを入出力できない可能性があります。断片化されたデータの復元は開発者が明示的に記述しなければいけません。
【 SophiaFramework UNIVERSE による解決】
バイナリデータ入出力クラスと同様、自動拡張されるバッファを用いてデータの入出力を可能にします。また、自動的にバッファリングされるためにデータの入出力が効率化されます。整数やオブジェクトなどを文字列化して入出力する機能も提供されます。
バッファ
バッファの自動管理
【 BREW の問題】
- メモリの解放し忘れ
- 不適切なメモリ解放
- バッファのオーバーフロー
【 SophiaFramework UNIVERSE による解決】
バッファが自動的にメモリ管理しますので、メモリリークの問題は発生しません。
文字列
文字列のわかりやすい操作
【 BREW の問題】
文字列の処理が煩雑です。
【 SophiaFramework UNIVERSE による解決】
文字列の処理が直感的に記述できます。
【例】文字列の連結のコード
BREW :
const char* str1 = "ABC"; const char* str2 = "DEF"; int len1 = STRLEN(str1); int len2 = STRLEN(str2); int len3 = len1 + len2; char* str3 = MALLOC(len3 + 1); STRCPY(str3, str1, len1); STRCAT(str3, str2, len3); .... str3 を使用 .... FREE(str3); // 使用後に必ず破棄しなければならない
SophiaFramework UNIVERSE :
SFXAnsiString str1("ABC"); SFXAnsiString str2("DEF"); SFXAnsiString str3 = str1 + str2; .... str3 を使用 .... // 使用後に破棄する必要はない
ANSI 文字列とワイド文字列の変換
【 BREW の問題】
ANSI 文字列とワイド文字列の変換をしてくれません。メモリ管理をしなければいけません。
【 SophiaFramework UNIVERSE による解決】
ANSI 文字列とワイド文字列は自動的に変換されます。メモリ管理は不要です。
【例】文字列変換のコード
BREW :
- ANSI 文字列の長さの計算
- ワイド文字列用のバッファの確保
- ANSI 文字列をワイド文字列へ変換
- バッファの破棄
char* astr = "ABC"; int astrLen = STRLEN(astr); int wstrBufSize = sizeof(AECHAR) * (astrLen + 1); AECHAR* wstr = MALLOC(astrBufSize); STREXPAND((byte*)astr, STRLEN(astr), wstr, strBufSize); .... ワイド文字列 wstr を使用する .... FREE(wstr);
SophiaFramework UNIVERSE :
char* astr = "ABC"; SFXWideString wstr(astr); .... ワイド文字列 wstr を使用する .... .... 変換後の文字列を破棄しなくてよい ....
文字列操作関数
【 BREW の問題】
文字列処理を実装しなければいけません。
【 SophiaFramework UNIVERSE による解決】
文字列のクラスを使えば、文字列処理の実装は不要です。
【例】文字列置換のコード
BREW :
文字列を置換する関数はありません
SophiaFramework UNIVERSE :
SFXAnsiString str("I like an orange."); str = str.Replace("orange", "apple");
日本語処理
【 BREW の問題】
Shift_JIS 文字コードの処理を実装しなければいけません。
【 SophiaFramework UNIVERSE による解決】
SFXShiftJIS クラスを使えば、Shift_JIS 文字コード処理の実装は不要です。
【例】全角カタカナをひらがなに変換するコード
BREW :
全角カタカナをひらがなに変換する API がありません。(実装が必要です。)
SophiaFramework UNIVERSE :
SFXWideString wstr = "ヒラガナ"; SFXShiftJIS::KatakanaToHiragana(wstr);
文字コード変換
【 BREW の問題】
文字コード変換処理を実装しなければいけません。
【 SophiaFramework UNIVERSE による解決】
SFXTextEncoding クラスを使えば、文字コード変換処理の実装は不要です。
【例】UTF-8 を Shift_JIS に変換するコード
BREW :
UTF-8 から Shift_JIS などへの文字コード変換の API がありません。(実装が必要です。)
SophiaFramework UNIVERSE :
SFXAnsiString srcString("あいうえお"); // 変換前文字列 SFXAnsiString destString; // 変換後文字列 UTF8ToShiftJIS(srcString, &destString); // 変換
図形
【 BREW の問題】
図形処理を実装しなければいけません。
【 SophiaFramework UNIVERSE による解決】
図形のクラスを使えば、図形処理の実装は不要です。
【例 1 】四角形の移動のコード
BREW :
AEERect rect; rect.x += 10; rect.y += 10;
SophiaFramework UNIVERSE :
SFXRectangle rectangle; rectangle.Offset(10,10);
【例 2 】四角形の上辺取得のコード
BREW :
AEERect rect; AEELine line; line.sx = rect.x; line.sy = rect.y; line.ex = rect.x + rect.dx - 1; line.ey = rect.y + rect.dy - 1;
SophiaFramework UNIVERSE :
SFXRectangle rectangle; SFXLine line; line = rectangle.GetEdgeTop();
カラー
図形と同じです。
SophiaFramework UNIVERSE では色の操作が簡単です。
コレクション
【 BREW の問題】
複雑な可変長データの処理を実装しなければいけません。
【 SophiaFramework UNIVERSE による解決】
コレクションを使えば、可変長データの処理の実装は不要です。
【例】動的配列のコード
BREW :
int* ar = NULL; int arSize = 0; ar = REALLOC(ar, sizeof(int) * (arSize + 1)); ar[arSize++] = 100; ar = REALLOC(ar, sizeof(int) * (arSize + 1)); ar[arSize++] = 200; ar = REALLOC(ar, sizeof(int) * (arSize + 1)); ar[arSize++] = 300; DBGPRINTF("%d", ar[0] + ar[1] + ar[2]); FREE(ar); // 使用後に破棄する // + 1 を忘れると、発見困難なバグになる
SophiaFramework UNIVERSE :
SFXArray<SInt32> ar; ar.Append(100); ar.Append(200); ar.Append(300); DBGPRINTF("%d", ar[0] + ar[1] + ar[2]); // 通常の配列のようにアクセスできる // 自動的に破棄される
数学演算
浮動小数点型 ( Float32, Float64 )
【 BREW の問題】
浮動小数点数演算は関数呼び出しです。三角関数や指数関数もありません。
【 SophiaFramework UNIVERSE による解決】
通常の数式記法で浮動小数点数演算ができます。三角関数や指数関数も使えます。
【例】 ( x + y ) * z のコード
BREW :
double x, y, z; z = FMUL(FADD(x, y), z);
SophiaFramework UNIVERSE :
Float x, y, z; z = ( x + y ) * z;
乱数クラス ( SFXBrewRandom, SFXLCGRandom, SFXMTRandom )
【 BREW の問題】
乱数生成で初期値が設定できません。
【 SophiaFramework UNIVERSE による解決】
乱数生成で 初期値が設定できます。BREW ネイティブ、線形合同法、MT 法の 3 種類の乱数があります。
三角関数テーブルクラス ( SFXTrigonometric )
【 BREW の問題】
三角関数がありません。
【 SophiaFramework UNIVERSE による解決】
三角関数テーブルを使えば、三角関数の計算が高速化されます。
汎用ユーティリティー
日付クラス ( SFXDate )
【 BREW の問題】
日付計算処理を実装しなければいけません。
【 SophiaFramework UNIVERSE による解決】
日付操作関数を使えば、日付計算処理の実装は不要です。
ヘルパー関数クラス ( SFXHelper )
【 BREW の問題】
BREW ヘルパー関数の呼び出しでプログラムが肥大化します。
【 SophiaFramework UNIVERSE による解決】
ヘルパー関数を呼び出してもプログラムサイズは肥大化しません。
【例】メモリ確保のコード
BREW :
void* buffer = MALLOC(256); //コンパイルすると 28 byte
SophiaFramework UNIVERSE :
void* buffer = SFXHelper::malloc(256); //コンパイルすると 8 byte ( 20 バイトの節約になる )
設定保存クラス ( SFXConfig )
【 BREW の問題】
ユーザー設定情報を読み書きする機能がありません。
【 SophiaFramework UNIVERSE による解決】
ユーザー設定情報を読み書きするクラスが使えます。
グラフィック描画クラス ( SFXGraphics )
【 BREW の問題】
IDisplay と IGraphics、2 つの描画インターフェースを管理しなければいけません。
【 SophiaFramework UNIVERSE による解決】
2 つの描画インターフェースが 1 つのクラスにまとめられています。
【例】四角形の領域に文字列を折り返して描画するコード
BREW : 実装しなければなりません。
SophiaFramework UNIVERSE : SFXGraphics::DrawString() 関数を呼び出すだけです。
デバッグ
メモリリーク検出
【 BREW の問題】
C++ コードで発生したメモリリークを検出できません。
【 SophiaFramework UNIVERSE による解決】
C++ コードでもメモリリークの発生場所を検出できます。
BREW C++ ラッパー
【 BREW の問題】
C 言語なので可読性に問題があります。インターフェースの解放を忘れると、メモリリークが発生します。
【 SophiaFramework UNIVERSE による解決】
C++ ラッパーを使って、完全な C++ オブジェクト指向プログラミングができます。使用後のインターフェースは自動的に解放されます。
【例】BREW API の HASH インターフェースの Restart 関数の呼び出し
ユーティリティーとの連携
SophiaFramework UNIVERSE では、文字列やバッファなどのユーティリティーと BREW API ラッパーが連携しています。
【例】BREW API の HASH インターフェースの Update 関数の呼び出し
BREW : バッファと、そのサイズを渡します。
SophiaFramework UNIVERSE : バッファオブジェクトを渡すだけです。