Thursday, July 25, 2013

regexp в C++

К своей радости узнал, что в VS2008 появились регулярные выражения TR1 в STL
Подробности тут: A TR1 Tutorial: Regular Expressions

А мне как раз понадобилось на С++ парсить исходники С++ на предмет поиска параметров printf() , имеющих следующий прототип:
%[flags][width][.precision][length]specifier
После долгой возни вокруг \t \n вот что у меня получилось:

#include <string>
#include <regex>

// text - printf format input, for instance:
//        "Unable to create %s!/nUnsufficient RAM: %3d."
//
// arr  - output array of printf format parameters, in this case:

//        {"%s", "\n", "%3d"}
int GetPrintfParameter(CString text,CStringArray & arr)
{
    text.TrimLeft();
    text.TrimRight();
    if(text.IsEmpty() )return 0;

    std::string prinfFormat = text;
    const std::tr1::regex pattern("((%(\\+|-|0|\\#)?(\\d+|\\*)?(.\\d+|.\\*)?(\\d)?(d|i|u|o|x|f|e|g|a|c|s|p|n|\\%))|(\\\\n|\\\\t|\\|))");
    const std::tr1::sregex_token_iterator end;
     for ( std::tr1::sregex_token_iterator i(prinfFormat.begin(),  prinfFormat.end(), pattern);
              i != end;
            ++i )
     {
       CString sep = (*i).str().c_str();
       arr.SetSize(arr.GetSize()+1);
       arr[arr.GetSize()-1] = sep;
     }

    return arr.GetSize();
}

Thursday, June 20, 2013

Короткое замыкание в С++

Инициализация ссылки
Как известно, в С++ ссылки, являющиеся переменными класса, нужно инициализировать в списке инициализации конструктора:
class A() {
   std::vector<int> & m_refData; // ссылка на массив
}
См. короткое замыкание...

Трассировка лёгкая как printf


Разобрался наконец как работать с переменным количеством аргументов, а точнее конструкцией ... в Си-шных функциях. Заодно написал полезняшку для отладки с помощью WinAPI-шной функции OutputDebugString, которая неудобна, т.к. принимает только строки, что заставляло меня писать громоздские конструкции для отладки.

Исходники void TraceString(const char *msg, ...) см. ниже


Непроходимые горы, Dependency Walker, sxstrace.exe и другие

Иногда перед программистом во время отладки, а особенно 64-битных приложений, на ровном месте вырастают непроходимые горы, как например эти:


(нарисовано в thisissand.com)

"...И горы встают перед ним на пути,
И он по горам начинает ползти,
А горы всё выше, а горы всё круче,
А горы уходят под самые тучи!...

И сейчас же с высокой скалы к Айболиту спустились орлы..." (с)

Monday, June 17, 2013

Welcome, gettext, this is VBasic script

Task description
There is a project containing thousands of CPP sources that have to be localized into Chinese ASAP. We're using gettext technique for localization and strings to be translated have to be wrapped with _(), for example:
::MessageBox( _("Translate me please"), _("Warning"), MB_OK)
We can run Visual Studio Find In Files->Current File for each file with the following regexp:
\".*\" 
in order to search all strings, а then insert _('s and )'s.
But this is dull and boring, so let's switch on the brains and write a VisualBasic script in VBasic IDE (Alt-F11) which can be invoked by pressing F5 (or whatever you like, use Tools->Customize-Keyboard to setup hotkey).
Now just you have to traverse "Find Results" window by pressing F4 and optionally pressing F5 on each string that should be wrapped with _(). You can even avoid watching into .cpp source in simple cases with MessageBoxes (90% of strings). This way you reduce summary time  of processing all the .cpp sources for at least thrice, and even five times.

Here is VBasic Script. Note that it even handles multiline strings!

Wednesday, April 3, 2013

Amount of emotions when moving

There is a blog one could probably find it interesting http://www.englishdadinmoscow.com/

Also I heard about a book called "America, What a Life?" from Nikolai Zlobin
it's like the complement of that, in russian, about the US

"It seems strange that ordinary Russians would still be hungry for details about how ordinary Americans eat, pay mortgages and hire teenage baby sitters"
Too many Russian have moved for better life to America that's why it's a point of interest
I have 1 friend mine, 3 colleagues and ~ 10 students of the same year who moved abroad
I understand their point, they've got all ranges of perspectives (maybe) and twice - 5 times higher salary
This is why I'm shocked about Americans and Europeans who're moving to Russia without even speaking Russian
The key thing here is that all dull and boring daily stuff becomes very interesting to foreigners because all things are different
Do you remember the Third Newton law

"When a first body exerts a force F1 on a second body, the second body simultaneously exerts a force F2 = −F1 on the first body."

Let's state a new theorem:

"amount of emotions when moving from RU to US would be the same as when moving from US to RU"
It would be nice to prove it somehow

Self-made simple C++ profiler

In order to measure routine time and find bottle neck in С++ sources (do profiling), and especially if we have enough time, we can try some of existing profilers: http://stackoverflow.com/questions/67554/whats-the-best-free-c-profiler-for-windows-if-there-are

But simple and quite powerful decision could be using of self-written profiler (for non-thread-safe application). Let's create a C++ class that you just insert at the begining of tested functions or even {} scopes, for example:

f()
{
    Profile me;
    f1();
    f2();
}
f1()
{
   Profile me;
...
}
f2()
{
   Profile me;
...
}


What does it do?

Class Profile:
  1. measures time intervals between its constructor and destructor calls,
    at desctructor saving result to some place: to  memory stream or via OutputDebugString, not  to file!!.
  2. counts its instances in order to support indenting in reports
class Profile{
   static st_profile_indent_count;
   LARGE_INTEGER start;
   Profile() {
      st_profile_indent_count++;
      QueryPerformanceCounter(&start)
   }
   ~Profile()
   {
       st_profile_indent_count--;
       LARGE_INTEGER stop;
       ::QueryPerformanceCounter(&stop);
       OutputIndent(st_profile_indent_count);
       OutputTimeSpan(stop.QuadPart - start.QuadPart);
   }
}


Here is is. Then we can improve it somehow, add comments or scope name:
f()
{
    Profile me("f()");
    f1();
    f2();
}


We can learn Profile to report % of total time load, for example:
f()
{
    Profile me("f()"); // Текст для трассировки
    for (int i = 0; i< 10000000; i ++)
    {
         f1();
    }
    f2();
}

It's clear that f1 is a critical one function here.

PS Here are just practical ideas, not instructions. I've used such a technique in KLA-Tencor project when optimizing 3D engine.