1. hiClassとは

hiClassライブラリはUNIX系シリアスプログラマのための実用C++クラス ライブラリです。
用意されるクラスは文字列クラスやコンテナクラスからソケット通信機、 スレッドクラスまで幅広いものとなっています。 コマンドライン解析や16進ダンプといった機構もクラスとして用意されています。

 1.1 hiClassの基本的考え、標準ライブラリとの違い

hiClassライブラリはANSI標準ライブラリ・STLとの混在が可能です。 hiClassの文字列hiStringはANSI標準ライブラリのstd::stringの派生です。 現実性を考慮したガードや機能追加を行っています。
STLを否定するものではありませんが、根本的な考え方に違いがあります。 STLのコンテナがオブジェクト指向というより値指向と呼ぶべき形態をとり、 インスタンス管理を行わず値管理としているのに対し、 hiClassのコンテナはよりオブジェクト指向的でありインスタンス管理となっ ています。
また、STLのコンテナ群は利用者のクラスに複製機能を要求しますが、 hiClassのコンテナ群は利用者クラスに複製機能を要求しません。
OSの機構に対する姿勢も全く異なります。
ANSI標準ライブラリ・STLが極端なまでにOS非依存性を重視しているのに対し、 hiClassは通信やスレッドといったOS依存が高いけれど現実のプログラミング上極めて重要な機構をクラス化し、 「実用性、現実性」を追求しています。

 1.2 クラス一覧

次のクラス、機能セットを持ちます

クラス/機能セット 説明
hiArgs コマンド起動引数解析
hiChain<T> 不定個インスタンス並び
hiConnector TCPソケットの接続口(サーバ側)
hiDebug デバグトレース出力機能セット
hiDict<K,T> 辞書
 hiIDict<T> intをキーとする辞書
 hiSDict<T> 文字列をキーとする辞書
hiFile ファイル (バイトストリーム通信機)
 hiTextFile テキストファイル
hiForm 数値 <--> 文字列変換器
 hiFormX 16進文字列変換
hiInfoBox テキストファイルによる簡易辞書
hiMemStream メモリ媒体 (バイトストリーム通信機)
hiPtr<T> 自動消去式ポインタ
hiRange 範囲(先頭位置、長さ)
 hiPRange 範囲(先頭位置、最後+1の位置)
hiRef<T> 参照カウンタ付き自動消去式ポインタ
hiRegex 正規表現
hiSelector i/oイベントselect機
hiSSL,hiSSLSock,hiSSLConnector SSL通信機
hiStream バイトストリーム仮想通信機ベース
hiString 文字列
hiThread<M> メッセージ駆動式スレッド
 hiThread_base 単純スレッドベース
 hiLock 自動初期化されるpthread_mutex_t変数
 hiAutoLock 自動開錠式ロック機構
 hiSync/hiSyncSymmetry スレッド同期機構
 hiSyncQueue 同期式のQUEUE
hiTimespec 時刻(ナノ秒まで表現)
 hiTime 時間(ナノ秒まで表現)
hiTCPSock TCPソケット (バイトストリーム通信機)
hiUDPSock UDPソケット
hiXML 単純XMLデータ構造
hiXY x,yの2個のlong値を持つ構造体
hi_env 環境インスタンス
u 基本enumセット
0初期化クラス群 0初期化されるクラス

 2. クラスの紹介

hiClassライブラリで用意されるクラスの一部を、プログラム断片を ならべて説明します。

 2.1 hiString:文字列

文字列を表すクラスhiStringが用意されています。
文字列リテラルによる初期化/代入ができます。

hiString s1 = "abc";  // "abc"という値を持つ文字列
hiString s2;          // 空文字列
hiString s3 = NULL;   // 空文字列
hiString s4 = s1;     // 複製
//
s1 = "XYZ"; // 代入,内容が"XYZ"に置き換わる
s1 = NULL;  // 空文字に置き換わる
文字列としての比較ができます。
if( s1=="abc" ) {...} // s1の内容が"abc"と等しいなら ...
if( s1< "xyz" ) {...} // s1の文字コード列が"xyz"文字コード列より小さいなら
if( s1==s2    ) {...} // s1がs2と等しいなら ...
if( s1< s2    ) {...} // s1の文字コード列がs2の文字コード列より小さいなら
bool変換、const char*変換が出来ます。
hiString s;
//...
if( s ) {           // sが文字列を持つ(空文字列でない)なら...
   ifstream ifs(s); // sをconst char*変換(ifstreamの引数はconst char*)
   //...
   }
