14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// fst-register.h 24a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// 34a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Licensed under the Apache License, Version 2.0 (the "License"); 44a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// you may not use this file except in compliance with the License. 54a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// You may obtain a copy of the License at 64a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// 74a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// http://www.apache.org/licenses/LICENSE-2.0 84a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// 94a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Unless required by applicable law or agreed to in writing, software 104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// distributed under the License is distributed on an "AS IS" BASIS, 114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// See the License for the specific language governing permissions and 134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// limitations under the License. 144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// 154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// 164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// \file 174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Classes for registering derived Fsts for generic reading 184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// 194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifndef FST_LIB_REGISTER_H__ 214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define FST_LIB_REGISTER_H__ 224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <map> 244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <dlfcn.h> 264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <pthread.h> 274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/compat.h" 294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectextern "C" { 314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project typedef void (*FstInitFunc)(); 324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectnamespace fst { 354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A> class Fst; 374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstruct FstReadOptions; 384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// This class holds the mapping from Fst name string to its reader 404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// and converter. 414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A> 424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectclass FstRegister { 434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project public: 444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project typedef Fst<A> *(*Reader)(istream &strm, const FstReadOptions &opts); 454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project typedef Fst<A> *(*Converter)(const Fst<A> &fst); 464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project struct Entry { 484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project Reader reader; 494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project Converter converter; 504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project Entry() : reader(0), converter(0) {} 514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project }; 524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project static FstRegister<A> *GetRegister() { 544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project pthread_once(®ister_init_, &FstRegister<A>::Init); 554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return register_; 564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project } 574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 5873018b4a1d088cdda0e7bd059fddf1f308a8195aIan Rogers Reader GetReader(const string &type) const { 594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return GetEntry(type).reader; 604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project } 614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 6273018b4a1d088cdda0e7bd059fddf1f308a8195aIan Rogers Converter GetConverter(const string &type) const { 634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return GetEntry(type).converter; 644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project } 654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project void SetEntry(const string &type, const Entry &entry) { 674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project MutexLock l(register_lock_); 684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project fst_table_.insert(make_pair(type, entry)); 694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project } 704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project private: 724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project static void Init() { 734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project register_lock_ = new Mutex; 744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project register_ = new FstRegister<A>; 754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project } 764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project Entry LookupEntry(const string &type) const { 784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project MutexLock l(register_lock_); 794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project typename map<string, Entry>::const_iterator it = fst_table_.find(type); 804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project if (it != fst_table_.end()) 814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return it->second; 824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project else 834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return Entry(); 844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project } 854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project Entry GetEntry(const string &type) const { 874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifdef FST_DL 884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project Entry entry = LookupEntry(type); 894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project if (entry.reader) 904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return entry; 914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project string so_file = type + "-fst.so"; 924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project void *handle = dlopen(so_file.c_str(), RTLD_LAZY); 934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project if (handle == 0) { 944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project LOG(ERROR) << "FstRegister::GetEntry: " << dlerror(); 954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return entry; 964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project } 974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project string init_name = type + "_fst_init"; 984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project FstInitFunc init_func = 994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project bit_cast<FstInitFunc>(dlsym(handle, init_name.c_str())); 1004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project if (init_func == 0) { 1014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project LOG(ERROR) << "FstRegister::GetEntry: " << dlerror(); 1024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return entry; 1034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project } 1044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project (*init_func)(); 1054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif // FST_DL 1064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return LookupEntry(type); 1074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project } 1084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project static pthread_once_t register_init_; // ensures only called once 1104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project static Mutex* register_lock_; // multithreading lock 1114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project static FstRegister<A> *register_; 1124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project map<string, Entry> fst_table_; 1144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}; 1154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A> 1174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectpthread_once_t FstRegister<A>::register_init_ = PTHREAD_ONCE_INIT; 1184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A> 1204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectMutex *FstRegister<A>::register_lock_ = 0; 1214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A> 1234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectFstRegister<A> *FstRegister<A>::register_ = 0; 1244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// This class registers an Fst type for generic reading and creating. 1264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// The Fst type must have a default constructor and a copy constructor 1274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// from 'Fst<Arc>' for this to work. 1284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class F> 1294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectclass FstRegisterer { 1304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project public: 1314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project typedef typename F::Arc Arc; 1324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project typedef typename FstRegister<Arc>::Entry Entry; 1334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project typedef typename FstRegister<Arc>::Reader Reader; 1344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project FstRegisterer() { 1364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project F fst; 1374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project F *(*reader)(istream &strm, 1384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project const FstReadOptions &opts) = &F::Read; 1394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project Entry entry; 1404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project entry.reader = reinterpret_cast<Reader>(reader); 1414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project entry.converter = &FstRegisterer<F>::Convert; 1424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project FstRegister<Arc> *registr = FstRegister<Arc>::GetRegister(); 1434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project registr->SetEntry(fst.Type(), entry); 1444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project } 1454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project private: 1474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project static Fst<Arc> *Convert(const Fst<Arc> &fst) { return new F(fst); } 1484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}; 1494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Convenience macro to generate static FstRegisterer instance. 1524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define REGISTER_FST(F, A) \ 1534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic fst::FstRegisterer< F<A> > F ## _ ## A ## _registerer 1544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Converts an fst to type 'type'. 1574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate <class A> 1584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectFst<A> *Convert(const Fst<A> &fst, const string &ftype) { 1594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project FstRegister<A> *registr = FstRegister<A>::GetRegister(); 1604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project const typename FstRegister<A>::Converter 1614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project converter = registr->GetConverter(ftype); 1624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project if (!converter) { 1634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project string atype = A::Type(); 1644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project LOG(ERROR) << "Fst::Convert: Unknown FST type \"" << ftype 1654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project << "\" (arc type = \"" << atype << "\")"; 1664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return 0; 1674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project } 1684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return converter(fst); 1694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 1704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} // namespace fst; 1724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif // FST_LIB_REGISTER_H__ 174