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