ドライブにも行かず。その2

<!DOCTYPE html>
<title>TEST</title>
<h1>CSV</h1>
<script>

var Q$MSXML2$XMLHttpRequest =
  (function () {
      var I = arguments.length;
      var i;
      
      for (i = 0; i < I; i++) {
          try {
              arguments[i] ();
              return arguments[i];
          } catch (err) { ; }
      }
      return null;
  }) (
      function () { return new ActiveXObject ('Msxml2.XMLHTTP.6.0'); },
      function () { return new ActiveXObject ('Msxml2.XMLHTTP.3.0'); }
      );

if ('undefined' === typeof XMLHttpRequest)
    eval ('var XMLHttpRequest = Q$MSXML2$XMLHttpRequest; ');


//___________________


var Q$CSV$parseCSV =
  (function () {
    return function (stringData, strict, separator) {
      if ((separator || (separator = ',')) === ',' || separator === '\t') {
        var isWellFormed = strict ? isStrict : isLoose;
        
        var pattern = new RegExp ('^(?:' + separator +
                                  '|(?:\\r\\n|\\r|\\n)' +
                                  '|"(?:""|[^"])*"' +
                                  '|[^\\r\\n"' + separator + '][^\\r\\n' + separator + ']*' +
                                  ')');
        var flength = 0;
        var findex  = 0;
        var fields  = [ '' ];
        var records = [ fields ];
        var token;
        
        for (
          stringData = trim (stringData);
          (token = pattern.exec (stringData)) && (token = token[0]);
          stringData = stringData.slice (token.length)
        ) {
            switch (token.charAt (0)) {
                
            case separator :
                fields[++findex] = '';
                break;
                
            case '\r' :
            case '\n' :
                if (! isWellFormed (flength || (flength = findex), findex)) {
                    throw new Error ('malformed CSV.');
                }
                fields = records[records.length] = [''], findex = 0;
                break;
                
            case '"' :
                fields[findex] = token.slice (1, -1).replace (/""/g, '"');
                break;
                
            default :
                fields[findex] = token;
                break;
            }
          }
        
          if (stringData === '' && isWellFormed (flength, findex)) {
              return records;
          }
        }
          
          throw new Error ('malformed CSV.');
      };
      
      function trim (str) {
          return String (str).replace (/^[\r\n]+|[\r\n]+$/g, '');
      }
      
      function isStrict (flength, findex) {
          return flength === findex;
      }
      
      function isLoose () {
          return true;
      }
  }) ();


var getFile =
  (function (fileName) {
    var text = '';
    var req = new XMLHttpRequest;

    if (req) {
      req.open ('GET', fileName, false);
      req.send (null);
      text = (200 == req.status)
             ? req.responseText
             : '';
      req = null;
    }
    
    return text;
  });



