Marsyas
0.6.0-alpha
|
00001 /* 00002 ** Copyright (C) 1998-2010 George Tzanetakis <gtzan@cs.uvic.ca> 00003 ** 00004 ** This program is free software; you can redistribute it and/or modify 00005 ** it under the terms of the GNU General Public License as published by 00006 ** the Free Software Foundation; either version 2 of the License, or 00007 ** (at your option) any later version. 00008 ** 00009 ** This program is distributed in the hope that it will be useful, 00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 ** GNU General Public License for more details. 00013 ** 00014 ** You should have received a copy of the GNU General Public License 00015 ** along with this program; if not, write to the Free Software 00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 */ 00018 00019 #include <marsyas/expr/ExVal.h> 00020 #include <marsyas/expr/ExNode.h> 00021 00022 using std::ostringstream; 00023 using namespace Marsyas; 00024 00025 /******************************************************************/ 00026 void 00027 ExVal::clear_list() 00028 { 00029 if (list_) { 00030 for (int i=0; i<natural_; ++i) { list_[i]->deref(); } 00031 delete [] list_; 00032 list_=NULL; 00033 } 00034 } 00035 00036 void 00037 ExVal::clear() 00038 { 00039 clear_list(); 00040 type_ =""; 00041 string_ =""; 00042 bool_ =false; 00043 natural_ =0; 00044 real_ =0.0; 00045 if (fun_) fun_->deref(); 00046 fun_ =NULL; 00047 timer_ =NULL; 00048 scheduler_ =NULL; 00049 list_ =NULL; 00050 } 00051 00052 void ExVal::set(ExFun* x) { clear(); type_=(x==NULL) ? "" : x->getType(); fun_=x; } 00053 void ExVal::set(const mrs_string x) { clear(); type_="mrs_string"; string_=x; } 00054 void ExVal::set(double x) { clear(); type_="mrs_real"; real_=x; } 00055 void ExVal::set(float x) { clear(); type_="mrs_real"; real_=x; } 00056 void ExVal::set(mrs_natural x) { clear(); type_="mrs_natural"; natural_=x; } 00057 void ExVal::set(mrs_bool x) { clear(); type_="mrs_bool"; bool_=x; } 00058 void ExVal::set(TmTimer** t) { clear(); type_="mrs_timer"; timer_=t; } 00059 void ExVal::set(Scheduler** t) { clear(); type_="mrs_scheduler"; scheduler_=t; } 00060 00061 void 00062 ExVal::set(mrs_natural len, ExNode** xs, std::string t) 00063 { 00064 clear(); 00065 if (xs!=NULL) { list_=xs; if((*xs)!=NULL&&len>0) { t=(*xs)->getType(); } } 00066 else { len=0; list_=new ExNode*[len]; } 00067 type_=t+" list"; natural_=len; 00068 } 00069 00070 void 00071 ExVal::set(mrs_natural len, std::string t) // what is this ?? 00072 { 00073 (void) len; // FIXME Unused parameter 00074 clear(); type_=t; natural_=0; list_=NULL; 00075 } 00076 00077 void 00078 ExVal::set(const ExVal& v) 00079 { 00080 clear(); 00081 kind_ =v.kind_; 00082 type_ =v.type_; 00083 string_ =v.string_; 00084 natural_ =v.natural_; 00085 real_ =v.real_; 00086 bool_ =v.bool_; 00087 fun_ =(v.fun_==NULL) ? NULL : v.fun_->copy(); 00088 timer_ =v.timer_; 00089 scheduler_ =v.scheduler_; 00090 if (is_list()) { // can do this now that type_=v.type_ 00091 list_=new ExNode*[natural_]; 00092 for (int i=0; i<natural_; ++i) { 00093 list_[i]=v.list_[i]; 00094 list_[i]->inc_ref(); 00095 } 00096 } 00097 else list_=NULL; 00098 } 00099 00100 ExVal::~ExVal() 00101 { 00102 if (fun_!=NULL) fun_->deref(); 00103 clear_list(); 00104 } 00105 00106 std::string 00107 ExVal::toString() const 00108 { 00109 if (type_=="mrs_string") { return string_; } 00110 else if (type_=="mrs_real") { return dtos(real_); } 00111 else if (type_=="mrs_natural") { return ltos(natural_); } 00112 else if (type_=="mrs_bool") { return btos(bool_); } 00113 else if (type_=="mrs_fun") { return "<mrs_fun>"; } 00114 else if (type_=="mrs_timer") { return "<mrs_timer>"; } 00115 else if (type_=="mrs_scheduler") { return "<mrs_scheduler>"; } 00116 else if (type_=="") { return "unknown value"; } 00117 return type_; 00118 } 00119 00120 ExVal 00121 ExVal::defaultExValue(std::string type)//{{{ 00122 { 00123 if (type=="mrs_string") return (std::string)""; 00124 if (type=="mrs_bool") return (bool)false; 00125 if (type=="mrs_natural") return (long)0; 00126 if (type=="mrs_real") return (double)0.0; 00127 if (type=="mrs_timer") { ExVal v((TmTimer**)NULL); return v; } 00128 if (type=="mrs_scheduler") { ExVal v((Scheduler**)NULL); return v; } 00129 return ExVal(); 00130 }//}}} 00131 00132 std::string 00133 ExVal::getBaseType() const 00134 { 00135 mrs_natural p=(mrs_natural)type_.find(' '); 00136 if (p<0) return type_; 00137 return type_.substr(0,p); 00138 } 00139 00140 std::string 00141 ExVal::getElemType() const 00142 { 00143 if (type_=="mrs_string") { 00144 return "mrs_string"; 00145 } 00146 else if (is_list()) { 00147 return type_.substr(0,type_.length()-5); 00148 } 00149 return ""; 00150 } 00151 00152 bool 00153 ExVal::is_list() const 00154 { // whoa! that's crazy man.. 00155 size_t len = type_.length(); 00156 return (len>3) 00157 && (type_[len-4]=='l') 00158 && (type_[len-3]=='i') 00159 && (type_[len-2]=='s') 00160 && (type_[len-1]=='t'); 00161 } 00162 00163 bool 00164 ExVal::is_seq() const 00165 { 00166 return type_=="mrs_string"||is_list(); 00167 } 00168 00169 ExVal 00170 ExVal::getSeqRange(int lidx, int ridx) 00171 { 00172 if (!is_seq()) { 00173 return defaultExValue(getBaseType()); // obviously an error, but what to do? 00174 } 00175 if (lidx<0) lidx=0; 00176 00177 mrs_natural len; 00178 if (is_list()) { 00179 len=natural_; 00180 if (len<=0||lidx>=len) { return ExVal(0,getType()); } 00181 00182 if (ridx<lidx) ridx=lidx; 00183 else if (ridx>=len) ridx=len-1; 00184 mrs_natural new_len=ridx-lidx; 00185 00186 ExNode** new_list=new ExNode*[new_len]; 00187 int p=0; 00188 for (int i=lidx; i<ridx; ++i) { 00189 ExNode* e=list_[i]; 00190 new_list[p]=e; p++; 00191 e->inc_ref(); 00192 } 00193 return ExVal(new_len,(ExNode**)new_list); 00194 } 00195 else { // mrs_string 00196 len=(mrs_natural)string_.length(); 00197 if (len<=0||lidx>=len) { return (std::string)""; } 00198 00199 if (ridx<lidx) ridx=lidx; 00200 else if (ridx>=len) ridx=len-1; 00201 00202 return (std::string)string_.substr(lidx,ridx-1); 00203 } 00204 } 00205 00206 ExVal 00207 ExVal::getSeqElem(int idx) 00208 { 00209 if (is_list()) { 00210 if (idx>=natural_||idx<0) { 00211 MRSWARN("ExVal::getSeqElem index exceeds list length"); 00212 return defaultExValue(getBaseType()); 00213 } 00214 return list_[idx]->eval(); 00215 } 00216 else if (type_=="mrs_string") { 00217 if (idx>=0&&idx<=(int)string_.length()) 00218 return (std::string)string_.substr(idx,1); 00219 return (std::string)""; 00220 } 00221 else { 00222 MRSWARN("ExVal::getSeqElem element access on non-sequence type: "+type_); 00223 return defaultExValue(getBaseType()); 00224 } 00225 } 00226 00227 void 00228 ExVal::setSeqElem(int idx, ExVal v) 00229 { 00230 if (idx<0||idx>=natural_) { 00231 MRSWARN("ExVal::set[] Index out of bounds"); 00232 return; 00233 } 00234 list_[idx]->deref(); 00235 list_[idx]=new ExNode(v); 00236 } 00237 00238 namespace Marsyas { 00239 std::ostream& 00240 operator<<(std::ostream& o, ExVal& v) 00241 { 00242 bool i_am_a_list = v.is_list(); 00243 if (i_am_a_list) { 00244 o<<"["; 00245 for (int i=0; i<v.natural_; ++i) { 00246 ExVal x=v.list_[i]->eval(); 00247 o<<x; 00248 if (i<v.natural_-1) { o<<", "; } 00249 } 00250 o<<"]"; 00251 } 00252 else if (v.type_=="mrs_string") o<<"'"<<v.string_<<"'"; 00253 else if (v.type_=="mrs_natural") o<<ltos(v.natural_); 00254 else if (v.type_=="mrs_real") o<<dtos(v.real_); 00255 else if (v.type_=="mrs_bool") o<<btos(v.bool_); 00256 return o; 00257 } 00258 } 00259 00260 ExVal 00261 ExVal::append(const ExVal v) const 00262 { 00263 if (!is_list()||!v.is_list()) { 00264 MRSWARN("ExVal::append only sequence types may be appended: "+getType()+", "+v.getType()); 00265 return *this; 00266 } 00267 if (getType()==" list"||v.getType()==" list"||getType()==v.getType()) { 00268 mrs_natural len=natural_+v.toNatural(); ExNode** elems=new ExNode*[len]; 00269 int l=0; 00270 if (natural_>0) { 00271 for (int i=0; i<natural_; ++i,l++) { 00272 elems[l]=list_[i]; 00273 elems[l]->inc_ref(); 00274 } 00275 } 00276 if (v.toNatural()>0) { 00277 for (int i=0; i<v.toNatural(); ++i,l++) { 00278 elems[l]=v.list_[i]; 00279 elems[l]->inc_ref(); 00280 } 00281 } 00282 return ExVal(len,elems); 00283 } 00284 MRSWARN("ExVal::append type mismatch in list concat: "+getType()+","+v.getType()); 00285 return *this; 00286 }