DiaDes  0.1
DIAgnosis of Discrete-Event System
AutFileDescriptor.hh
Go to the documentation of this file.
1 
9 #ifndef __DIADES__AUTOMATA__EXPERIMENTAL__AUTFILEDESCRIPTOR__HH__
10 #define __DIADES__AUTOMATA__EXPERIMENTAL__AUTFILEDESCRIPTOR__HH__
11 
12 #include<string>
13 #include<set>
14 #include <sstream>
15 #include <istream>
16 #include <diades/utils/Label.hh>
18 
19 namespace Diades
20 {
21  namespace Automata
22  {
23  namespace Experimental
24  {
25 
32  template<typename EventType>
33  struct ReadEvent
34  {
35 
36  bool operator()(std::istream & stream,
37  EventType & event) const
38  {
39  stream >> event;
40  return stream.good() || stream.eof();
41  }
42  };
43 
50  template<>
51  struct ReadEvent<std::string>
52  {
53 
54  bool operator()(std::istream & stream,
55  std::string & evtLabel) const
56  {
57  return Diades::Utils::readLabel(stream, evtLabel);
58  }
59  };
60 
69  template<typename EventType>
70  struct PrintEvent
71  {
72 
73  bool operator()(std::ostream & stream,
74  const EventType & event) const
75  {
76  stream << event;
77  return stream.good();
78  }
79  };
80 
89  template<>
90  struct PrintEvent<std::string>
91  {
92 
93  bool operator()(std::ostream & stream,
94  const std::string & event) const
95  {
96 
97  Diades::Utils::UnquotedStringLabel unqLabel(event);
98  //std::cout << "uq=" << unqLabel.toString() << '\n';
99 
100  if(unqLabel.isNull())
101  {
102  stream << event;
103  }
104  else
105  {
106  stream << "\"" << event << "\"";
107  }
108  return stream.good();
109  }
110  };
111 
144  template<typename _Event>
146  {
147  public:
148 
152  using State = size_t;
153  using Event = _Event;
156 
163  {
164  private:
168 
169  public:
170 
177  Transition(State source, Event event, State target) :
178  _source(source), _event(event), _target(target)
179  {
180  }
181 
187  State
188  setSource(State source)
189  {
190  return _source = source;
191  }
192 
197  State
198  source() const
199  {
200  return _source;
201  }
202 
208  const Event &
209  setEvent(const Event & event)
210  {
211  return _event = event;
212  }
213 
218  const Event &
219  event() const
220  {
221  return _event;
222  }
223 
229  State
230  setTarget(State target)
231  {
232  return _target = target;
233  }
234 
239  State
240  target() const
241  {
242  return _target;
243  }
244 
250  bool operator==(const Transition & transition) const
251  {
252  return source() == transition.source() && target() == transition.target()
253  && event() == transition.event();
254  }
255 
263  bool operator<(const Transition & transition) const
264  {
265  auto result = source() < transition.source();
266  if(!result)
267  {
268  if(source() == transition.source())
269  {
270  result = target() < transition.target();
271  if(!result)
272  {
273  if(target() == transition.target())
274  {
275  result = event() < transition.event();
276  }
277  }
278  }
279  }
280  return result;
281  }
282 
286  Transition() = default;
287 
288 
293  Transition(Transition const& other) = default;
299  Transition& operator=(Transition const& other) = default;
304  Transition(Transition&& other) = default;
310  Transition& operator=(Transition&& other) = default;
314  ~Transition() = default;
315 
316 
317 
318 
319 
320 
321 
322 
323  };
324 
325  private:
326  size_t _nbStates;
327  std::set< Transition > _transitions;
328  std::set<State> _initials;
329 
330  public:
331 
332  using ConstTransitionIterator = typename std::set< Transition >::const_iterator;
333  using TransitionIterator = typename std::set< Transition >::iterator;
334  using ConstInitialIterator = typename std::set< State >::const_iterator;
335  using InitialIterator = typename std::set< State >::iterator;
336 
340  AutFileDescriptor() = default;
341 
346  AutFileDescriptor(AutFileDescriptor const& other) = default;
352  AutFileDescriptor& operator=(AutFileDescriptor const& other) = default;
357  AutFileDescriptor(AutFileDescriptor&& other) = default;
363  AutFileDescriptor& operator=(AutFileDescriptor&& other) = default;
367  virtual ~AutFileDescriptor() = default;
368 
376  virtual bool
377  readStream(std::istream& stream)
378  {
379  clear();
380  State initialState = 0;
381  size_t nbTransitions = 0;
382  _nbStates = 0;
383  bool ok = true;
384  autFileHeader(stream, initialState, nbTransitions, _nbStates, ok);
385  if(!ok)
386  {
387  std::cout << "autFileHeader pb\n";
388  return false;
389  }
390  setInitial(0);
391 
392  while(numberOfTransitions() != nbTransitions)
393  {
394  State source = 0;
395  Event label;
396  State target = 0;
397  autFileTransition(stream, source, label, target, ok);
398  if(!ok)
399  {
400  std::cout << "reading transition pb\n";
401  return false;
402  }
403 
404  if(source >= _nbStates)
405  {
406  std::cout << "source " << source << " >= " << _nbStates << " \n";
407  return false;
408  }
409  if(target >= _nbStates)
410  {
411  std::cout << "target " << target << " >= " << _nbStates << " \n";
412  return false;
413  }
414  addTransition(Transition(source, label, target));
415  }
416  return true;
417  }
418 
424  virtual bool
425  toStream(std::ostream& stream)
426  {
427  if(numberOfStates() == 0)
428  {
429  return false;
430  }
431  stream << "des(0," << numberOfTransitions() << "," << numberOfStates() << ")\n";
432  std::for_each(transBegin(), transEnd(),
433  [&](Transition t)
434  {
435  stream << "(" << t.source()
436  << ",";
437  MyPrintEvent()(stream, t.event());
438  stream << "," << t.target()
439  << ")\n";
440 
441 
442 
443 
444  });
445  return true;
446 
447 
448  }
449 
454  size_t
456  {
457  return _nbStates;
458  }
459 
465  size_t
466  setNumberOfStates(size_t nbStates)
467  {
468  return _nbStates = nbStates;
469  }
470 
475  size_t
477  {
478  return _transitions.size();
479  }
480 
486  transBegin() const
487  {
488  return _transitions.begin();
489  }
490 
496  transEnd() const
497  {
498  return _transitions.end();
499  }
500 
507  std::pair<AutFileDescriptor::TransitionIterator, bool>
508  addTransition(Transition && transition)
509  {
510  return _transitions.emplace(transition);
511  }
512 
521  removeTransition(const Transition & transition)
522  {
523  auto it = _transitions.find(transition);
524  if(it == _transitions.end())
525  {
526  return it;
527  }
528  return _transitions.erase(it);
529  }
530 
535  virtual void
537  {
538  _nbStates = 0;
539  _transitions.clear();
540  _initials.clear();
541  }
542 
548  initialBegin() const
549  {
550  return _initials.begin();
551  }
552 
558  initialEnd() const
559  {
560  return _initials.end();
561  }
562 
569  std::pair<InitialIterator, bool>
571  {
572  return _initials.insert(s);
573  }
574 
579  size_t
581  {
582  return _initials.size();
583  }
584 
588  void
590  {
591  _initials.clear();
592  }
593 
594  private:
595 
603  bool
604  autFileTransitionEvent(const std::string & betweenFirstAndLastComma,
605  Event & event)
606  {
607  std::stringstream sstreamLabel;
608  sstreamLabel << betweenFirstAndLastComma;
609  return MyReadEvent()(sstreamLabel, event);
610  }
611 
618  bool
619  autFileSourceState(const std::string & beforeFirstComma, State & source)
620  {
621  std::size_t index = 0;
622  while(std::isblank(beforeFirstComma.at(index)))
623  {
624  ++index;
625  }
626  if(beforeFirstComma.at(index) != '(')
627  {
628  std::cout << "autFileSourceState: no '(' \n";
629  return false;
630  }
631  ++index;
632  while(std::isblank(beforeFirstComma.at(index)))
633  {
634  ++index;
635  }
636  std::string sourceState;
637  if(!std::isdigit(beforeFirstComma.at(index)))
638  {
639  std::cout << "autFileSourceState: found character " << beforeFirstComma.at(index) << "\n";
640  std::cout << "autFileSourceState: no digit after '( ' \n";
641  return false;
642  }
643  while(index < beforeFirstComma.size() && (std::isdigit(beforeFirstComma.at(index))))
644  {
645  sourceState += beforeFirstComma.at(index);
646  ++index;
647  }
648  if(index < beforeFirstComma.size())
649  {
650  do
651  {
652  if(!std::isblank(beforeFirstComma.at(index)))
653  {
654  std::cout << "autFileSourceState: strange character after '( digits ' \n";
655  return false;
656  }
657  ++index;
658  }
659  while(index < beforeFirstComma.size());
660  }
661  std::stringstream sstream;
662  sstream << sourceState;
663  sstream >> source;
664  return true;
665  }
666 
673  bool
674  autFileTargetState(const std::string & afterLastComma, State & target)
675  {
676 
677  std::string targetState;
678  unsigned index = 0;
679  while(std::isblank(afterLastComma.at(index)))
680  {
681  ++index;
682  }
683  if(!std::isdigit(afterLastComma.at(index)))
684  {
685  std::cout << "autFileTargetState: no digit after blanks\n";
686  return false;
687  }
688  while(index < afterLastComma.size() && (std::isdigit(afterLastComma.at(index))))
689  {
690  targetState += afterLastComma.at(index);
691  ++index;
692  }
693  while(std::isblank(afterLastComma.at(index)))
694  {
695  ++index;
696  }
697  if(afterLastComma.at(index) != ')')
698  {
699  std::cout << "autFileTargetState: no ')'\n";
700  return false;
701  }
702  while(std::isblank(afterLastComma.at(index)))
703  {
704  ++index;
705  }
706  std::stringstream sstream;
707  sstream << targetState;
708  sstream >> target;
709  return true;
710  }
711 
722  std::istream &
723  autFileTransition(std::istream & stream,
724  State & source,
725  Event & event,
726  State & target,
727  bool & ok)
728  {
729  // transline: (<from-state>, <label>, <to-state>)
730  std::string transline;
731  ok = std::getline(stream, transline).good();
732  if(!ok)
733  {
734  std::cout << "autFileTransition: readline pb\n";
735  return stream;
736  }
737  std::size_t firstComma = transline.find_first_of(",");
738  ok = firstComma != std::string::npos;
739  if(!ok)
740  {
741  std::cout << "autFileTransition: no comma's\n";
742  return stream;
743  }
744  std::size_t lastComma = transline.find_last_of(",");
745  ok = firstComma != lastComma;
746  if(!ok)
747  {
748  std::cout << "autFileTransition: only one comma \n";
749  return stream;
750  }
751 
752  ok = autFileSourceState(transline.substr(0, firstComma), source);
753  if(!ok)
754  {
755  std::cout << "autFileTransition: reading source state\n";
756  return stream;
757  }
758 
759 
760  ok = autFileTransitionEvent(transline.substr(firstComma + 1, lastComma - firstComma - 1), event);
761  if(!ok)
762  {
763  std::cout << "autFileTransition: reading label\n";
764  return stream;
765  }
766 
767  ok = autFileTargetState(transline.substr(lastComma + 1), target);
768  if(!ok)
769  {
770  std::cout << "autFileTransition: reading target state\n";
771  return stream;
772  }
773 
774  return stream;
775  }
776 
793  std::istream &
794  autFileHeader(std::istream& stream,
795  State & initialState,
796  size_t & numberOfTransitions,
797  size_t & numberOfStates,
798  bool & ok)
799  {
800  // // see http://www.cplusplus.com/reference/regex/ECMAScript/
801  // std::regex des("^[[:blank:]]*des[[:blank:]]*\(");
802  // std::regex initState("[[:blank:]]*0 [[:blank:]]*,");
803  // std::regex nbTrans("[[:blank:]]*[[:digit:]]+ [[:blank:]]*,");
804  // std::regex nbStates("[[:blank:]]*[[:digit:]]+ [[:blank:]]*\)[[:blank:]]*$");
805  //
806 
807 
808  std::string headerLine;
809  std::getline(stream, headerLine);
810  std::stringstream stream2;
811  stream2 << headerLine;
812  char c = '\0';
813  ok = Diades::Utils::readChars(stream2,{' ', '\t'}, c);
814  if(!ok)
815  {
816  std::cout << "AutFileHeader: not reading ' character'\n";
817  return stream;
818  }
819  ok = (c == 'd');
820  ok = (stream2 >> c).good();
821  if(!ok)
822  {
823  std::cout << "AutFileHeader: not reading ' d'\n";
824  return stream;
825  }
826  ok = (c == 'e');
827  if(!ok)
828  {
829  std::cout << "AutFileHeader: not reading ' de'\n";
830  return stream;
831  }
832  ok = (stream2 >> c).good();
833  if(!ok)
834  {
835  return stream;
836  }
837  ok = (c == 's');
838  if(!ok)
839  {
840  std::cout << "AutFileHeader: not reading ' des'\n";
841  return stream;
842  }
843  ok = Diades::Utils::readChars(stream2,{' ', '\t'}, c);
844  if(!ok)
845  {
846  std::cout << "AutFileHeader: not reading ' des character'\n";
847  return stream;
848  }
849  ok = c == '(';
850  if(!ok)
851  {
852  std::cout << "AutFileHeader: not reading ' des ('\n";
853  return stream;
854  }
855  char comma1;
856  char comma2;
857  char rightParen;
858 
859  ok = (stream2 >> initialState).good();
860  if(!ok)
861  {
862  std::cout << "AutFileHeader: not reading ' des ( digit'\n";
863  return stream;
864  }
865  ok = Diades::Utils::readChars(stream2,{' ', '\t'}, comma1);
866  ok = (comma1 == ',');
867  if(!ok)
868  {
869  std::cout << "AutFileHeader: not reading ' des ( digit,'\n";
870  std::cout << "comma1 = " << comma1 << "\n";
871  return stream;
872  }
873 
874  ok = (stream2 >> numberOfTransitions).good();
875  if(!ok)
876  {
877  std::cout << "AutFileHeader: not reading ' des ( digit,digit'\n";
878  return stream;
879  }
880  ok = Diades::Utils::readChars(stream2,{' ', '\t'}, comma2);
881  ok = (comma2 == ',');
882  if(!ok)
883  {
884  std::cout << "AutFileHeader: not reading ' des ( digit,digit,'\n";
885  std::cout << "comma2 = " << comma2 << "\n";
886  return stream;
887  }
888  ok = (stream2 >> numberOfStates).good();
889  if(!ok)
890  {
891  std::cout << "AutFileHeader: not reading ' des ( digit,digit,digit'\n";
892  return stream;
893  }
894  ok = Diades::Utils::readChars(stream2,{' ', '\t'}, rightParen);
895  ok = (rightParen == ')');
896  if(!ok)
897  {
898  std::cout << "AutFileHeader: not reading ' des ( digit, digit, digit )'\n";
899  std::cout << "rightParen = " << rightParen << "\n";
900  return stream;
901  }
902  ok = !Diades::Utils::readChars(stream2,{' ', '\t'}, c);
903  if(!ok)
904  {
905  std::cout << "AutFileHeader: not reading ' des ( digit, digit, digit ) '\n";
906  std::cout << "AutFileHeader: found character " << c << "\n";
907  return stream;
908  }
909  ok = (initialState == 0) && (numberOfStates > 0);
910  if(!ok)
911  {
912  std::cout << "AutFileHeader: initialstate = "
913  << initialState
914  << " and "
915  << "numberOfStates = "
916  << numberOfStates
917  << "\n";
918  return stream;
919  }
920  return stream;
921  }
922  };
923 
924 
925  };
926  };
927 };
928 
929 #endif /* __DIADES__AUTOMATA__EXPERIMENTAL__AUTFILEDESCRIPTOR__HH__ */
930 
bool operator()(std::ostream &stream, const std::string &event) const
Diades::Graph::Edge Transition
Definition: Component.hh:46
bool autFileSourceState(const std::string &beforeFirstComma, State &source)
bool operator()(std::ostream &stream, const EventType &event) const
STL namespace.
std::istream & autFileTransition(std::istream &stream, State &source, Event &event, State &target, bool &ok)
TransitionIterator removeTransition(const Transition &transition)
bool autFileTargetState(const std::string &afterLastComma, State &target)
std::pair< InitialIterator, bool > setInitial(State s)
bool readLabel(std::basic_istream< CharT > &stream, std::basic_string< CharT, Traits, Alloc > &label)
Definition: Label.hh:279
bool operator()(std::istream &stream, EventType &event) const
Namespace of the Diades project.
bool autFileTransitionEvent(const std::string &betweenFirstAndLastComma, Event &event)
std::istream & autFileHeader(std::istream &stream, State &initialState, size_t &numberOfTransitions, size_t &numberOfStates, bool &ok)
virtual bool readStream(std::istream &stream)
bool isNull() const
Definition: Label.hh:50
typename std::set< State >::const_iterator ConstInitialIterator
std::pair< AutFileDescriptor::TransitionIterator, bool > addTransition(Transition &&transition)
bool readChars(std::basic_istream< CharT > &is, const std::unordered_set< CharT > &characters, CharT &next)
Definition: StreamTools.hh:27
bool operator()(std::istream &stream, std::string &evtLabel) const
typename std::set< Transition >::const_iterator ConstTransitionIterator