LCOV - code coverage report
Current view: top level - oks/src - method.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 17.6 % 244 43
Test Date: 2026-07-12 15:23:06 Functions: 15.0 % 20 3

            Line data    Source code
       1              : // DUNE DAQ modification notice:
       2              : // This file has been modified from the original ATLAS oks source for the DUNE DAQ project.
       3              : // Fork baseline commit: oks-08-03-04 (2022-04-14).
       4              : // Renamed since fork: no.
       5              : 
       6              : #define _OksBuildDll_
       7              : 
       8              : #include "oks/method.hpp"
       9              : #include "oks/xml.hpp"
      10              : #include "oks/class.hpp"
      11              : #include "oks/cstring.hpp"
      12              : 
      13              : #include <stdexcept>
      14              : #include <sstream>
      15              : 
      16              : namespace dunedaq {
      17              : namespace oks {
      18              : 
      19              : const char OksMethodImplementation::method_impl_xml_tag[] = "method-implementation";
      20              : const char OksMethodImplementation::language_xml_attr[]   = "language";
      21              : const char OksMethodImplementation::prototype_xml_attr[]  = "prototype";
      22              : const char OksMethodImplementation::body_xml_attr[]       = "body";
      23              : 
      24              : const char OksMethod::method_xml_tag[]                    = "method";
      25              : const char OksMethod::name_xml_attr[]                     = "name";
      26              : const char OksMethod::description_xml_attr[]              = "description";
      27              : 
      28              : 
      29            0 : OksMethodImplementation::OksMethodImplementation(const std::string& language, const std::string& prototype, const std::string& body, OksMethod * p) :
      30            0 :  p_language  (language),
      31            0 :  p_prototype (prototype),
      32            0 :  p_body      (body),
      33            0 :  p_method    (p)
      34              : {
      35            0 :   oks::validate_not_empty(p_language, "method implementation language");
      36            0 :   oks::validate_not_empty(p_prototype, "method implementation prototype");
      37            0 : }
      38              : 
      39              : bool
      40            0 : OksMethodImplementation::operator==(const class OksMethodImplementation &i) const
      41              : {
      42            0 :   return (
      43            0 :     ( this == &i ) ||
      44            0 :     ( p_language == i.p_language && p_prototype == i.p_prototype && p_body == i.p_body )
      45            0 :   );
      46              : }
      47              : 
      48              : std::ostream&
      49            0 : operator<<(std::ostream& s, const OksMethodImplementation& i)
      50              : {
      51            0 :   s << "  Method implementation:\n"
      52            0 :        "    language:  \"" << i.get_language()  << "\"\n"
      53            0 :        "    prototype: \"" << i.get_prototype() << "\"\n"
      54            0 :        "    body:      \"" << i.get_body()      << "\"\n";
      55              : 
      56            0 :   return s;
      57              : }
      58              : 
      59              : 
      60              : void
      61            0 : OksMethodImplementation::save(OksXmlOutputStream& s) const
      62              : {
      63            0 :   s.put("   ");
      64              : 
      65            0 :   s.put_start_tag(method_impl_xml_tag, sizeof(method_impl_xml_tag)-1);
      66              : 
      67            0 :   s.put_attribute( language_xml_attr,  sizeof(language_xml_attr)-1,  get_language().c_str()  );
      68            0 :   s.put_attribute( prototype_xml_attr, sizeof(prototype_xml_attr)-1, get_prototype().c_str() );
      69            0 :   s.put_attribute( body_xml_attr,      sizeof(body_xml_attr)-1,      get_body().c_str()      );
      70              : 
      71            0 :   s.put_end_tag();
      72            0 : }
      73              : 
      74              : 
      75         3076 : OksMethodImplementation::OksMethodImplementation(OksXmlInputStream& s, OksMethod * parent) :
      76         3076 :  p_method (parent)
      77              : {
      78        12304 :   try {
      79        21532 :     while(true) {
      80        12304 :       OksXmlAttribute attr(s);
      81              : 
      82              :         // check for close of tag
      83              : 
      84        12304 :       if(oks::cmp_str1(attr.name(), "/")) { break; }
      85              : 
      86              :         // check for known oks-method-implementation' attributes
      87              : 
      88         9228 :       else if( oks::cmp_str8(attr.name(), language_xml_attr)  ) p_language.assign(attr.value(), attr.value_len());
      89         6152 :       else if( oks::cmp_str9(attr.name(), prototype_xml_attr) ) p_prototype.assign(attr.value(), attr.value_len());
      90         3076 :       else if( oks::cmp_str4(attr.name(), body_xml_attr)      ) p_body.assign(attr.value(), attr.value_len());
      91              :       else {
      92            0 :         s.throw_unexpected_attribute(attr.name());
      93              :       }
      94         9228 :     }
      95              :   }
      96            0 :   catch(oks::exception & e) {
      97            0 :     throw oks::FailedRead("xml method implementation", e);
      98            0 :   }
      99            0 :   catch (std::exception & e) {
     100            0 :     throw oks::FailedRead("xml method implementation", e.what());
     101            0 :   }
     102              : 
     103         3076 :   try {
     104         3076 :     oks::validate_not_empty(p_language, "method implementation language");
     105         3076 :     oks::validate_not_empty(p_prototype, "method implementation prototype");
     106              :   }
     107            0 :   catch(std::exception& ex) {
     108            0 :     throw oks::FailedRead("oks method implementation", oks::BadFileData(ex.what(), s.get_line_no(), s.get_line_pos()));
     109            0 :   }
     110         3076 : }
     111              : 
     112              : 
     113            0 : OksMethod::OksMethod(const std::string& nm, OksClass * p) :
     114            0 :   p_class               (p),
     115            0 :   p_name                (nm),
     116            0 :   p_implementations     (nullptr)
     117              : {
     118            0 :   try {
     119            0 :     oks::validate_not_empty(p_name, "method name");
     120              :   }
     121            0 :   catch(std::exception& ex) {
     122            0 :     Oks::error_msg("OksMethod::OksMethod()") << ex.what() << std::endl;
     123            0 :   }
     124            0 : }
     125              : 
     126            0 : OksMethod::OksMethod(const std::string& nm, const std::string& desc, OksClass * p) :
     127            0 :   p_class               (p),
     128            0 :   p_name                (nm),
     129            0 :   p_description         (desc),
     130            0 :   p_implementations     (nullptr)
     131              : {
     132            0 :   oks::validate_not_empty(p_name, "method name");
     133            0 : }
     134              : 
     135         2833 : OksMethod::~OksMethod()
     136              : {
     137         2833 :   if(p_implementations) {
     138         5909 :     while(!p_implementations->empty()) {
     139         3076 :       OksMethodImplementation * i = p_implementations->front();
     140         3076 :       p_implementations->pop_front();
     141         3076 :       delete i;
     142              :     }
     143              : 
     144         2833 :     delete p_implementations;
     145              :   }
     146         2833 : }
     147              : 
     148              : 
     149              : bool
     150            0 : OksMethod::operator==(const class OksMethod &m) const
     151              : {
     152              :     // check if compare with self
     153              : 
     154            0 :   if(this == &m) return true;
     155              : 
     156              : 
     157              :     // check if attributes are different
     158              : 
     159            0 :   if(p_name != m.p_name || p_description != m.p_description) return false;
     160              : 
     161              : 
     162              :     // check if methods have no implementations
     163              : 
     164            0 :   if(p_implementations == 0 && m.p_implementations == 0) return true;
     165              : 
     166              : 
     167              :     // check if only one method has implementation
     168              : 
     169            0 :   if(p_implementations == 0 || m.p_implementations == 0) return false;
     170              : 
     171              : 
     172              :     // check if numbers of implementations are different
     173              : 
     174            0 :   if(p_implementations->size() != m.p_implementations->size()) return false;
     175              : 
     176              : 
     177              :     // check implementations
     178              : 
     179            0 :   std::list<OksMethodImplementation *>::const_iterator i1 = p_implementations->begin();
     180            0 :   std::list<OksMethodImplementation *>::const_iterator i2 = m.p_implementations->begin();
     181              :   
     182            0 :   for(;i1 != p_implementations->end(); ++i1, ++i2) {
     183            0 :     if( !(*(*i1) == *(*i2)) ) return false;
     184              :   }
     185              :   
     186              :   return true;
     187              : }
     188              : 
     189              : std::ostream&
     190            0 : operator<<(std::ostream& s, const OksMethod& m)
     191              : {
     192            0 :   s << "Method name: \"" << m.p_name << "\"\n"
     193            0 :        " description: \"" << m.p_description << "\"\n";
     194              :         
     195            0 :   if(m.p_implementations) {
     196            0 :     s << " implementations:\n";
     197              : 
     198            0 :     for(std::list<OksMethodImplementation *>::const_iterator i = m.p_implementations->begin(); i != m.p_implementations->end(); ++i)
     199            0 :       s << *(*i);
     200              :   }
     201              :   else
     202            0 :     s << " there are no implementation(s)\n";
     203              : 
     204            0 :   return s;
     205              : }
     206              : 
     207              : 
     208              : void
     209            0 : OksMethod::save(OksXmlOutputStream& s) const
     210              : {
     211            0 :   s.put_raw(' ');
     212            0 :   s.put_raw(' ');
     213              : 
     214            0 :   s.put_start_tag(method_xml_tag, sizeof(method_xml_tag)-1);
     215              :   
     216            0 :   s.put_attribute(name_xml_attr, sizeof(name_xml_attr)-1, p_name.c_str());
     217            0 :   s.put_attribute(description_xml_attr, sizeof(description_xml_attr)-1, p_description.c_str());
     218              : 
     219            0 :   s.put_raw('>');
     220            0 :   s.put_raw('\n');
     221              : 
     222            0 :   if(p_implementations) {
     223            0 :     for(std::list<OksMethodImplementation *>::iterator i = p_implementations->begin(); i != p_implementations->end(); ++i)
     224            0 :       (*i)->save(s);
     225              :   }
     226              : 
     227            0 :   s.put_raw(' ');
     228            0 :   s.put_raw(' ');
     229              : 
     230            0 :   s.put_last_tag(method_xml_tag, sizeof(method_xml_tag)-1);
     231            0 : }
     232              : 
     233              : 
     234         2833 : OksMethod::OksMethod(OksXmlInputStream& s, OksClass * parent) :
     235         2833 :  p_class           (parent),
     236         2833 :  p_implementations (0)
     237              : {
     238         8499 :   try {
     239        14165 :     while(true) {
     240         8499 :       OksXmlAttribute attr(s);
     241              : 
     242              :         // check for close of tag
     243              : 
     244         8499 :       if(oks::cmp_str1(attr.name(), ">")) { break; }
     245              : 
     246              :         // check for known oks-relationship' attributes
     247              : 
     248         5666 :       else if(oks::cmp_str4(attr.name(), name_xml_attr)) p_name.assign(attr.value(), attr.value_len());
     249         2833 :       else if(oks::cmp_str11(attr.name(), description_xml_attr)) p_description.assign(attr.value(), attr.value_len());
     250              :       else {
     251            0 :         s.throw_unexpected_attribute(attr.name());
     252              :       }
     253         5666 :     }
     254              :   }
     255            0 :   catch(oks::exception & e) {
     256            0 :     throw oks::FailedRead("xml method", e);
     257            0 :   }
     258            0 :   catch (std::exception & e) {
     259            0 :     throw oks::FailedRead("xml method", e.what());
     260            0 :   }
     261              : 
     262              :     // check validity of read values
     263              : 
     264         2833 :   try {
     265         2833 :     oks::validate_not_empty(p_name, "method name");
     266              :   }
     267            0 :   catch(std::exception& ex) {
     268            0 :     throw oks::FailedRead("oks method", oks::BadFileData(ex.what(), s.get_line_no(), s.get_line_pos()));
     269            0 :   }
     270              : 
     271              : 
     272              :     // read 'body' and 'method-actions'
     273              : 
     274         5909 :   {
     275         8985 :     while(true) try {
     276         5909 :       const char * tag_start = s.get_tag_start();
     277              : 
     278         5909 :       if(oks::cmp_str7(tag_start, "/method")) { break; }
     279              : 
     280         3076 :       else if(!strcmp(tag_start, "method-implementation")) {
     281         3076 :         if(!p_implementations) p_implementations = new std::list<OksMethodImplementation *>();
     282         3076 :         p_implementations->push_back(new OksMethodImplementation(s, this));
     283              :       }
     284              : 
     285              :       else {
     286            0 :         std::ostringstream text;
     287            0 :         text << "Unexpected tag \'" << tag_start << "\' inside method \'" << p_name << "\'\n";
     288            0 :         throw std::runtime_error( text.str().c_str() );
     289            0 :       }
     290              : 
     291              :     }
     292            0 :     catch (oks::exception & e) {
     293            0 :       throw oks::FailedRead("method tag", e);
     294            0 :     }
     295            0 :     catch (std::exception & e) {
     296            0 :       throw oks::FailedRead("method tag", e.what());
     297         3076 :     }
     298              :   }
     299         2833 : }
     300              : 
     301              : 
     302              : void
     303            0 : OksMethod::set_name(const std::string& new_name)
     304              : {
     305              :     // ignore when name is the same
     306              : 
     307            0 :   if(p_name == new_name) return;
     308              : 
     309              : 
     310              :     // additional checks are required,
     311              :     // if the method already belongs to some class
     312              : 
     313            0 :   if(p_class) {
     314              : 
     315              :       // check allowed length for attribute name
     316              : 
     317            0 :     try {
     318            0 :       oks::validate_not_empty(new_name, "name");
     319              :     }
     320            0 :     catch(std::exception& ex) {
     321            0 :       throw oks::SetOperationFailed("OksMethod::set_name", ex.what());
     322            0 :     }
     323              : 
     324              : 
     325              :       // having a direct method with the same name is an error
     326              : 
     327            0 :     if(p_class->find_direct_method(new_name) != 0) {
     328            0 :       std::ostringstream text;
     329            0 :       text << "Class \"" << p_class->get_name() << "\" already has direct method \"" << new_name << '\"';
     330            0 :       throw oks::SetOperationFailed("OksMethod::set_name", text.str());
     331            0 :     }
     332              : 
     333              : 
     334              :       // check that it is possible to lock the file
     335              : 
     336            0 :     p_class->lock_file("OksMethod::set_name");
     337              : 
     338              : 
     339              :       // probably a non-direct method already exists
     340              : 
     341            0 :     OksMethod * m = p_class->find_method(new_name);
     342              : 
     343              : 
     344              :       // change the name
     345              : 
     346            0 :     p_name = new_name;
     347              : 
     348              : 
     349              :       // registrate the change
     350              : 
     351            0 :     p_class->registrate_class_change(OksClass::ChangeMethodsList, (const void *)m);
     352              :   }
     353              :   else {
     354            0 :     p_name = new_name;
     355              :   }
     356              : }
     357              : 
     358              : OksMethodImplementation *
     359            0 : OksMethod::find_implementation(const std::string& language) const
     360              : {
     361            0 :   if(p_implementations) {
     362            0 :     for(std::list<OksMethodImplementation *>::iterator i = p_implementations->begin(); i != p_implementations->end(); ++i)
     363            0 :       if(language == (*i)->get_language()) return *i;
     364              :   }
     365              : 
     366              :   return 0;
     367              : }
     368              : 
     369              : void
     370            0 : OksMethod::add_implementation(const std::string& language, const std::string& prototype, const std::string& body)
     371              : {
     372            0 :   if(find_implementation(language)) {
     373            0 :     std::ostringstream text;
     374            0 :     text << "Cannot add implementation on language \"" << language << "\" since it already exists.";
     375            0 :     throw oks::SetOperationFailed("OksMethod::add_implementation", text.str());
     376            0 :   }
     377              : 
     378            0 :   if(p_class) p_class->lock_file("OksMethod::add_implementation");
     379              : 
     380            0 :   if(!p_implementations) {
     381            0 :     p_implementations = new std::list<OksMethodImplementation *>();
     382              :   }
     383              : 
     384            0 :   OksMethodImplementation * i = new OksMethodImplementation(language, prototype, body);
     385              : 
     386            0 :   p_implementations->push_back(i);
     387            0 :   i->p_method = this;
     388              : 
     389            0 :   if(p_class) p_class->registrate_class_change(OksClass::ChangeMethodImplementation, (const void *)this);
     390            0 : }
     391              : 
     392              : void
     393            0 : OksMethod::remove_implementation(const std::string& language)
     394              : {
     395            0 :   OksMethodImplementation * i = find_implementation(language);
     396              : 
     397            0 :   if(i == 0) {
     398            0 :     std::ostringstream text;
     399            0 :     text << "Cannot remove implementation on language \"" << language << "\" since it does not exist.";
     400            0 :     throw oks::SetOperationFailed("OksMethod::remove_implementation", text.str());
     401            0 :   }
     402              : 
     403            0 :   if(p_class) p_class->lock_file("OksMethod::remove_implementation");
     404              : 
     405            0 :   p_implementations->remove(i);
     406              : 
     407            0 :   if(p_implementations->empty()) {
     408            0 :     delete p_implementations;
     409            0 :     p_implementations = 0;
     410              :   }
     411              : 
     412            0 :   if(p_class) p_class->registrate_class_change(OksClass::ChangeMethodImplementation, (const void *)this);
     413            0 : }
     414              : 
     415              : 
     416              : void
     417            0 : OksMethod::set_description(const std::string& desc)
     418              : {
     419            0 :   if(p_description != desc) {
     420            0 :     if(p_class) p_class->lock_file("OksMethod::set_description");
     421              : 
     422            0 :     p_description = desc;
     423              : 
     424            0 :     if(p_class) p_class->registrate_class_change(OksClass::ChangeMethodDescription, (const void *)this);
     425              :   }
     426            0 : }
     427              : 
     428              : void
     429            0 : OksMethodImplementation::set_language(const std::string& s)
     430              : {
     431            0 :   if(p_language != s) {
     432            0 :     if(p_method) {
     433            0 :       if(p_method->find_implementation(s) != 0) {
     434            0 :         std::ostringstream text;
     435            0 :         text << "cannot rename \"" << p_method->p_name << "\" method implementation to language \"" << s << "\" "
     436            0 :              "since the method already has implementation with such language.";
     437            0 :         throw oks::SetOperationFailed("OksMethodImplementation::set_language", text.str());
     438            0 :       }
     439              : 
     440            0 :       try {
     441            0 :         oks::validate_not_empty(s, "language");
     442              :       }
     443            0 :       catch(std::exception& ex) {
     444            0 :         throw oks::SetOperationFailed("OksMethodImplementation::set_language", ex.what());
     445            0 :       }
     446              : 
     447            0 :       if(p_method->p_class) p_method->p_class->lock_file("OksMethodImplementation::set_language");
     448              :     }
     449              : 
     450            0 :     p_language = s;
     451              : 
     452            0 :     if(p_method && p_method->p_class) {
     453            0 :       p_method->p_class->registrate_class_change(OksClass::ChangeMethodImplementation, (const void *)this);
     454              :     }
     455              :   }
     456            0 : }
     457              : 
     458              : void
     459            0 : OksMethodImplementation::set_prototype(const std::string& s)
     460              : {
     461            0 :   if(p_prototype != s) {
     462            0 :     try {
     463            0 :       oks::validate_not_empty(s, "prototype");
     464              :     }
     465            0 :     catch(std::exception& ex) {
     466            0 :       throw oks::SetOperationFailed("OksMethodImplementation::set_prototype", ex.what());
     467            0 :     }
     468              : 
     469            0 :     if(p_method && p_method->p_class) p_method->p_class->lock_file("OksMethodImplementation::set_prototype");
     470              : 
     471            0 :     p_prototype = s;
     472              : 
     473            0 :     if(p_method && p_method->p_class) {
     474            0 :       p_method->p_class->registrate_class_change(OksClass::ChangeMethodImplementation, (const void *)this);
     475              :     }
     476              :   }
     477            0 : }
     478              : 
     479              : void
     480            0 : OksMethodImplementation::set_body(const std::string& s)
     481              : {
     482            0 :   if(p_body != s) {
     483            0 :     if(p_method && p_method->p_class) p_method->p_class->lock_file("OksMethodImplementation::set_body");
     484              : 
     485            0 :     p_body = s;
     486              : 
     487            0 :     if(p_method && p_method->p_class) {
     488            0 :       p_method->p_class->registrate_class_change(OksClass::ChangeMethodImplementation, (const void *)this);
     489              :     }
     490              :   }
     491            0 : }
     492              : 
     493              : } // namespace oks
     494              : } // namespace dunedaq
        

Generated by: LCOV version 2.0-1