New content are available at http://tis-method.org/. All articles from this site will be moved to the new location.

среда, 29 сентября 2010 г.

Scanning file using boost::regex [windows specific]

Task statement
Make light wrapper around file on disk to work with boost::regex.

"Brute force"
Open file, read all data into a string, use boost::regex.

File mapping
Represent file as byte-array, using file mapping into a memory.
Below, possible solution.
template < class charT >
class basic_regex_file< charT, z3d::platform::windows >
{
public:
 ///
 typedef charT
  char_t;
 ///
 typedef std::basic_string< char_t >
  string_t;
 ///
 typedef char_t*
  iterator;
 ///
 typedef char_t const*
  const_iterator;
 ///
 typedef char_t*
  view_t;
 ///
 explicit basic_regex_file( string_t const& sname ) : 
 mapping( 0 )
  , view( 0 )
  , size_lo( 0 )
  , size_hi( 0 )
 {
  HANDLE file = open_file( sname, boost::mpl::identity< char_t >() );
  this->mapping = CreateFileMapping( file, NULL, PAGE_READONLY, 0, 0, NULL );
  this->view  = reinterpret_cast< view_t >( MapViewOfFile( this->mapping, FILE_MAP_READ, 0, 0, 0 ) );
  //
  if ( ( file != INVALID_HANDLE_VALUE ) && ( this->mapping != NULL ) && ( this->view != NULL ) )
  {
   this->size_lo = GetFileSize( file, &(this->size_hi) );
  }
  CloseHandle( file );
 }
 ~basic_regex_file()
 {
  if ( this->view != NULL )
  {
   ::UnmapViewOfFile( this->view );
  }
  if ( this->mapping != NULL )
  {
   ::CloseHandle( this->mapping );
  }
 }
 ///
 const_iterator begin() const
 { return ( &( this->view[0] ) ); }
 ///
 const_iterator end() const
 { return ( &( this->view[ this->size_lo / sizeof( char_t ) ] ) ); }
 ///
 operator bool() const
 { return ( ( this->view != 0 ) && ( this->size_lo || this->size_hi ) ); }

private:
 ///
 HANDLE
  mapping;
 ///
 view_t
  view;
 ///
 DWORD
  size_lo;
 ///
 DWORD
  size_hi;
 ///
 HANDLE open_file( string_t const& sname, boost::mpl::identity< wchar_t > )
 { return CreateFileW( sname.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); }
 ///
 HANDLE open_file( string_t const& sname, boost::mpl::identity< char > )
 { return CreateFileA( sname.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); }
};
typedef basic_regex_file< char, z3d::platform::windows > win_regex_file;
typedef basic_regex_file< wchar_t, z3d::platform::windows > wwin_regex_file;

How to use
z3d::util::win_regex_file wrf( "file.txt" );
if ( wrf && boost::regex_match( wrf.begin(), wrf.end(), boost::regex( ".*ABC.*" ) ) )
{
 // found
}

Where to find
Use classes located in z3d/util/regex-file.hpp from z3d.



четверг, 23 сентября 2010 г.

C++ type string representation


During integration CInt & C++ i found very interesting task. I saw it before in "C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond, By David Abrahams, Aleksey Gurtovoy" as exercises to chapter 2.

Task statement
Generation full function call signature string representation, including type description and parameters value.
When i call CInt script function from C++ code, like this
call< void >( "func10", 0, 'A', 1.f, 1, 'B', 2.f, 3, 'C', 3.f, true );

i have to build string
"func10((int)0,(char)'A',(float)1,(int)1,(char)'B',(float)2,(int)3,(char)'C',(float)3,(bool)1);"
and then exec it in CInt sandbox, using G__calc (CInt API function).

For each function argument i have to generate type string representation and argument value in the valid form.
call<void>( "f1", 1 ); -> "f1( (int)1 );"
int i = 1;
call<void>( "f2",  &i ); -> "f2( (int*)0x00FC0632 );"

Additionally, will be great, if i can process user defined types too.
struct my_struct {} v;
call<int>( "f3", &v ); -> "f3( (my_struct*)0x00DFCC02 );"

Step by step
The basis of the solution is set of template partial specializations
template < typename > struct term_;

 This define is used for quick setup types recognition partial specialization
#define Z3D_TYPE_NAME_DEF_TERM( t ) \
 template <>\
 struct term_< t >\
 {\
  enum { length = sizeof( #t ) - 1 };\
  std::ostream& name( std::ostream& os ) const { return( os << #t ); }\
 };

This done for all basic types: void, bool, char, signed char, unsigned char, wchar_t, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double.
Z3D_TYPE_NAME_DEF_TERM( void );
...
Z3D_TYPE_NAME_DEF_TERM( long double );

Next define should be use to add user defined type into types recognition scope:
Z3D_TYPE_NAME_DEF_TERM_USER( my_struct );

The same mechanic used to recognizing
  • const, volatile, &, *, [], [N]
  • function from R(*)() to R(*)(P1, ..., P10)
  • pointer to the member T C::*
  • pointer to the member function from R(C::*)() to R(C::*)(P1, ..., P10)
Template class type_ is intended for collect whole type information. Template function format_ should be use for getting string represent of pair "type description" & "value"

How to use
It's very simple.
std::cout << z3d::type_name::type_< unsigned char(*)( void*(*)(int&) ) >::name() << std::endl;

will output
unsigned char(*)(void *(*)(int &))

and
std::cout << z3d::type_name::param_( L"abcdef" ) << std::endl;

will print something like that
(wchar_t const *)0x01180EF8

Sources
z3d::type_name.hpp

Use cases:
z3d/utests/type_name_ut01.hpp


вторник, 21 сентября 2010 г.

HOWTO build CInt under Windows using cygwin and msvc9(msvc8, msvc7)

CInt site
 

Assume that:
CInt installed into "C:\cint\"
MSVC9 installed into "C:\Program Files"
Cygwin installed into "C:\cygwin"

1. Install cygwin. You may use cygwin default packages, but additionally, add /Devel/make package.

2. Get CInt sources from site or from project repository.

3. Add to file "C:\cygwin\Cygwin.bat" two lines «call "C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat"» and 
«SET CINTSYSDIR = "C:\cint"» befor line "bash --login -i"

4. Replace in file
"C:\cygwin\etc\profile" line «PATH=/usr/local/bin:/usr/bin:/bin:$PATH» to «PATH=/cygdrive/c/Program\ Files/Microsoft\ Visual\ Studio\ 9.0/VC/bin/:/usr/local/bin:/usr/bin:/bin:$PATH»

5. Launch cygwin.bat. At the command line set current folder to CInt sources. Exec command «./configure --arch=msvc9 && make»

6. After compiling & linking, folder "C:\cint\bin" will contain dll modile – libCint.dll, folder
"C:\cint\libexport" library – libCint.lib

Current CInt version (5.18.00) depends from msvc CRT, so you need to have both debug and release builds of library to use in you application. Just exec «./configure --arch=msvc9 --debug && make» and you will have debug CInt build.
Issue is that the library names will stay the same (libCint.dll, libCint.lib). It's little awkward during library linking.
I built libCintD.dll, libCintD.lib, by changing output names in the makefiles. But it looks like workaround. When i will find legally work-flow, i will post it.