--- nono/lib/object.h 2026/04/29 17:04:31 1.1.1.2 +++ nono/lib/object.h 2026/04/29 17:04:49 1.1.1.6 @@ -1,91 +1,100 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // #pragma once -#include "header.h" +#include "mystring.h" #include "textscreen.h" +#include #include +// ログ表示に指定するラムダ式の便利マクロ。 +// fmt 内では __func__ が使えないので代わりに lam_func を使うこと。 +// lstr("%s value=%d", lam_func, value) のようになる。 +// 他のキャプチャ指定子が必要になったらまた考える。 +#define lstr(fmt...) \ + [&, lam_func = __func__] { (void)lam_func; return string_format(fmt); } + // // 基本オブジェクト // // ログ出力機能を持つ。 // -class Object +class Object : public IMonitor { public: Object(); - virtual ~Object(); + virtual ~Object() override; // // ログ // // ログ識別名 - std::string logname; + std::string logname {}; // ログレベル // 0: 未実装動作などのデバッグログではない情報 // 1: 大雑把なデバッグログ // 2: 詳細なデバッグログ // 3: うるさいデバッグログ - int loglevel = 0; + int loglevel {}; // メッセージ出力 - // loglevel が lv 以上の時だけ表示。 - // こちらは仮想時刻、現在の PC を表示しない。Init() など VM 実行前や + // メッセージは仮想時刻も現在の PC も表示しない。Init() など VM 実行前や // 仮想マシン(特に仮想時刻、PC) に関係ないあたりはこちらを使用。 - inline void - putmsg(int lv, const char *fmt, ...) __printflike(3, 4) - { - if (__predict_false(loglevel >= lv)) { - va_list ap; - va_start(ap, fmt); - vputmsg(fmt, ap); - va_end(ap); + // レベル指定なし、フォーマット版。(レベルを評価した後で使う) + void putmsgn(const char *fmt, ...) const __printflike(2, 3); + + // レベル指定あり、フォーマット版。 +#define putmsg(lv, fmt...) do { \ + if (__predict_false(loglevel >= (lv))) { \ + putmsgn(fmt); \ + } \ +} while (0) + + // レベル指定あり、ラムダ式版。 + void putmsgf(int lv, std::function msgf) const { + if (__predict_false(loglevel >= lv)) { + putmsgn("%s", msgf().c_str()); } } - // メッセージ出力 - void putmsg(const char *fmt, ...) const __printflike(2, 3); - void vputmsg(const char *fmt, va_list ap) const __printflike(2, 0); // ログ出力 - // loglevel が lv 以上の時だけ表示。 - // 仮想時刻と現在の PC も表示する。VM 実行中は基本的にこれで表示。 - inline void - putlog(int lv, const char *fmt, ...) const __printflike(3, 4) - { - if (__predict_false(loglevel >= lv)) { - va_list ap; + // ログは仮想時刻と現在の PC も表示する。VM 実行中は基本的にこれで表示。 + + // レベル指定なし、フォーマット版。(レベルを評価した後で使う) + void putlogn(const char *fmt, ...) const __printflike(2, 3); + + // レベル指定あり、フォーマット版。 +#define putlog(lv, fmt...) do { \ + if (__predict_false(loglevel >= (lv))) { \ + putlogn(fmt); \ + } \ +} while (0) - va_start(ap, fmt); - vputlog(fmt, ap); - va_end(ap); + // レベル指定あり、ラムダ式版。 + void putlogf(int lv, std::function msgf) const { + if (__predict_false(loglevel >= lv)) { + putlogn("%s", msgf().c_str()); } } - // ログ出力(ログレベル限定なし) - void putlog(const char *fmt, ...) const __printflike(2, 3); - void vputlog(const char *fmt, va_list ap) const __printflike(2, 0); // デバイス名(デバッグ表示用) // XXX オブジェクトなのにデバイス名とは一体... - const char *devname = NULL; + std::string devname {}; // // モニター // // モニター更新 (派生クラス側で用意) - // 戻り値はモニタースクリーンの有無。 - // 基底クラスのこれはモニタースクリーンを提供していないので false を返す。 - // 派生クラス側のは必ず true を返すこと。 - virtual bool MonitorUpdate(); - - // モニター用のテキストスクリーン - TextScreen monitor; + void MonitorUpdate(TextScreen&) override { } + nnSize GetMonitorSize() override { return monitor_size; } + nnSize monitor_size {}; }; // 全オブジェクトのリスト