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

Generated by: LCOV version 2.0-1