[KLF Backend][KLF Tools][KLF Home]
KLatexFormula Project
klfdefs.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * file klfdefs.cpp
3 * This file is part of the KLatexFormula Project.
4 * Copyright (C) 2011 by Philippe Faist
5 * philippe.faist at bluewin.ch
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 *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22/* $Id$ */
23
24#include <stdlib.h>
25#include <stdio.h> // vsprintf(), vsnprintf
26#include <stdarg.h> // va_list, va_arg, va_end in klfFmt()
27#include <sys/time.h>
28
29#include <QDir>
30#include <QFile>
31#include <QFileInfo>
32#include <QRegExp>
33#include <QApplication>
34#include <QMetaObject>
35#include <QDebug>
36#include <QDateTime>
37
38#include "klfdefs.h"
39
50/* * This is not a bug, it's cosmetic... \ bug Remove Qt3 support w/ KLFBACKEND_QT4 in all files */
51
52
591/* -- * ------- NOT PROVIDED. NOT NICE. -------------------
592 \def KLF_PROPERTY_GET
593 \hideinitializer
594
595 \bug DOES THIS MACRO PREVENT DOXYGEN DOCUMENTATION ?
596
597 Declares a functions, one public designed to get a property value. This macro is to be used
598 within a class declaration.
599
600 Useful in conjunction with Q_PROPERTY declarations.
601
602 This macro expands to
603 \code
604 public: <type and propertyName>() const;
605 \endcode
606
607 \param type_and_prop is the type and the name of the property, separated by space
608
609 Possible definitions of this functions are provided with the macros \ref KLF_DEFINE_PROPERTY_GET
610 and \ref KLF_DEFINE_PROPERTY_GETSET.
611*/
612
878// INTERNAL
879
903static char __klf_version_string[] = KLF_VERSION_STRING;
904
905
906KLF_EXPORT const char * klfVersion()
907{
908 return __klf_version_string;
909}
910
912{
913 return KLF_VERSION_MAJ;
914}
916{
917 return KLF_VERSION_MIN;
918}
920{
921 return KLF_VERSION_REL;
922}
923
924
925
926
927// declared in klfdebug.h
928
929class KLFDebugObjectWatcherPrivate
930{
931public:
933};
934
935// static
936KLFDebugObjectWatcher *KLFDebugObjectWatcher::instance = NULL;
937// static
939{
940 if (instance == NULL)
941 instance = new KLFDebugObjectWatcher;
942 return instance;
943}
944
946{
947 p->refInfos[(quintptr)object] = refinfo;
948}
949
950KLFDebugObjectWatcher::KLFDebugObjectWatcher()
951 : QObject(qApp)
952{
953 p = new KLFDebugObjectWatcherPrivate;
954}
955KLFDebugObjectWatcher::~KLFDebugObjectWatcher()
956{
957 delete p;
958}
960{
961 quintptr obji = (quintptr) object;
962 if (p->refInfos.contains(obji)) {
963 klfDbg(klfFmtCC("Object destroyed: (%s*)%p; object reference name is `%s'",
964 (object ? object->metaObject()->className() : "void"),
965 (void*)object, qPrintable(p->refInfos[obji])));
966 } else {
967 klfDbg(klfFmtCC("Object destroyed: (%s*)%p",
968 (object ? object->metaObject()->className() : "void"),
969 (void*)object));
970 }
971}
972
973
974
976{
977 // returns the section between the last space before the first open paren and the first open paren
978 int iSpc, iParen;
979 iParen = funcname.indexOf('(');
980 iSpc = funcname.lastIndexOf(' ', iParen-2);
981 // if iSpc is -1, leave it at -1 (eg. constructor signature), the following code still works.
982 if (iParen == -1 || iSpc > iParen) {
983 qWarning("klfShortFuncSignature('%s'): Signature parse error!", funcname.constData());
984 return funcname;
985 }
986 // shorten name
987 QByteArray f = funcname.mid(iSpc+1, iParen-(iSpc+1));
988 // special case: if 'operator...' then keep the arguments, because it doesn't help us much otherwise!
989 if (f.startsWith("operator")) {
990 return funcname.mid(iSpc+1);
991 }
992 return f;
993}
994
995
996
997
998KLF_EXPORT QByteArray klfFmt(const char * fmt, va_list pp)
999{
1000 static const int bufferSize = 8192;
1001 char buffer[bufferSize];
1002 int len;
1003#if defined(_BSD_SOURCE) || _XOPEN_SOURCE >= 500 || defined(_ISOC99_SOURCE)
1004 // stdio.h provided vsnprintf()
1005 len = vsnprintf(buffer, bufferSize, fmt, pp);
1006 if (len >= bufferSize) {
1007 // output was truncated
1008 qWarning("%s(): output from format string \"%s\" was truncated from %d to %d bytes.",
1009 KLF_FUNC_NAME, fmt, len, (bufferSize-1));
1010 len = bufferSize-1;
1011 }
1012#else
1013 len = vsprintf(buffer, fmt, pp);
1014#endif
1015
1016 if (len < 0) {
1017 qWarning("%s(): vs(n)printf() failed for format \"%s\"", KLF_FUNC_NAME, fmt);
1018 return QByteArray();
1019 }
1020
1021 // create a QByteArray
1022 QByteArray data;
1023 data = QByteArray(buffer, len);
1024 return data;
1025}
1026
1027KLF_EXPORT QByteArray klfFmt(const char * fmt, ...)
1028{
1029 va_list pp;
1030 va_start(pp, fmt);
1031 QByteArray data = klfFmt(fmt, pp);
1032 va_end(pp);
1033 return data;
1034}
1035
1036
1037KLF_EXPORT QByteArray klfFmtDouble(double num, char fmt, int precision)
1038{
1039 QString s = QString::number(num, fmt, precision);
1040
1041 QByteArray data;
1042 data = s.toLatin1();
1043 return data;
1044}
1045
1046
1047
1048
1050{
1051 struct timeval tv;
1052 gettimeofday(&tv, NULL);
1053 char temp[128];
1054 if (shortfmt)
1055 sprintf(temp, "%03ld.%06ld", (ulong)tv.tv_sec % 1000, (ulong)tv.tv_usec);
1056 else
1057 sprintf(temp, "%ld.%06ld", (ulong)tv.tv_sec, (ulong)tv.tv_usec);
1058 return QString::fromLatin1(temp);
1059}
1060
1061
1062//#ifdef KLF_DEBUG // see comment in KLFDebugBlock::KLFDebugBlock()
1063static int __klf_dbg_block_depth_counter = 0;
1064//#endif
1065
1067 : pBlockName(blockName), pPrintMsg(true)
1068{
1069 // unconditionally display the debug message. If we compile the library without KLF_DEBUG
1070 // and then use this feature in a program /with/ KLF_DEBUG, then we want the debug message
1071 // to display.
1072
1073 //#ifdef KLF_DEBUG
1074 qDebug("%s: [%02d]block begin", qPrintable(pBlockName), ++__klf_dbg_block_depth_counter);
1075 //#endif
1076}
1077KLFDebugBlock::KLFDebugBlock(bool printmsg, const QString& blockName)
1078 : pBlockName(blockName), pPrintMsg(printmsg)
1079{
1080 //#ifdef KLF_DEBUG // see comment in other constructor.
1081 // convention: __klf_dbg_block_depth_counter is incremented/decremented only when displayed
1082 if (printmsg)
1083 qDebug("%s: [%02d]block begin", qPrintable(pBlockName), ++__klf_dbg_block_depth_counter);
1084 //#endif
1085}
1087{
1088 //#ifdef KLF_DEBUG // see comment in KLFDebugBlock::KLFDebugBlock()
1089 // convention: __klf_dbg_block_depth_counter is incremented/decremented only when displayed
1090 if (pPrintMsg)
1091 qDebug("%s: [%02d]block end", qPrintable(pBlockName), __klf_dbg_block_depth_counter--);
1092 //#endif
1093}
1095 : KLFDebugBlock(false, blockName)
1096{
1097 //#ifdef KLF_DEBUG // see comment in KLFDebugBlock::KLFDebugBlock()
1098 // convention: __klf_dbg_block_depth_counter is incremented/decremented only when displayed
1099 qDebug("+T:%s: %s: [%02d]block begin", KLF_SHORT_TIME, qPrintable(pBlockName), ++__klf_dbg_block_depth_counter);
1100 //#endif
1101}
1103{
1104 //#ifdef KLF_DEBUG // see comment in KLFDebugBlock::KLFDebugBlock()
1105 // convention: __klf_dbg_block_depth_counter is incremented/decremented only when displayed
1106 qDebug("+T:%s: %s: [%02d]block end", KLF_SHORT_TIME, qPrintable(pBlockName), __klf_dbg_block_depth_counter--);
1107 //#endif
1108}
1109
1110inline QString func_name_w_parens(const char *f)
1111{
1112 QString s = QLatin1String(f);
1113 if (s.indexOf('(') == -1)
1114 return s+"()";
1115 return s;
1116}
1117
1118// the following is defined for both debug and non-debug modes. In non-debug modes, it provides the symbol
1119// __klf_dbg_hdr for debugging eg. plugins compiled in debug mode
1120KLF_EXPORT QDebug __klf_dbg_hdr(QDebug dbg, const char * funcname, const char *refinstance, const char * shorttime)
1121{
1122 if (shorttime == NULL)
1123 return dbg.nospace()<<qPrintable(func_name_w_parens(funcname))<<":"<<refinstance
1124 <<"\n ";
1125 else
1126 return dbg.nospace()<<"+T:"<<shorttime<<": "<<qPrintable(func_name_w_parens(funcname))<<":"<<refinstance
1127 <<"\n ";
1128}
1129
1130KLF_EXPORT QDebug __klf_warning_hdr(QDebug warndbg, const char * funcname, const char * shorttime)
1131{
1132 Q_UNUSED(shorttime) ; // maybe if I one day decide to change the format to include shorttime... (?)
1133 return warndbg.nospace()<<"***** In function "<<qPrintable(func_name_w_parens(funcname))
1134 <<" " // shorttime is too short:
1135 <<qPrintable(QDateTime::currentDateTime().toString(Qt::DefaultLocaleShortDate))
1136 <<" *****"
1137 <<"\n ";
1138
1139}
1140
1141
1142
1143// ----------------------------------------
1144
1145
1146
1147
1149 QStringList() << "a" << "alpha" << "b" << "beta" << "p" << "pre" << "preview" << "RC" << "rc"
1150/* */ << "" // empty suffix or any unrecognized suffix
1151/* */ << "post" << "dev" << "devel";
1152
1153static int __klf_version_compare_suffix_words(QString w1, QString w2)
1154{
1155 // a list of known words
1156 const QStringList& words = klf_version_suffixes;
1157 // now compare the words
1158 int borderBeforeAfter = words.indexOf("");
1159 if (borderBeforeAfter < 0)
1160 qWarning("klfVersionCompare: suffix words list doesn't contain \"\"!");
1161 int i1 = words.indexOf(w1);
1162 int i2 = words.indexOf(w2);
1163 if (i1 == -1 && i2 == -1)
1164 return QString::compare(w1, w2);
1165 if (i2 == -1)
1166 return i1 < borderBeforeAfter ? -1 : +1;
1167 if (i1 == -1)
1168 return i2 < borderBeforeAfter ? +1 : -1;
1169 // both are recognized words
1170 return i1 - i2;
1171}
1172
1173#define VERSION_RX "^(\\d+)(\\.(\\d+)(\\.(\\d+)([a-zA-Z]+\\d*)?)?)?$"
1174
1176{
1177 QRegExp rx(VERSION_RX);
1178 return rx.exactMatch(v);
1179}
1180
1182{
1183 qDebug("klfVersionCompare(): Comparing versions %s and %s", qPrintable(v1), qPrintable(v2));
1184 if (v1 == v2)
1185 return 0;
1186 if (v1.isEmpty()) // v1 is empty, but v2 is not empty because of test above
1187 return -1;
1188 if (v2.isEmpty()) // v2 is empty, but not v1 because of test above
1189 return 1;
1190 // *1 2 *3 4 *5 *6
1191 QRegExp rx1(VERSION_RX);
1192 QRegExp rx2(rx1);
1193 if (!rx1.exactMatch(v1)) {
1194 qWarning("klfVersionLessThan: Invalid version number format: %s", qPrintable(v1));
1195 return -200;
1196 }
1197 if (!rx2.exactMatch(v2)) {
1198 qWarning("klfVersionLessThan: Invalid version number format: %s", qPrintable(v2));
1199 return -200;
1200 }
1201 int maj1 = rx1.cap(1).toInt();
1202 int maj2 = rx2.cap(1).toInt();
1203 if (maj1 != maj2)
1204 return maj1 - maj2;
1205 bool hasmin1 = !rx1.cap(2).isEmpty();
1206 bool hasmin2 = !rx2.cap(2).isEmpty();
1207 if ( ! hasmin1 && ! hasmin2 )
1208 return 0; // equal
1209 if ( ! hasmin1 && hasmin2 )
1210 return -1; // 3 < 3.x
1211 if ( hasmin1 && ! hasmin2 )
1212 return +1; // 3.x > 3
1213 int min1 = rx1.cap(3).toInt();
1214 int min2 = rx2.cap(3).toInt();
1215 if ( min1 != min2 )
1216 return min1 - min2;
1217
1218 bool hasrel1 = !rx1.cap(4).isEmpty();
1219 bool hasrel2 = !rx2.cap(4).isEmpty();
1220 if ( ! hasrel1 && ! hasrel2 )
1221 return 0; // equal
1222 if ( ! hasrel1 && hasrel2 )
1223 return -1; // 3.x < 3.x.y
1224 if ( hasrel1 && ! hasrel2 )
1225 return +1; // 3.x.y > 3.x
1226 int rel1 = rx1.cap(5).toInt();
1227 int rel2 = rx2.cap(5).toInt();
1228 if ( rel1 != rel2 )
1229 return rel1 - rel2;
1230
1231 QString suffix1 = rx1.cap(6);
1232 QString suffix2 = rx2.cap(6);
1233
1234 // qDebug("Suffix1=%s, suffix2=%s", qPrintable(suffix1), qPrintable(suffix2));
1235
1236 if (suffix1 == suffix2)
1237 return 0; // equal
1238
1239 // 1 2
1240 QRegExp rxs1("^([a-zA-Z]*)(\\d*)$");
1241 QRegExp rxs2(rxs1);
1242 rxs1.exactMatch(suffix1); // must necessarily match, already matched global regex
1243 rxs2.exactMatch(suffix2);
1244
1245 QString w1 = rxs1.cap(1);
1246 QString w2 = rxs2.cap(1);
1247 QString ns1 = rxs1.cap(2);
1248 QString ns2 = rxs2.cap(2);
1249
1250 int cmp = __klf_version_compare_suffix_words(w1, w2);
1251 if (cmp != 0)
1252 return cmp; // words are enough to make the difference
1253
1254 // the words are the same -> compare ns1<->ns2
1255 if (ns1.isEmpty()) {
1256 if (ns2.isEmpty())
1257 return 0; // equal
1258 // with suffix number compares greater than without
1259 return -1;
1260 }
1261 if (ns2.isEmpty()) {
1262 return +1;
1263 }
1264
1265 int n1 = ns1.toInt();
1266 int n2 = ns2.toInt();
1267 return n1 - n2;
1268}
1269
1271{
1272 return klfVersionCompare(v1,v2) < 0;
1273}
1274
1275
Utility to time the execution of a block.
Definition klfdebug.h:46
KLFDebugBlock(const QString &blockName)
Definition klfdefs.cpp:1066
virtual ~KLFDebugBlock()
Definition klfdefs.cpp:1086
QString pBlockName
Definition klfdebug.h:54
KLFDebugBlockTimer(const QString &blockName)
Definition klfdefs.cpp:1094
virtual ~KLFDebugBlockTimer()
Definition klfdefs.cpp:1102
void registerObjectRefInfo(QObject *object, const QString &refInfo)
Definition klfdefs.cpp:945
void debugObjectDestroyed(QObject *object)
Definition klfdefs.cpp:959
static KLFDebugObjectWatcher * getWatcher()
Definition klfdefs.cpp:938
#define KLF_SHORT_TIME
Definition klfdebug.h:42
#define klfDbg(streamableItems)
print debug stream items
Definition klfdebug.h:158
KLF_EXPORT int klfVersionCompare(const QString &v1, const QString &v2)
Compares two version strings.
Definition klfdefs.cpp:1181
QString func_name_w_parens(const char *f)
Definition klfdefs.cpp:1110
#define VERSION_RX
Definition klfdefs.cpp:1173
KLF_EXPORT QString klfTimeOfDay(bool shortfmt)
Definition klfdefs.cpp:1049
KLF_EXPORT QByteArray klfShortFuncSignature(const QByteArray &funcname)
Definition klfdefs.cpp:975
KLF_EXPORT bool klfVersionCompareLessThan(const QString &v1, const QString &v2)
Same as klfVersionCompare(v1,v2) < 0
Definition klfdefs.cpp:1270
QStringList klf_version_suffixes
Definition klfdefs.cpp:1148
KLF_EXPORT QByteArray klfFmtDouble(double num, char fmt, int precision)
Definition klfdefs.cpp:1037
KLF_EXPORT const char * klfVersion()
Definition klfdefs.cpp:906
KLF_EXPORT QByteArray klfFmt(const char *fmt, va_list pp)
Definition klfdefs.cpp:998
KLF_EXPORT QDebug __klf_warning_hdr(QDebug warndbg, const char *funcname, const char *shorttime)
Definition klfdefs.cpp:1130
KLF_EXPORT int klfVersionMin()
Definition klfdefs.cpp:915
KLF_EXPORT int klfVersionMaj()
Definition klfdefs.cpp:911
KLF_EXPORT int klfVersionRelease()
Definition klfdefs.cpp:919
KLF_EXPORT bool klfIsValidVersion(const QString &v)
Definition klfdefs.cpp:1175
KLF_EXPORT QDebug __klf_dbg_hdr(QDebug dbg, const char *funcname, const char *refinstance, const char *shorttime)
Definition klfdefs.cpp:1120
Base declarations for klatexformula and some utilities.
#define klfFmtCC
Definition klfdefs.h:61
#define KLF_EXPORT
Definition klfdefs.h:41
const char * constData() const
int indexOf(char ch, int from) const
int lastIndexOf(char ch, int from) const
QByteArray mid(int pos, int len) const
bool startsWith(const QByteArray &ba) const
QDateTime currentDateTime()
QDebug & nospace()
bool contains(const Key &key) const
const char * className() const
virtual const QMetaObject * metaObject() const
QString cap(int nth) const
bool exactMatch(const QString &str) const
int compare(const QString &other, Qt::CaseSensitivity cs) const
QString fromLatin1(const char *str, int size)
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
bool isEmpty() const
QString number(int n, int base)
int toInt(bool *ok, int base) const
QByteArray toLatin1() const
int indexOf(const QRegExp &rx, int from) const

Generated by doxygen 1.12.0