docs: function _parseSmartTable(lines,
                                ignoreLinesCount,
                                regSplitRow,
                                funcCheckTableEnd)
      {
          /* Example 1:
  
           ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED
             1 Raw_Read_Error_Rate     0x0003   100   100   006    Pre-fail  Always
             3 Spin_Up_Time            0x0003   100   100   000    Pre-fail  Always
             4 Start_Stop_Count        0x0002   100   100   020    Old_age   Always
             5 Reallocated_Sector_Ct   0x0003   100   100   036    Pre-fail  Always
             9 Power_On_Hours          0x0003   100   100   000    Pre-fail  Always
            12 Power_Cycle_Count       0x0003   100   100   000    Pre-fail  Always
           190 Airflow_Temperature_Cel 0x0003   069   069   050    Pre-fail  Always
  
             Example 2:
  
           Num  Test_Description    Status    Remaining  LifeTime
           # 1  Vendor (0xff)       Completed       00%       463
           # 2  Vendor (0xff)       Completed       00%       288
           # 3  Extended offline    Completed       00%       263
           # 4  Short offline       Completed       00%       263
          */
  
          var resultObj = [];
          var colHeaders;
          regSplitRow = regSplitRow || /\s{2,}/; //default to split with more than 2 spaces
  
          if (lines.length <= ignoreLinesCount + 1) { //should contains at least the column header row
              return resultObj;
          }
  
          //The first line should be the column header
          colHeaders = lines[ignoreLinesCount].split(/\s+/);
          if (colHeaders[0].trim().length === 0) {
              colHeaders.shift();
          }
  
          for (var i = ignoreLinesCount + 1; i < lines.length; i+=1) {
              if (funcCheckTableEnd && funcCheckTableEnd(lines[i])) {
                  break; //skip early if reach the end of table
              }
  
              var arr = lines[i].split(regSplitRow);
              if (arr[0].trim().length === 0) {
                  arr.shift();
              }
  
              var entry = {};
              var j;
              for (j = 0; j < colHeaders.length - 1; j += 1) {
                  entry[colHeaders[j]] = arr[j]; //Fill each column data
              }
              //There maybe more cells than the header, we append these cells to the last column.
              //For example, the 'RAW_VALUE' in the attributes table may be like '31 (Min/Max 31/31)'
              entry[colHeaders[j]] = arr.slice(j, arr.length).join(' ');
              resultObj.push(entry);
          }
  
          return resultObj;
      }