root/library/bdm/base/user_info.cpp @ 394

Revision 394, 12.3 kB (checked in by mido, 15 years ago)

1) UI_File renamed to UIFile
2) part UI's documentation
3) stat/mixtures.h renamed to stat/emix.h and related changes applied

  • Property svn:eol-style set to native
Line 
1//
2// C++ Implementation: itpp_ext
3//
4// Description:
5//
6//
7// Author: smidl <smidl@utia.cas.cz>, (C) 2008
8//
9// Copyright: See COPYING file that comes with this distribution
10//
11//
12
13#include "user_info.h"
14
15namespace bdm
16{
17///////////////////////////// Class UIFile /////////////////////////////////////////////
18
19UIFile::UIFile()
20{
21}
22
23UIFile::UIFile ( const string &file_name )
24{
25    try
26    {
27        readFile( file_name.c_str()  );
28                // this flag has to be set AFTER each file load, that is why it is right here
29                setAutoConvert( true );
30    }
31    catch ( FileIOException f )
32    {
33        it_error ( "UI error: file " + file_name + " not found." );
34    }
35    catch ( ParseException& P )
36    {
37        stringstream msg;
38        msg << "UI error: parsing error """ << P.getError() << """ in file " << file_name << " on line " <<  P.getLine() << ".";
39        it_error ( msg.str() );
40    }
41}
42
43
44void UIFile::save(const string &file_name )
45{
46    try
47    {
48        writeFile ( file_name.c_str()  );
49    }
50    catch ( FileIOException f )
51    {
52        it_error( "UI error: file " + file_name + " is inacessible." );
53    }
54}
55
56UIFile::operator Setting&()
57{
58    return getRoot();
59}
60
61///////////////////////////// Class UI::MappedUI /////////////////////////////////////////////
62
63UI::MappedUI::StringToUIMap& UI::MappedUI::mapped_strings()
64{
65        // this way it is ensured that there is only one instance of StringTpUIMap, and
66        // what is more, this declaration leaves its allocation/deallocation on the compiler
67    static StringToUIMap var;
68    return var;
69}
70
71UI::MappedUI::TypeInfoToStringMap& UI::MappedUI::mapped_type_infos()
72{
73        // this way it is ensured that there is only one instance of TypeInfoToStringMap, and
74        // what is more, this declaration leaves its allocation/deallocation on the compiler
75    static TypeInfoToStringMap var;
76    return var;
77}
78
79void UI::MappedUI::add_class( const string &class_name, const type_info * const class_type_info, const UI* const ui )
80{
81    pair< const string, const UI* const > new_pair = make_pair( class_name, ui );
82    mapped_strings().insert( new_pair );
83    mapped_type_infos().insert( make_pair( class_type_info, new_pair.first ) );
84}
85
86void UI::MappedUI::unregistered_class_error( const string &unregistered_class_name )
87{
88        stringstream msg;
89    msg << "UI error: class " + unregistered_class_name + " was not properly registered. Use the macro ""UIREGISTER([class name]);"" within your code." << endl;
90
91        if( mapped_strings().size() )
92        {
93            StringToUIMap::const_iterator iter = mapped_strings().begin();
94                msg << "These classes are already registered: " << iter->first;
95                for(; iter != mapped_strings().end(); iter++)
96                        msg << ", " << iter->first;
97                msg << "." << endl;
98        }                       
99        else
100                msg << "There is not any registered class yet!" << endl;
101       
102    it_error ( msg.str() );             
103}
104
105const UI& UI::MappedUI::retrieve_ui( const string &class_name )
106{
107    StringToUIMap::const_iterator iter = mapped_strings().find( class_name );
108    if ( iter == mapped_strings().end())
109                unregistered_class_error( class_name );
110           
111        return *iter->second;
112}
113
114const string& UI::MappedUI::retrieve_class_name( const type_info * const class_type_info )
115{
116    TypeInfoToStringMap::const_iterator iter = mapped_type_infos().find( class_type_info );
117    if ( iter == mapped_type_infos().end())
118                unregistered_class_error( "with RTTI name " + string(class_type_info->name()) );
119    return iter->second;
120}
121
122///////////////////////////// Class UI::SettingResolver /////////////////////////////////////////////
123
124UI::SettingResolver::SettingResolver( const Setting &potential_link )
125        : result( initialize_reference( file, potential_link ) )
126{
127}
128
129const Setting& UI::SettingResolver::initialize_reference(UIFile *&file, const Setting &potential_link)
130{
131        file = NULL;
132
133    if ( potential_link.getType() !=  Setting::TypeString )
134            return potential_link;
135       
136        string link = (const char*) potential_link;
137    size_t aerobase = link.find('@');
138
139        const Setting *result;
140    if ( aerobase != string::npos )
141    {
142        string file_name = link.substr( aerobase + 1, link.length() );
143        file = new UIFile( file_name );
144        result = &(Setting&)(*file);
145        link = link.substr( 0, aerobase );
146    }
147    else
148        {
149                result = &potential_link;
150        while ( !result->isRoot() )
151            result = &result->getParent();
152        }
153
154    if ( !result->exists( link ) )
155        ui_error( "linked setting was not found", potential_link );
156
157    return (*result)[link];
158}
159
160UI::SettingResolver::~SettingResolver()
161{
162    if ( file ) delete file;
163}
164
165///////////////////////////// Class UI /////////////////////////////////////////////
166
167void UI::ui_error( string message, const Setting &element )
168{
169    stringstream error_message;
170    error_message << "UI error: " << message << "! Check path """ << element.getPath() << """, source line " << element.getSourceLine() << ".";
171    it_error ( error_message.str() );
172}
173
174const Setting& UI::to_child_setting( const Setting &element, const int index )
175{
176    if ( !element.isList())
177        ui_error( "only TypeList elements could be indexed by integers", element );
178
179    if ( element.getLength() <= index )
180        ui_error( "there is not any child with index " + index, element );
181
182    return element[index];
183}
184
185const Setting& UI::to_child_setting( const Setting &element, const string &name )
186{
187    if ( !element.isGroup())
188        ui_error( "only TypeGroup elements could be indexed by strings", element );
189
190    if ( !element.exists( name ) )
191        ui_error( "there is not any child named """ + name, element );
192
193    return element[name];
194}
195
196void UI::save( const int &integer, Setting &element, const string &name)
197{
198    Setting &set = (name == "") ? element.add( Setting::TypeInt )
199                                            : element.add( name, Setting::TypeInt );
200    set = integer;
201}
202
203void UI::save( const double &real, Setting &element, const string &name)
204{
205    Setting &set = (name == "") ? element.add( Setting::TypeFloat )
206                                            : element.add( name, Setting::TypeFloat );
207    set = real;
208}
209
210void UI::save( const string &str, Setting &element, const string &name)
211{
212    Setting &set = (name == "") ? element.add( Setting::TypeString )
213                                            : element.add( name, Setting::TypeString );
214    set = str;
215}
216
217void UI::save( const mat &matrix, Setting &element, const string &name)
218{
219    Setting &set = (name == "") ? element.add( Setting::TypeList )
220                                            : element.add( name, Setting::TypeList );
221
222    Setting &cols = set.add( Setting::TypeInt );
223    cols = matrix.cols();
224
225    Setting &rows = set.add( Setting::TypeInt );
226    rows = matrix.rows();
227
228    Setting &elements = set.add( Setting::TypeArray );
229
230    // build matrix row-wise
231    for ( int i=0; i<matrix.rows(); i++ )
232        for ( int j=0; j<matrix.cols(); j++)
233        {
234            Setting &new_field = elements.add(Setting::TypeFloat);
235            new_field = matrix(i,j);
236        }
237}
238
239void UI::save( const ivec &vector, Setting &element, const string &name)
240{
241    Setting &set = (name == "") ? element.add( Setting::TypeArray )
242                    : element.add( name, Setting::TypeArray );
243    for ( int i=0; i<vector.length(); i++ )
244    {
245        Setting &new_field = set.add(Setting::TypeInt);
246        new_field = vector(i);
247    }
248}
249
250void UI::save( const vec &vector, Setting &element, const string &name)
251{
252    Setting &set = (name == "") ? element.add( Setting::TypeArray )
253                    : element.add( name, Setting::TypeArray );
254    for ( int i=0; i<vector.length(); i++ )
255    {
256                Setting &new_field = set.add(Setting::TypeFloat);
257        new_field = vector(i);
258    }
259}
260
261void UI::from_setting( mat& matrix, const Setting &element )
262{
263    const SettingResolver link( element );
264
265    if ( link.result.isNumber() )
266    {
267        matrix.set_size( 1, 1 );
268        matrix(0,0) = link.result;
269        return;
270    }
271
272    if ( link.result.isList() )
273    {
274                int data_offset;
275
276                if ( link.result.getLength() == 3 )
277                        data_offset = 0;
278                else if ( link.result.getLength() == 4 )
279                {
280                ASSERT_UITYPE(link.result[0],TypeString);
281                        const char* elem1=(const char*)link.result[0];
282                        if( (strcmp(elem1, "matrix") ))
283                                ui_error( "the setting supposed to represent a matrix element has wrong syntax", link.result );
284
285                        data_offset = 1;
286                }
287                else
288                        ui_error( "the setting supposed to represent a matrix element has wrong syntax", link.result );
289
290        Setting &rows_setting = link.result[0 + data_offset];
291        Setting &cols_setting = link.result[1 + data_offset];
292        Setting &elements = link.result[2 + data_offset];
293
294        ASSERT_UITYPE(cols_setting,TypeInt);
295        ASSERT_UITYPE(rows_setting,TypeInt);
296        ASSERT_UITYPE(elements,TypeArray);
297
298        int cols = cols_setting;
299        int rows = rows_setting;
300
301        if ( cols < 0 | rows < 0 )
302            ui_error( "the dimensions of a matrix has to be non-negative", link.result );
303
304        if ( elements.getLength() != cols * rows )
305            ui_error( "the count of the matrix elements is incompatible with matrix dimension", elements );
306
307        matrix.set_size( rows, cols );
308
309        if ( cols == 0 || rows == 0 )
310            return;
311
312        if ( !elements[0].isNumber() )
313            ui_error( "matrix elements have to be numbers", elements[0] );
314
315        // build matrix row-wise
316        int k = 0;
317        for ( int i=0; i<rows; i++ )
318            for ( int j=0; j<cols; j++)
319                matrix(i,j) = elements[k++];
320        return;
321    }
322
323    ui_error( "only numeric types or TypeList are supported as matrix values", link.result );
324}
325
326void UI::from_setting( ivec &vector, const Setting &element )
327{
328    const SettingResolver link( element );
329
330    if ( link.result.isNumber() )
331    {
332  //      ASSERT_UITYPE(link.result,TypeInt);
333        vector.set_length( 1 );
334        vector(0) = link.result;
335        return;
336    }
337
338    if ( link.result.isList() )
339    {
340                mat matrix;
341                from_setting( matrix, link.result );
342
343        if ( matrix.cols() != 1 & matrix.rows() !=1)
344                        ui_error( "the vector length is invalid, it seems to be rather a matrix", link.result );
345
346        int len = matrix.rows() * matrix.cols();
347        vector.set_length ( len );
348        if ( len == 0 ) return;
349
350                Setting &elements = link.result[2];
351        // ASSERT_UITYPE(elements[0],TypeInt); -- spolehame an autoconvert
352
353        if ( matrix.cols() == 1 )
354                        for ( int i=0; i<len; i++ )
355                                vector(i) = matrix(i,0);
356                else
357                        for ( int i=0; i<len; i++ )
358                                vector(i) = matrix(0,i);
359        return;
360
361    }
362
363    if ( link.result.isArray() )
364    {
365        int len = link.result.getLength();
366        vector.set_length( len );
367        if ( len == 0 ) return;
368
369        ASSERT_UITYPE(link.result[0],TypeInt);
370        for ( int i=0; i < len; i++ )
371            vector(i) = link.result[i];
372        return;
373    }
374
375    ui_error( "only numeric types, TypeArray or TypeList are supported as vector values", link.result );
376}
377
378void UI::from_setting( vec &vector, const Setting &element )
379{
380    const SettingResolver link( element );
381
382    if ( link.result.isNumber() )
383    {
384        vector.set_length( 1 );
385        vector(0) = link.result;
386        return;
387    }
388
389    if ( link.result.isList() )
390    {
391                mat matrix;
392                from_setting( matrix, link.result );
393
394        if ( matrix.cols() != 1 & matrix.rows() !=1)
395                        ui_error( "the vector length is invalid, it seems to be rather a matrix", link.result );
396
397        int len = matrix.rows() * matrix.cols();
398        vector.set_length ( len );
399        if ( len == 0 ) return;
400
401        if ( matrix.cols() == 1 )
402                        for ( int i=0; i<len; i++ )
403                                vector(i) = matrix(i,0);
404                else
405                        for ( int i=0; i<len; i++ )
406                                vector(i) = matrix(0,i);
407        return;
408    }
409
410    if ( link.result.isArray() )
411    {
412        int len = link.result.getLength();
413        vector.set_length( len );
414        if ( len == 0 ) return;
415
416        if ( !link.result[0].isNumber())
417            ui_error("a vector element has to be a number", link.result[0]);
418
419        for ( int i=0; i < len; i++ ) 
420            vector(i) = link.result[i];
421
422                return;
423    }
424
425    ui_error( "only numeric types, TypeArray or TypeList are supported as vector values", link.result );
426}
427
428void UI::from_setting( string &str, const Setting &element )
429{
430    ASSERT_UITYPE(element,TypeString);
431    str = (const char*) element;
432}
433
434void UI::from_setting( int &integer, const Setting &element )
435{
436    ASSERT_UITYPE(element,TypeInt);
437    integer = element;
438}
439
440void UI::from_setting( double &real, const Setting &element )
441{
442    ASSERT_UITYPE(element,TypeFloat);
443    real = element;
444}
445
446}
Note: See TracBrowser for help on using the browser.