[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: klfdefs.cpp 991 2017-01-04 09:15:43Z phfaist $ */
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 
903 static char __klf_version_string[] = KLF_VERSION_STRING;
904 
905 
906 KLF_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 
929 class KLFDebugObjectWatcherPrivate
930 {
931 public:
932  QMap<quintptr, QString> refInfos;
933 };
934 
935 // static
936 KLFDebugObjectWatcher *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 
950 KLFDebugObjectWatcher::KLFDebugObjectWatcher()
951  : QObject(qApp)
952 {
953  p = new KLFDebugObjectWatcherPrivate;
954 }
955 KLFDebugObjectWatcher::~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 
998 KLF_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 
1027 KLF_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 
1037 KLF_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()
1063 static 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 }
1077 KLFDebugBlock::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 
1110 inline 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
1120 KLF_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 
1130 KLF_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 
1153 static 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 
1181 KLF_EXPORT int klfVersionCompare(const QString& v1, const QString& v2)
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 
KLF_EXPORT QByteArray klfShortFuncSignature(const QByteArray &funcname)
Definition: klfdefs.cpp:975
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QString cap(int nth) const
#define KLF_SHORT_TIME
Definition: klfdebug.h:42
KLF_EXPORT QByteArray klfFmtDouble(double num, char fmt, int precision)
Definition: klfdefs.cpp:1037
KLF_EXPORT int klfVersionMaj()
Definition: klfdefs.cpp:911
KLF_EXPORT QDebug __klf_dbg_hdr(QDebug dbg, const char *funcname, const char *refinstance, const char *shorttime)
Definition: klfdefs.cpp:1120
void debugObjectDestroyed(QObject *object)
Definition: klfdefs.cpp:959
virtual ~KLFDebugBlock()
Definition: klfdefs.cpp:1086
QString pBlockName
Definition: klfdebug.h:54
int lastIndexOf(char ch, int from) const
Base declarations for klatexformula and some utilities.
KLF_EXPORT QByteArray klfFmt(const char *fmt, va_list pp)
Definition: klfdefs.cpp:998
bool startsWith(const QByteArray &ba) const
QDebug & nospace()
#define klfDbg(streamableItems)
print debug stream items
virtual const QMetaObject * metaObject() const
KLF_EXPORT int klfVersionMin()
Definition: klfdefs.cpp:915
void registerObjectRefInfo(QObject *object, const QString &refInfo)
Definition: klfdefs.cpp:945
KLF_EXPORT QDebug __klf_warning_hdr(QDebug warndbg, const char *funcname, const char *shorttime)
Definition: klfdefs.cpp:1130
KLF_EXPORT int klfVersionCompare(const QString &v1, const QString &v2)
Compares two version strings.
Definition: klfdefs.cpp:1181
int indexOf(char ch, int from) const
QString number(int n, int base)
#define VERSION_RX
Definition: klfdefs.cpp:1173
#define KLF_EXPORT
Definition: klfdefs.h:41
int toInt(bool *ok, int base) const
bool isEmpty() const
const char * constData() const
QByteArray mid(int pos, int len) const
#define klfFmtCC
Definition: klfdefs.h:61
#define KLF_FUNC_NAME
const char * className() const
KLF_EXPORT QString klfTimeOfDay(bool shortfmt)
Definition: klfdefs.cpp:1049
QDateTime currentDateTime()
QByteArray toLatin1() const
KLF_EXPORT int klfVersionRelease()
Definition: klfdefs.cpp:919
Utility to time the execution of a block.
Definition: klfdebug.h:45
KLFDebugBlockTimer(const QString &blockName)
Definition: klfdefs.cpp:1094
KLF_EXPORT const char * klfVersion()
Definition: klfdefs.cpp:906
virtual ~KLFDebugBlockTimer()
Definition: klfdefs.cpp:1102
QString func_name_w_parens(const char *f)
Definition: klfdefs.cpp:1110
QStringList klf_version_suffixes
Definition: klfdefs.cpp:1148
QString fromLatin1(const char *str, int size)
int indexOf(const QRegExp &rx, int from) const
KLF_EXPORT bool klfIsValidVersion(const QString &v)
Definition: klfdefs.cpp:1175
static KLFDebugObjectWatcher * getWatcher()
Definition: klfdefs.cpp:938
int compare(const QString &other, Qt::CaseSensitivity cs) const
bool exactMatch(const QString &str) const
KLFDebugBlock(const QString &blockName)
Definition: klfdefs.cpp:1066
KLF_EXPORT bool klfVersionCompareLessThan(const QString &v1, const QString &v2)
Same as klfVersionCompare(v1,v2) < 0
Definition: klfdefs.cpp:1270

Generated by doxygen 1.8.13