(function () {

  var REG_CSV_FRAGMENT =
    (function () {
      var DIGIT    = '[\\x30-\\x39]';
      var TEXTDATA = '[\\x23-\\x2B\\x2D-\\x3C\\x3E-\\x7E]';

      var rownum   = DIGIT + '+';
      var column   = '(?:' + DIGIT + '+' + '|' + TEXTDATA + '+)';
      var rowspec  = '(?:\\*' + '|' + rownum + ')';
      var colspec  = column;
      var val      = TEXTDATA + '+';
      var col      = TEXTDATA + '+';
      var kvpairs  = '(?:' + col + '=' + val + '(?:,|$)){1,}';
      var wheresel = '(?:(where):' +  '(' + kvpairs + '))';
      var colsel   = '(?:(col):' + '(' + colspec + '))';
      var rowsel   = '(?:(row):' + '(' + rowspec + '))';
      var headersel = '(head)';
      
      return new RegExp ('^#?(?:' + headersel + 
                              '|' + wheresel +
                              '|' + colsel +
                              '|' + rowsel + ')$');
    }) ();


  function decomposition (fgmt) {
    return REG_CSV_FRAGMENT.exec (fgmt);
  }


  function fileLoad (fileName) {
    this.csv = (fileName)
               ? Q$CSV$parseCSV (getFile (fileName))
               : null;
    
    return !! (this.csv);
  }


  function getHeader () {
    return this.csv[0].slice (0);
  }
  
  
  function getBody () {
    return this.csv.slice (1);
  }
  
  
  //__________________
  
  function CSVFragment () {
     this.csv = [];
  }


  function _getIdentifiers (cmd, parm) {
    var no;
    var pr;
    var hd;
    var cond;
    var conds = [];
    var hideList = [];
    var body = getBody.call (this);

    switch (cmd) {
    
    case 'head' :
      return getHeader.call (this);


    case 'where' :
      hd = getHeader.call (this);
      
      conds = parm.split (',')
                  .map (
                    function (cond) {
                      return cond.split ('=', 2);
                    }
                  );
      
      for (var i = 0; cond = conds[i]; i++) {
        no = hd.indexOf (cond[0]);
        if (-1 === no) {
          throw new Error ('Not found field name.');
        }
        
        hideList[no] = true;

        pr = { no : no, val : cond[1] };
        body = body.filter (
                      function (cells) {
                        return (cells[this.no] === this.val);
                      },
                      pr
                    );
      }
      
      return [getHeader.call (this)].concat (body)
               .map (
                 function (cells) {
                   return cells.filter (
                     function (_, idx) {
                       return ! (this[idx]);
                     },
                     this
                   );
                 },
                 hideList
               );
      
    
    case 'col' :
      if (isNaN (parm)) {
        hd = getHeader.call (this);
        no = hd.indexOf (parm);
        
        if (-1 === no) {
          throw new Error ('Not found field name.');
        }
        pr = { no : no };
      }
      else {
        pr = { no : Number (parm) };
      }

      return getBody.call (this)
                    .map (
                      function (cells) {
                        return cells [ this.no ];
                      },
                      pr);


    case 'row' :
      if (isNaN (parm)) {
        if ('*' !== parm) {
          throw new Error ('Syntax Error : row');
        }
        return getBody.call (this);
      }
      else {
        return getBody.call (this) [ Number (parm) ]; // this.csv [Number (parm) + 1]
      }

    
    default :
      throw new Error ();
    }
  
  }


  function getIdentifiers (fgmt) {
    var op = (fgmt) ? decomposition (fgmt): null;

    if (op){
      return _getIdentifiers.call (
        this,
        op[1] || op[2] || op[4] || op[6],
        op[3] || op[5] || op[7]);
    }
    else {
     throw new Error ('Syntax error : fragument.');
   }
  }





  //_______________


  function create (url) {
    var obj;

    if (url) {
      obj = new CSVFragment;
      if (fileLoad.call (obj, url)) {
        return obj;
      }
    }

    return null;
  }
  

  
  CSVFragment.prototype.getIdentifiers = getIdentifiers;
//CSVFragment.prototype.getHeader      = getHeader;
//CSVFragment.prototype.getBody        = getHeader;
  
  CSVFragment.create = create;
  
  //this.CSVFragment = CSVFragment;

  //__________________
  
  function getCSVData (url) {
    if (0 === arguments.length)
      return null;
    
    var fgmt = /^[^:/?#]+#(.+)$/.exec (url);
    var obj = CSVFragment.create (url);

    return (fgmt)
           ? obj.getIdentifiers (fgmt[1])
           : null;
  }
  
  //_______________

  this.getCSVFVragmentIdentifiers = getCSVData;
  
}) ();

/*
alert (getCSVFVragmentIdentifiers ('sample.csv#head'));
alert (getCSVFVragmentIdentifiers ('sample.csv#row:2'));
alert (getCSVFVragmentIdentifiers ('sample.csv#row:*').join("\n"));
alert (getCSVFVragmentIdentifiers ('sample.csv#col:temperature').join("\n"));
alert (getCSVFVragmentIdentifiers ('sample.csv#col:2').join("\n"));
*/
alert (getCSVFVragmentIdentifiers ('sample.csv#where:date=2011-01-01').join("\n"));
alert (getCSVFVragmentIdentifiers ('sample.csv#where:date=2011-01-01,place=Galway').join("\n"));



</script>
<ul>
  <li>http://tools.ietf.org/id/draft-hausenblas-csv-fragment-00.html
  <li>http://www39.atwiki.jp/eriax/pages/124.html
  <li>http://translate.google.co.jp/translate?hl=ja&sl=en&tl=ja&u=http%3A%2F%2Ftools.ietf.org%2Fhtml%2F%2Fdraft-hausenblas-csv-fragment-00
</ul>