Changeset 9:f909044a9f7b in rrlib_rtti_conversion for tConversionOperationSequence.cpp


Ignore:
Timestamp:
22.09.2017 01:26:15 (2 years ago)
Author:
Max Reichardt <mreichardt@…>
Branch:
17.03
Phase:
public
Message:

Adds option to specify type conversions operations that are not usually combined (you could call combinations deprecated) and fixes various bugs found with unit test in finroc_plugins_runtime_construction

File:
1 edited

Legend:

Unmodified
Added
Removed
  • tConversionOperationSequence.cpp

    r8 r9  
    7171 
    7272/*! Enum for binary serialization */ 
    73 enum tOperationSerializationFlags : uint8_t { cFULL_OPERATION = 1, cPARAMETER = 2 }; 
     73enum tOperationSerializationFlags : uint8_t { cFULL_OPERATION = 1, cPARAMETER = 2, cSTRING_PARAMETER = 4 }; 
    7474 
    7575//---------------------------------------------------------------------- 
     
    125125  if (second_operation && ambiguous_operation_lookup[1]) 
    126126  { 
    127     second_operation = &tRegisteredConversionOperation::Find(first_operation->Name(), intermediate_type, destination_type); 
     127    second_operation = &tRegisteredConversionOperation::Find(second_operation->Name(), intermediate_type, destination_type); 
    128128  } 
    129129 
     
    298298  result.operations[1].operation = second_operation; 
    299299  result.destination_type = last_conversion->destination_type; 
     300  static_cast<tConversionOperationSequence&>(result).intermediate_type = this->intermediate_type; 
    300301 
    301302  // Handle special case: only const offsets 
     
    306307    result.fixed_offset_first = static_cast<unsigned int>(conversion1->const_offset_reference_to_source_object + (conversion2 ? conversion2->const_offset_reference_to_source_object : 0)); 
    307308    result.flags = tFlag::cRESULT_INDEPENDENT | tFlag::cRESULT_REFERENCES_SOURCE_DIRECTLY | tFlag::cDEEPCOPY_ONLY; 
    308     return result; 
    309   } 
    310  
    311   // Handle cases where first operation is const offset 
    312   bool first_op_is_const_offset = conversion1->type == tConversionOptionType::CONST_OFFSET_REFERENCE_TO_SOURCE_OBJECT; 
    313   result.type_after_first_fixed_offset = first_op_is_const_offset ? conversion1->destination_type : conversion1->source_type; 
    314   if (first_op_is_const_offset) 
    315   { 
    316     result.fixed_offset_first = static_cast<unsigned int>(conversion1->const_offset_reference_to_source_object); 
    317  
    318     // first operation is done, so move second to first 
    319     conversion1 = nullptr; 
    320     std::swap(conversion1, conversion2); 
    321     result.flags |= tFlag::cFIRST_OPERATION_OPTIMIZED_AWAY; 
    322   } 
    323   result.intermediate_type = conversion1->destination_type; 
    324  
    325   // Single operation REFERENCES_SOURCE 
    326   if (conversion1->type == tConversionOptionType::RESULT_REFERENCES_SOURCE_OBJECT && (!conversion2)) 
    327   { 
    328     result.conversion_function_first = allow_reference_to_source ? conversion1->final_conversion_function : conversion1->first_conversion_function; 
    329     result.flags = allow_reference_to_source ? tFlag::cRESULT_REFERENCES_SOURCE_INTERNALLY : (tFlag::cRESULT_INDEPENDENT | tFlag::cDO_FINAL_DEEPCOPY_AFTER_FIRST_FUNCTION); 
    330   } 
    331   // First operation is standard or REFERENCES_SOURCE 
    332   else if (conversion1->type == tConversionOptionType::STANDARD_CONVERSION_FUNCTION || conversion1->type == tConversionOptionType::RESULT_REFERENCES_SOURCE_OBJECT) 
    333   { 
    334     result.conversion_function_first = conversion2 ? conversion1->first_conversion_function : conversion1->final_conversion_function; 
    335     result.flags = tFlag::cRESULT_INDEPENDENT; 
    336     if (conversion2 && conversion2->type == tConversionOptionType::STANDARD_CONVERSION_FUNCTION) 
    337     { 
    338       result.conversion_function_final = conversion2->final_conversion_function; 
    339     } 
    340     else if (conversion2 && conversion2->type == tConversionOptionType::CONST_OFFSET_REFERENCE_TO_SOURCE_OBJECT) 
    341     { 
    342       if (conversion2->const_offset_reference_to_source_object == 0 && conversion2->source_type == conversion2->destination_type && (conversion1->type == tConversionOptionType::STANDARD_CONVERSION_FUNCTION || allow_reference_to_source)) 
    343       { 
    344         result.conversion_function_first =  conversion1->final_conversion_function; // second operation can be optimized away 
    345         result.intermediate_type = result.destination_type; 
    346         if (conversion1->type == tConversionOptionType::RESULT_REFERENCES_SOURCE_OBJECT) 
    347         { 
    348           assert(allow_reference_to_source); 
    349           result.flags = tFlag::cRESULT_REFERENCES_SOURCE_INTERNALLY; 
    350         } 
    351       } 
    352       else 
    353       { 
    354         result.flags |= tFlag::cDO_FINAL_DEEPCOPY_AFTER_FIRST_FUNCTION; 
    355         result.fixed_offset_final = conversion2->const_offset_reference_to_source_object; 
    356       } 
    357     } 
    358     else if (conversion2 && (conversion2->type == tConversionOptionType::VARIABLE_OFFSET_REFERENCE_TO_SOURCE_OBJECT || conversion2->type == tConversionOptionType::RESULT_REFERENCES_SOURCE_OBJECT)) 
    359     { 
    360       result.conversion_function_final = conversion2->first_conversion_function; 
    361       result.flags |= tFlag::cDO_FINAL_DEEPCOPY_AFTER_SECOND_FUNCTION; 
    362     } 
    363   } 
    364   // First operation is variable offset 
    365   else if (conversion1->type == tConversionOptionType::VARIABLE_OFFSET_REFERENCE_TO_SOURCE_OBJECT) 
    366   { 
    367     bool reference_result = allow_reference_to_source && ((!conversion2) || conversion2->type != tConversionOptionType::STANDARD_CONVERSION_FUNCTION); 
    368     if (reference_result) 
    369     { 
    370       if (conversion2 && conversion2->type == tConversionOptionType::RESULT_REFERENCES_SOURCE_OBJECT) 
    371       { 
    372         result.flags |= tFlag::cRESULT_REFERENCES_SOURCE_INTERNALLY; 
    373         result.conversion_function_first = conversion1->first_conversion_function; 
     309  } 
     310  else 
     311  { 
     312    // Handle cases where first operation is const offset 
     313    bool first_op_is_const_offset = conversion1->type == tConversionOptionType::CONST_OFFSET_REFERENCE_TO_SOURCE_OBJECT; 
     314    result.type_after_first_fixed_offset = first_op_is_const_offset ? conversion1->destination_type : conversion1->source_type; 
     315    if (first_op_is_const_offset) 
     316    { 
     317      result.fixed_offset_first = static_cast<unsigned int>(conversion1->const_offset_reference_to_source_object); 
     318 
     319      // first operation is done, so move second to first 
     320      conversion1 = nullptr; 
     321      std::swap(conversion1, conversion2); 
     322      result.flags |= tFlag::cFIRST_OPERATION_OPTIMIZED_AWAY; 
     323    } 
     324    result.intermediate_type = conversion1->destination_type; 
     325 
     326    // Single operation REFERENCES_SOURCE 
     327    if (conversion1->type == tConversionOptionType::RESULT_REFERENCES_SOURCE_OBJECT && (!conversion2)) 
     328    { 
     329      result.conversion_function_first = allow_reference_to_source ? conversion1->final_conversion_function : conversion1->first_conversion_function; 
     330      result.flags = allow_reference_to_source ? tFlag::cRESULT_REFERENCES_SOURCE_INTERNALLY : (tFlag::cRESULT_INDEPENDENT | tFlag::cDO_FINAL_DEEPCOPY_AFTER_FIRST_FUNCTION); 
     331    } 
     332    // First operation is standard or REFERENCES_SOURCE 
     333    else if (conversion1->type == tConversionOptionType::STANDARD_CONVERSION_FUNCTION || conversion1->type == tConversionOptionType::RESULT_REFERENCES_SOURCE_OBJECT) 
     334    { 
     335      result.conversion_function_first = conversion2 ? conversion1->first_conversion_function : conversion1->final_conversion_function; 
     336      result.flags = tFlag::cRESULT_INDEPENDENT; 
     337      if (conversion2 && conversion2->type == tConversionOptionType::STANDARD_CONVERSION_FUNCTION) 
     338      { 
    374339        result.conversion_function_final = conversion2->final_conversion_function; 
    375340      } 
    376       else 
    377       { 
    378         result.flags |= tFlag::cRESULT_REFERENCES_SOURCE_DIRECTLY; 
    379         result.get_destination_reference_function_first = conversion2->destination_reference_function; 
    380         if (conversion2 && conversion2->type == tConversionOptionType::CONST_OFFSET_REFERENCE_TO_SOURCE_OBJECT) 
    381         { 
     341      else if (conversion2 && conversion2->type == tConversionOptionType::CONST_OFFSET_REFERENCE_TO_SOURCE_OBJECT) 
     342      { 
     343        if (conversion2->const_offset_reference_to_source_object == 0 && conversion2->source_type == conversion2->destination_type && (conversion1->type == tConversionOptionType::STANDARD_CONVERSION_FUNCTION || allow_reference_to_source)) 
     344        { 
     345          result.conversion_function_first =  conversion1->final_conversion_function; // second operation can be optimized away 
     346          result.intermediate_type = result.destination_type; 
     347          if (conversion1->type == tConversionOptionType::RESULT_REFERENCES_SOURCE_OBJECT) 
     348          { 
     349            assert(allow_reference_to_source); 
     350            result.flags = tFlag::cRESULT_REFERENCES_SOURCE_INTERNALLY; 
     351          } 
     352        } 
     353        else 
     354        { 
     355          result.flags |= tFlag::cDO_FINAL_DEEPCOPY_AFTER_FIRST_FUNCTION; 
    382356          result.fixed_offset_final = conversion2->const_offset_reference_to_source_object; 
    383357        } 
    384         else if (conversion2 && conversion2->type == tConversionOptionType::VARIABLE_OFFSET_REFERENCE_TO_SOURCE_OBJECT) 
    385         { 
    386           result.get_destination_reference_function_final = conversion2->destination_reference_function; 
    387         } 
    388       } 
    389     } 
    390     else 
    391     { 
    392       result.conversion_function_first = conversion1->first_conversion_function; 
    393       result.flags |= tFlag::cRESULT_INDEPENDENT; 
    394       if (!conversion2) 
    395       { 
    396         result.flags |= tFlag::cDO_FINAL_DEEPCOPY_AFTER_FIRST_FUNCTION; 
    397       } 
    398       else if (conversion2->type == tConversionOptionType::STANDARD_CONVERSION_FUNCTION) 
    399       { 
    400         result.conversion_function_final = conversion2->final_conversion_function; 
    401       } 
    402       else if (conversion2->type == tConversionOptionType::CONST_OFFSET_REFERENCE_TO_SOURCE_OBJECT) 
    403       { 
    404         result.flags |= tFlag::cDO_FINAL_DEEPCOPY_AFTER_FIRST_FUNCTION; 
    405         result.fixed_offset_final = conversion2->const_offset_reference_to_source_object; 
    406358      } 
    407359      else if (conversion2 && (conversion2->type == tConversionOptionType::VARIABLE_OFFSET_REFERENCE_TO_SOURCE_OBJECT || conversion2->type == tConversionOptionType::RESULT_REFERENCES_SOURCE_OBJECT)) 
     
    409361        result.conversion_function_final = conversion2->first_conversion_function; 
    410362        result.flags |= tFlag::cDO_FINAL_DEEPCOPY_AFTER_SECOND_FUNCTION; 
     363      } 
     364    } 
     365    // First operation is variable offset 
     366    else if (conversion1->type == tConversionOptionType::VARIABLE_OFFSET_REFERENCE_TO_SOURCE_OBJECT) 
     367    { 
     368      bool reference_result = allow_reference_to_source && ((!conversion2) || conversion2->type != tConversionOptionType::STANDARD_CONVERSION_FUNCTION); 
     369      if (reference_result) 
     370      { 
     371        if (conversion2 && conversion2->type == tConversionOptionType::RESULT_REFERENCES_SOURCE_OBJECT) 
     372        { 
     373          result.flags |= tFlag::cRESULT_REFERENCES_SOURCE_INTERNALLY; 
     374          result.conversion_function_first = conversion1->first_conversion_function; 
     375          result.conversion_function_final = conversion2->final_conversion_function; 
     376        } 
     377        else 
     378        { 
     379          result.flags |= tFlag::cRESULT_REFERENCES_SOURCE_DIRECTLY; 
     380          result.get_destination_reference_function_first = conversion2->destination_reference_function; 
     381          if (conversion2 && conversion2->type == tConversionOptionType::CONST_OFFSET_REFERENCE_TO_SOURCE_OBJECT) 
     382          { 
     383            result.fixed_offset_final = conversion2->const_offset_reference_to_source_object; 
     384          } 
     385          else if (conversion2 && conversion2->type == tConversionOptionType::VARIABLE_OFFSET_REFERENCE_TO_SOURCE_OBJECT) 
     386          { 
     387            result.get_destination_reference_function_final = conversion2->destination_reference_function; 
     388          } 
     389        } 
     390      } 
     391      else 
     392      { 
     393        result.conversion_function_first = conversion1->first_conversion_function; 
     394        result.flags |= tFlag::cRESULT_INDEPENDENT; 
     395        if (!conversion2) 
     396        { 
     397          result.flags |= tFlag::cDO_FINAL_DEEPCOPY_AFTER_FIRST_FUNCTION; 
     398        } 
     399        else if (conversion2->type == tConversionOptionType::STANDARD_CONVERSION_FUNCTION) 
     400        { 
     401          result.conversion_function_final = conversion2->final_conversion_function; 
     402        } 
     403        else if (conversion2->type == tConversionOptionType::CONST_OFFSET_REFERENCE_TO_SOURCE_OBJECT) 
     404        { 
     405          result.flags |= tFlag::cDO_FINAL_DEEPCOPY_AFTER_FIRST_FUNCTION; 
     406          result.fixed_offset_final = conversion2->const_offset_reference_to_source_object; 
     407        } 
     408        else if (conversion2 && (conversion2->type == tConversionOptionType::VARIABLE_OFFSET_REFERENCE_TO_SOURCE_OBJECT || conversion2->type == tConversionOptionType::RESULT_REFERENCES_SOURCE_OBJECT)) 
     409        { 
     410          result.conversion_function_final = conversion2->first_conversion_function; 
     411          result.flags |= tFlag::cDO_FINAL_DEEPCOPY_AFTER_SECOND_FUNCTION; 
     412        } 
    411413      } 
    412414    } 
     
    471473    auto operation = sequence[i]; 
    472474    auto parameter_value = sequence.GetParameterValue(i); 
    473     uint8_t flags = (operation.second ? cFULL_OPERATION : 0) | (parameter_value ? cPARAMETER : 0); 
     475    uint8_t flags = (operation.second ? cFULL_OPERATION : 0) | (parameter_value && operation.second && parameter_value.GetType() == operation.second->Parameter().GetType() ? cPARAMETER : (parameter_value ? cSTRING_PARAMETER : 0)); 
    474476    stream.WriteByte(flags); 
    475477    if (operation.second) 
     
    482484      stream << operation.first; 
    483485    } 
    484     if (parameter_value) 
     486    if (flags & cPARAMETER) 
    485487    { 
    486488      parameter_value.Serialize(stream); 
     489    } 
     490    else if (flags & cSTRING_PARAMETER) 
     491    { 
     492      assert(parameter_value.GetType() == tDataType<std::string>()); 
     493      stream << *parameter_value.Get<std::string>(); 
    487494    } 
    488495  } 
     
    534541          throw std::runtime_error("No parameter defined in conversion operation to deserialize"); 
    535542        } 
    536         if ((!sequence.operations[i].parameter)) 
     543        if ((!sequence.operations[i].parameter) || sequence.operations[i].parameter->GetType() != sequence.operations[i].operation->Parameter().GetType()) 
    537544        { 
    538545          sequence.operations[i].parameter.reset(sequence.operations[i].operation->Parameter().GetType().CreateGenericObject()); 
     
    540547        sequence.operations[i].parameter->Deserialize(stream); 
    541548      } 
     549      else if (flags & cSTRING_PARAMETER) 
     550      { 
     551        if (!sequence.operations[i].operation) 
     552        { 
     553          throw std::runtime_error("No conversion operation found"); 
     554        } 
     555        if ((!sequence.operations[i].parameter) || sequence.operations[i].parameter->GetType() != tDataType<std::string>()) 
     556        { 
     557          sequence.operations[i].parameter.reset(tDataType<std::string>().CreateGenericObject()); 
     558        } 
     559        stream >> sequence.operations[i].parameter->GetData<std::string>(); 
     560      } 
    542561      else 
    543562      { 
Note: See TracChangeset for help on using the changeset viewer.