Home | History | Annotate | Download | only in fst
      1 // vector-fst.h
      2 
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 //
     15 // Copyright 2005-2010 Google, Inc.
     16 // Author: riley (at) google.com (Michael Riley)
     17 //
     18 // \file
     19 // Simple concrete, mutable FST whose states and arcs are stored in STL
     20 // vectors.
     21 
     22 #ifndef FST_LIB_VECTOR_FST_H__
     23 #define FST_LIB_VECTOR_FST_H__
     24 
     25 #include <string>
     26 #include <vector>
     27 using std::vector;
     28 
     29 #include <fst/mutable-fst.h>
     30 #include <fst/test-properties.h>
     31 
     32 
     33 namespace fst {
     34 
     35 template <class A> class VectorFst;
     36 template <class F, class G> void Cast(const F &, G *);
     37 
     38 
     39 // States and arcs implemented by STL vectors, templated on the
     40 // State definition. This does not manage the Fst properties.
     41 template <class State>
     42 class VectorFstBaseImpl : public FstImpl<typename State::Arc> {
     43  public:
     44   typedef typename State::Arc Arc;
     45   typedef typename Arc::Weight Weight;
     46   typedef typename Arc::StateId StateId;
     47 
     48   VectorFstBaseImpl() : start_(kNoStateId) {}
     49 
     50   ~VectorFstBaseImpl() {
     51     for (StateId s = 0; s < states_.size(); ++s)
     52       delete states_[s];
     53   }
     54 
     55   StateId Start() const { return start_; }
     56 
     57   Weight Final(StateId s) const { return states_[s]->final; }
     58 
     59   StateId NumStates() const { return states_.size(); }
     60 
     61   size_t NumArcs(StateId s) const { return states_[s]->arcs.size(); }
     62 
     63   void SetStart(StateId s) { start_ = s; }
     64 
     65   void SetFinal(StateId s, Weight w) { states_[s]->final = w; }
     66 
     67   StateId AddState() {
     68     states_.push_back(new State);
     69     return states_.size() - 1;
     70   }
     71 
     72   StateId AddState(State *state) {
     73     states_.push_back(state);
     74     return states_.size() - 1;
     75   }
     76 
     77   void AddArc(StateId s, const Arc &arc) {
     78     states_[s]->arcs.push_back(arc);
     79   }
     80 
     81   void DeleteStates(const vector<StateId>& dstates) {
     82     vector<StateId> newid(states_.size(), 0);
     83     for (size_t i = 0; i < dstates.size(); ++i)
     84       newid[dstates[i]] = kNoStateId;
     85     StateId nstates = 0;
     86     for (StateId s = 0; s < states_.size(); ++s) {
     87       if (newid[s] != kNoStateId) {
     88         newid[s] = nstates;
     89         if (s != nstates)
     90           states_[nstates] = states_[s];
     91         ++nstates;
     92       } else {
     93         delete states_[s];
     94       }
     95     }
     96     states_.resize(nstates);
     97     for (StateId s = 0; s < states_.size(); ++s) {
     98       vector<Arc> &arcs = states_[s]->arcs;
     99       size_t narcs = 0;
    100       for (size_t i = 0; i < arcs.size(); ++i) {
    101         StateId t = newid[arcs[i].nextstate];
    102         if (t != kNoStateId) {
    103           arcs[i].nextstate = t;
    104           if (i != narcs)
    105             arcs[narcs] = arcs[i];
    106           ++narcs;
    107         } else {
    108           if (arcs[i].ilabel == 0)
    109             --states_[s]->niepsilons;
    110           if (arcs[i].olabel == 0)
    111             --states_[s]->noepsilons;
    112         }
    113       }
    114       arcs.resize(narcs);
    115     }
    116     if (Start() != kNoStateId)
    117       SetStart(newid[Start()]);
    118   }
    119 
    120   void DeleteStates() {
    121     for (StateId s = 0; s < states_.size(); ++s)
    122       delete states_[s];
    123     states_.clear();
    124     SetStart(kNoStateId);
    125   }
    126 
    127   void DeleteArcs(StateId s, size_t n) {
    128     states_[s]->arcs.resize(states_[s]->arcs.size() - n);
    129   }
    130 
    131   void DeleteArcs(StateId s) { states_[s]->arcs.clear(); }
    132 
    133   State *GetState(StateId s) { return states_[s]; }
    134 
    135   const State *GetState(StateId s) const { return states_[s]; }
    136 
    137   void SetState(StateId s, State *state) { states_[s] = state; }
    138 
    139   void ReserveStates(StateId n) { states_.reserve(n); }
    140 
    141   void ReserveArcs(StateId s, size_t n) { states_[s]->arcs.reserve(n); }
    142 
    143   // Provide information needed for generic state iterator
    144   void InitStateIterator(StateIteratorData<Arc> *data) const {
    145     data->base = 0;
    146     data->nstates = states_.size();
    147   }
    148 
    149   // Provide information needed for generic arc iterator
    150   void InitArcIterator(StateId s, ArcIteratorData<Arc> *data) const {
    151     data->base = 0;
    152     data->narcs = states_[s]->arcs.size();
    153     data->arcs = data->narcs > 0 ? &states_[s]->arcs[0] : 0;
    154     data->ref_count = 0;
    155   }
    156 
    157  private:
    158   vector<State *> states_;      // States represenation.
    159   StateId start_;               // initial state
    160 
    161   DISALLOW_COPY_AND_ASSIGN(VectorFstBaseImpl);
    162 };
    163 
    164 // Arcs implemented by an STL vector per state.
    165 template <class A>
    166 struct VectorState {
    167   typedef A Arc;
    168   typedef typename A::Weight Weight;
    169   typedef typename A::StateId StateId;
    170 
    171   VectorState() : final(Weight::Zero()), niepsilons(0), noepsilons(0) {}
    172 
    173   Weight final;              // Final weight
    174   vector<A> arcs;            // Arcs represenation
    175   size_t niepsilons;         // # of input epsilons
    176   size_t noepsilons;         // # of output epsilons
    177 };
    178 
    179 // This is a VectorFstBaseImpl container that holds VectorState's.  It
    180 // manages Fst properties and the # of input and output epsilons.
    181 template <class A>
    182 class VectorFstImpl : public VectorFstBaseImpl< VectorState<A> > {
    183  public:
    184   using FstImpl<A>::SetInputSymbols;
    185   using FstImpl<A>::SetOutputSymbols;
    186   using FstImpl<A>::SetType;
    187   using FstImpl<A>::SetProperties;
    188   using FstImpl<A>::Properties;
    189 
    190   using VectorFstBaseImpl<VectorState<A> >::Start;
    191   using VectorFstBaseImpl<VectorState<A> >::NumStates;
    192   using VectorFstBaseImpl<VectorState<A> >::GetState;
    193   using VectorFstBaseImpl<VectorState<A> >::ReserveArcs;
    194 
    195   friend class MutableArcIterator< VectorFst<A> >;
    196 
    197   typedef VectorFstBaseImpl< VectorState<A> > BaseImpl;
    198   typedef typename A::Weight Weight;
    199   typedef typename A::StateId StateId;
    200 
    201   VectorFstImpl() {
    202     SetType("vector");
    203     SetProperties(kNullProperties | kStaticProperties);
    204   }
    205   explicit VectorFstImpl(const Fst<A> &fst);
    206 
    207   static VectorFstImpl<A> *Read(istream &strm, const FstReadOptions &opts);
    208 
    209   size_t NumInputEpsilons(StateId s) const { return GetState(s)->niepsilons; }
    210 
    211   size_t NumOutputEpsilons(StateId s) const { return GetState(s)->noepsilons; }
    212 
    213   void SetStart(StateId s) {
    214     BaseImpl::SetStart(s);
    215     SetProperties(SetStartProperties(Properties()));
    216   }
    217 
    218   void SetFinal(StateId s, Weight w) {
    219     Weight ow = BaseImpl::Final(s);
    220     BaseImpl::SetFinal(s, w);
    221     SetProperties(SetFinalProperties(Properties(), ow, w));
    222   }
    223 
    224   StateId AddState() {
    225     StateId s = BaseImpl::AddState();
    226     SetProperties(AddStateProperties(Properties()));
    227     return s;
    228   }
    229 
    230   void AddArc(StateId s, const A &arc) {
    231     VectorState<A> *state = GetState(s);
    232     if (arc.ilabel == 0) {
    233       ++state->niepsilons;
    234     }
    235     if (arc.olabel == 0) {
    236       ++state->noepsilons;
    237     }
    238 
    239     const A *parc = state->arcs.empty() ? 0 : &(state->arcs.back());
    240     SetProperties(AddArcProperties(Properties(), s, arc, parc));
    241 
    242     BaseImpl::AddArc(s, arc);
    243   }
    244 
    245   void DeleteStates(const vector<StateId> &dstates) {
    246     BaseImpl::DeleteStates(dstates);
    247     SetProperties(DeleteStatesProperties(Properties()));
    248   }
    249 
    250   void DeleteStates() {
    251     BaseImpl::DeleteStates();
    252     SetProperties(DeleteAllStatesProperties(Properties(),
    253                                             kStaticProperties));
    254   }
    255 
    256   void DeleteArcs(StateId s, size_t n) {
    257     const vector<A> &arcs = GetState(s)->arcs;
    258     for (size_t i = 0; i < n; ++i) {
    259       size_t j = arcs.size() - i - 1;
    260       if (arcs[j].ilabel == 0)
    261         --GetState(s)->niepsilons;
    262       if (arcs[j].olabel == 0)
    263         --GetState(s)->noepsilons;
    264     }
    265     BaseImpl::DeleteArcs(s, n);
    266     SetProperties(DeleteArcsProperties(Properties()));
    267   }
    268 
    269   void DeleteArcs(StateId s) {
    270     GetState(s)->niepsilons = 0;
    271     GetState(s)->noepsilons = 0;
    272     BaseImpl::DeleteArcs(s);
    273     SetProperties(DeleteArcsProperties(Properties()));
    274   }
    275 
    276   // Properties always true of this Fst class
    277   static const uint64 kStaticProperties = kExpanded | kMutable;
    278 
    279  private:
    280   // Current file format version
    281   static const int kFileVersion = 2;
    282   // Minimum file format version supported
    283   static const int kMinFileVersion = 1;
    284 
    285   DISALLOW_COPY_AND_ASSIGN(VectorFstImpl);
    286 };
    287 
    288 template <class A> const uint64 VectorFstImpl<A>::kStaticProperties;
    289 template <class A> const int VectorFstImpl<A>::kFileVersion;
    290 template <class A> const int VectorFstImpl<A>::kMinFileVersion;
    291 
    292 
    293 template <class A>
    294 VectorFstImpl<A>::VectorFstImpl(const Fst<A> &fst) {
    295   SetType("vector");
    296   SetInputSymbols(fst.InputSymbols());
    297   SetOutputSymbols(fst.OutputSymbols());
    298   BaseImpl::SetStart(fst.Start());
    299   if (fst.Properties(kExpanded, false))
    300     BaseImpl::ReserveStates(CountStates(fst));
    301 
    302   for (StateIterator< Fst<A> > siter(fst);
    303        !siter.Done();
    304        siter.Next()) {
    305     StateId s = siter.Value();
    306     BaseImpl::AddState();
    307     BaseImpl::SetFinal(s, fst.Final(s));
    308     ReserveArcs(s, fst.NumArcs(s));
    309     for (ArcIterator< Fst<A> > aiter(fst, s);
    310          !aiter.Done();
    311          aiter.Next()) {
    312       const A &arc = aiter.Value();
    313       BaseImpl::AddArc(s, arc);
    314       if (arc.ilabel == 0)
    315         ++GetState(s)->niepsilons;
    316       if (arc.olabel == 0)
    317         ++GetState(s)->noepsilons;
    318     }
    319   }
    320   SetProperties(fst.Properties(kCopyProperties, false) | kStaticProperties);
    321 }
    322 
    323 template <class A>
    324 VectorFstImpl<A> *VectorFstImpl<A>::Read(istream &strm,
    325                                          const FstReadOptions &opts) {
    326   VectorFstImpl<A> *impl = new VectorFstImpl;
    327   FstHeader hdr;
    328   if (!impl->ReadHeader(strm, opts, kMinFileVersion, &hdr)) {
    329     delete impl;
    330     return 0;
    331   }
    332   impl->BaseImpl::SetStart(hdr.Start());
    333   if (hdr.NumStates() != kNoStateId) {
    334     impl->ReserveStates(hdr.NumStates());
    335   }
    336 
    337   StateId s = 0;
    338   for (;hdr.NumStates() == kNoStateId || s < hdr.NumStates(); ++s) {
    339     typename A::Weight final;
    340     if (!final.Read(strm)) break;
    341     impl->BaseImpl::AddState();
    342     VectorState<A> *state = impl->GetState(s);
    343     state->final = final;
    344     int64 narcs;
    345     ReadType(strm, &narcs);
    346     if (!strm) {
    347       LOG(ERROR) << "VectorFst::Read: read failed: " << opts.source;
    348       delete impl;
    349       return 0;
    350     }
    351     impl->ReserveArcs(s, narcs);
    352     for (size_t j = 0; j < narcs; ++j) {
    353       A arc;
    354       ReadType(strm, &arc.ilabel);
    355       ReadType(strm, &arc.olabel);
    356       arc.weight.Read(strm);
    357        ReadType(strm, &arc.nextstate);
    358        if (!strm) {
    359         LOG(ERROR) << "VectorFst::Read: read failed: " << opts.source;
    360         delete impl;
    361         return 0;
    362       }
    363       impl->BaseImpl::AddArc(s, arc);
    364       if (arc.ilabel == 0)
    365         ++state->niepsilons;
    366       if (arc.olabel == 0)
    367         ++state->noepsilons;
    368     }
    369   }
    370   if (hdr.NumStates() != kNoStateId && s != hdr.NumStates()) {
    371     LOG(ERROR) << "VectorFst::Read: unexpected end of file: " << opts.source;
    372     delete impl;
    373     return 0;
    374   }
    375   return impl;
    376 }
    377 
    378 // Converts a string into a weight.
    379 template <class W> class WeightFromString {
    380  public:
    381   W operator()(const string &s);
    382 };
    383 
    384 // Generic case fails.
    385 template <class W> inline
    386 W WeightFromString<W>::operator()(const string &s) {
    387   FSTERROR() << "VectorFst::Read: Obsolete file format";
    388   return W::NoWeight();
    389 }
    390 
    391 // TropicalWeight version.
    392 template <> inline
    393 TropicalWeight WeightFromString<TropicalWeight>::operator()(const string &s) {
    394   float f;
    395   memcpy(&f, s.data(), sizeof(f));
    396   return TropicalWeight(f);
    397 }
    398 
    399 // LogWeight version.
    400 template <> inline
    401 LogWeight WeightFromString<LogWeight>::operator()(const string &s) {
    402   float f;
    403   memcpy(&f, s.data(), sizeof(f));
    404   return LogWeight(f);
    405 }
    406 
    407 // Simple concrete, mutable FST. This class attaches interface to
    408 // implementation and handles reference counting, delegating most
    409 // methods to ImplToMutableFst. Supports additional operations:
    410 // ReserveStates and ReserveArcs (cf. STL vectors).
    411 template <class A>
    412 class VectorFst : public ImplToMutableFst< VectorFstImpl<A> > {
    413  public:
    414   friend class StateIterator< VectorFst<A> >;
    415   friend class ArcIterator< VectorFst<A> >;
    416   friend class MutableArcIterator< VectorFst<A> >;
    417   template <class F, class G> friend void Cast(const F &, G *);
    418 
    419   typedef A Arc;
    420   typedef typename A::StateId StateId;
    421   typedef VectorFstImpl<A> Impl;
    422 
    423   VectorFst() : ImplToMutableFst<Impl>(new Impl) {}
    424 
    425   explicit VectorFst(const Fst<A> &fst)
    426       : ImplToMutableFst<Impl>(new Impl(fst)) {}
    427 
    428   VectorFst(const VectorFst<A> &fst) : ImplToMutableFst<Impl>(fst) {}
    429 
    430   // Get a copy of this VectorFst. See Fst<>::Copy() for further doc.
    431   virtual VectorFst<A> *Copy(bool safe = false) const {
    432     return new VectorFst<A>(*this);
    433   }
    434 
    435   VectorFst<A> &operator=(const VectorFst<A> &fst) {
    436     SetImpl(fst.GetImpl(), false);
    437     return *this;
    438   }
    439 
    440   virtual VectorFst<A> &operator=(const Fst<A> &fst) {
    441     if (this != &fst) SetImpl(new Impl(fst));
    442     return *this;
    443   }
    444 
    445   // Read a VectorFst from an input stream; return NULL on error
    446   static VectorFst<A> *Read(istream &strm, const FstReadOptions &opts) {
    447     Impl* impl = Impl::Read(strm, opts);
    448     return impl ? new VectorFst<A>(impl) : 0;
    449   }
    450 
    451   // Read a VectorFst from a file; return NULL on error
    452   // Empty filename reads from standard input
    453   static VectorFst<A> *Read(const string &filename) {
    454     Impl* impl = ImplToExpandedFst<Impl, MutableFst<A> >::Read(filename);
    455     return impl ? new VectorFst<A>(impl) : 0;
    456   }
    457 
    458   virtual bool Write(ostream &strm, const FstWriteOptions &opts) const {
    459     return WriteFst(*this, strm, opts);
    460   }
    461 
    462   virtual bool Write(const string &filename) const {
    463     return Fst<A>::WriteFile(filename);
    464   }
    465 
    466   template <class F>
    467   static bool WriteFst(const F &fst, ostream &strm,
    468                        const FstWriteOptions &opts);
    469 
    470   void ReserveStates(StateId n) {
    471     MutateCheck();
    472     GetImpl()->ReserveStates(n);
    473   }
    474 
    475   void ReserveArcs(StateId s, size_t n) {
    476     MutateCheck();
    477     GetImpl()->ReserveArcs(s, n);
    478   }
    479 
    480   virtual void InitStateIterator(StateIteratorData<Arc> *data) const {
    481     GetImpl()->InitStateIterator(data);
    482   }
    483 
    484   virtual void InitArcIterator(StateId s, ArcIteratorData<Arc> *data) const {
    485     GetImpl()->InitArcIterator(s, data);
    486   }
    487 
    488   virtual inline
    489   void InitMutableArcIterator(StateId s, MutableArcIteratorData<A> *);
    490 
    491  private:
    492   explicit VectorFst(Impl *impl) : ImplToMutableFst<Impl>(impl) {}
    493 
    494   // Makes visible to friends.
    495   Impl *GetImpl() const { return ImplToFst< Impl, MutableFst<A> >::GetImpl(); }
    496 
    497   void SetImpl(Impl *impl, bool own_impl = true) {
    498     ImplToFst< Impl, MutableFst<A> >::SetImpl(impl, own_impl);
    499   }
    500 
    501   void MutateCheck() { return ImplToMutableFst<Impl>::MutateCheck(); }
    502 };
    503 
    504 // Specialization for VectorFst; see generic version in fst.h
    505 // for sample usage (but use the VectorFst type!). This version
    506 // should inline.
    507 template <class A>
    508 class StateIterator< VectorFst<A> > {
    509  public:
    510   typedef typename A::StateId StateId;
    511 
    512   explicit StateIterator(const VectorFst<A> &fst)
    513       : nstates_(fst.GetImpl()->NumStates()), s_(0) {}
    514 
    515   bool Done() const { return s_ >= nstates_; }
    516 
    517   StateId Value() const { return s_; }
    518 
    519   void Next() { ++s_; }
    520 
    521   void Reset() { s_ = 0; }
    522 
    523  private:
    524   StateId nstates_;
    525   StateId s_;
    526 
    527   DISALLOW_COPY_AND_ASSIGN(StateIterator);
    528 };
    529 
    530 // Writes Fst to file, will call CountStates so may involve two passes if
    531 // called from an Fst that is not derived from Expanded.
    532 template <class A>
    533 template <class F>
    534 bool VectorFst<A>::WriteFst(const F &fst, ostream &strm,
    535                             const FstWriteOptions &opts) {
    536   static const int kFileVersion = 2;
    537   bool update_header = true;
    538   FstHeader hdr;
    539   hdr.SetStart(fst.Start());
    540   hdr.SetNumStates(kNoStateId);
    541   size_t start_offset = 0;
    542   if (fst.Properties(kExpanded, false) || (start_offset = strm.tellp()) != -1) {
    543     hdr.SetNumStates(CountStates(fst));
    544     update_header = false;
    545   }
    546   uint64 properties = fst.Properties(kCopyProperties, false) |
    547       VectorFstImpl<A>::kStaticProperties;
    548   FstImpl<A>::WriteFstHeader(fst, strm, opts, kFileVersion, "vector",
    549                              properties, &hdr);
    550   StateId num_states = 0;
    551   for (StateIterator<F> siter(fst); !siter.Done(); siter.Next()) {
    552     typename A::StateId s = siter.Value();
    553     fst.Final(s).Write(strm);
    554     int64 narcs = fst.NumArcs(s);
    555     WriteType(strm, narcs);
    556     for (ArcIterator<F> aiter(fst, s); !aiter.Done(); aiter.Next()) {
    557       const A &arc = aiter.Value();
    558       WriteType(strm, arc.ilabel);
    559       WriteType(strm, arc.olabel);
    560       arc.weight.Write(strm);
    561       WriteType(strm, arc.nextstate);
    562     }
    563     num_states++;
    564   }
    565   strm.flush();
    566   if (!strm) {
    567     LOG(ERROR) << "VectorFst::Write: write failed: " << opts.source;
    568     return false;
    569   }
    570   if (update_header) {
    571     hdr.SetNumStates(num_states);
    572     return FstImpl<A>::UpdateFstHeader(fst, strm, opts, kFileVersion, "vector",
    573                                        properties, &hdr, start_offset);
    574   } else {
    575     if (num_states != hdr.NumStates()) {
    576       LOG(ERROR) << "Inconsistent number of states observed during write";
    577       return false;
    578     }
    579   }
    580   return true;
    581 }
    582 
    583 // Specialization for VectorFst; see generic version in fst.h
    584 // for sample usage (but use the VectorFst type!). This version
    585 // should inline.
    586 template <class A>
    587 class ArcIterator< VectorFst<A> > {
    588  public:
    589   typedef typename A::StateId StateId;
    590 
    591   ArcIterator(const VectorFst<A> &fst, StateId s)
    592       : arcs_(fst.GetImpl()->GetState(s)->arcs), i_(0) {}
    593 
    594   bool Done() const { return i_ >= arcs_.size(); }
    595 
    596   const A& Value() const { return arcs_[i_]; }
    597 
    598   void Next() { ++i_; }
    599 
    600   void Reset() { i_ = 0; }
    601 
    602   void Seek(size_t a) { i_ = a; }
    603 
    604   size_t Position() const { return i_; }
    605 
    606   uint32 Flags() const {
    607     return kArcValueFlags;
    608   }
    609 
    610   void SetFlags(uint32 f, uint32 m) {}
    611 
    612  private:
    613   const vector<A>& arcs_;
    614   size_t i_;
    615 
    616   DISALLOW_COPY_AND_ASSIGN(ArcIterator);
    617 };
    618 
    619 // Specialization for VectorFst; see generic version in fst.h
    620 // for sample usage (but use the VectorFst type!). This version
    621 // should inline.
    622 template <class A>
    623 class MutableArcIterator< VectorFst<A> >
    624   : public MutableArcIteratorBase<A> {
    625  public:
    626   typedef typename A::StateId StateId;
    627   typedef typename A::Weight Weight;
    628 
    629   MutableArcIterator(VectorFst<A> *fst, StateId s) : i_(0) {
    630     fst->MutateCheck();
    631     state_ = fst->GetImpl()->GetState(s);
    632     properties_ = &fst->GetImpl()->properties_;
    633   }
    634 
    635   bool Done() const { return i_ >= state_->arcs.size(); }
    636 
    637   const A& Value() const { return state_->arcs[i_]; }
    638 
    639   void Next() { ++i_; }
    640 
    641   size_t Position() const { return i_; }
    642 
    643   void Reset() { i_ = 0; }
    644 
    645   void Seek(size_t a) { i_ = a; }
    646 
    647   void SetValue(const A &arc) {
    648     A& oarc = state_->arcs[i_];
    649     if (oarc.ilabel != oarc.olabel)
    650       *properties_ &= ~kNotAcceptor;
    651     if (oarc.ilabel == 0) {
    652       --state_->niepsilons;
    653       *properties_ &= ~kIEpsilons;
    654       if (oarc.olabel == 0)
    655         *properties_ &= ~kEpsilons;
    656     }
    657     if (oarc.olabel == 0) {
    658       --state_->noepsilons;
    659       *properties_ &= ~kOEpsilons;
    660     }
    661     if (oarc.weight != Weight::Zero() && oarc.weight != Weight::One())
    662       *properties_ &= ~kWeighted;
    663     oarc = arc;
    664     if (arc.ilabel != arc.olabel) {
    665       *properties_ |= kNotAcceptor;
    666       *properties_ &= ~kAcceptor;
    667     }
    668     if (arc.ilabel == 0) {
    669       ++state_->niepsilons;
    670       *properties_ |= kIEpsilons;
    671       *properties_ &= ~kNoIEpsilons;
    672       if (arc.olabel == 0) {
    673         *properties_ |= kEpsilons;
    674         *properties_ &= ~kNoEpsilons;
    675       }
    676     }
    677     if (arc.olabel == 0) {
    678       ++state_->noepsilons;
    679       *properties_ |= kOEpsilons;
    680       *properties_ &= ~kNoOEpsilons;
    681     }
    682     if (arc.weight != Weight::Zero() && arc.weight != Weight::One()) {
    683       *properties_ |= kWeighted;
    684       *properties_ &= ~kUnweighted;
    685     }
    686     *properties_ &= kSetArcProperties | kAcceptor | kNotAcceptor |
    687         kEpsilons | kNoEpsilons | kIEpsilons | kNoIEpsilons |
    688         kOEpsilons | kNoOEpsilons | kWeighted | kUnweighted;
    689   }
    690 
    691   uint32 Flags() const {
    692     return kArcValueFlags;
    693   }
    694 
    695   void SetFlags(uint32 f, uint32 m) {}
    696 
    697 
    698  private:
    699   // This allows base-class virtual access to non-virtual derived-
    700   // class members of the same name. It makes the derived class more
    701   // efficient to use but unsafe to further derive.
    702   virtual bool Done_() const { return Done(); }
    703   virtual const A& Value_() const { return Value(); }
    704   virtual void Next_() { Next(); }
    705   virtual size_t Position_() const { return Position(); }
    706   virtual void Reset_() { Reset(); }
    707   virtual void Seek_(size_t a) { Seek(a); }
    708   virtual void SetValue_(const A &a) { SetValue(a); }
    709   uint32 Flags_() const { return Flags(); }
    710   void SetFlags_(uint32 f, uint32 m) { SetFlags(f, m); }
    711 
    712   struct VectorState<A> *state_;
    713   uint64 *properties_;
    714   size_t i_;
    715 
    716   DISALLOW_COPY_AND_ASSIGN(MutableArcIterator);
    717 };
    718 
    719 // Provide information needed for the generic mutable arc iterator
    720 template <class A> inline
    721 void VectorFst<A>::InitMutableArcIterator(
    722     StateId s, MutableArcIteratorData<A> *data) {
    723   data->base = new MutableArcIterator< VectorFst<A> >(this, s);
    724 }
    725 
    726 // A useful alias when using StdArc.
    727 typedef VectorFst<StdArc> StdVectorFst;
    728 
    729 }  // namespace fst
    730 
    731 #endif  // FST_LIB_VECTOR_FST_H__
    732