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

Revision 392, 11.4 kB (checked in by smidl, 15 years ago)

compilation fixes - UI_build use exceptions now!!!!

  • 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///////////////////////// UI FILE /////////////////////////////////////////////
18
19UI_File::UI_File ()
20{
21    setAutoConvert( true );
22}
23
24//! loads root element from a file
25UI_File::UI_File ( const string &file_name )
26{
27    try
28    {
29        readFile( file_name.c_str()  );
30        setAutoConvert( true );
31    }
32    catch ( FileIOException f )
33    {
34        it_error ( "UI error: file " + file_name + " not found." );
35    }
36    catch ( ParseException& P )
37    {
38        stringstream msg;
39        msg << "UI error: parsing error """ << P.getError() << """ in file " << file_name << " on line " <<  P.getLine() << ".";
40        it_error ( msg.str() );
41    }
42}
43
44
45//! save UserInfo to the file (typically with an XML extension)
46void UI_File::save(  const string &file_name )
47{
48    try
49    {
50        writeFile ( file_name.c_str()  );
51    }
52    catch ( FileIOException f )
53    {
54        it_error( "UI error: file " + file_name + " is inacessible." );
55    }
56}
57
58UI_File::operator Setting&()
59{
60    return getRoot();
61}
62///////////////////////// INTERNAL MAPPED_UI /////////////////////////////////////////////
63
64UI::Mapped_UI::String_To_UI_Map& UI::Mapped_UI::mapped_strings()
65{
66    static String_To_UI_Map var;
67    return var;
68}
69
70UI::Mapped_UI::Type_Info_To_String_Map& UI::Mapped_UI::mapped_type_infos()
71{
72    static Type_Info_To_String_Map var;
73    return var;
74}
75
76void UI::Mapped_UI::add_class( const string &class_name, const type_info * const class_type_info, const UI* const ui )
77{
78    pair< const string, const UI* const > new_pair = make_pair( class_name, ui );
79    mapped_strings().insert( new_pair );
80    mapped_type_infos().insert( make_pair( class_type_info, new_pair.first ) );
81}
82
83const UI& UI::Mapped_UI::retrieve_ui( const string &class_name )
84{
85    String_To_UI_Map::const_iterator iter = mapped_strings().find( class_name );
86    if ( iter == mapped_strings().end())
87                // TODO dat sem vypis seznamu registrovanych trid
88        it_error ( "UI error: class " + class_name + " was not properly registered. Use the macro ""UIREGISTER([class name]);"" within your code." );
89    return *iter->second;
90}
91
92const string& UI::Mapped_UI::retrieve_class_name( const type_info * const class_type_info )
93{
94    Type_Info_To_String_Map::const_iterator iter = mapped_type_infos().find( class_type_info );
95    if ( iter == mapped_type_infos().end())
96        it_error ( "UI error: class with RTTI name " + string(class_type_info->name()) + " was not properly registered. Use the macro ""UIREGISTER([class name]);"" within your code." );
97    return iter->second;
98}
99
100///////////////////////// INTERNAL LINK EXPANDER /////////////////////////////////////////////
101
102UI::SettingResolver::SettingResolver( const Setting &potential_link ): result( initialize_reference( file, potential_link ) )
103{
104}
105
106const Setting& UI::SettingResolver::initialize_reference(UI_File *&file, const Setting &potential_link)
107{
108        file = NULL;
109
110    if ( potential_link.getType() !=  Setting::TypeString )
111            return potential_link;
112       
113        string link = (const char*) potential_link;
114    size_t aerobase = link.find('@');
115
116        const Setting *result;
117    if ( aerobase != string::npos )
118    {
119        string file_name = link.substr( aerobase + 1, link.length() );
120        file = new UI_File( file_name );
121        result = &(Setting&)(*file);
122        link = link.substr( 0, aerobase );
123    }
124    else
125        {
126                result = &potential_link;
127        while ( !result->isRoot() )
128            result = &result->getParent();
129        }
130
131    if ( !result->exists( link ) )
132        ui_error( "linked Setting was not found", potential_link );
133
134    return (*result)[link];
135}
136
137UI::SettingResolver::~SettingResolver()
138{
139    if ( file ) delete file;
140}
141
142///////////////////////// UI /////////////////////////////////////////////
143
144void UI::ui_error( string message, const Setting &element )
145{
146    stringstream error_message;
147    error_message << "UI error: " << message << "! Check path """ << element.getPath() << """, source line " << element.getSourceLine() << ".";
148    it_error ( error_message.str() );
149}
150
151//! This methods - kvuli ukladani pole stringu, dat jen privatne?
152void UI::save( const string &str, Setting &element )
153{
154    Setting &set = element.add( Setting::TypeString );
155    set = str;
156}
157
158void UI::save( const mat &matrix, Setting &element, const string &name)
159{
160
161    Setting &set = (name == "") ? element.add( Setting::TypeList )
162                    : element.add( name, Setting::TypeList );
163
164    Setting &cols = set.add( Setting::TypeInt );
165    cols = matrix.cols();
166
167    Setting &rows = set.add( Setting::TypeInt );
168    rows = matrix.rows();
169
170    Setting &elements = set.add( Setting::TypeArray );
171
172    // build matrix row-wise
173    for ( int i=0; i<matrix.rows(); i++ )
174        for ( int j=0; j<matrix.cols(); j++)
175        {
176            Setting &new_field = elements.add(Setting::TypeFloat);
177            new_field = matrix(i,j);
178        }
179}
180
181
182//! This methods tries to save a integer vector
183void UI::save( const ivec &vector, Setting &element, const string &name)
184{
185
186    Setting &set = (name == "") ? element.add( Setting::TypeArray )
187                    : element.add( name, Setting::TypeArray );
188    for ( int i=0; i<vector.length(); i++ )
189    {
190        Setting &new_field = set.add(Setting::TypeInt);
191        new_field = vector(i);
192    }
193}
194
195
196//! This methods tries to save a double vector
197void UI::save( const vec &vector, Setting &element, const string &name)
198{
199    Setting &set = (name == "") ? element.add( Setting::TypeArray )
200                    : element.add( name, Setting::TypeArray );
201    for ( int i=0; i<vector.length(); i++ )
202    {
203                Setting &new_field = set.add(Setting::TypeFloat);
204        new_field = vector(i);
205    }
206}
207
208
209//! This methods tries to build a new double matrix
210
211void UI::from_setting( mat& matrix, const Setting &element )
212{
213    const SettingResolver link( element );
214
215    if ( link.result.isNumber() )
216    {
217        matrix.set_size( 1, 1 );
218        matrix(0,0) = link.result;
219        return;
220    }
221
222    if ( link.result.isList() )
223    {
224                int data_offset;
225
226                if ( link.result.getLength() == 3 )
227                        data_offset = 0;
228                else if ( link.result.getLength() == 4 )
229                {
230                ASSERT_UITYPE(link.result[0],TypeString);
231                        const char* elem1=(const char*)link.result[0];
232                        if( (strcmp(elem1, "matrix") ))
233                                ui_error( "the setting supposed to represent a matrix element has wrong syntax", link.result );
234
235                        data_offset = 1;
236                }
237                else
238                        ui_error( "the setting supposed to represent a matrix element has wrong syntax", link.result );
239
240        Setting &rows_setting = link.result[0 + data_offset];
241        Setting &cols_setting = link.result[1 + data_offset];
242        Setting &elements = link.result[2 + data_offset];
243
244        ASSERT_UITYPE(cols_setting,TypeInt);
245        ASSERT_UITYPE(rows_setting,TypeInt);
246        ASSERT_UITYPE(elements,TypeArray);
247
248        int cols = cols_setting;
249        int rows = rows_setting;
250
251        if ( cols < 0 | rows < 0 )
252            ui_error( "the dimensions of a matrix has to be non-negative", link.result );
253
254        if ( elements.getLength() != cols * rows )
255            ui_error( "the count of the matrix elements is incompatible with matrix dimension", elements );
256
257        matrix.set_size( rows, cols );
258
259        if ( cols == 0 || rows == 0 )
260            return;
261
262        if ( !elements[0].isNumber() )
263            ui_error( "matrix elements have to be numbers", elements[0] );
264
265        // build matrix row-wise
266        int k = 0;
267        for ( int i=0; i<rows; i++ )
268            for ( int j=0; j<cols; j++)
269                matrix(i,j) = elements[k++];
270        return;
271    }
272
273    ui_error( "only numeric types or TypeList are supported as matrix values", link.result );
274}
275
276//! This methods tries to build a new integer vector
277void UI::from_setting( ivec &vector, const Setting &element )
278{
279    const SettingResolver link( element );
280
281    if ( link.result.isNumber() )
282    {
283  //      ASSERT_UITYPE(link.result,TypeInt);
284        vector.set_length( 1 );
285        vector(0) = link.result;
286        return;
287    }
288
289    if ( link.result.isList() )
290    {
291                mat matrix;
292                from_setting( matrix, link.result );
293
294        if ( matrix.cols() != 1 & matrix.rows() !=1)
295                        ui_error( "the vector length is invalid, it seems to be rather a matrix", link.result );
296
297        int len = matrix.rows() * matrix.cols();
298        vector.set_length ( len );
299        if ( len == 0 ) return;
300
301                Setting &elements = link.result[2];
302        // ASSERT_UITYPE(elements[0],TypeInt); -- spolehame an autoconvert
303
304
305        if ( matrix.cols() == 1 )
306                        for ( int i=0; i<len; i++ )
307                                vector(i) = matrix(i,0);
308                else
309                        for ( int i=0; i<len; i++ )
310                                vector(i) = matrix(0,i);
311        return;
312
313    }
314
315    if ( link.result.isArray() )
316    {
317        int len = link.result.getLength();
318        vector.set_length( len );
319        if ( len == 0 ) return;
320
321        ASSERT_UITYPE(link.result[0],TypeInt);
322        for ( int i=0; i < len; i++ )
323            vector(i) = link.result[i];
324        return;
325    }
326
327    ui_error( "only numeric types, TypeArray or TypeList are supported as vector values", link.result );
328}
329
330//! This methods tries to build a new double vector
331void UI::from_setting( vec &vector, const Setting &element )
332{
333    const SettingResolver link( element );
334
335    if ( link.result.isNumber() )
336    {
337        vector.set_length( 1 );
338        vector(0) = link.result;
339        return;
340    }
341
342    if ( link.result.isList() )
343    {
344                mat matrix;
345                from_setting( matrix, link.result );
346
347        if ( matrix.cols() != 1 & matrix.rows() !=1)
348                        ui_error( "the vector length is invalid, it seems to be rather a matrix", link.result );
349
350        int len = matrix.rows() * matrix.cols();
351        vector.set_length ( len );
352        if ( len == 0 ) return;
353
354        if ( matrix.cols() == 1 )
355                        for ( int i=0; i<len; i++ )
356                                vector(i) = matrix(i,0);
357                else
358                        for ( int i=0; i<len; i++ )
359                                vector(i) = matrix(0,i);
360        return;
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        if ( !link.result[0].isNumber())
370            ui_error("a vector element has to be a number", link.result[0]);
371
372        for ( int i=0; i < len; i++ ) 
373            vector(i) = link.result[i];
374
375                return;
376    }
377
378    ui_error( "only numeric types, TypeArray or TypeList are supported as vector values", link.result );
379}
380
381
382void UI::from_setting( string &str, const Setting &element )
383{
384    ASSERT_UITYPE(element,TypeString);
385    str = (const char*) element;
386}
387
388
389///////////////////////// UI FILE /////////////////////////////////////////////
390//! This methods tries to save an instance of type T (or some of its descendant types)
391//! and build DOM tree accordingly. Then, it creates a new DOMNode named according class_name
392//! and connecti it to the passed Setting as a new child node.
393const Setting& UI::to_child_setting( const Setting &element, const int index )
394{
395    if ( !element.isList())
396        ui_error( "only TypeList elements could be indexed by integers", element );
397
398    if ( element.getLength() <= index )
399        ui_error( "there is not any child with index " + index, element );
400
401    return element[index];
402}
403
404const Setting& UI::to_child_setting( const Setting &element, const string &name )
405{
406    ASSERT_UITYPE(element,TypeGroup);
407    if ( !element.exists( name ) )
408        ui_error( "there is not any child named """ + name, element );
409    return element[name];
410}
411
412
413}
Note: See TracBrowser for help on using the browser.