1 /*
2
3 Copyright (c) 2002-2008, Yauheni Akhotnikau
4 Copyright (c) 2008-2016, The SObjectizer Project
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 - Redistributions of source code must retain the above copyright notice, this
11 list of conditions and the following disclaimer.
12
13 - Redistributions in binary form must reproduce the above copyright notice, this
14 list of conditions and the following disclaimer in the documentation and/or
15 other materials provided with the distribution.
16
17 - The name of the author may not be used to endorse or promote products derived
18 from this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
21 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
23 EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
25 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
28 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
29 OF SUCH DAMAGE.
30
31 */
32
33 #include <algorithm>
34
35 #include <oess_2/defs/h/ex.hpp>
36
37 #include <oess_2/scheme/h/errno.hpp>
38 #include <oess_2/scheme/h/builtin_names.hpp>
39
40 #include <oess_2/scheme/impl/h/scheme_impl.hpp>
41
42 namespace oess_2 {
43
44 namespace scheme {
45
46 namespace impl {
47
48 //FIXME it is necessary to provide as much information as possible
49 //in exceptions related to illegal or invalid type names.
50 //(something like name of attribute for which invalid type name was
51 //specified).
52
53 //
54 // std_attr_editor_t
55 //
std_attr_editor_t(std_scheme_t & scheme)56 std_attr_editor_t::std_attr_editor_t(
57 std_scheme_t & scheme ) :
58 m_scheme( scheme )
59 {
60 }
61
~std_attr_editor_t()62 std_attr_editor_t::~std_attr_editor_t()
63 {
64 }
65
66 void
def(const std::string & attr_name,const std::string & type_name,size_t extension_level)67 std_attr_editor_t::def(
68 const std::string & attr_name,
69 const std::string & type_name,
70 size_t extension_level )
71 {
72 m_ref_attr = ref_std_attr_t( new std_attr_t(
73 attr_name,
74 find_type( type_name ),
75 extension_level ) );
76 }
77
78 ref_attr_t
query_ref_attr() const79 std_attr_editor_t::query_ref_attr() const
80 {
81 return m_ref_attr;
82 }
83
84 void
make_ptr_kind()85 std_attr_editor_t::make_ptr_kind()
86 {
87 m_ref_attr->set_type_kind( attr_type_t::PTR );
88 }
89
90 void
make_extension_kind()91 std_attr_editor_t::make_extension_kind()
92 {
93 m_ref_attr->set_type_kind( attr_type_t::EXTENSION );
94 }
95
96 void
make_stl_vector_kind(packing_format_t packing_format)97 std_attr_editor_t::make_stl_vector_kind(
98 packing_format_t packing_format )
99 {
100 m_ref_attr->set_container_info(
101 container_info_t::make_as_ordinal(
102 container_info_t::VECTOR,
103 packing_format ) );
104 }
105
106 void
make_stl_list_kind(packing_format_t packing_format)107 std_attr_editor_t::make_stl_list_kind(
108 packing_format_t packing_format )
109 {
110 m_ref_attr->set_container_info(
111 container_info_t::make_as_ordinal(
112 container_info_t::LIST,
113 packing_format ) );
114 }
115
116 void
make_stl_deque_kind(packing_format_t packing_format)117 std_attr_editor_t::make_stl_deque_kind(
118 packing_format_t packing_format )
119 {
120 m_ref_attr->set_container_info(
121 container_info_t::make_as_ordinal(
122 container_info_t::DEQUE,
123 packing_format ) );
124 }
125
126 void
make_stl_set_kind(packing_format_t packing_format)127 std_attr_editor_t::make_stl_set_kind(
128 packing_format_t packing_format )
129 {
130 m_ref_attr->set_container_info(
131 container_info_t::make_as_ordinal(
132 container_info_t::SET,
133 packing_format ) );
134 }
135
136 void
make_stl_multiset_kind(packing_format_t packing_format)137 std_attr_editor_t::make_stl_multiset_kind(
138 packing_format_t packing_format )
139 {
140 m_ref_attr->set_container_info(
141 container_info_t::make_as_ordinal(
142 container_info_t::MULTI_SET,
143 packing_format ) );
144 }
145
146 void
make_stl_map_kind(const std::string & key_type_name,packing_format_t packing_format)147 std_attr_editor_t::make_stl_map_kind(
148 const std::string & key_type_name,
149 packing_format_t packing_format )
150 {
151 const type_t & type = find_type( key_type_name );
152 m_ref_attr->set_container_info(
153 container_info_t::make_as_map(
154 type,
155 packing_format ) );
156 }
157
158 void
make_stl_multimap_kind(const std::string & key_type_name,packing_format_t packing_format)159 std_attr_editor_t::make_stl_multimap_kind(
160 const std::string & key_type_name,
161 packing_format_t packing_format )
162 {
163 const type_t & type = find_type( key_type_name );
164 m_ref_attr->set_container_info(
165 container_info_t::make_as_multimap(
166 type,
167 packing_format ) );
168 }
169
170 void
make_fixed_vector_kind(size_t capacity)171 std_attr_editor_t::make_fixed_vector_kind(
172 size_t capacity )
173 {
174 m_ref_attr->set_container_info(
175 container_info_t::make_as_fixed_size_vector(
176 capacity ) );
177 }
178
179 void
set_default_existence(bool is_optional)180 std_attr_editor_t::set_default_existence(
181 bool is_optional )
182 {
183 m_ref_attr->make_std_attr_default( is_optional );
184 }
185
186 void
set_cpp_default(const std::string & expr)187 std_attr_editor_t::set_cpp_default(
188 const std::string & expr )
189 {
190 m_ref_attr->std_attr_default().set_cpp( expr );
191 }
192
193 void
set_cpp_present_if(const std::string & expr)194 std_attr_editor_t::set_cpp_present_if(
195 const std::string & expr )
196 {
197 m_ref_attr->std_attr_default().std_present_if().set_cpp( expr );
198 }
199
200 const type_t &
find_type(const std::string & type_name) const201 std_attr_editor_t::find_type(
202 const std::string & type_name ) const
203 {
204 const ref_std_type_t & ref_type =
205 m_scheme.find_or_create_type( type_name );
206
207 return *( ref_type.get() );
208 }
209
210
211 //
212 // std_cpp_mapping_editor_t
213 //
std_cpp_mapping_editor_t(std_cpp_mapping_t & cpp_mapping)214 std_cpp_mapping_editor_t::std_cpp_mapping_editor_t(
215 std_cpp_mapping_t & cpp_mapping ) :
216 m_cpp_mapping( cpp_mapping )
217 {
218 }
219
~std_cpp_mapping_editor_t()220 std_cpp_mapping_editor_t::~std_cpp_mapping_editor_t()
221 {
222 }
223
224 void
set_name(const std::string & name)225 std_cpp_mapping_editor_t::set_name(
226 const std::string & name )
227 {
228 m_cpp_mapping.set_name( name );
229 }
230
231 //
232 // std_type_editor_t
233 //
std_type_editor_t(std_scheme_t & scheme)234 std_type_editor_t::std_type_editor_t(
235 std_scheme_t & scheme )
236 : m_scheme( scheme )
237 , m_extension_deep( 0 )
238 {
239 }
240
~std_type_editor_t()241 std_type_editor_t::~std_type_editor_t()
242 {
243 }
244
245 void
def(const std::string & name)246 std_type_editor_t::def( const std::string & name )
247 {
248 m_ref_type = m_scheme.find_or_create_type( name );
249 if( m_ref_type->is_defined() )
250 OESS_THROW_LOGIC(
251 oess_2::scheme::err::c_type_already_defined,
252 "type: " << name )
253
254 m_ref_cpp_mapping_editor = ref_std_cpp_mapping_editor_t(
255 new std_cpp_mapping_editor_t(
256 m_ref_type->query_cpp_mapping() ) );
257 }
258
259 void
make_defined()260 std_type_editor_t::make_defined()
261 {
262 m_ref_type->make_defined();
263 }
264
265 void
make_abstract()266 std_type_editor_t::make_abstract()
267 {
268 m_ref_type->make_abstract();
269 }
270
271 void
make_extensible()272 std_type_editor_t::make_extensible()
273 {
274 m_ref_type->make_extensible();
275 }
276
277 void
turn_subclassing_by_extension_on()278 std_type_editor_t::turn_subclassing_by_extension_on()
279 {
280 m_ref_type->turn_subclassing_by_extension_on();
281 }
282
283 void
add_base(const std::string & name,bool is_virtual)284 std_type_editor_t::add_base(
285 const std::string & name,
286 bool is_virtual )
287 {
288 const ref_std_type_t & ref_type =
289 m_scheme.find_or_create_type( name );
290
291 if( ref_type->is_builtin() )
292 OESS_THROW_LOGIC(
293 oess_2::scheme::err::c_builtin_type_as_base,
294 "builtin type: " << name << " as base for: "
295 << m_ref_type->query_name() )
296
297 ref_base_t ref_base( new std_base_t(
298 *( ref_type.get() ), is_virtual ) );
299 m_ref_type->add_base( ref_base );
300 }
301
302 void
add_base_as_extension(const std::string & name)303 std_type_editor_t::add_base_as_extension(
304 const std::string & name )
305 {
306 const ref_std_type_t & ref_type =
307 m_scheme.find_or_create_type( name );
308
309 if( ref_type->is_builtin() )
310 OESS_THROW_LOGIC(
311 oess_2::scheme::err::c_builtin_type_as_base,
312 "builtin type: " << name << " as base for: "
313 << m_ref_type->query_name() )
314
315 ref_base_t ref_base( new std_base_t(
316 *ref_type,
317 std_base_t::subclassing_by_extension ) );
318 m_ref_type->add_base_as_extension( ref_base );
319 }
320
321 attr_editor_t &
start_attr_def(const std::string & attr_name,const std::string & type_name)322 std_type_editor_t::start_attr_def(
323 const std::string & attr_name,
324 const std::string & type_name )
325 {
326 if( m_ref_attr_editor.get() )
327 OESS_THROW_PHYSIC( oess_2::scheme::err::c_attr_editor_exists,
328 "std_type_editor_t::start_attr_def( \""
329 << attr_name << "\", \""
330 << type_name << "\")" )
331
332 ref_std_attr_editor_t ref_editor(
333 new std_attr_editor_t( m_scheme ) );
334 ref_editor->def( attr_name, type_name, m_extension_deep );
335
336 // If we are here then editor is successfully created.
337 m_ref_attr_editor = ref_editor;
338
339 return *( m_ref_attr_editor.get() );
340 }
341
342 void
commit_attr_def()343 std_type_editor_t::commit_attr_def()
344 {
345 if( !m_ref_attr_editor.get() )
346 OESS_THROW_PHYSIC( oess_2::scheme::err::c_attr_editor_not_exists,
347 "std_type_editor_t::commit_attr_def()" )
348
349 ref_std_attr_editor_t ref_editor( m_ref_attr_editor );
350 m_ref_attr_editor.reset();
351
352 m_ref_type->add_attr(
353 ref_editor->query_ref_attr(), m_extension_deep );
354 }
355
356 void
rollback_attr_def()357 std_type_editor_t::rollback_attr_def()
358 {
359 if( !m_ref_attr_editor.get() )
360 OESS_THROW_PHYSIC( oess_2::scheme::err::c_attr_editor_not_exists,
361 "std_type_editor_t::rollback_attr_def()" )
362
363 m_ref_attr_editor.reset();
364 }
365
366 cpp_mapping_editor_t &
cpp_mapping()367 std_type_editor_t::cpp_mapping()
368 {
369 return *( m_ref_cpp_mapping_editor.get() );
370 }
371
372 void
start_extension()373 std_type_editor_t::start_extension()
374 {
375 if( m_ref_attr_editor.get() )
376 OESS_THROW_PHYSIC( oess_2::scheme::err::c_attr_editor_exists,
377 "unable to start extension when unfinished attr exists" )
378
379 ++m_extension_deep;
380 m_ref_type->start_extension();
381 }
382
383 const type_id_value_t &
query_type_id() const384 std_type_editor_t::query_type_id() const
385 {
386 return m_ref_type->query_type_id();
387 }
388
389 void
set_type_id(type_id_value_t && type_id)390 std_type_editor_t::set_type_id( type_id_value_t && type_id )
391 {
392 m_ref_type->set_type_id( std::move(type_id) );
393 }
394
395 void
turn_on_bitmask_use()396 std_type_editor_t::turn_on_bitmask_use()
397 {
398 m_ref_type->turn_on_bitmask_use();
399 }
400
401 void
ensure_correctness() const402 std_type_editor_t::ensure_correctness() const
403 {
404 m_ref_type->ensure_correctness();
405 }
406
407 //
408 // std_scheme_t
409 //
std_scheme_t()410 std_scheme_t::std_scheme_t()
411 {
412 fill_builtin_types();
413 }
414
~std_scheme_t()415 std_scheme_t::~std_scheme_t()
416 {
417 }
418
419 size_t
query_type_count() const420 std_scheme_t::query_type_count() const
421 {
422 return m_user_types.size();
423 }
424
425 const type_t &
query_type(size_t index) const426 std_scheme_t::query_type( size_t index ) const
427 {
428 if( index >= m_user_types.size() )
429 OESS_THROW_LOGIC( oess_2::scheme::err::c_invalid_index_of_type,
430 "type count: " << m_user_types.size()
431 << ", index: " << index )
432
433 return *( m_user_types[ index ].get() );
434 }
435
436 const type_t *
find_type(const std::string & name) const437 std_scheme_t::find_type( const std::string & name ) const
438 {
439 type_map_t::const_iterator it = m_type_map.find( name );
440 if( it != m_type_map.end() )
441 return (*it).second;
442 else
443 return 0;
444 }
445
446 type_editor_t &
start_type_def(const std::string & name)447 std_scheme_t::start_type_def(
448 const std::string & name )
449 {
450 if( m_ref_type_editor.get() )
451 OESS_THROW_PHYSIC( oess_2::scheme::err::c_type_editor_exists,
452 "std_scheme_t::start_type_def( \""
453 << name << "\")" )
454
455 ref_std_type_editor_t ref_editor(
456 new std_type_editor_t( *this ) );
457 ref_editor->def( name );
458
459 // If we are here then type editor is created.
460 m_ref_type_editor = ref_editor;
461
462 return *m_ref_type_editor;
463 }
464
465 void
commit_type_def()466 std_scheme_t::commit_type_def()
467 {
468 if( !m_ref_type_editor.get() )
469 OESS_THROW_PHYSIC( oess_2::scheme::err::c_type_editor_not_exists,
470 "std_scheme_t::commit_type_def()" )
471
472 ref_std_type_editor_t ref_editor( m_ref_type_editor );
473 m_ref_type_editor.reset();
474
475 ref_editor->make_defined();
476 }
477
478 void
rollback_type_def()479 std_scheme_t::rollback_type_def()
480 {
481 if( !m_ref_type_editor.get() )
482 OESS_THROW_PHYSIC( oess_2::scheme::err::c_type_editor_not_exists,
483 "std_scheme_t::rollback_type_def()" )
484
485 m_ref_type_editor.reset();
486 }
487
488 const ref_std_type_t &
find_or_create_type(const std::string & name)489 std_scheme_t::find_or_create_type(
490 const std::string & name )
491 {
492 const auto finder = [&name]( const ref_std_type_t & t ) {
493 return name == t->query_name();
494 };
495
496 ref_std_type_deque_t::iterator it = std::find_if(
497 m_builtin_types.begin(), m_builtin_types.end(), finder );
498 if( it != m_builtin_types.end() )
499 return (*it);
500
501 it = std::find_if(
502 m_user_types.begin(), m_user_types.end(), finder );
503 if( it != m_user_types.end() )
504 return (*it);
505
506 // A new type should be created and added to the list of user types.
507 ref_std_type_t ref_type(
508 new std_type_t( name, OESS_1_FIXED_SIZE_FORMAT ) );
509 m_user_types.push_back( ref_type );
510 add_to_map( *ref_type );
511
512 return (*(m_user_types.rbegin()));
513 }
514
515 void
add_to_map(std_type_t & type)516 std_scheme_t::add_to_map( std_type_t & type )
517 {
518 m_type_map.insert( type_map_t::value_type(
519 type.query_name(), &type ) );
520 }
521
522 void
fill_builtin_types()523 std_scheme_t::fill_builtin_types()
524 {
525 add_builtin_type( builtin_char(), OESS_1_FIXED_SIZE_FORMAT );
526 add_builtin_type( builtin_schar(), OESS_1_FIXED_SIZE_FORMAT );
527 add_builtin_type( builtin_uchar(), OESS_1_FIXED_SIZE_FORMAT );
528 add_builtin_type( builtin_short(), OESS_1_FIXED_SIZE_FORMAT );
529 add_builtin_type( builtin_ushort(), OESS_1_FIXED_SIZE_FORMAT );
530 add_builtin_type( builtin_int(), OESS_1_FIXED_SIZE_FORMAT );
531 add_builtin_type( builtin_uint(), OESS_1_FIXED_SIZE_FORMAT );
532 add_builtin_type( builtin_single(), OESS_1_FIXED_SIZE_FORMAT );
533 add_builtin_type( builtin_double(), OESS_1_FIXED_SIZE_FORMAT );
534 add_builtin_type( builtin_std_string(), OESS_1_FIXED_SIZE_FORMAT );
535 add_builtin_type(
536 builtin_small_std_string(),
537 OESS_2_VARIABLE_SIZE_FORMAT,
538 "std::string" );
539
540 add_builtin_serializable_t();
541 }
542
543 void
add_builtin_type(const std::string & name,packing_format_t packing_format,const std::string & cpp_type_name)544 std_scheme_t::add_builtin_type(
545 const std::string & name,
546 packing_format_t packing_format,
547 const std::string & cpp_type_name )
548 {
549 std_type_t * ptr = new std_type_t( name, packing_format, true );
550 if( !cpp_type_name.empty() )
551 ptr->query_cpp_mapping().set_name( cpp_type_name );
552 ptr->make_defined();
553
554 ref_std_type_t ref_type( ptr );
555 m_builtin_types.push_back( ref_type );
556 add_to_map( *ref_type );
557 }
558
559 void
add_builtin_serializable_t()560 std_scheme_t::add_builtin_serializable_t()
561 {
562 std_type_t * ptr = new std_type_t(
563 builtin_stdsn_serializable(), OESS_1_FIXED_SIZE_FORMAT, true );
564 ptr->make_defined();
565 ptr->make_abstract();
566
567 ref_std_type_t ref_type( ptr );
568 m_builtin_types.push_back( ref_type );
569 add_to_map( *ref_type );
570 }
571
572 //
573 // create_std_scheme
574 //
575 scheme_t *
create_std_scheme()576 create_std_scheme() {
577 return new std_scheme_t();
578 }
579
580 //
581 // destroy_std_scheme
582 //
583 void
destroy_std_scheme(scheme_t * ptr)584 destroy_std_scheme( scheme_t * ptr ) {
585 delete ptr;
586 }
587
588 } /* namespace impl */
589
590 } /* namespace scheme */
591
592 } /* namespace oess_2 */
593
594