GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/logger.cpp Lines: 67 173 38.7 %
Date: 2017-11-29 Branches: 81 284 28.5 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2004-2009  The Mana World Development Team
4
 *  Copyright (C) 2009-2010  The Mana Developers
5
 *  Copyright (C) 2011-2017  The ManaPlus Developers
6
 *
7
 *  This file is part of The ManaPlus Client.
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include "logger.h"
24
25
#include "settings.h"
26
27
#include "listeners/debugmessagelistener.h"
28
29
#include "utils/cast.h"
30
#include "utils/foreach.h"
31
#include "utils/stringutils.h"
32
33
#include <iostream>
34
35
#ifdef WIN32
36
#include <windows.h>
37
#elif defined __APPLE__
38
#include <Carbon/Carbon.h>
39
#endif  // WIN32
40
41
#include <sys/time.h>
42
43
#include <sstream>
44
45
#ifdef USE_SDL2
46
#include <SDL_messagebox.h>
47
#endif  // USE_SDl2
48
49
#ifdef ENABLEDEBUGLOG
50
#if defined(__ANDROID__)
51
#include <android/log.h>
52
#ifdef SPECIAL_LOGGING
53
#define SPECIALLOG(x) __android_log_print(ANDROID_LOG_INFO, "manaplus", x);
54
#define DSPECIALLOG(x) __android_log_print(ANDROID_LOG_VERBOSE, \
55
    "manaplus", x);
56
#else  // SPECIAL_LOGGING
57
#define SPECIALLOG(x) if (mDebugLog) \
58
    __android_log_print(ANDROID_LOG_INFO, "manaplus", x);
59
#define DSPECIALLOG(x) if (mDebugLog) \
60
    __android_log_print(ANDROID_LOG_VERBOSE, "manaplus", x);
61
#endif  // SPECIAL_LOGGING
62
#elif defined __native_client__
63
#ifdef SPECIAL_LOGGING
64
#define SPECIALLOG(x) std::cerr << x;
65
#define DSPECIALLOG(x) std::cerr << x;
66
#else  // SPECIAL_LOGGING
67
#define SPECIALLOG(x) if (mDebugLog) \
68
    std::cerr << x;
69
#define DSPECIALLOG(x) if (mDebugLog) \
70
    std::cerr << x;
71
#endif  // SPECIAL_LOGGING
72
#else  // defined(__ANDROID__)
73
#define SPECIALLOG(x)
74
#define DSPECIALLOG(x)
75
#endif  // defined(__ANDROID__)
76
#endif  // ENABLEDEBUGLOG
77
78
#include "debug.h"
79
80
#define DATESTREAM \
81
    timeStr << "[" \
82
        << ((((tv.tv_sec / 60) / 60) % 24 < 10) ? "0" : "") \
83
        << CAST_S32(((tv.tv_sec / 60) / 60) % 24) \
84
        << ":" \
85
        << (((tv.tv_sec / 60) % 60 < 10) ? "0" : "") \
86
        << CAST_S32((tv.tv_sec / 60) % 60) \
87
        << ":" \
88
        << ((tv.tv_sec % 60 < 10) ? "0" : "") \
89
        << CAST_S32(tv.tv_sec % 60) \
90
        << "." \
91
        << (((tv.tv_usec / 10000) % 100) < 10 ? "0" : "") \
92
        << CAST_S32((tv.tv_usec / 10000) % 100) \
93
        << "] ";
94
95
Logger *logger = nullptr;          // Log object
96
97
2
Logger::Logger() :
98
    mLogFile(),
99
    mDelayedLog(),
100
2
    mMutex(SDL_CreateMutex()),
101
    mThreadLocked(false),
102
    mLogToStandardOut(true),
103
    mDebugLog(false),
104
6
    mReportUnimplemented(false)
