Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

08.09.2008, 18:45

Logging System auf Basis des Streamsystems

Also, schreib gerade ne Engine neu ... hab mir mal ein Logging-System einfallen lassen ... Kritik und so erwünscht ...

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
namespace log
{
    struct BasicBuffer : public std::wstreambuf
    {};

    class LineBasicBuffer : public BasicBuffer
    {
        std::vector< traits_type::char_type >   m_data;
            
    public:
        typedef std::basic_string<traits_type::char_type, traits_type> string_type;

    public:
        virtual int_type overflow(int_type c = traits_type::eof())
        {
            if (!traits_type::eq_int_type(c, traits_type::eof())) m_data.push_back(traits_type::to_char_type(c));
            else 
            {
                m_data.push_back(traits_type::to_char_type(traits_type::eof()));
                on_new_line(&m_data[0]);
                m_data.clear();
            }
            return traits_type::not_eof(c);    
        }

    protected:
        virtual void on_new_line(string_type const& line) = 0;
    };

    class Listener : public std::wstreambuf
    {
        std::vector<BasicBuffer*>   m_buffers;

    protected:
        virtual int_type overflow(int_type c = traits_type::eof())
        {
            if (!traits_type::eq_int_type(c, traits_type::eof()))
            {
                const traits_type::char_type x(traits_type::to_char_type(c));
                for (std::vector<BasicBuffer*>::const_iterator it(m_buffers.begin()); it != m_buffers.end(); ++it)
                    if (traits_type::eq_int_type((*it)->sputc(x), traits_type::eof())) return traits_type::eof();
            }
            return traits_type::not_eof( c );
        } 

    public:
        void add_listener(BasicBuffer* ptr_buffer) { m_buffers.push_back(ptr_buffer); }
    };
}; // log
...
Nun kann man unterscheiden, ob man jedes Zeichen im Stream sofort verarbeiten will (BasicBuffer), oder auf Zeilenweise Eingabe (LineBasicBuffer) reagieren will. Den Listener StreamBuf muss man nur für std::wclog.rdbuf setzen ... (am besten RAII nutzen!) und add_listener für nen beliebigen aufrufen. So kann man z.B. die Ausgabe in einer Ingame-Console, in ein Logfile (beliebiges Format .. XML, HTML, Plain Text) packen.

Anmerkungen u. Kritik bitte ;)
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

2

08.09.2008, 19:12

Jo, dann mal was mir auf den ersten Blick aufgefallen ist:

o Ich finds unschön bei überschriebenen Methoden nochmal virtual voranzustellen. Das verwirrt mehr als es hilft.
o Lass overflow protected
o In overflow kannst du dir mindestens eine Zeile sparen! :-)
o Lass die unnötigen const Qualifizierer weg (=>const traits_type::char_type x)
o Der Name der Klasse Listener ist irgendwie fehl leitend
o Der Listener sollte meiner Meinung nach kein Puffertyp sein. Sondern in die andren Puffer (optional) integriert werden
o Das wär eigentlich ein wunderbares Einsatzgebiet für Policybased Design.
@D13_Dreinig

3

08.09.2008, 23:44

Hm erstmal danke für die Rückmeldung! :)

Zitat

o Ich finds unschön bei überschriebenen Methoden nochmal virtual voranzustellen. Das verwirrt mehr als es hilft.
Ich hab es nur so drin, weil so der Benutzer auch auf die einzellnen Zeichen Zugriff hat. Kommt aber raus, weil eigtl. unnötig.

Zitat

o Lass overflow protected
Beim Aufräumen nicht aufgepasst. Ja soll protected sein. Danke!

Zitat

o In overflow kannst du dir mindestens eine Zeile sparen! Smile

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
virtual int_type overflow(int_type c = traits_type::eof())
{
    m_data.push_back(traits_type::to_char_type(c));

    if (traits_type::eq_int_type(c, traits_type::eof())) 
    {
        on_new_line(&m_data[0]);
        m_data.clear();
    }
    return traits_type::not_eof(c);   
}
so oder wie meinst de? :P

Zitat

o Der Name der Klasse Listener ist irgendwie fehl leitend
Ja, aber wie soll ich den sonst nennen Manager? :D Er Hört ja auf die Log-Messages ;)

Zitat

o Der Listener sollte meiner Meinung nach kein Puffertyp sein. Sondern in die andren Puffer (optional) integriert werden
Nja es bietet sich aber an, da er die eingabe in einen Stream (dann schön durch std::wclog.rdbuf(ListenerInstance) machbar) auf mehrere Umleitet. Wie würdest du es machen?

Zitat

o Das wär eigentlich ein wunderbares Einsatzgebiet für Policybased Design.
In konkreta?

Aber daaanke :)
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

4

09.09.2008, 09:29

Zitat von »"Deviloper"«

[...]so oder wie meinst de? :P


Genau, so in etwa! :)

Zitat von »"Deviloper"«

Ja, aber wie soll ich den sonst nennen Manager? :D Er Hört ja auf die Log-Messages ;)


Ja, aber eigentlich lauscht nicht er sondern die Puffer in der Liste. Der Listener ist ja eher eine Art verteiler oder Listener-Liste.

Zitat von »"Deviloper"«

Nja es bietet sich aber an, da er die eingabe in einen Stream (dann schön durch std::wclog.rdbuf(ListenerInstance) machbar) auf mehrere Umleitet. Wie würdest du es machen?


Ich hab z.B. für alle konkreten Logsysteme ein Interface das die Möglichkeit bietet an das jeweilige System einen, oder mehrere, Listener anzubringen. So hat jede Implementierung die Möglichkeit die Ausgabe zu verteilen.

Zitat von »"Deviloper"«

In konkreta?


Naja, im Grund hast du ja, mehr oder weniger, dreimal die gleiche Klasse, mit leicht unterschiedlichem Verhalten.
Das Verhalten könntest du auslagern. Und per Templateparameter übergeben.
@D13_Dreinig

5

09.09.2008, 14:23

Eine Frage: Was soll geloggt werden?

Werbeanzeige