Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Examples

vos/corelibs/typechain/typechain.cc

Go to the documentation of this file.
00001 /* $Id: typechain.cc,v 1.32 2003/07/24 16:12:05 reed Exp $ */
00002 
00003 /*
00004     This file is part of the Virtual Object System of
00005     the Interreality project (http://interreality.org).
00006 
00007     Copyright (C) 2001, 2002 Reed Hedges <reed@zerohour.net>
00008 
00009     This library is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU Lesser General Public
00011     License as published by the Free Software Foundation; either
00012     version 2 of the License, or (at your option) any later version.
00013 
00014     This library is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017     Lesser General Public License for more details.
00018 
00019     You should have received a copy of the GNU Lesser General Public
00020     License along with this library; if not, write to the Free Software
00021     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00022 */
00023 
00024 #include <sys/types.h>
00025 
00026 #include <errno.h>
00027 #include <sys/stat.h>
00028 #include <string.h>
00029 #include <dirent.h>
00030 
00031 #ifdef HAVE_UNISTD_H
00032 #include <unistd.h>
00033 #endif
00034 
00035 
00036 #include <stdarg.h>
00037 
00038 #include <string>
00039 #include <map>
00040 #include <vector>
00041 #include <list>
00042 #include <iostream>
00043 
00044 #include <pluginloader/plugins.hh>
00045 
00046 #include "typechain.hh"
00047 #include "typehandler.hh"
00048 
00049 #include "tclexer.hh"
00050 
00051 // a macro for debugging (e.g.: "make typechain CPPFLAGS+=-DLOGLEV=3")
00052 
00053 #if !defined(LOGLEV)
00054 #define LOGLEV  2
00055 #else
00056 //#warning Using predefined LOGLEV.
00057 #endif
00058 
00059 #define LOG(c, l, m)    if (l <= LOGLEV) std::clog << c << ": " << m << endl;
00060 
00061 
00062 /* A lexer which decodes as it scans */
00063 class DecodingTCLexer : public TypechainLexer {
00064 protected:
00065     // these store state only for the course of one call to decode or
00066     // encode.
00067     string* datap;
00068     string finaltype;
00069     map<string,string> finalparams;
00070 
00071     void complete_token(string token, map<string, string> params) ;
00072     void final_type(string type, map<string, string> params);
00073 
00074 
00075 public:
00076     DecodingTCLexer(const string& t);
00077     string decode(string& data, map<string,string>& params) ;
00078 };
00079 
00080 /* A lexer which encodes as it scans */
00081 class EncodingTCLexer : public TypechainLexer {
00082 protected:
00083     // these store state only for the course of one call to decode or
00084     // encode.
00085     string* datap;
00086     string finaltype;
00087     map<string, string> finalparams;
00088     void complete_token(string token, map<string, string> params);
00089     void final_type(string type, map<string, string> params);
00090 public:
00091     EncodingTCLexer(const string& t);
00092     void encode(string& data, map<string, string>& params);
00093 };
00094 
00095 
00096     /* TODO lexer which encodes as it scans (needs a reversed typechain string!) */
00097 
00098 
00099 
00100 /* A lexer that makes a string of abbreviated type identifiers as it scans, for file names (used by makeFilename) */
00101 class FilenameTCLexer : public TypechainLexer {
00102 protected:
00103     string filename;
00104     void complete_token(string token, map<string, string> params) ;
00105     void final_type(string type, map<string, string> params) ;
00106 public:
00107     FilenameTCLexer(string t) : TypechainLexer(t) {
00108     }
00109     string makeExtensions() ;
00110 };
00111 
00112 
00113 /* The lexer that decodes */
00114 
00115 DecodingTCLexer::DecodingTCLexer(const string& t) :
00116     TypechainLexer(t), datap(0) { }
00117 
00118 string DecodingTCLexer::decode(string& targetdata, map<string,string>& params)  {
00119     datap = &targetdata;
00120     LOG("DecodingTCLexer::decode", 5, "parsing data...");
00121     yylex();
00122     LOG("DecodingTCLexer::decode", 5, "done parsing data. final type is " << finaltype);
00123     params = finalparams;
00124     //targetdata = *datap;
00125     return finaltype;
00126 }
00127 
00128 void DecodingTCLexer::complete_token(string token, map<string,string> params)  {
00129     if( (token != "") && (token != "type") && (token != "?") )    // type is to be ignored.
00130     {
00131         if (TypeChain::handlers.find(token) == TypeChain::handlers.end()) {
00132             throw TypeChain::DecodeError("No handler found", token);
00133         }
00134 
00135 
00136         LOG("TypeChain decoding lexer", 5, "decoding data of type " << token << "...");
00137         TypeChain::handlers[token]->decode(*datap, params);
00138     }
00139 }
00140 
00141 void DecodingTCLexer::final_type(string token, map<string,string> params) {
00142     finaltype = token;
00143     finalparams = params;
00144 }
00145 
00146 
00147 /* The encoding lexer */
00148 
00149 EncodingTCLexer::EncodingTCLexer(const string& t) :
00150     TypechainLexer(t), datap(0) { }
00151 
00152 void EncodingTCLexer::encode(string& targetdata, map<string, string>& params) {
00153     datap = &targetdata;
00154     yylex();
00155     params = finalparams;
00156     //targetdata = *datap;
00157 }
00158 
00159 void EncodingTCLexer::complete_token(string token, map<string, string> params) {
00160     if( (token != "") && (token != "type") && (token != "?") )
00161     {
00162         if(TypeChain::handlers.find(token) == TypeChain::handlers.end()) {
00163             throw TypeChain::EncodeError("No handler found", token);
00164         }
00165         TypeChain::handlers[token]->encode(*datap, params);
00166     }
00167 }
00168 
00169 void EncodingTCLexer::final_type(string token, map<string, string> params) {
00170     finaltype = token;
00171     finalparams = params;
00172 }
00173 
00174 
00175 
00176 
00177 /* Static TypeChain class */
00178 
00179 map<string,TypeHandler*> TypeChain::handlers;
00180 map<string,string> TypeChain::filename_extensions;
00181 
00182 
00183 void TypeChain::initialize() {
00184     TypeChain::registerHandler(new TypeHandler("identity"));
00185     Plugins::scanDir(TC_PLUGIN_DIR, "plugin_init", (void*)&TypeChain::registerHandler);
00186 }
00187 
00188 
00189 void TypeChain::initialize(const char *dirname, ...) {
00190 
00191     LOG("typechain", 4, "initialize: registering handler for identity");
00192     TypeChain::registerHandler(new TypeHandler("identity"));
00193 
00194     LOG("typechain", 4, "initialize: scanning directory with libplugins: " << dirname);
00195 
00196     Plugins::scanDir(dirname, "plugin_init", (void*)&TypeChain::registerHandler);
00197 
00198     va_list args;
00199     va_start(args, dirname);
00200     for(;;) {
00201         char* dir=va_arg(args, char*);
00202         if(dir == 0) break;
00203         LOG("typechain", 4, "initialize: scanning directory with libplugins: " << dir);
00204         Plugins::scanDir(dir, "plugin_init", (void*)&TypeChain::registerHandler);
00205     }
00206     va_end(args);
00207 
00208     LOG("typechain", 4, "initialize: scanning directory: " << TC_PLUGIN_DIR);
00209     Plugins::scanDir(TC_PLUGIN_DIR, "plugin_init", (void*)&TypeChain::registerHandler);
00210 }
00211 
00212 void TypeChain::uninitialize() {
00213 
00214     LOG("typechain", 3, "uninitialize: deleting handlers...");
00215 
00216     for( map<string, TypeHandler*>::iterator i = handlers.begin(); i != handlers.end(); i++) {
00217         LOG("typechain", 4, "removing handler for " << (*i).first);
00218         if( (*i).second != NULL )
00219             delete (*i).second;
00220         else
00221             LOG("typechain", 4, "handler was NULL. not deleted.");
00222         handlers.erase(i);
00223     }
00224 
00225     for( map<string, string>::iterator i = filename_extensions.begin(); i != filename_extensions.end(); i++) {
00226         filename_extensions.erase(i);
00227     }
00228 
00229     LOG("typechain", 3, "closing plugins...");
00230 
00231     Plugins::closeAll();
00232     LOG("typechain", 3, "done.");
00233 }
00234 
00235 string TypeChain::decode(string& data, const string& type, map<string,string>& params)  {
00236     LOG("typechain", 5, "TypeChain::decode: calling DecodingTCLexer.decode()");
00237     DecodingTCLexer lexer(type);
00238     return lexer.decode(data, params);
00239 }
00240 
00241 
00242 
00243 
00244 void TypeChain::encode(string& data, const string& type, map<string,string>& params) {
00245     EncodingTCLexer lexer(type);
00246     lexer.encode(data, params);
00247 }
00248 
00249 
00250 void TypeChain::registerHandler(TypeHandler* handler) {
00251     LOG("typechain", 3, "registering handler for " << handler->type_name);
00252     handlers[handler->type_name] = handler;
00253     filename_extensions[handler->filename_extension] = handler->type_name;
00254 }
00255 
00256 
00257 
00258 TypeHandler* TypeChain::removeHandler(const string& type) {
00259     TypeHandler* h;
00260     h = handlers[type];
00261     handlers.erase(type);
00262     return h;
00263 }
00264 
00265 void TypeChain::deleteHandler(const string& type) {
00266     TypeHandler* h;
00267     h = handlers[type];
00268     handlers.erase(type);
00269     delete h;
00270 }
00271 
00272 // does nothing.
00273 inline string string_tolower(string s) {
00274     return s;
00275 //  return string(  strlwr( s.c_str() )  );
00276 }
00277 
00278 string TypeChain::guessTypeFromFilename(const string& filename) {
00279     unsigned int oldpos, pos;
00280     string type;
00281 
00282     oldpos = filename.find('.') + 1;
00283     pos = filename.find('.', oldpos);
00284     while(pos != filename.npos) {
00285         type = ";" +  filename_extensions[ string_tolower( filename.substr(oldpos, (pos-oldpos)) ) ] + type;;
00286         pos = filename.find('.', oldpos);
00287         oldpos = pos + 1;
00288     }
00289 
00290 
00291     type.erase(0, 1); // the above loop causes the first char to always be '|'
00292 
00293     return type;
00294 }
00295 
00296 
00297 string TypeChain::makeFilename(const string& type, const string& basename) {
00298     FilenameTCLexer lex(type);
00299     return basename + lex.makeExtensions();
00300 }
00301 
00302 void FilenameTCLexer::complete_token(string token, map<string, string> params) {
00303     filename = "." + TypeChain::handlers[token]->filename_extension + filename;
00304 }
00305 
00306 void FilenameTCLexer::final_type(string type, map<string, string> params) {
00307     complete_token(type, params);
00308 }
00309 
00310 string FilenameTCLexer::makeExtensions() {
00311     filename = "";
00312     yylex();
00313     return filename;
00314 }
00315 
00316 /* lexer which counts the number of encodings */
00317 class CountEncodingsLexer : public TypechainLexer {
00318 protected:
00319     int n;
00320 public:
00321     CountEncodingsLexer(string t) : TypechainLexer(t), n(0) {};
00322     void complete_token(string, map<string,string>) {
00323         n++;
00324     }
00325     void final_type(string /*type*/, map<string, string> /*params*/) { } 
00326     int count() {
00327         n = 0;
00328         yylex();
00329         return n;
00330     }
00331 };
00332 
00333 int TypeChain::countEncodings(const string& type) {
00334     CountEncodingsLexer lexer(type);
00335     return lexer.count();
00336 }

Generated on Tue Aug 12 03:55:39 2003 for Interreality Project - VOS by doxygen 1.3.2