Torc  0.1
torccoreutils.cpp
Go to the documentation of this file.
1 /* TorcCoreUtils
2 *
3 * This file is part of the Torc project.
4 *
5 * Copyright (C) Mark Kendall 2012-18
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 * USA.
21 */
22 
23 // Qt
24 #include <QThread>
25 #include <QStringList>
26 
27 // Std
28 #include <time.h>
29 #include <errno.h>
30 
31 // Torc
32 #include "torccompat.h"
33 #include "torclogging.h"
34 #include "torccoreutils.h"
35 
36 // zlib
37 #ifdef USING_ZLIB
38 #include "zlib.h"
39 #endif
40 
42 QDateTime TorcCoreUtils::DateTimeFromString(const QString &String)
43 {
44  if (String.isEmpty())
45  return QDateTime();
46 
47  if (!String.contains('-') && String.length() == 14)
48  {
49  // must be in yyyyMMddhhmmss format
50  return QDateTime::fromString(String, QStringLiteral("yyyyMMddhhmmss"));
51  }
52 
53  return QDateTime::fromString(String, Qt::ISODate);
54 }
55 
62 {
63 #ifdef Q_OS_WIN
64  LARGE_INTEGER ticksPerSecond;
65  LARGE_INTEGER ticks;
66  if (QueryPerformanceFrequency(&ticksPerSecond))
67  {
68  QueryPerformanceCounter(&ticks);
69  return (quint64)(((qreal)ticks.QuadPart / ticksPerSecond.QuadPart) * 1000000);
70  }
71  return GetTickCount() * 1000;
72 #elif defined(Q_OS_MAC)
73  struct timeval timenow;
74  gettimeofday(&timenow, nullptr);
75  return (timenow.tv_sec * 1000000) + timenow.tv_usec;
76 #else
77  timespec timenow;
78  clock_gettime(CLOCK_MONOTONIC, &timenow);
79  return (timenow.tv_sec * 1000000) + ((timenow.tv_nsec + 500) / 1000);
80 #endif
81 }
82 
87 void TorcCoreUtils::QtMessage(QtMsgType Type, const QMessageLogContext &Context, const QString &Message)
88 {
89  const char *function = Context.function ? Context.function : __FUNCTION__;
90  const char *file = Context.file ? Context.file : __FILE__;
91  int line = Context.line ? Context.line : __LINE__;
92 
93  int level = LOG_UNKNOWN;
94  switch (Type)
95  {
96  case QtFatalMsg: level = LOG_CRIT; break;
97  case QtDebugMsg: level = LOG_INFO; break;
98  default: level = LOG_ERR;
99  }
100 
101  if (VERBOSE_LEVEL_CHECK(VB_GENERAL, level))
102  {
103  PrintLogLine(VB_GENERAL, (LogLevel)level,
104  file, line, function,
105  Message.toLocal8Bit().constData());
106  }
107 
108  if (LOG_CRIT == level)
109  {
110  QThread::msleep(100);
111  abort();
112  }
113 }
114 
117 {
118 #ifdef USING_ZLIB
119  return true;
120 #else
121  return false;
122 #endif
123 }
124 
130 QByteArray TorcCoreUtils::GZipCompress(QByteArray &Source)
131 {
132  QByteArray result;
133 
134 #ifndef USING_ZLIB
135  (void) Source;
136  return result;
137 #else
138  // this shouldn't happen
139  if (Source.size() < 0)
140  return result;
141 
142  // initialise zlib (see zlib usage examples)
143  static const int chunksize = 16384;
144  char outputbuffer[chunksize];
145 
146  z_stream stream;
147  stream.zalloc = nullptr;
148  stream.zfree = nullptr;
149  stream.opaque = nullptr;
150  stream.avail_in = Source.size();
151  stream.next_in = (Bytef*)Source.data();
152 
153  if (Z_OK != deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY))
154  {
155  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Failed to setup zlip decompression"));
156  return result;
157  }
158 
159  do
160  {
161  stream.avail_out = chunksize;
162  stream.next_out = (Bytef*)outputbuffer;
163 
164  int error = deflate(&stream, Z_FINISH);
165 
166  if (Z_NEED_DICT == error || error < Z_OK)
167  {
168  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Failed to compress data"));
169  deflateEnd(&stream);
170  return result;
171  }
172 
173  result.append(outputbuffer, chunksize - stream.avail_out);
174  } while (stream.avail_out == 0);
175 
176  deflateEnd(&stream);
177  return result;
178 #endif
179 }
180 
186 QByteArray TorcCoreUtils::GZipCompressFile(QFile &Source)
187 {
188  QByteArray result;
189 
190 #ifndef USING_ZLIB
191  (void) Source;
192  return result;
193 #else
194  // this shouldn't happen
195  if (Source.size() < 0)
196  return result;
197 
198  // initialise zlib (see zlib usage examples)
199  static const int chunksize = 32768;
200  char inputbuffer[chunksize];
201  char outputbuffer[chunksize];
202 
203  z_stream stream;
204  stream.zalloc = nullptr;
205  stream.zfree = nullptr;
206  stream.opaque = nullptr;
207 
208  if (Z_OK != deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY))
209  {
210  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Failed to setup zlip decompression"));
211  return result;
212  }
213 
214  // this should have been checked already
215  if (!Source.isOpen())
216  if (!Source.open(QIODevice::ReadOnly))
217  return result;
218 
219  while (Source.bytesAvailable() > 0)
220  {
221  stream.avail_out = chunksize;
222  stream.next_out = (Bytef*)outputbuffer;
223 
224  qint64 read = Source.read(inputbuffer, qMin(Source.bytesAvailable(), (qint64)chunksize));
225 
226  if (read > 0)
227  {
228  stream.avail_in = read;
229  stream.next_in = (Bytef*)inputbuffer;
230 
231  int error = deflate(&stream, Source.bytesAvailable() ? Z_SYNC_FLUSH : Z_FINISH);
232 
233  if (error == Z_OK || error == Z_STREAM_END)
234  {
235  result.append(outputbuffer, chunksize - stream.avail_out);
236  continue;
237  }
238  }
239 
240  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Failed to compress file"));
241  deflateEnd(&stream);
242  return result;
243  }
244 
245  deflateEnd(&stream);
246  return result;
247 #endif
248 }
bool HasZlib(void)
Return true if zlib support is available.
quint64 GetMicrosecondCount(void)
Get the current system clock time in microseconds.
QDateTime DateTimeFromString(const QString &String)
Parse a QDateTime from the given QString.
void PrintLogLine(uint64_t mask, LogLevel level, const char *file, int line, const char *function, const char *format,...)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: torclogging.h:20
QByteArray GZipCompressFile(QFile &Source)
Compress the given file using GZip.
QByteArray GZipCompress(QByteArray &Source)
Compress the supplied data using GZip.
void QtMessage(QtMsgType Type, const QMessageLogContext &Context, const QString &Message)
A handler routine for Qt messages.
#define VERBOSE_LEVEL_CHECK(_MASK_, _LEVEL_)
Definition: torclogging.h:17