Writing - some reformulations.
[fic.git] / modules.cpp
blobe2ba5c3bce4199bf340a0882614e09e2e3d86a6a
1 #include "interfaces.h"
3 #include "modules/root.h"
4 #include "modules/colorModel.h"
5 #include "modules/squarePixels.h"
6 #include "modules/quadTree.h"
7 #include "modules/stdDomains.h"
8 #include "modules/quality2SE.h"
9 #include "modules/stdEncoder.h"
10 #include "modules/vliCodec.h"
11 #include "modules/saupePredictor.h"
12 #include "modules/noPredictor.h"
14 #include "util.h"
15 #include "fileUtil.h"
17 #include "FerrisLoki/DataGenerators.h"
19 using namespace std;
21 typedef Loki::TL::MakeTypelist< MRoot, MColorModel, MSquarePixels, MQuadTree, MStdDomains
22 , MQuality2SE_std, MStandardEncoder, MDifferentialVLICodec, MSaupePredictor, NoPredictor
23 , MQuality2SE_alt >
24 ::Result Modules;
26 const int powers[31]= { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2*1024 /* 2^11 */
27 , 4*1024, 8*1024, 16*1024, 32*1024, 64*1024, 128*1024, 256*1024, 512*1024 /* 2^19 */
28 , 1024*1024, 2*1024*1024, 4*1024*1024, 8*1024*1024, 16*1024*1024, 32*1024*1024 /* 2^25 */
29 , 64*1024*1024, 128*1024*1024, 256*1024*1024, 512*1024*1024, 1024*1024*1024 }; /* 2^30 */
32 const bool UpdateInfo::noTerminate;
33 const UpdateInfo UpdateInfo::none= UpdateInfo
34 ( UpdateInfo::noTerminate, &UpdateInfo::emptyFunction, &UpdateInfo::emptyFunction );
37 namespace NOSPACE {
38 using namespace Loki;
39 using namespace Loki::TL;
41 /** Compatible<TypeList,Iface> struct template - leaves in the TypeList only derivates
42 * of Iface class parameter - used by Inteface<Iface>, hidden for others */
43 template <class Typelist,class Interface>
44 struct Compatible;
46 template <class Iface>
47 struct Compatible<NullType,Iface> {
48 typedef NullType Result;
51 template <class Head,class Tail,class Iface>
52 struct Compatible< Typelist<Head,Tail> , Iface > {
53 typedef typename Select
54 <SuperSubclass<Iface,Head>::value
55 ,Typelist< Head , typename Compatible<Tail,Iface>::Result >
56 ,typename Compatible<Tail,Iface>::Result
57 >::Result Result;
60 template <class T> struct ExtractId {
61 int operator()() const
62 { return Loki::TL::IndexOf<Modules,T>::value; }
65 template<class Iface> const vector<int>& Interface<Iface>::getCompMods() {
66 using namespace Loki::TL;
67 typedef typename Compatible<Modules,Iface>::Result CompList;
68 // if compMods_ vector is empty, create it and fill it
69 if ( compMods_.empty() && Length<CompList>::value ) {
70 compMods_.reserve(Length<CompList>::value);
71 IterateTypes<CompList,ExtractId> gendata;
72 gendata( back_inserter(compMods_) );
74 return compMods_;
76 template <class Iface> std::vector<int> Interface<Iface>::compMods_;
79 //// Module class members
80 const Module::SettingTypeItem Module::SettingTypeItem
81 ::stopper= { 0, 0, {Stop,{i:-1},{text:0}} };
83 Module::SettingItem* Module::copySettings(CloneMethod method) const {
84 ASSERT( method==DeepCopy || method==ShallowCopy );
85 // copy the settings array
86 int length= info().setLength;
87 if (!length)
88 return 0;
89 SettingItem *result= new SettingItem[length];
90 copy( settings, settings+length, result );
92 SettingItem *item= result, *itemEnd= result+length;
93 if (method==DeepCopy)
94 // make child modules copy themselves (deeply again)
95 while (item!=itemEnd) {
96 if (item->m)
97 item->m= item->m->abstractClone(DeepCopy);
98 ++item;
100 else // ShallowCopy
101 // null module links
102 while (item!=itemEnd) {
103 item->m= 0;
104 ++item;
107 return result;
109 void Module::initDefaultModuleLinks() {
110 // iterate over all settings
111 const SettingTypeItem *setType= info().setType;
112 for (int i=0; setType[i].type.type!=Stop; ++i )
113 if (setType[i].type.type==ModuleCombo) {
114 // it is a module link -> initialize it with the right prototype
115 ASSERT(!settings[i].m);
116 settings[i].m= constCast(&ModuleFactory::prototype(
117 (*setType[i].type.data.compatIDs)[settings[i].val.i]
121 void Module::nullModuleLinks() {
122 // iterate over all settings
123 SettingItem *itEnd= settings+info().setLength;
124 for (SettingItem *it=settings; it!=itEnd; ++it)
125 it->m= 0;
127 template<class M> M* Module::concreteClone(CloneMethod method) const {
128 ASSERT( this && info().id == ModuleFactory::getModuleID<M>() );
129 // create a new instance of the same type and fill its settings with a copy of mine
130 M *result= new M;
131 result->settings= copySettings(method);
132 return result;
135 void Module::createDefaultSettings() {
136 ASSERT(!settings);
137 const TypeInfo &inf= info();
138 settings= new SettingItem[inf.setLength];
139 copy( inf.setType, inf.setType+inf.setLength, settings );
142 void Module::file_saveModuleType( ostream &os, int which ) {
143 // do some assertions - we expect to have the child module, etc.
144 ASSERT( which>=0 && which<info().setLength );
145 SettingItem &setItem= settings[which];
146 ASSERT( info().setType[which].type.type==ModuleCombo && setItem.m );
147 // put the module's identifier
148 put<Uchar>( os, setItem.m->info().id );
150 void Module::file_loadModuleType( istream &is, int which ) {
151 // do some assertions - we expect not to have the child module, etc.
152 ASSERT( which>=0 && which<info().setLength );
153 const SettingTypeItem &setType= info().setType[which];
154 SettingItem &setItem= settings[which];
155 ASSERT( setType.type.type==ModuleCombo && !setItem.m );
156 // get module identifier and check its existence
157 int newId= get<Uchar>(is);
158 checkThrow( 0<=newId && newId<Loki::TL::Length<Modules>::value );
159 // check module compatibility
160 const vector<int> &v= *setType.type.data.compatIDs;
161 settings[which].val.i= find(v.begin(),v.end(),newId) - v.begin();
162 checkThrow( settings[which].val.i < (int)v.size() );
163 // create a new correct empty module
164 setItem.m= ModuleFactory::newModule(newId,ShallowCopy);
167 void Module::file_saveAllSettings(std::ostream &stream) {
168 int setLength= info().setLength;
169 if (!setLength)
170 return;
171 else
172 ASSERT( settings && setLength>0 );
174 const SettingTypeItem *setType= info().setType;
175 for (int i=0; i<setLength; ++i)
176 switch(setType[i].type.type) {
177 case Int:
178 case IntLog2:
179 case Combo:
180 put<Uint32>( stream, settings[i].val.i );
181 break;
182 case Float:
183 put<float>( stream, settings[i].val.f );
184 break;
185 case ModuleCombo:
186 file_saveModuleType( stream, i );
187 settings[i].m->file_saveAllSettings(stream);
188 break;
189 default:
190 ASSERT(false);
191 } // switch
194 void Module::file_loadAllSettings(std::istream &stream) {
195 int setLength= info().setLength;
196 ASSERT(setLength>=0);
197 if (!setLength)
198 return;
199 if (!settings)
200 settings= new SettingItem[setLength];
202 const SettingTypeItem *setType= info().setType;
203 for (int i=0; i<setLength; ++i)
204 switch(setType[i].type.type) {
205 case Int:
206 case IntLog2:
207 case Combo:
208 settings[i].val.i= get<Uint32>(stream);
209 break;
210 case Float:
211 settings[i].val.f= get<float>(stream);
212 break;
213 case ModuleCombo:
214 file_loadModuleType( stream, i );
215 settings[i].m->file_loadAllSettings(stream);
216 break;
217 default:
218 ASSERT(false);
219 } // switch
222 //// ModuleFactory class members
223 ModuleFactory* ModuleFactory::instance=0;
225 template<class M> int ModuleFactory::getModuleID()
226 { return Loki::TL::IndexOf<Modules,M>::value; }
229 void ModuleFactory::initialize() {
230 // create one instance of each module-type
231 ASSERT( prototypes.empty() );
232 prototypes.reserve( Loki::TL::Length<Modules>::value );
233 Loki::TL::IterateTypes<Modules,Creator> gendata;
234 gendata( back_inserter(prototypes) );
235 // initialize the prototypes' settings and interconnections
236 for_each( prototypes.begin(), prototypes.end()
237 , mem_fun(&Module::createDefaultSettings) );
238 for_each( prototypes.begin(), prototypes.end()
239 , mem_fun(&Module::initDefaultModuleLinks) );
241 void ModuleFactory::changeDefaultSettings(const Module &module) {
242 // get the right prototype
243 const Module::TypeInfo &mi= module.info();
244 Module::SettingItem *protSet= prototype(mi.id).settings;
245 // replace prototype's settings
246 ASSERT( protSet && module.settings );
247 copy( module.settings, module.settings+mi.setLength, protSet );
248 // convert module-links to links to the correct prototypes
249 for (const Module::SettingTypeItem *setType= mi.setType
250 ; setType->type.type!=Module::Stop; ++setType,++protSet)
251 if ( setType->type.type==Module::ModuleCombo ) {
252 ASSERT(protSet->m);
253 protSet->m= constCast(&prototype( protSet->m->info().id ));
258 template<class T> int ModuleFactory::Instantiator<T>::operator()() const {
259 int i= getModuleID<T>();
260 Module *m= T::newCompatibleModule();
261 m= m->concreteClone<T>(Module::DeepCopy);
262 i+= T::getCompMods().front();
263 return i;
265 void ModuleFactory::instantiateModules() {
266 IterateTypes<Modules,Instantiator> gendata;
267 vector<int> v;
268 gendata(back_inserter(v));