is_in(),contains()関数で部分文字列の検索ができます。
if( s.is_in("aabcdefgg") ) {...}   // sが"aabcdefgg"の中にあれば ...
if( s.contains("def" ) )   {...}   // sが"def"を含んでいれば...
部分文字列検索時は検索結果の範囲が得られます。 これを元に部分文字列の置き換えといった作業も可能です。
hiRange range;
if( range=s.contains(hi_pos(2),"XX") ){ // sが0オリジン2の位置以降に
                                        // "XX"を含んでいれば
   s.replace(range,"abc");              // その部分を"abc"に置き換える
   }
一括分割ができます。
hiString s1="ab:cd:ef";
hiChain<hiString> CS   = divide(s1,':'); // s1を':'で分解する
                                         // "ab" "cd" "ef"が得られる
hiString s2=concat(CS,':');              // ':'を挟んで結合する
                                         // "ab:cd:ed"が得られる
hiString s3="ab-cd xy 'A B'";
hiChain<hiString> tkns = tokens(s3);     // トークン分割する
                                         // "ab-cd" "xy" "A B"が得られる
正規表現hiRegexとのパターン比較/部分文字列検索ができます。
全体比較はhiRegexとhiStringを==の左右どちらに書いても構いません。
hiRegex  re("aB*c");
hiString s ="aBBBBc";
if( re==s  ) {...} // パターンがマッチすれば... 
if( s ==re ) {...} // パターンがマッチすれば... 
部分比較はhiRegex側からはis_in、hiString側からはcontainsメソッドで行い ます。
   
   hiRegex  re= "[A-Z]+";
   hiString s ="abCDefGhIJklm";
   hiString s2=s;
   hiRange  pos;
   while( pos= re.is_in(s,nextof(pos) ){     // reがsの中にあるか
      pos= s.replace(pos,"#");     // 見つけた範囲を"#"に置き換える
      }
   pos=0;
   while( pos= s2.contains(nextof(pos),re) ){ // s2がreを含むか
      pos= s2.replace(pos,"#");  // 見つけた範囲を"#"に置き換える
      }
   // この例では、発見した範囲を、新しい文字列"#"で置き換え(replace)
   // その範囲の後ろ(nextof(pos))をさらに探索している。
   // どちらも同じab#ef#h#klmとなる

 2.2 位置引数、長さ引数、範囲型

整数引数が「位置」を意味するか「長さ」を意味するかを明確にするための explicit typedefとしてhi_len,hi_posを用意してあります。

*** コード
hiString s("abcdef");
cerr<<s.substr(hi_pos(2),hi_len(3))<<endl;// 位置2から長さ3
cerr<<s.substr(hi_pos(2),hi_pos(3))<<endl;// 位置2から位置3
*** 出力
cde
cd
範囲はhiRangeクラスで表します。先頭位置オフセットと長さの情報を持ちま す。領域の後ろ(右)の位置オフセットをhi_pos型で取り出すnextof(const hiRange&)関数なども用意されています。
もちろんexplicit typedefという機能はC++にはありません。enum定義あるい はsturctを用いています。

 2.3 コンテナ

hiClassライブラリにはテンプレートを用いたコンテナクラスを幾つか用意し てあります。


全てインスタンス管理機能をもち、自分自身が消去されるとき、内容インスタンスも消去します(hiRefは参照カウントが0になる時内容消去)。
hiRef以外は自分自身の複製機能を持ちません。

 2.3.1 hiChain<T>:不定個の要素の並び

不定個のインスタンスの並びを管理します。

要素の登録には多くの場面で <<オペレータ(右側:後ろから追加) が用 いられます。

hiChain<hiString> CS;
CS << new hiString("abc");
//...
CS << new hiString("zzz");
先頭(左)への追加や指定位置への追加機能も用意されています。
投入されているデータにアクセスするには

  1. hiChain自身が持つカレント位置管理を使う
    foreach(CS){
       cerr<<"data="<< CS()<<endl;
       }
    
  2. 反復子(hiChain<T>::iterあるいはhiChain<T>::c_iter)を使う
    hiChain<T>::c_iter it(CS);
    foreach(it){
       cerr<<"data="<<*it<<endl;
       }
    
の2つの方法が主に使われます。foreach(X)は
for((X).standby();(X).next();)

と展開されるマクロに過ぎません。
利用者はforeachを使わずstandby(),next()あるいはtop(),last(),prev()といったメソッドで位置を変更しながらアクセスすることが出来ます。
反復子には++.--,==,*,->といったSTLにそろえたインターフェイスも用意してありますので、STLのアルゴリズム群を適用させることもできます。
hiChain<T>を関数戻りとしたい場合は移動子hiChain<T>::moverを使います。

 2.3.2 hiDict<K,T>:辞書

hiDict<K,T>は型Kの値をキーとするハッシュ辞書です。Kは幾つかの事項を 満足すれはどんな型でも使うことができます。

hiClassでは使用頻度が高いであろう、文字列をキーとする辞書(hiDict)と、整数をキーとする辞書(hiDict)をhiSDict,hiIDictとして用意してあります。

hiSDict<myClass> dic;
dic["name-1"] = new myClass();              // キー指定で登録
if( dic["name-3"] ){ dic().doSomething(); }  // キー検索/アクセス
アクセスには2つのモデルが用意されています。 です。

オペレータの組み合わせによるアクセス:
 次のようなアクセスが可能です。

hiSDict<hiString> DS;
DS["name-1"] = new hiString("abc");    // キー指定で登録
DS["name-2"] = new hiString("XYZ");
//
if( DS["name-3"] ){                    // キー検索
   cout<<DS();                 // 検索結果にアクセス
   }
関数とポインタによるアクセスと混在させても構いません。

関数とポインタによるアクセス:
 次のようなアクセスが可能です。
hiSDict<hiString> DS;
DS.set("name-1",new hiString("abc"));   // キー指定で登録
DS.set("name-2",new hiString("XYZ"));
//
hiString* sP;
if( sP=DS.search("name-3") ){           // キー検索
   cout<<*sP;                   // 検索結果にアクセス
   }

残念ながら、オペレータによるアクセスに比べ、視認性に劣りますが、関数アクセスの方が慣れているという方はこちらを使っても問題ありません。

 2.3.3 hiPtr<T>:自動消去式ポインタ

hiPtr<T>は自動消去式のポインタです。セットされたインスタンスはhiPtr<T>解体時に消去されます。

殆どポインタと同様の操作が出来ます。

void foo(){
   hiPtr<hiString> strP=new hiString("abc"); // ポインタを直接セット
   //--- アクセス
   if( strP ){                     // nullで無ければ...
      strP->append("XYZ");         // ->でアクセス
      cerr << *strP << endl;       // *でアクセス
      }
   //--- 自動消去
   if( なにかあれば ) return;     // 自動消去
   boo();                         // もしboo()でexceptionがあっても自動消去
   }                              // 自動消去

hiPtr<T>の特徴は
 * 複製を禁止
してあることです。これによりhiPtr<T>でのインスタンス参照は必ず1箇所のみで行われ混乱を避けています。

hiPtr<hiString> strP=new hiString("abc"); 
hiPtr<hiString> strP2(strP);// !NG 禁止です。コンパイルエラーとなります

hiPtr<T>からhiPtr<T>への移動にはmove_to(),move_from()関数の他、移動子クラスhiPtr<T>::moverを用意してあります。

 2.3.4 hiRef<T>:参照カウンタ式自動消去ポインタ

hiRef<T>は参照カウンタを持つ自動消去ポインタです。 複数のhiRef<T>から1個のTインスタンスを参照します。 複製構築子や=オペレータによる複製時に参照カウンタがカウントアップされ、 hiRef≤T>の解体時に参照カウンタがカウントダウンされます。 参照カウンタが0となると、セットされたインスタンスは消去されます。
殆どポインタと同様の操作が出来ます。
hiPtrと異なりhiRef
 * 複製可能
です。
hiRef<T>の複製は、セットされたインスタンスはそのままで、リファレンスカウントが+1されます。

hiRef<hiString> strR=new hiString("abc"); // 参照数1
hiRef<hiString> strR2(strR);              // 参照数2
hiRef<hiString> strR3;                    
strR3 = strR;                             // 参照数3
//.. strR,strR2,strR3全ての解体子が動いた時点でhiString("abc")は消去され
// ます。


 2.4 通信

通信はhiClassの基本です。通信媒体を仮想化した機構の上に TCP、メモリ、ファイルなどを用いて情報のやり取りが出来る ようになっています。またUDP通信機もクラス化されています。

 2.4.1 TCPソケット通信

TCPソケット通信機が用意されています。
次の例はクライアント(tcpHelloC)からサーバ(tcpHelloS)に接続し、サーバ からクライアントのに文字列が送られ、クライアントで印字後、接続を断ちま す。

TCPコネクションの張り方は

という形をとります。
データの送受信は「仮想バイトストリーム通信機構」に則って行われます。


 2.4.2 仮想バイトストリーム通信機構

ソケットやファイル、あるいはメモリ等媒体によらず同じ形でバイナリデー タの送受信(読み書き)が行えます。

hiSDict<hiString> DS,DS2;
//       ファイル"original.dat"にデータが予め入ってるとして...
hiFile f_in("original.dat",hiFile::r);   // ファイル(入力用)
f_in  >> DS;                             // ファイルから読込み
hiTCPSock so("hostX:50304");             // TCPソケット
so    << DS;                             // TCPソケット送信
so    >> DS2;                            // TCPソケット受信
hiFile f_out("processed.dat",hiFile::w); // ファイル(出力用)
f_out << DS2;                            // ファイルへ書き込み

基本的な通信機構として仮想バイトストリーム通信機構(hiStream)を用意してあります。
送受信には

を使います。
通信されるデータクラスにhiStreamに対する送受信機能が用意されていれば、実hiStream通信機のいずれとも送受信が可能です。例えば、先の例ではhiSDictをhiFile,hiTCPSockという異なる通信機相手に送受信(読み書き)していますが、それぞれ別対応している訳ではなく、hiSDictとしては仮想バイトストリーム(hiStream)との送受信手続きのみが定義されているだけです。
実hiStream通信機としては

が用意されています。_read(),_write()関数を用意できるなら、利用者がhiStream通信機を作成することも可能です。
基本のデータ型、intやlong,doubleそれにhiStringなどにはhiStream通信機能が与えられています。またコンテナにもhiStream通信機能が備わっています。
hiStream通信のためにデータ型に要求されるのは

   void  put(hiStream&,const データ型&)
   void  get(hiStream&,データ型&)

の2つの外部関数です。operator<<,operator>>はこれら2つの関数を呼び 出します。利用者のクラスであっても、この関数を用意すればhiStream通信機 を使った通信が出来ます。

 2.4.5 UDP通信

hiStreamではありませんがUDP通信機構hiUDPSockもあります。
hiStream機構の支援を受けないため、電文作成に手間がかかりますが、TCPと異なりデータ滞留によるプログラム停止などが発生しませんので、リアルタイム性の要求されるもの、状態モニタ、ヘルスチェック、プロセス同期などに有用です。

 2.4.6 イベント駆動

i/oイベントの多重待ちを行うクラスhiSelectorが用意されています。 ファイルディスクリプタio機構クラス(hiFdElemntクラスの派生)

のイベントはいずれも多重にhiSelectorで待つことが出来ます。
hiConnector~hiFilePairのi/o機構クラスにはいずれもそれぞれのイベント 専用のユーザベースクラスがあります。その派生クラスを利用者クラスとし て作りイベント受け取りメソッドをオーバーロードし、インスタンスを各io 機構クラスのインスタンスに登録しておきます。
hiSelectorに登録されたio機構クラスインスタンスにイベントが発生すると、 hiSelectorからそのio機構クラスが呼ばれ、そこから利用者クラスの関数が 呼び出されます。

class myClass:public hiConnector_user,
              public hiTCPSock_user,
              public hiUDPSock_user{
public:
   bool event(hiTCPSock&p,hiSelector&se){  // hiTCPSockのイベントで呼ばれる
      // ...
      return true;
      }
   bool event(hiConnector&co,hiSelector&se){// hiConnectorのイベントで呼出
      sos<<new hiTCPSock(co);  // <1> hiTCPSock生成
      sos().set_user(*this);   // <2> hiTCPSockにユーザ登録
      se.set(sos());           // <3> hiTCPSockをhiSelectorに登録
      return true;
      }
   bool data_come(const unsigned char* data,// hiUDPSockのイベントで呼ばれる
                  long                 len,
                  hiSockAddr&          from,
                  hiUDPSock&           sock,
                  hiSelector&          se){
      // ...
      return true;
      }
   hiChain sos;
   };
int main(){
   hiSelector  se;
   myClass     user;
   hiConnector co("7777");   // <1> hiConnector生成
   co.set_user(user);        // <2> hiConnectorにユーザ登録
   se.set(co);               // <3> hiConnectorをhiSelectorに登録
   hiUDPSock   uso("7777");  // <1> hiUDPSock生成
   uso.set_user(user);       // <2> hiUDPSockにユーザ登録
   se.set(uso);              // <3> hiSelectorにhiUDPSock登録
   se.run();
   }
// もちろん、イベント毎に別のユーザクラスを作っても良い。
 2.5 スレッド

マルチスレッドは極めて強力な仕組みですが、バグを生みやすいもので もあります。
hiClassでは

形で使えるスレッドクラスを用意しています。
その他次のクラス

を用意しています。

 2.5.1 単純なスレッド関数の作り方

単純なスレッド関数の作成法を2つ用意してあります。

例えば、hiThread_baseを用いる手法では

class myThread:public hiThread_base{
public:
   myThread(int _n):n(_n){}    // 情報は構築子で引き渡す
   void thread_func(){        // スレッド起動される関数
      while(--n>0) {...}      // 何か重い処理等
      }
   int n;
   };
****
int main(){
   myThread th(10000);
   th.start(u::join);
   th.join();
   }

といった形となります。u::joinは「スレッド完了を後でjoinで待つ」という 指定です。特に待つ必要がない場合はu::detachを指定してください。
hiThreadFUNCnマクロを使う手法は

class myThread:public hiUser{
public:
   hiThreadFUNC1(myThread,tfunc,int);  // 引数1個のスレッド関数の定義
   void tfunc(int n){                  // スレッド起動される関数
      while(--n>0){...}                 // 何か重い処理等
      }
   };
***
int main(){
   myThread th;
   pthread_t tid= th.do_tfunc(10000,u::join);
   join(tid);
   }

といった形となります。情報をdo_関数()の引数で引き渡すことが出来ます。

 2.5.2 排他ロック

排他ロック変数hiLockを用意しています。 これはpthread_mutex_tに初期化機能を付けただけの簡単なものです。 が、しかし、pthread_mutex_tの初期化忘れによるデッドロックは起こし やすいバグです。 hiLockを用いれば避けることが出来ます。 lock() , unlock()メソッドをもちます。
自動開錠機hiAutoLockを用意しています。 これは構築子で施錠(lock)し解体子で開錠(unlock)するもので、 unlock忘れによるデッドロックを避けることが出来ます。 通常はlock()/unlock()を使うよりこのhiAutoLockを使う方が安全です。

hiLock lock_val;
void boo(){
   hiAutoLock boo_lock(lock_val);
   //
   if( なにかの事情 ) return;  // でも大丈夫。確実にunlockされる
   //
   foo();                      // 仮にexceptionがthrowされてもunlockされる
   //
   };                          // もちろん関数の終わりではunlockされる


 2.5.3 同期

スレッド間同期機構hiSync,hiSyncV<M>,hiSyncSymmetry,hiSyncStock<M> を用意してあります。

hiSyncは片側がwait()で待っているのをwakeup()で起こします。 wakeup側は常に即復帰します。wakeup()が先に呼ばれていた場合、 wait()は即復帰します。
hiSyncVではメッセージ送付が可能です。 wakeup側は常に即復帰します。wakeup()が先に呼ばれていた場合、 wait()は即復帰します。
hiSyncSymmetryはsync()関数で同期をとります。先に呼んだ方が待たされます。
hiSyncStockはメッセージの蓄積機で、put_messageでメッセージを積み get_messageでメッセージを取り出します。 メッセージが無い状態でget_messageを呼ぶとメッセージが来るまで待たされます。

 2.5.4 メッセージ駆動スレッドエンジン

hiThread<M>はスレッド間でメッセージの送付を行う機構です。
メッセージ送付側のスレッドからput_message()メソッドでメッセージを送ると、 受け取り側のスレッドのmessage_come()メソッドが呼び出されます。 メッセージはqueue管理されており、大量にput_message()が発行された場合 message_come()が終了ししだい再びmessage_come()が呼び出されます。 put_message()のたびにスレッドが起動されるのではありません。
例えば、ファイルi/oと通信を別スレッドとし、数個のバッファを相互に 送付する形で効率のよいファイル転送システムを構築することなどができます。


上の図は, 様子を表した概念図です。



 2.6 秒以下の時刻/時間

秒以下で時刻を管理するhiTimespecと秒以下で時間を管理するhiTimeを 用意してあります。
hiTimerspecには構築子およびset関数で次のようにして値が設定できます。

hiTimespec ts(u::current);         // 現在時刻
hiTimespec ts2(500,u::msec_after); // 現在より500ミリ秒後
hiTimespec ts3(u::local,2002,u::year,6,u::month,6,u::day); // local時刻
                               // 2002年6月6日
ts.set(2.1,u::sec_after);          // 現在時刻より2.1秒後
hiTimeには構築子およびset関数で次のようにして値が設定できます。
hiTime  t(100,u::usec);            // 100マイクロ秒
t.set(0.5,u::sec);                 // 0,5秒
hiTimespec,hiTimeには時刻/時間の演算が用意されています。

印字機能を持ちます。

hiTimespec start(u::current);
foo(); // なにか時間のかかる処理
hiTimespec end(u::current);
cout<<"foo start:"<<start<<", end:"<<end<<endl;
cout<<"foo took:"<<(end-start)<<" sec."<<endl;
*****
foo start 2002-06-21/20:01:48.161+09:00, end:2002-06-21/20:01:48.872+09:00
foo took:0.711739 sec.
秒以下のsleep関数(外部関数)を用意してあります。
 sleep(0.5,u::sec); // 0.5秒sleepする

hiTimespec指定(時刻指定)のsleep関数が用意されています。時間演算と 組み合わせて、実働部時間による差が蓄積しないsleepを実現できます。

 2.7 引数/環境/情報設定ファイル

起動引数を解析する、環境情報を得る、情報設定ファイルを取り扱うとい う作業が実用プログラムでは必要になることが多いものです。
ただ、これらは単純とは言え煩雑で、プログラムの本質でないにも関わらず かなりの工数がかかり、かつバグを生みやすいものです。
hiClassライブラリでは

を用意しました。

 2.7.1 起動引数解析:hiArgs

例えば

% com -A 数値 [-B 名前] {-X 名前|-Y 名前}
#   -A引数は必須
#   -B引数はオプショナル
#   -X,-Y引数はどちらか片方のみを必ず指定する必要がある
などという起動引数の解析は次のように行うことができます。
int main(int argc,char*argv[]){
   int      A_val;
   hiString B_val,X_val,Y_val;
   hiArgs   args;
   args.arg_int("-A",A_val,hiArgs::mandatory); // -Aはintで必須
   args.arg_str("-B",B_val);                   // -Bは文字列
   args.arg_str("-X",X_val");                  // -Xは文字列
   args.arg_str("-Y",Y_val);                   // -Yは文字列
   args.arg_group(hiArgs::mandatory|hiArgs::only_one,
                  "-X","-Y");                  // -Xと-Yはどちらか片方だけ
                         // が必ず指定される
   if( !args.check(argc,argv) ) help();    // 引数を解析して、変数にセット
   //...
   }
引数の数だけ応用プログラムでループするといった作業は不要です。

 2.7.2 環境情報取り扱い:hi_env

環境変数を得たり、ディレクトリ変更を行ったり、 hiClassのエラーメッセージの取り扱いを変えたりといった動作環境操作 がhi_envインスタンスを使って出来ます。

if( hi_env["REPORT_EOF"]=="yes" ){  // 環境変数REPORT_EOFがyesなら
   hi_env.err_msg_on(u::eof);       // eof発生もメッセージ出力する
   }

2.7.3 情報設定ファイル:infoBox

テキストによる簡易の辞書形式を用意してあります。 記述形式は キー=内容 です。

// config.ib
output = "./test.out"
X_do   = yes
//Y_do   = yes
msg1 = <<<
?1は?2では使用できません。
>>>

******
hiInfoBox ib("config.ib");
hiString ofile=ib["output"};
ofstream ofs(ofile);
if( !ib["X_do"] ) cerr<<ib.expand("msg1","X","this configuration");
if( !ib["Y_do"] ) cerr<<ib.expand("msg1","Y","this configuration");
//...

 2.7.4 デバグトレース/16進ダンプ

デバグ用にトレース文を仕込む方法は原始的ではありますが、単純で分かりやすく確実な手法です。
hiDebugで用意するマクロセットによるトレースでは

という特徴を持ちます。
% dbgSmpl dbgSmpl.C strTst.C
dbgSmpl-8023:-->dbgSmpl:main 
dbgSmpl-8023:|  -->in loop 
dbgSmpl-8023:|  |  -->foo dbgSmpl.C
dbgSmpl-8023:|  |  |  open dbgSmpl.C OK
dbgSmpl-8023:|  |  |  copying
dbgSmpl-8023:|  |  |  done
dbgSmpl-8023:|  |  <--foo 
dbgSmpl-8023:|  <--in loop 
dbgSmpl-8023:|  -->in loop 
dbgSmpl-8023:|  |  -->foo strTst.C
dbgSmpl-8023:|  |  |  open strTst.C OK
dbgSmpl-8023:|  |  |  copying
dbgSmpl-8023:|  |  |  done
dbgSmpl-8023:|  |  <--foo 
dbgSmpl-8023:|  <--in loop 
dbgSmpl-8023:<--dbgSmpl:main 

基本的には 関数の最初で _TRC_ マクロを使い、途中出力したい場所で_DSP_マクロを使って下さい。

データを16進ダンプしたいことは良くあります。
 hiFormXは単純16進表示と、アドレス付き表示の機能を持ちます。

char buf[64];
// ...
cerr<<"buf="<<hiFormX(buf,16)<<endl; // 単純16進表示
cerr<<hiFormX(buf,64,0)<<endl;       // アドレス付き表示(ここでは0から)
****
buf=b88e0461626364656667004008532940
0000: b8 8e 04 61 62 63 64 65  66 67 00 40 08 53 29 40 : @@`abcde fg`@`S)@
0010: 01 52 29 40 41 92 0f 40  d0 bc 04 08 58 f9 ff bf : `R)@A@`@ @@``X@@@
0020: 58 58 58 2d 59 59 59 2d  5a 5a 5a 08 68 f9 ff bf : XXX-YYY- ZZZ`h@@@
0030: 18 62 1a 40 34 42 29 40  80 af 00 40 78 f9 ff bf : `b`@4B)@ @@`@x@@@
 2.8 hiXライブラリ(参考)

本格的なGUIを構築するものではありませんが、自照式のon/offボタン や時系列グラフ、ランプなどを用意し、状態モニタや操作パネルの作成ができます

もちろん普通のボタンもあります。単純なテキスト入力や、 メニューなどの機能も用意されています。

現時点ではあくまで補助的なもので、インターフェイス変更の可能性 もありますが、デモやデバグなどに役に立つものだとは考えています。 hiXの仕様はマニュアルの付録に載せてあります。