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