105
{
106
#if defined __native_client__ && defined(NACL_LOG)
107
    std::cout.setf(std::ios_base::unitbuf);
108
#endif  // defined __native_client__ && defined(NACL_LOG)
109
2
}
110
111
Logger::~Logger()
112
{
113
    if (mLogFile.is_open())
114
        mLogFile.close();
115
    SDL_DestroyMutex(mMutex);
116
}
117
118
void Logger::setLogFile(const std::string &logFilename)
119
{
120
    if (mLogFile.is_open())
121
        mLogFile.close();
122
123
    mLogFile.open(logFilename.c_str(), std::ios_base::trunc);
124
125
    if (!mLogFile.is_open())
126
    {
127
        std::cout << "Warning: error while opening " << logFilename <<
128
            " for writing.\n";
129
        mLogToStandardOut = true;
130
    }
131
    else
132
    {
133
        mLogToStandardOut = false;
134
    }
135
}
136
137
4348
void Logger::log(const std::string &str)
138
{
139

4348
    log("%s", str.c_str());
140
4348
}
141
142
#ifdef ENABLEDEBUGLOG
143
void Logger::dlog(const std::string &str)
144
{
145
    if (!mDebugLog)
146
        return;
147
148
    // Get the current system time
149
    timeval tv;
150
    gettimeofday(&tv, nullptr);
151
152
    // Print the log entry
153
    std::stringstream timeStr;
154
    DATESTREAM
155
    DSPECIALLOG(str.c_str())
156
157
    if (mLogFile.is_open())
158
        mLogFile << timeStr.str() << str << std::endl;
159
160
    if (mLogToStandardOut)
161
        std::cout << timeStr.str() << str << std::endl;
162
}
163
164
void Logger::dlog2(const std::string &str,
165
                   const int pos,
166
                   const char* const comment)
