00001 /*!@file Psycho/EyeLinkAscParser.C EyeLink eye-tracker parses the 00002 *.asc eyetracking file. Usually this comes from the *.edf file that the 00003 eyetracker produces, then processed by EDF2ASC executable. */ 00004 // //////////////////////////////////////////////////////////////////// // 00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00006 // by the University of Southern California (USC) and the iLab at USC. // 00007 // See http://iLab.usc.edu for information about this project. // 00008 // //////////////////////////////////////////////////////////////////// // 00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00011 // in Visual Environments, and Applications'' by Christof Koch and // 00012 // Laurent Itti, California Institute of Technology, 2001 (patent // 00013 // pending; application number 09/912,225 filed July 23, 2001; see // 00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00015 // //////////////////////////////////////////////////////////////////// // 00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00017 // // 00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00019 // redistribute it and/or modify it under the terms of the GNU General // 00020 // Public License as published by the Free Software Foundation; either // 00021 // version 2 of the License, or (at your option) any later version. // 00022 // // 00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00026 // PURPOSE. See the GNU General Public License for more details. // 00027 // // 00028 // You should have received a copy of the GNU General Public License // 00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00031 // Boston, MA 02111-1307 USA. // 00032 // //////////////////////////////////////////////////////////////////// // 00033 // 00034 // Primary maintainer for this file: Christian Siagian <siagian@usc.edu> 00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Psycho/EyeLinkAsc.C $ 00036 // $Id: $ 00037 // 00038 00039 #include "Psycho/EyeLinkAscParser.H" 00040 #include "Util/Timer.H" 00041 #include "Raster/Raster.H" 00042 00043 #include <cstdio> 00044 #include <math.h> 00045 00046 #define trialLength 15.0 00047 #define frameRate 30.0 00048 00049 #define D_WIDTH 1024.0 00050 #define D_HEIGHT 768.0 00051 #define IM_WIDTH 640 00052 #define IM_HEIGHT 480 00053 00054 #define CREATE_EYE_S false 00055 00056 // ###################################################################### 00057 EyeLinkAscParser::EyeLinkAscParser(std::string fileName) 00058 { 00059 std::string::size_type dpos = fileName.find_last_of('.'); 00060 std::string::size_type spos = fileName.find_last_of('/'); 00061 if(spos != std::string::npos) 00062 itsSubjectName = fileName.substr(spos+1, dpos-spos-1); 00063 else 00064 itsSubjectName = fileName.substr(0, dpos); 00065 00066 LDEBUG("<<%s>> -> <<%s>>", fileName.c_str(), itsSubjectName.c_str()); 00067 00068 parse(fileName); 00069 } 00070 00071 // ###################################################################### 00072 EyeLinkAscParser::~EyeLinkAscParser() 00073 { } 00074 00075 // ###################################################################### 00076 void EyeLinkAscParser::parse(std::string fileName) 00077 { 00078 FILE *fp; char inLine[200]; 00079 FILE *eyesFile = 0; 00080 bool createEyeS = CREATE_EYE_S; 00081 // open the file 00082 LINFO("Parsing: %s", fileName.c_str()); 00083 if((fp = fopen(fileName.c_str(),"rb")) == NULL) 00084 { LINFO("not found"); return; } 00085 00086 int ldpos = fileName.find_last_of('.'); 00087 std::string eyeSfile_prefix = fileName.substr(0, ldpos); 00088 LINFO("string: %s", eyeSfile_prefix.c_str()); 00089 00090 // determine recorded eye 00091 // also skip the header information 00092 std::string recordedEye; 00093 while(fgets(inLine, 200, fp) != NULL) 00094 { 00095 // get the word tokens 00096 std::vector<std::string> currLine = tokenize(inLine); 00097 00098 if(currLine.size() >= 4 && !currLine[0].compare("EVENTS")) 00099 { 00100 if(!currLine[2].compare("RIGHT")) 00101 recordedEye = std::string("RIGHT"); 00102 else if (!currLine[2].compare("LEFT") && 00103 !currLine[3].compare("RIGHT")) 00104 recordedEye = std::string("BOTH"); 00105 else 00106 recordedEye = std::string("LEFT"); 00107 break; 00108 } 00109 } 00110 fclose(fp); 00111 00112 LINFO("Recorded Eye: %s", recordedEye.c_str()); 00113 00114 // start over and reread the file 00115 // read and store data 00116 if((fp = fopen(fileName.c_str(),"rb")) == NULL) 00117 { LINFO("not found"); return; } 00118 00119 uint iTrial = 0; 00120 uint iTime = 0; 00121 uint fTime = 0; 00122 uint iSacc = 0; 00123 //uint iBlink = 0; 00124 uint iFix = 0; 00125 bool isDriftCorrecting = false; 00126 bool isBlinking = false; 00127 bool isSaccading = false; 00128 00129 // this is for .eyeS file 00130 float targetx = 0.0F; 00131 float targety = 0.0F; 00132 float amp = 0.0F; 00133 float pvel = 0.0F; 00134 double timeOn = 0.0F; 00135 double timeOff = 0.0F; 00136 float interval = 0.0F; 00137 double startTime = 0.0F; 00138 00139 // get each line in the file 00140 while(fgets(inLine, 200, fp) != NULL) 00141 { 00142 // get the word tokens 00143 std::vector<std::string> currLine = tokenize(inLine); 00144 00145 if(currLine.size() == 0) continue; 00146 00147 // skip calibration lines 00148 if(currLine.size() == 3 && !currLine[2].compare("!CAL")) 00149 continue; 00150 00151 // check the line first argument 00152 00153 // events: MSG 00154 if(currLine.size() > 0 && !currLine[0].compare("MSG")) 00155 { 00156 // get rid of unnecessary MSG lines 00157 // if length(tmp2) < 5 00158 // tmp2 00159 // continue 00160 // end 00161 00162 // START of the current trial 00163 if(currLine.size() > 6 && 00164 !currLine[4].compare("SESSION") && !currLine[5].compare("START")) 00165 { 00166 fTime = 0; 00167 iTime = 0; 00168 iSacc = 0; 00169 //iBlink = 0; 00170 iFix = 0; 00171 iTrial = iTrial + 1; 00172 itsTrialStart.push_back(atoi(currLine[1].c_str())); 00173 // for now to see if drift correction 00174 // is in the middle of the trial 00175 itsTrialEnd.push_back(-1); 00176 00177 itsFlipTime.push_back(std::vector<int>()); 00178 itsFlipFixations.push_back 00179 (std::vector<std::vector<Point2D<float> > >()); 00180 itsFlipFrame.push_back(std::vector<int>()); 00181 00182 itsSaccadeStart.push_back(std::vector<int>()); 00183 itsSaccadeEnd.push_back(std::vector<int>()); 00184 itsSaccadeDuration.push_back(std::vector<int>()); 00185 itsSaccadeStartLocation.push_back(std::vector<Point2D<float> >()); 00186 itsSaccadeEndLocation.push_back(std::vector<Point2D<float> >()); 00187 itsSaccadeAmplitude.push_back(std::vector<float>()); 00188 itsSaccadePeakVel.push_back(std::vector<float>()); 00189 00190 itsFixationStart.push_back(std::vector<int>()); 00191 itsFixationEnd.push_back(std::vector<int>()); 00192 itsFixationDuration.push_back(std::vector<int>()); 00193 itsFixationAvgLocation.push_back(std::vector<Point2D<float> >()); 00194 itsFixationAvgPupilSize.push_back(std::vector<float>()); 00195 00196 itsGazeTime.push_back(std::vector<int>()); 00197 itsLeftGaze.push_back(std::vector<Point2D<float> >()); 00198 itsLeftGazePupilSize.push_back(std::vector<float>()); 00199 00200 itsRightGaze.push_back(std::vector<Point2D<float> >()); 00201 itsRightGazePupilSize.push_back(std::vector<float>()); 00202 00203 if(iTrial != uint(atoi(currLine[6].c_str()))) 00204 LINFO("Trial Mismatch!"); 00205 LDEBUG("%s",inLine); 00206 LDEBUG("Start trial %s", currLine[6].c_str()); 00207 00208 // print in the header 00209 if(createEyeS) 00210 { 00211 std::string fName = 00212 sformat("%s_%d.eyeS", eyeSfile_prefix.c_str(), iTrial); 00213 eyesFile = fopen(fName.c_str(), "wt"); 00214 00215 std::string period("period = 1000Hz\n"); 00216 fputs (period.c_str(), eyesFile); 00217 00218 std::string ppd("ppd = 36.3\n"); 00219 fputs (ppd.c_str(), eyesFile); 00220 00221 std::string trash("trash = 0\n"); 00222 fputs (trash.c_str(), eyesFile); 00223 00224 std::string header("cols = x y pd status *targetx *targety " 00225 "*amp *pvel *timeon *timeoff " 00226 "*interval *typenum\n"); 00227 fputs (header.c_str(), eyesFile); 00228 00229 LINFO("creating: %s", fName.c_str()); 00230 } 00231 } 00232 00233 // Nothing to do until the start of the first trial is found 00234 if(iTrial == 0) continue; 00235 00236 // New Video Frame is just shown 00237 if(currLine.size() == 4 && 00238 !currLine[2].compare("MARKERID") && !currLine[3].compare("Flip")) 00239 { 00240 itsFlipTime[iTrial-1].push_back(atof(currLine[1].c_str())); 00241 00242 if(fTime == 0) 00243 itsFlipFrame[iTrial-1].push_back(0); 00244 else 00245 { 00246 if((itsFlipTime[iTrial-1][fTime] - itsFlipTime[iTrial-1][0]) 00247 > trialLength * 1000) 00248 { 00249 //LINFO("[%d][%"ZU"]", iTrial-1, itsFlipFrame[iTrial-1].size()); 00250 itsFlipFrame[iTrial-1].push_back(trialLength * frameRate); 00251 } 00252 else 00253 { 00254 int tDiff = 00255 itsFlipTime[iTrial-1][fTime] - itsFlipTime[iTrial-1][0]; 00256 float mspfr = 1000/frameRate; 00257 int frNum = floor(tDiff/mspfr); 00258 itsFlipFrame[iTrial-1].push_back(frNum); 00259 } 00260 } 00261 //LINFO("Flip at %d to frame %d\n", 00262 // itsFlipTime[iTrial-1][fTime], itsFlipFrame[iTrial-1][fTime]); 00263 fTime = fTime + 1; 00264 itsFlipFixations[iTrial-1].push_back 00265 (std::vector<Point2D<float> >()); 00266 00267 if(fTime == 1) startTime = atoi(currLine[1].c_str()); 00268 } 00269 00270 // END of the current trial 00271 if (currLine.size() > 6 && 00272 !currLine[4].compare("SESSION") && !currLine[5].compare("END")) 00273 { 00274 itsTrialEnd[iTrial-1] = atoi(currLine[1].c_str()); 00275 if (iTrial != uint(atoi(currLine[6].c_str()))) 00276 LINFO("Trial Mismatch!"); 00277 00278 LDEBUG("%s",inLine); 00279 LDEBUG("trial: %d to %d", 00280 itsFlipTime[iTrial-1][0], itsFlipTime[iTrial-1][fTime-1]); 00281 LDEBUG("there are %"ZU" saccades and %"ZU" fixations", 00282 itsSaccadeStart[iTrial-1].size(), 00283 itsFixationStart[iTrial-1].size()); 00284 00285 if(createEyeS) 00286 fclose (eyesFile); 00287 } 00288 00289 // Nothing to do if the ending of the trial is already found 00290 if (itsTrialEnd[iTrial-1] != -1.0) continue; 00291 00292 // drift correction 00293 if (currLine.size() > 4 && !currLine[4].compare("CORRECTION")) 00294 { 00295 LINFO("in between drifting: %s",inLine); 00296 // 00297 if(currLine.size() == 5 && !currLine[3].compare("DRIFT")) 00298 { 00299 isDriftCorrecting = 1; 00300 itsDriftCorrectionStart.push_back(atoi(currLine[1].c_str())); 00301 LINFO("Start in between drifting correction at: %d", 00302 itsDriftCorrectionStart[iTrial-1]); 00303 } 00304 else if(currLine.size() == 6 && !currLine[5].compare("DONE")) 00305 { 00306 isDriftCorrecting = 0; 00307 itsDriftCorrectionDone.push_back(atoi(currLine[1].c_str())); 00308 LINFO("End in between drifting correction at: %d", 00309 itsDriftCorrectionDone[iTrial-1]); 00310 } 00311 else 00312 LINFO("Wrong Drift Correction Message!"); 00313 } 00314 } 00315 00316 // 00317 else if (currLine.size() > 0 && 00318 (!currLine[0].compare("SSACC") || 00319 !currLine[0].compare("ESACC") || 00320 !currLine[0].compare("SFIX") || 00321 !currLine[0].compare("EFIX") || 00322 !currLine[0].compare("SBLINK") || 00323 !currLine[0].compare("EBLINK") )) 00324 { 00325 // Nothing to do until the start of the first trial is found 00326 if (iTrial == 0) continue; 00327 00328 // Nothing to do if the ending of the trial is already found 00329 if (itsTrialEnd[iTrial-1] != -1.0) continue; 00330 00331 //LINFO("Saccading, etc: %s",inLine); 00332 00333 // SACCADE of the current saccade 00334 if(!currLine[0].compare("SSACC")) 00335 { 00336 isSaccading = true; 00337 iSacc = iSacc + 1; 00338 00339 // we have to go move forward 00340 // that has the saccade information 00341 00342 // get current position 00343 fpos_t pos; 00344 fgetpos(fp, &pos); 00345 char tline[200]; 00346 bool foundESACC = false; 00347 while(!foundESACC && fgets(tline, 200, fp) != NULL) 00348 { 00349 // get the word tokens 00350 std::vector<std::string> cLine = tokenize(tline); 00351 00352 // found ESACC 00353 if(cLine.size() > 0 && !cLine[0].compare("ESACC")) 00354 { 00355 targetx = atof(cLine[7].c_str())/D_WIDTH*IM_WIDTH; 00356 targety = atof(cLine[8].c_str())/D_HEIGHT*IM_HEIGHT; 00357 amp = atof(cLine[9].c_str()); 00358 pvel = atof(cLine[10].c_str()); 00359 timeOn = atof(cLine[2].c_str()) - startTime; 00360 timeOff = atof(cLine[3].c_str()) - startTime; 00361 interval = atof(cLine[4].c_str()); 00362 foundESACC = true; 00363 00364 LDEBUG("%.1f %.1f %.1f %.1f %.1f %.1f %.1f %d", 00365 targetx, targety, amp, pvel, 00366 timeOn, timeOff, interval, iSacc); 00367 } 00368 } 00369 00370 // then we move back to the original line 00371 fsetpos(fp, &pos); 00372 } 00373 00374 // END of the current saccade 00375 if(!currLine[0].compare("ESACC")) 00376 { 00377 itsSaccadeStart [iTrial-1].push_back(atoi(currLine[2].c_str())); 00378 itsSaccadeEnd [iTrial-1].push_back(atoi(currLine[3].c_str())); 00379 itsSaccadeDuration [iTrial-1].push_back(atoi(currLine[4].c_str())); 00380 itsSaccadeStartLocation[iTrial-1].push_back 00381 (Point2D<float>(atof(currLine[5].c_str()), atof(currLine[6].c_str()))); 00382 itsSaccadeEndLocation [iTrial-1].push_back 00383 (Point2D<float>(atof(currLine[7].c_str()), atof(currLine[8].c_str()))); 00384 itsSaccadeAmplitude [iTrial-1].push_back(atof(currLine[9].c_str())); 00385 itsSaccadePeakVel [iTrial-1].push_back(atof(currLine[10].c_str())); 00386 //fprintf('Saccade %d\n', iSacc) 00387 00388 isSaccading = false; 00389 } 00390 00391 // we won't process: SFIX 00392 00393 // END of the current fixation 00394 else if(!currLine[0].compare("EFIX")) 00395 { 00396 iFix = iFix + 1; 00397 00398 itsFixationStart [iTrial-1].push_back(atoi(currLine[2].c_str())); 00399 itsFixationEnd [iTrial-1].push_back(atoi(currLine[3].c_str())); 00400 itsFixationDuration [iTrial-1].push_back(atoi(currLine[4].c_str())); 00401 itsFixationAvgLocation [iTrial-1].push_back 00402 (Point2D<float>(atof(currLine[5].c_str()), atof(currLine[6].c_str()))); 00403 itsFixationAvgPupilSize[iTrial-1].push_back(atof(currLine[7].c_str())); 00404 //fprintf('Fixation %d: at: (%7.2d %7.2d) for %f \n', iFix, iT(iTrial).FIX{iFix}.avg_x, iT(iTrial).FIX{iFix}.avg_y, iT(iTrial).FIX{iFix}.duration); 00405 } 00406 else if(!currLine[0].compare("SBLINK")) 00407 isBlinking = true; 00408 else if(!currLine[0].compare("EBLINK")) 00409 isBlinking = false; 00410 } 00411 00412 // not processing these commands 00413 else if (currLine.size() > 0 && 00414 (!currLine[0].compare("START") || 00415 !currLine[0].compare("END") || 00416 !currLine[0].compare("PRESCALER") || 00417 !currLine[0].compare("VPRESCALER") || 00418 !currLine[0].compare("PUPIL") || 00419 !currLine[0].compare("SAMPLES") || 00420 !currLine[0].compare(">>>>>>>") )) 00421 { continue; } 00422 00423 else if (currLine.size() > 0 && !currLine[0].compare("EVENTS")) 00424 { 00425 // if changing specs for which eye is being recorded 00426 if(!currLine[1].compare("GAZE")) 00427 { 00428 if(!currLine[2].compare("RIGHT")) 00429 recordedEye = std::string("RIGHT"); 00430 else if(!currLine[2].compare("LEFT") && !currLine[3].compare("RIGHT")) 00431 recordedEye = std::string("BOTH"); 00432 else 00433 recordedEye = std::string("LEFT"); 00434 LDEBUG("Recorded Eye: %s", recordedEye.c_str()); 00435 } 00436 } 00437 00438 // skipping 'INPUT .... 120' 00439 // not sure who inserted this line 00440 else if (currLine.size() > 0 && !currLine[0].compare("INPUT")) 00441 { continue; } 00442 00443 // first element exception 00444 else if(atoi(currLine[0].c_str()) == 0) 00445 { 00446 LDEBUG("First Element Exception: Skipped: %s", inLine); 00447 continue; 00448 } 00449 00450 // otherwise it's gaze for current timeStamp 00451 else 00452 { 00453 // Nothing to do until the start of the first trial is found 00454 if (iTrial == 0) continue; 00455 00456 // Nothing to do if the ending of the trial is already found 00457 if(itsTrialEnd[iTrial-1] != -1.0) continue; 00458 00459 // Nothing to do if currently correcting drift 00460 if (isDriftCorrecting) continue; 00461 00462 // we record to eyeS file even on blinks 00463 // status: 00464 // 0: regular fixation 00465 // 1: saccade 00466 // 2: blink 00467 // 3: saccade + blink 00468 // 4: smooth pursuit: NOT IMPLEMENTED HERE 00469 // 5: invalid 00470 // 6: combined saccade: NOT IMPLEMENTED HERE 00471 if(fTime != 0) 00472 { 00473 uint status = 0; 00474 if(!isBlinking && isSaccading) status = 1; 00475 if( isBlinking && !isSaccading) status = 2; 00476 if( isBlinking && isSaccading) status = 3; 00477 00478 uint freq = 0; if(targetx != 0.0F) freq = iSacc; 00479 std::string line = 00480 sformat("%.1f %.1f %.1f %d %.1f %.1f %.1f %.1f %.1f %.1f %.1f %d \n", 00481 atof(currLine[1].c_str())/D_WIDTH *IM_WIDTH, 00482 atof(currLine[2].c_str())/D_HEIGHT*IM_HEIGHT, 00483 atof(currLine[3].c_str()), status, 00484 targetx, targety, amp, pvel, timeOn, timeOff, interval, freq); 00485 if(createEyeS) 00486 fputs (line.c_str(), eyesFile); 00487 00488 if(targetx != 0.0F) 00489 { 00490 targetx = 0.0F; 00491 targety = 0.0F; 00492 amp = 0.0F; 00493 pvel = 0.0F; 00494 timeOn = 0.0F; 00495 timeOff = 0.0F; 00496 interval = 0.0F; 00497 } 00498 } 00499 00500 // Nothing to do until stop blink 00501 if (isBlinking) continue; 00502 00503 // retrieve the data 00504 //LINFO("times: %s",inLine); 00505 iTime = iTime + 1; 00506 00507 // get time stamp 00508 itsGazeTime[iTrial-1].push_back(atoi(currLine[0].c_str())); 00509 if(fTime != 0) 00510 { 00511 itsFlipFixations[iTrial-1][fTime-1].push_back 00512 (Point2D<float>(atof(currLine[1].c_str()), atof(currLine[2].c_str()))); 00513 } 00514 LDEBUG("GAZE[%5d][%5d]: %s size: %"ZU, 00515 iTrial-1, fTime-1, inLine, itsGazeTime[iTrial-1].size()); 00516 00517 if(!recordedEye.compare("LEFT") || !recordedEye.compare("BOTH")) 00518 { 00519 // left eye X, Y 00520 if (!currLine[1].compare(".") || !currLine[2].compare(".")) 00521 itsLeftGaze[iTrial-1].push_back(Point2D<float>(-1.0, -1.0)); 00522 else 00523 itsLeftGaze[iTrial-1].push_back 00524 (Point2D<float>(atof(currLine[1].c_str()), atof(currLine[2].c_str()))); 00525 00526 // left eye pupil 00527 if (!currLine[3].compare(".")) 00528 itsLeftGazePupilSize[iTrial-1].push_back(-1.0); 00529 else 00530 itsLeftGazePupilSize[iTrial-1].push_back(atof(currLine[3].c_str())); 00531 } 00532 00533 if(!recordedEye.compare("BOTH")) 00534 { 00535 // right eye X, Y 00536 if (!currLine[4].compare(".") || !currLine[5].compare(".")) 00537 itsRightGaze[iTrial-1].push_back(Point2D<float>(-1.0, -1.0)); 00538 else 00539 itsRightGaze[iTrial-1].push_back 00540 (Point2D<float>(atof(currLine[4].c_str()), atof(currLine[5].c_str()))); 00541 00542 // right eye pupil 00543 if (!currLine[6].compare(".")) 00544 itsRightGazePupilSize[iTrial-1].push_back(-1.0); 00545 else 00546 itsRightGazePupilSize[iTrial-1].push_back(atof(currLine[6].c_str())); 00547 } 00548 00549 if(!recordedEye.compare("RIGHT")) 00550 { 00551 // right eye X, Y 00552 if (!currLine[1].compare(".") || !currLine[2].compare(".")) 00553 itsRightGaze[iTrial-1].push_back(Point2D<float>(-1.0, -1.0)); 00554 else 00555 itsRightGaze[iTrial-1]. 00556 push_back(Point2D<float>(atof(currLine[1].c_str()), atof(currLine[2].c_str()))); 00557 00558 // right eye pupil 00559 if (!currLine[3].compare(".")) 00560 itsRightGazePupilSize[iTrial-1].push_back(-1.0); 00561 else 00562 itsRightGazePupilSize[iTrial-1].push_back(atof(currLine[3].c_str())); 00563 } 00564 } 00565 } 00566 } 00567 00568 // ###################################################################### 00569 std::vector<std::string> EyeLinkAscParser::tokenize(std::string line) 00570 { 00571 bool endOfLine = false; 00572 00573 // take out the carriage return at the back of the line 00574 if(!line.substr(line.length()-1).compare(std::string("\n"))) 00575 line = line.substr(0, line.length()-2); 00576 00577 std::vector<std::string> currLine; 00578 while(!endOfLine) 00579 { 00580 std::string token; std::string rest; 00581 std::string::size_type fspos = line.find_first_of(' '); 00582 std::string::size_type ftpos = line.find_first_of('\t'); 00583 if(ftpos != std::string::npos && ftpos < fspos) fspos = ftpos; 00584 00585 if(fspos != std::string::npos) 00586 { 00587 token = line.substr(0,fspos); 00588 rest = trim(line.substr(fspos)); 00589 00590 LDEBUG("[[%s]] [[%s]]", token.c_str(), rest.c_str()); 00591 00592 currLine.push_back(token); 00593 if(!rest.substr(0,1).compare(std::string("\t"))) 00594 rest = trim(rest.substr(1)); 00595 line = rest; 00596 } 00597 else 00598 { 00599 if(line.length() != 0) 00600 { 00601 currLine.push_back(line); 00602 LDEBUG("[[%s]]", line.c_str()); 00603 } 00604 endOfLine = true; 00605 } 00606 } 00607 00608 return currLine; 00609 } 00610 00611 // ###################################################################### 00612 std::string EyeLinkAscParser::trim(std::string str) 00613 { 00614 std::string::size_type pos = str.find_last_not_of(' '); 00615 00616 if(pos != std::string::npos) { 00617 str.erase(pos + 1); 00618 pos = str.find_first_not_of(' '); 00619 if(pos != std::string::npos) str.erase(0, pos); 00620 } 00621 else str.erase(str.begin(), str.end()); 00622 00623 return str; 00624 } 00625 00626 00627 // ###################################################################### 00628 /* So things look consistent in everyone's emacs... */ 00629 /* Local Variables: */ 00630 /* mode: c++ */ 00631 /* indent-tabs-mode: nil */ 00632 /* End: */