source: cpp/common/loggers/loggers.cpp @ 1075

Last change on this file since 1075 was 1075, checked in by Maciej Komosinski, 3 years ago

Fixed dangerous size_t-1

  • Property svn:eol-style set to native
File size: 4.5 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2019  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#include "loggers.h"
6#include <common/util-string.h>
7#include <string.h>
8
9void logMessage(const char *obj, const char *method, int level, const char *msg)
10{
11        tlsGetRef(message_handler_manager_instance).send(obj, method, level, msg);
12}
13
14THREAD_LOCAL_DEF(LoggerManager, message_handler_manager_instance);
15
16void LoggerManager::send(int position, const char *obj, const char *method, int level, const char *msg)
17{
18        if (position >= int(loggers.size())) position = int(loggers.size()) - 1;
19        bool blocked = false;
20        for (int i = position; i >= 0; i--)
21        {
22                LoggerBase *logger = loggers[i];
23                if ((!(logger->options & LoggerBase::Paused)) &&
24                        ((!blocked) || (logger->options & LoggerBase::CannotBeBlocked)))
25                {
26                        logger->handle(obj, method, level, msg);
27                        if (!(logger->options & LoggerBase::DontBlock)) blocked = true;
28                }
29        }
30}
31
32int LoggerManager::add(LoggerBase *logger)
33{
34        logger->manager = this;
35        loggers.push_back(logger);
36        return int(loggers.size()) - 1;
37}
38
39void LoggerManager::remove(int i)
40{
41        LoggerBase *h = loggers[i];
42        h->manager = NULL;
43        loggers.erase(loggers.begin() + i);
44}
45
46void LoggerManager::remove(LoggerBase *logger)
47{
48        int index = find(logger);
49        if (index >= 0)
50                remove(index);
51}
52
53void LoggerManager::removeAll()
54{
55        while (loggers.size() > 0)
56                remove(int(loggers.size()) - 1);
57}
58
59//////////////////////////////////
60
61void LoggerBase::send(const char *obj, const char *method, int level, const char *msg)
62{
63        if (!isEnabled()) return;
64        int position = manager->find(this);
65        if (position >= 0) manager->send(position - 1, obj, method, level, msg);
66}
67
68void LoggerBase::logPrintf(const char *obj, const char *method, int level, const char *msg, ...)
69{
70        if (!isEnabled()) return;
71        string buf;
72        va_list argptr;
73        va_start(argptr, msg);
74        buf = ssprintf_va(msg, argptr);
75        va_end(argptr);
76        send(obj, method, level, buf.c_str());
77}
78
79
80void LoggerBase::enable()
81{
82        if (isEnabled()) return;
83        tlsGetRef(message_handler_manager_instance).add(this);
84}
85
86void LoggerBase::disable()
87{
88        if (!isEnabled()) return;
89        tlsGetRef(message_handler_manager_instance).remove(this);
90}
91
92void LoggerBase::pause()
93{
94        if (isPaused()) return;
95        options |= Paused;
96}
97
98void LoggerBase::resume()
99{
100        if (!isPaused()) return;
101        options &= ~Paused;
102}
103
104void LoggerBase::handle(const char *obj, const char *method, int level, const char *msg)
105{
106        int line = 0; //all lines except the first one get the "..." prefix
107        const char* nextsep;
108        do
109        {
110                nextsep = strchr(msg, '\n');
111                if (nextsep == NULL) //last chunk, until the end
112                        nextsep = strchr(msg, '\0');
113                if ((nextsep > msg) && (nextsep[-1] == '\r'))
114                        nextsep--;
115                if (line == 0)
116                {
117                        if (*nextsep == 0) //there was only one line! no need to modify it in any way.
118                                handleSingleLine(obj, method, level, msg);
119                        else //first line from multi-line
120                                handleSingleLine(obj, method, level, string(msg, nextsep - msg).c_str());
121                }
122                else //consecutive lines from multi-line
123                        handleSingleLine(obj, method, level, (LOG_MULTILINE_CONTINUATION + string(msg, nextsep - msg)).c_str()); //could also add line numbers like ...(3)... but let's keep the prefix short and simple
124                line++;
125                if ((options & Paused) != 0) break; //seemingly pointless test (it was already checked), but 'options' can change inside handleSingleLine().
126                if ((nextsep[0] == '\r') && (nextsep[1] == '\n'))
127                        msg = nextsep + 2;
128                else if (*nextsep)
129                        msg = nextsep + 1;
130        } while (*nextsep);
131}
132
133/////////////////////////////////
134
135void LoggerToMemory::handle(const char *obj, const char *method, int level, const char *msg)
136{
137        if (level > maxlevel) maxlevel = level;
138        if (level >= LOG_INFO) infocount++;
139        if (level >= LOG_WARN) warncount++;
140        if (level >= LOG_ERROR) errcount++;
141
142        if (level >= minleveltostore)
143        {
144                storedcount++;
145                if (options & (StoreFirstMessage | StoreAllMessages))
146                {
147                        if (!((options&StoreFirstMessage) && (msgs.length() > 0)))
148                        {
149                                if (msgs.length() > 0) msgs += '\n';
150                                msgs += ssprintf(LOG_FORMAT, logLevelName(level), obj, method, msg);
151                        }
152                }
153        }
154}
155
156string LoggerToMemory::getCountSummary() const
157{
158        if (getInfoCount())
159        {
160                string msg;
161                if (getErrorCount())
162                        msg = ssprintf("%d error(s)", getErrorCount());
163                int w;
164                if ((w = getWarningCount() - getErrorCount()))
165                        msg += ssprintf("%s%d warning(s)", (getErrorCount() ? ", " : ""), w);
166                if ((w = getInfoCount() - getWarningCount()))
167                        msg += ssprintf("%s%d message(s)", (getWarningCount() ? ", " : ""), w);
168                return msg;
169        }
170        return string("");
171}
Note: See TracBrowser for help on using the repository browser.