167
{
168
    if (!mDebugLog)
169
        return;
170
171
    // Get the current system time
172
    timeval tv;
173
    gettimeofday(&tv, nullptr);
174
175
    // Print the log entry
176
    std::stringstream timeStr;
177
    DATESTREAM
178
    DSPECIALLOG(str.c_str())
179
180
    if (mLogFile.is_open())
181
    {
182
        if (comment != nullptr)
183
        {
184
            mLogFile << timeStr.str();
185
            mLogFile.fill('0');
186
            mLogFile.width(4);
187
            mLogFile << pos << " ";
188
            mLogFile << str << ": " << comment << std::endl;
189
        }
190
        else
191
        {
192
            mLogFile << timeStr.str();
193
            mLogFile.fill('0');
194
            mLogFile.width(4);
195
            mLogFile << pos << " ";
196
            mLogFile << str << std::endl;
197
        }
198
    }
199
200
    if (mLogToStandardOut)
201
    {
202
        if (comment != nullptr)
203
        {
204
            std::cout << timeStr.str();
205
            std::cout.fill('0');
206
            std::cout.width(4);
207
            std::cout << pos << " ";
208
            std::cout << str << ": " << comment << std::endl;
209
        }
210
        else
211
        {
212
            std::cout << timeStr.str();
213
            std::cout.fill('0');
214
            std::cout.width(4);
215
            std::cout << pos << " ";
216
            std::cout << str << std::endl;
217
        }
218
    }
219
}
220
#endif  // ENABLEDEBUGLOG
221
222
19419
void Logger::log1(const char *const buf)
223
{
224
19419
    if (settings.disableLoggingInGame)
225
        return;
226
227
    // Get the current system time
228
    timeval tv;
229
19419
    gettimeofday(&tv, nullptr);
230
231
    // Print the log entry
232
38838
    std::stringstream timeStr;
233






77676
    DATESTREAM
234
    SPECIALLOG(buf)
235
236
38838
    if (mLogFile.is_open())
237
        mLogFile << timeStr.str() << buf << std::endl;
238
239
19419
    if (mLogToStandardOut)
240
77676
        std::cout << timeStr.str() << buf << std::endl;
241
}
242
243
43778
void Logger::log(const char *const log_text, ...)
244
{
245
43778
    if (settings.disableLoggingInGame)
246
        return;
247
248
43778
    unsigned size = 1024;
249
43778
    if (strlen(log_text) * 3 > size)
250
        size = CAST_U32(strlen(log_text) * 3);
251
252
43778
    char* buf = new char[CAST_SIZE(size + 1)];
253
    va_list ap;
254
255
    // Use a temporary buffer to fill in the variables
256
43778
    va_start(ap, log_text);
257
87556
    vsnprintf(buf, size, log_text, ap);
258
43778
    buf[size] = 0;
259
43778
    va_end(ap);
260
261
    // Get the current system time
262
    timeval tv;
263
43778
    gettimeofday(&tv, nullptr);
264
265
    // Print the log entry
266
87556
    std::stringstream timeStr;
267






175112
    DATESTREAM
268
    SPECIALLOG(buf)
269
270
87556
    if (mLogFile.is_open())
271
        mLogFile << timeStr.str() << buf << std::endl;
272
273
43778
    if (mLogToStandardOut)
274
175112
        std::cout << timeStr.str() << buf << std::endl;
275
276
    // Delete temporary buffer
277
43778
    delete [] buf;
278
}
279
280
140
void Logger::assertLog(const char *const log_text, ...)
281
{
282
140
    if (settings.disableLoggingInGame)
283
        return;
284
285
140
    unsigned size = 1024;
286
140
    if (strlen(log_text) * 3 > size)
287
        size = CAST_U32(strlen(log_text) * 3);
288
289
140
    char* buf = new char[CAST_SIZE(size + 1)];
290
    va_list ap;
291
292
    // Use a temporary buffer to fill in the variables
293
140
    va_start(ap, log_text);
294
280
    vsnprintf(buf, size, log_text, ap);
295
140
    buf[size] = 0;
296
140
    va_end(ap);
297
298
    // Get the current system time
299
    timeval tv;
300
140
    gettimeofday(&tv, nullptr);
301
302
    // Print the log entry
303
280
    std::stringstream timeStr;
304






560
    DATESTREAM
305
    SPECIALLOG(buf)
306
307
280
    if (mLogFile.is_open())
308
        mLogFile << timeStr.str() << buf << std::endl;
309
310
140
    if (mLogToStandardOut)
311
560
        std::cout << timeStr.str() << buf << std::endl;
312
313

560
    DebugMessageListener::distributeEvent(buf);
314
315
    // Delete temporary buffer
316
140
    delete [] buf;
317
}
318
319
16
void Logger::log_r(const char *const log_text, ...)
320
{
321
16
    if (settings.disableLoggingInGame)
322
        return;
323
324
16
    SDL_mutexP(mMutex);
325
326
16
    unsigned size = 1024;
327
16
    if (strlen(log_text) * 3 > size)
328
        size = CAST_U32(strlen(log_text) * 3);
329
330
16
    char* buf = new char[CAST_SIZE(size + 1)];
331
    va_list ap;
332
333
    // Use a temporary buffer to fill in the variables
334
16
    va_start(ap, log_text);
335
32
    vsnprintf(buf, size, log_text, ap);
336
16
    buf[size] = 0;
337
16
    va_end(ap);
338
339
    // Get the current system time
340
    timeval tv;
341
16
    gettimeofday(&tv, nullptr);
342
343
    // Print the log entry
344
32
    std::stringstream timeStr;
345






64
    DATESTREAM
346
    SPECIALLOG(buf)
347
348
32
    if (mLogFile.is_open())
349
    {
350
        timeStr << buf;
351
        mThreadLocked = true;
352
        mDelayedLog.push_back(timeStr.str());
353
        mThreadLocked = false;
354
    }
355
356
16
    if (mLogToStandardOut)
357
64
        std::cout << timeStr.str() << buf << std::endl;
358
359
    // Delete temporary buffer
360
16
    delete [] buf;
361
362
16
    SDL_mutexV(mMutex);
363
}
364
365
void Logger::flush()
366
{
367
    if (!mThreadLocked)
368
    {
369
        SDL_mutexP(mMutex);
370
        FOR_EACH (STD_VECTOR<std::string>::const_iterator, it, mDelayedLog)
371
            mLogFile << *it << std::endl;
372
        mDelayedLog.clear();
373
        SDL_mutexV(mMutex);
374
    }
375
}
376
377
// here string must be safe for any usage
378
void Logger::safeError(const std::string &error_text)
379
{
380
    log("Error: %s", error_text.c_str());
381
#ifdef USE_SDL2
382
    SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
383
        "Error",
384
        error_text.c_str(),
385
        nullptr);
