[KLF Backend][KLF Tools][KLF Home]
KLatexFormula Project
src/klftools/klfdefs.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002  *   file klfdefs.cpp
00003  *   This file is part of the KLatexFormula Project.
00004  *   Copyright (C) 2011 by Philippe Faist
00005  *   philippe.faist at bluewin.ch
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00021  ***************************************************************************/
00022 /* $Id$ */
00023 
00024 #include <stdlib.h>
00025 #include <stdio.h> // vsprintf(), vsnprintf
00026 #include <stdarg.h> // va_list, va_arg, va_end in klfFmt()
00027 #include <sys/time.h>
00028 
00029 #include <QDir>
00030 #include <QFile>
00031 #include <QFileInfo>
00032 #include <QRegExp>
00033 #include <QApplication>
00034 #include <QMetaObject>
00035 #include <QDebug>
00036 #include <QDateTime>
00037 
00038 #include "klfdefs.h"
00039 
00050 /* * This is not a bug, it's cosmetic... \ bug Remove Qt3 support w/ KLFBACKEND_QT4 in all files */
00051 
00052 
00591 /* -- * ------- NOT PROVIDED. NOT NICE. -------------------
00592   \def KLF_PROPERTY_GET
00593   \hideinitializer
00594  
00595   \bug DOES THIS MACRO PREVENT DOXYGEN DOCUMENTATION ?
00596  
00597   Declares a functions, one public designed to get a property value. This macro is to be used
00598   within a class declaration.
00599  
00600   Useful in conjunction with Q_PROPERTY declarations.
00601  
00602   This macro expands to
00603   \code 
00604     public: <type and propertyName>() const;
00605   \endcode
00606  
00607   \param type_and_prop is the type and the name of the property, separated by space
00608  
00609   Possible definitions of this functions are provided with the macros \ref KLF_DEFINE_PROPERTY_GET
00610   and \ref KLF_DEFINE_PROPERTY_GETSET.
00611 */
00612 
00878 // INTERNAL
00879 
00903 static char __klf_version_string[] = KLF_VERSION_STRING;
00904 
00905 
00906 KLF_EXPORT const char * klfVersion()
00907 {
00908   return __klf_version_string;
00909 }
00910 
00911 KLF_EXPORT int klfVersionMaj()
00912 {
00913   return KLF_VERSION_MAJ;
00914 }
00915 KLF_EXPORT int klfVersionMin()
00916 {
00917   return KLF_VERSION_MIN;
00918 }
00919 KLF_EXPORT int klfVersionRelease()
00920 {
00921   return KLF_VERSION_REL;
00922 }
00923 
00924 
00925 
00926 
00927 // declared in klfdebug.h
00928 
00929 class KLFDebugObjectWatcherPrivate
00930 {
00931 public:
00932   QMap<quintptr, QString> refInfos;
00933 };
00934 
00935 // static
00936 KLFDebugObjectWatcher *KLFDebugObjectWatcher::instance = NULL;
00937 // static
00938 KLFDebugObjectWatcher *KLFDebugObjectWatcher::getWatcher()
00939 {
00940   if (instance == NULL)
00941     instance = new KLFDebugObjectWatcher;
00942   return instance;
00943 }
00944 
00945 void KLFDebugObjectWatcher::registerObjectRefInfo(QObject *object, const QString& refinfo)
00946 {
00947   p->refInfos[(quintptr)object] = refinfo;
00948 }
00949 
00950 KLFDebugObjectWatcher::KLFDebugObjectWatcher()
00951   : QObject(qApp)
00952 {
00953   p = new KLFDebugObjectWatcherPrivate;
00954 }
00955 KLFDebugObjectWatcher::~KLFDebugObjectWatcher()
00956 {
00957   delete p;
00958 }
00959 void KLFDebugObjectWatcher::debugObjectDestroyed(QObject *object)
00960 {
00961   quintptr obji = (quintptr) object;
00962   if (p->refInfos.contains(obji)) {
00963     klfDbg(klfFmtCC("Object destroyed: (%s*)%p; object reference name is `%s'",
00964                     (object ? object->metaObject()->className() : "void"),
00965                     (void*)object, qPrintable(p->refInfos[obji])));
00966   } else {
00967     klfDbg(klfFmtCC("Object destroyed: (%s*)%p",
00968                     (object ? object->metaObject()->className() : "void"),
00969                     (void*)object));
00970   }
00971 }
00972 
00973 
00974 
00975 KLF_EXPORT QByteArray klfShortFuncSignature(const QByteArray& funcname)
00976 {
00977   // returns the section between the last space before the first open paren and the first open paren
00978   int iSpc, iParen;
00979   iParen = funcname.indexOf('(');
00980   iSpc = funcname.lastIndexOf(' ', iParen-2);
00981   // if iSpc is -1, leave it at -1 (eg. constructor signature), the following code still works.
00982   if (iParen == -1 || iSpc > iParen) {
00983     qWarning("klfShortFuncSignature('%s'): Signature parse error!", funcname.constData());
00984     return funcname;
00985   }
00986   // shorten name
00987   QByteArray f = funcname.mid(iSpc+1, iParen-(iSpc+1));
00988   // special case: if 'operator...' then keep the arguments, because it doesn't help us much otherwise!
00989   if (f.startsWith("operator")) {
00990     return funcname.mid(iSpc+1);
00991   }
00992   return f;
00993 }
00994 
00995 
00996 
00997 
00998 KLF_EXPORT QByteArray klfFmt(const char * fmt, va_list pp)
00999 {
01000   static const int bufferSize = 8192;
01001   char buffer[bufferSize];
01002   int len;
01003 #if defined(_BSD_SOURCE) || _XOPEN_SOURCE >= 500 || defined(_ISOC99_SOURCE)
01004   // stdio.h provided vsnprintf()
01005   len = vsnprintf(buffer, bufferSize, fmt, pp);
01006   if (len >= bufferSize) {
01007     // output was truncated
01008     qWarning("%s(): output from format string \"%s\" was truncated from %d to %d bytes.",
01009              KLF_FUNC_NAME, fmt, len, (bufferSize-1));
01010     len = bufferSize-1;
01011   }
01012 #else
01013   len = vsprintf(buffer, fmt, pp);
01014 #endif
01015 
01016   if (len < 0) {
01017     qWarning("%s(): vs(n)printf() failed for format \"%s\"", KLF_FUNC_NAME, fmt);
01018     return QByteArray();
01019   }
01020 
01021   // create a QByteArray
01022   QByteArray data;
01023   data = QByteArray(buffer, len);
01024   return data;
01025 }
01026 
01027 KLF_EXPORT QByteArray klfFmt(const char * fmt, ...)
01028 {
01029   va_list pp;
01030   va_start(pp, fmt);
01031   QByteArray data = klfFmt(fmt, pp);
01032   va_end(pp);
01033   return data;
01034 }
01035 
01036 
01037 KLF_EXPORT QByteArray klfFmtDouble(double num, char fmt, int precision)
01038 {
01039   QString s = QString::number(num, fmt, precision);
01040 
01041   QByteArray data;
01042   data = s.toLatin1();
01043   return data;
01044 }
01045 
01046 
01047 
01048 
01049 KLF_EXPORT QString klfTimeOfDay(bool shortfmt)
01050 {
01051   struct timeval tv;
01052   gettimeofday(&tv, NULL);
01053   char temp[128];
01054   if (shortfmt)
01055     sprintf(temp, "%03ld.%06ld", (ulong)tv.tv_sec % 1000, (ulong)tv.tv_usec);
01056   else
01057     sprintf(temp, "%ld.%06ld", (ulong)tv.tv_sec, (ulong)tv.tv_usec);
01058   return QString::fromLatin1(temp);
01059 }
01060 
01061 
01062 //#ifdef KLF_DEBUG // see comment in KLFDebugBlock::KLFDebugBlock()
01063 static int __klf_dbg_block_depth_counter = 0;
01064 //#endif
01065 
01066 KLFDebugBlock::KLFDebugBlock(const QString& blockName)
01067   : pBlockName(blockName), pPrintMsg(true)
01068 {
01069   // unconditionally display the debug message. If we compile the library without KLF_DEBUG
01070   // and then use this feature in a program /with/ KLF_DEBUG, then we want the debug message
01071   // to display.
01072 
01073   //#ifdef KLF_DEBUG
01074   qDebug("%s: [%02d]block begin", qPrintable(pBlockName), ++__klf_dbg_block_depth_counter);
01075   //#endif
01076 }
01077 KLFDebugBlock::KLFDebugBlock(bool printmsg, const QString& blockName)
01078   : pBlockName(blockName), pPrintMsg(printmsg)
01079 {
01080   //#ifdef KLF_DEBUG // see comment in other constructor.
01081   // convention: __klf_dbg_block_depth_counter is incremented/decremented only when displayed
01082   if (printmsg)
01083     qDebug("%s: [%02d]block begin", qPrintable(pBlockName), ++__klf_dbg_block_depth_counter);
01084   //#endif
01085 }
01086 KLFDebugBlock::~KLFDebugBlock()
01087 {
01088   //#ifdef KLF_DEBUG // see comment in KLFDebugBlock::KLFDebugBlock()
01089   // convention: __klf_dbg_block_depth_counter is incremented/decremented only when displayed
01090   if (pPrintMsg)
01091     qDebug("%s: [%02d]block end", qPrintable(pBlockName), __klf_dbg_block_depth_counter--);
01092   //#endif
01093 }
01094 KLFDebugBlockTimer::KLFDebugBlockTimer(const QString& blockName)
01095   : KLFDebugBlock(false, blockName)
01096 {
01097   //#ifdef KLF_DEBUG // see comment in KLFDebugBlock::KLFDebugBlock()
01098   // convention: __klf_dbg_block_depth_counter is incremented/decremented only when displayed
01099   qDebug("+T:%s: %s: [%02d]block begin", KLF_SHORT_TIME, qPrintable(pBlockName), ++__klf_dbg_block_depth_counter);
01100   //#endif
01101 }
01102 KLFDebugBlockTimer::~KLFDebugBlockTimer()
01103 {
01104   //#ifdef KLF_DEBUG // see comment in KLFDebugBlock::KLFDebugBlock()
01105   // convention: __klf_dbg_block_depth_counter is incremented/decremented only when displayed
01106   qDebug("+T:%s: %s: [%02d]block end", KLF_SHORT_TIME, qPrintable(pBlockName), __klf_dbg_block_depth_counter--);
01107   //#endif
01108 }
01109 
01110 inline QString func_name_w_parens(const char *f)
01111 {
01112   QString s = QLatin1String(f);
01113   if (s.indexOf('(') == -1)
01114     return s+"()";
01115   return s;
01116 }
01117 
01118 // the following is defined for both debug and non-debug modes. In non-debug modes, it provides the symbol
01119 // __klf_dbg_hdr for debugging eg. plugins compiled in debug mode
01120 KLF_EXPORT QDebug __klf_dbg_hdr(QDebug dbg, const char * funcname, const char *refinstance, const char * shorttime)
01121 {
01122   if (shorttime == NULL)
01123     return dbg.nospace()<<qPrintable(func_name_w_parens(funcname))<<":"<<refinstance
01124                         <<"\n        ";
01125   else
01126     return dbg.nospace()<<"+T:"<<shorttime<<": "<<qPrintable(func_name_w_parens(funcname))<<":"<<refinstance
01127                         <<"\n        ";
01128 }
01129 
01130 KLF_EXPORT QDebug __klf_warning_hdr(QDebug warndbg, const char * funcname, const char * shorttime)
01131 {
01132   Q_UNUSED(shorttime) ; // maybe if I one day decide to change the format to include shorttime... (?)
01133   return warndbg.nospace()<<"***** In function "<<qPrintable(func_name_w_parens(funcname))
01134                           <<"  " // shorttime is too short:
01135                           <<qPrintable(QDateTime::currentDateTime().toString(Qt::DefaultLocaleShortDate))
01136                           <<" *****"
01137                           <<"\n        ";
01138 
01139 }
01140 
01141 
01142 
01143 // ----------------------------------------
01144 
01145 
01146 
01147 
01148 QStringList klf_version_suffixes =
01149   QStringList() << "a" << "alpha" << "b" << "beta" << "p" << "pre" << "preview" << "RC" << "rc"
01150 /* */           << "" // empty suffix or any unrecognized suffix
01151 /* */           << "post" << "dev" << "devel";
01152 
01153 static int __klf_version_compare_suffix_words(QString w1, QString w2)
01154 {
01155   // a list of known words
01156   const QStringList& words = klf_version_suffixes;
01157   // now compare the words
01158   int borderBeforeAfter = words.indexOf("");
01159   if (borderBeforeAfter < 0)
01160     qWarning("klfVersionCompare: suffix words list doesn't contain \"\"!");
01161   int i1 = words.indexOf(w1);
01162   int i2 = words.indexOf(w2);
01163   if (i1 == -1 && i2 == -1)
01164     return QString::compare(w1, w2);
01165   if (i2 == -1)
01166     return i1 < borderBeforeAfter ? -1 : +1;
01167   if (i1 == -1)
01168     return i2 < borderBeforeAfter ? +1 : -1;
01169   // both are recognized words
01170   return i1 - i2;
01171 }
01172 
01173 #define VERSION_RX "^(\\d+)(\\.(\\d+)(\\.(\\d+)([a-zA-Z]+\\d*)?)?)?$"
01174 
01175 KLF_EXPORT bool klfIsValidVersion(const QString& v)
01176 {
01177   QRegExp rx(VERSION_RX);
01178   return rx.exactMatch(v);
01179 }
01180 
01181 KLF_EXPORT int klfVersionCompare(const QString& v1, const QString& v2)
01182 {
01183   qDebug("klfVersionCompare(): Comparing versions %s and %s", qPrintable(v1), qPrintable(v2));
01184   if (v1 == v2)
01185     return 0;
01186   if (v1.isEmpty()) // v1 is empty, but v2 is not empty because of test above
01187     return -1;
01188   if (v2.isEmpty()) // v2 is empty, but not v1 because of test above
01189     return 1;
01190   //           *1     2  *3     4  *5    *6
01191   QRegExp rx1(VERSION_RX);
01192   QRegExp rx2(rx1);
01193   if (!rx1.exactMatch(v1)) {
01194     qWarning("klfVersionLessThan: Invalid version number format: %s", qPrintable(v1));
01195     return -200;
01196   }
01197   if (!rx2.exactMatch(v2)) {
01198     qWarning("klfVersionLessThan: Invalid version number format: %s", qPrintable(v2));
01199     return -200;
01200   }
01201   int maj1 = rx1.cap(1).toInt();
01202   int maj2 = rx2.cap(1).toInt();
01203   if (maj1 != maj2)
01204     return maj1 - maj2;
01205   bool hasmin1 = !rx1.cap(2).isEmpty();
01206   bool hasmin2 = !rx2.cap(2).isEmpty();
01207   if ( ! hasmin1 && ! hasmin2 )
01208     return 0; // equal
01209   if ( ! hasmin1 && hasmin2 )
01210     return -1; // 3 < 3.x
01211   if ( hasmin1 && ! hasmin2 )
01212     return +1; // 3.x > 3
01213   int min1 = rx1.cap(3).toInt();
01214   int min2 = rx2.cap(3).toInt();
01215   if ( min1 != min2 )
01216     return min1 - min2;
01217 
01218   bool hasrel1 = !rx1.cap(4).isEmpty();
01219   bool hasrel2 = !rx2.cap(4).isEmpty();
01220   if ( ! hasrel1 && ! hasrel2 )
01221     return 0; // equal
01222   if ( ! hasrel1 && hasrel2 )
01223     return -1; // 3.x < 3.x.y
01224   if ( hasrel1 && ! hasrel2 )
01225     return +1; // 3.x.y > 3.x
01226   int rel1 = rx1.cap(5).toInt();
01227   int rel2 = rx2.cap(5).toInt();
01228   if ( rel1 != rel2 )
01229     return rel1 - rel2;
01230 
01231   QString suffix1 = rx1.cap(6);
01232   QString suffix2 = rx2.cap(6);
01233 
01234   //  qDebug("Suffix1=%s, suffix2=%s", qPrintable(suffix1), qPrintable(suffix2));
01235 
01236   if (suffix1 == suffix2)
01237     return 0; // equal
01238 
01239   //             1          2
01240   QRegExp rxs1("^([a-zA-Z]*)(\\d*)$");
01241   QRegExp rxs2(rxs1);
01242   rxs1.exactMatch(suffix1); // must necessarily match, already matched global regex
01243   rxs2.exactMatch(suffix2);
01244 
01245   QString w1 = rxs1.cap(1);
01246   QString w2 = rxs2.cap(1);
01247   QString ns1 = rxs1.cap(2);
01248   QString ns2 = rxs2.cap(2);
01249 
01250   int cmp = __klf_version_compare_suffix_words(w1, w2);
01251   if (cmp != 0)
01252     return cmp; // words are enough to make the difference
01253 
01254   // the words are the same -> compare ns1<->ns2
01255   if (ns1.isEmpty()) {
01256     if (ns2.isEmpty())
01257       return 0; // equal
01258     // with suffix number compares greater than without
01259     return -1;
01260   }
01261   if (ns2.isEmpty()) {
01262     return +1;
01263   }
01264 
01265   int n1 = ns1.toInt();
01266   int n2 = ns2.toInt();
01267   return n1 - n2;
01268 }
01269 
01270 KLF_EXPORT bool klfVersionCompareLessThan(const QString& v1, const QString& v2)
01271 {
01272   return klfVersionCompare(v1,v2) < 0;
01273 }
01274 
01275 

Generated by doxygen 1.7.6.1. The KLatexFormula website is hosted on sourceforge.net