386
#else  // USE_SDL2
387
#ifdef WIN32
388
    MessageBox(nullptr, error_text.c_str(), "Error", MB_ICONERROR | MB_OK);
389
#elif defined __APPLE__
390
//    Str255 msg;
391
//    CFStringRef error;
392
//    error = CFStringCreateWithCString(nullptr,
393
//                                      error_text.c_str(),
394
//                                      kCFStringEncodingMacRoman);
395
//    CFStringGetPascalString(error, msg, 255, kCFStringEncodingMacRoman);
396
//    StandardAlert(kAlertStopAlert,
397
//                  (const unsigned char*)"\pError",
398
//                  (ConstStr255Param) msg, nullptr, nullptr);
399
#elif defined(__linux__) || defined(__linux)
400
    std::cerr << "Error: " << error_text << std::endl;
401
    const std::string msg = std::string("xmessage \"").append(
402
        error_text).append("\"");
403
    if (system(msg.c_str()) == -1)
404
        std::cerr << "Error: " << error_text << std::endl;
405
#else  // WIN32
406
407
    std::cerr << "Error: " << error_text << std::endl;
408
#endif  // WIN32
409
#endif  // USE_SDL2
410
411
    exit(1);
412
}
413
414
// here string can be unsafe strings
415
void Logger::error(const std::string &error_text)
416
{
417
    log("Error: %s", error_text.c_str());
418
#ifdef USE_SDL2
419
    SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
420
        "Error",
421
        error_text.c_str(),
422
        nullptr);
423
#else  // USE_SDL2
424
#ifdef WIN32
425
    MessageBox(nullptr, error_text.c_str(), "Error", MB_ICONERROR | MB_OK);
426
#elif defined __APPLE__
427
//    Str255 msg;
428
//    CFStringRef error;
429
//    error = CFStringCreateWithCString(nullptr,
430
//                                      error_text.c_str(),
431
//                                      kCFStringEncodingMacRoman);
432
//    CFStringGetPascalString(error, msg, 255, kCFStringEncodingMacRoman);
433
//    StandardAlert(kAlertStopAlert,
434
//                  (const unsigned char*)"\pError",
435
//                  (ConstStr255Param) msg, nullptr, nullptr);
436
#elif defined(__linux__) || defined(_linux)
437
    std::cerr << "Error: " << error_text << std::endl;
438
    const std::string msg("xmessage \"Error happened. "
439
        "Please see log file for more information.\"");
440
    if (system(msg.c_str()) == -1)
441
        std::cerr << "Error: " << error_text << std::endl;
442
#else  // WIN32
443
444
    std::cerr << "Error: " << error_text << std::endl;
445
#endif  // WIN32
446
#endif  // USE_SDL2
447
448
    exit(1);
449
}
450
451
void Logger::unimplemented(const int id)
452
{
453
    if (!mReportUnimplemented)
454
        return;
455
456
    const std::string str = strprintf("Unimplimented packet: %d (0x%x)",
457
        id,
458
        CAST_U32(id));
459
    DebugMessageListener::distributeEvent(str);
460
    log(str);
461
}
462
463
void Logger::unimplemented(const int id,
464
                           const int id2)
465
{
466
    if (!mReportUnimplemented)
467
        return;
468
469
    const std::string str = strprintf(
470
        "Unimplimented field value %d for packet %d (0x%x)",
471
        id2,
472
        id,
473
        CAST_U32(id));
474
    DebugMessageListener::distributeEvent(str);
475
    log(str);
476
}
477
478
void Logger::unimplemented(const uint32_t id,
479
                           const uint32_t id2,
480
                           const uint32_t id3) const
481
{
482
    if (!mReportUnimplemented)
483
        return;
484
485
    const std::string str = strprintf(
486
        "Wrong actual or planned inbound packet size!. "
487
        "Packet id: %u(0x%x), Planned size: %u, Actual size: %u",
488
        id,
489
        id,
490
        id2,
491
        id3);
492
    DebugMessageListener::distributeEvent(str);
493
4
}