www.gusucode.com > datastoreio工具箱 matlab源码程序 > datastoreio/+matlab/+io/+datastore/@TabularTextDatastore/concatLiteral.m

    function [outCellStr, outSkipVec] = concatLiteral(inFormatCell, strOrCellStrFlag)
%concatLiteral preserves/concatenates literal with/to primitive formats to
%return data
%   This function is responsible for either combining literals with
%   primitive formats to make them format specifiers which return data or
%   preserve the customer specified format without modifying the ordering
%   of literals based on strOrCellStrFlag. When the flag is false every
%   literal is concatenated to the primitive format on its right. If the
%   literal does not find a primitive format on the right, it appends the
%   literal to the format found on the left. When the flag is true we do
%   not modify the ordering of literals. The function also returns a
%   logical vector indicating the skipped formats

%   Copyright 2014 The MathWorks, Inc.

% imports
import matlab.io.datastore.TabularTextDatastore;

% input format string
inStr = strjoin(inFormatCell);

% using the builtin textscan interface to validate the given format
builtin('_textscan_interface', TabularTextDatastore.DEFAULT_TEXTSCAN_STRING, ...
                                                                    inStr);

% preserve the literal ordering in the formats
if strOrCellStrFlag
    numElements = numel(inFormatCell);
    outSkipVec = zeros(1,numElements);
    
    for i = 1:numElements
        outSkipVec = setSkippedVecWhenCombinedWithPrev(inFormatCell{i}, ...
                                                            i, outSkipVec);
    end    
    outCellStr = inFormatCell;
    return
end

% we order the literal formats here based on the rules described above.
% construct a format parser struct
inStruct = matlab.iofun.internal.formatParser(inStr);

% check if all the format specifiers are literals.
litVec = inStruct.IsLiteral;
if all(litVec)
    error(message('MATLAB:datastoreio:tabulartextdatastore:invalidLiteralFormat'));
end

% when inCellStr is a cell of one string, it cannot be a skipped format
inCellStr = inStruct.Format;
inSkipVec = inStruct.IsSkipped;
startIdx = 1;
curr = startIdx;
outCurr = startIdx;
endIdx = numel(inCellStr);
outSkipVec = zeros(1,endIdx);

% a single literal is accounted for above.
if startIdx == endIdx
    outSkipVec = inSkipVec;
    outCellStr = inCellStr;
    return
end

% loop over individual formats 
while(curr <= endIdx)
    next = curr + 1;
    prev = outCurr - 1;
    
    combinedWithNext = 0;
    combinedWithPrev = 0;
    
    if (litVec(curr))        
        if curr == startIdx
            % processing the first element
            if litVec(next)
                % combine literals until we find a non-literal format
                nonLiteralPos = find(~litVec,1);
                outCellStr{outCurr} = ...
                         strjoin(inCellStr(curr:nonLiteralPos));%#ok<AGROW>
                combinedWithNext = nonLiteralPos - 1;
                outSkipVec = setSkippedVec(inSkipVec,nonLiteralPos, ...
                                                       outCurr,outSkipVec);
            else
                outCellStr{outCurr} = ...
                                  strjoin(inCellStr(curr:next));%#ok<AGROW>
                combinedWithNext = 1;
                outSkipVec = setSkippedVec(inSkipVec,next,outCurr, ...
                                                               outSkipVec);
            end
        elseif curr == endIdx
            % processing the last element.
            outCellStr = combineWithPrev(prev, inCellStr{curr}, outCellStr);            
            combinedWithPrev = 1;
            outSkipVec = ...
                setSkippedVecWhenCombinedWithPrev(outCellStr{prev}, ...
                                                         prev, outSkipVec);
        else
            % processing for the in between elements
            if litVec(next)
                outCellStr = combineWithPrev(prev, inCellStr{curr}, ...
                                                               outCellStr);
                combinedWithPrev = 1;
                outSkipVec = ...
                    setSkippedVecWhenCombinedWithPrev(outCellStr{prev}, ...
                                                         prev, outSkipVec);
            else
                outCellStr{outCurr} = strjoin(inCellStr(curr:next), ...
                                                           ''); %#ok<AGROW> 
                combinedWithNext = 1;                
                outSkipVec = setSkippedVec(inSkipVec, next, outCurr, ...
                                                               outSkipVec);
            end
        end
    else
        % handling formats without literals
        outCellStr{outCurr} = inCellStr{curr}; %#ok<AGROW>
        outSkipVec = setSkippedVec(inSkipVec, curr, outCurr, outSkipVec);        
    end
    
    % post processing
    curr = curr + combinedWithNext + 1;
    outCurr= outCurr + 1 - combinedWithPrev;
end

% resizing to size the outputLogical
outSkipVec(numel(outCellStr) + 1: end) = [];
end

function skippedVec = setSkippedVecWhenCombinedWithPrev(str, prev, skippedVec)
%SETSKIPPEDVECWHENCOMBINEDWITHPREV sets the skipped vector
%   This function is used to find a skipped non-literal format from a
%   format specifier and set the skipped vector accordingly. The format
%   that is passed into this function is a result of a combination of the
%   current format with the previous format. This is needed to create a
%   logical vector of the formats which are skipped and non-literal. This
%   function guards against formats with %'s and *'s in them and
%   differntiates them from traditional skipped formats like (%*s etc)

%   Copyright 2014 The MathWorks, Inc.

% create a formatParser struct
tempStruct = matlab.iofun.internal.formatParser(str);

% a single literal format is invalid
if (1 == numel(tempStruct.Format)) && (tempStruct.IsLiteral)
    error(message('MATLAB:datastoreio:tabulartextdatastore:invalidLiteralFormat'))
end

numPrimitiveFormats = nnz(~tempStruct.IsSkipped);
numSkipOnlyFormats = nnz(tempStruct.IsSkipped & ~tempStruct.IsLiteral);

% number of skipped only formats (non-literal) for a given string should be
% 1, or the number of unskipped formats should be 1, and both should not be
% same
if (numPrimitiveFormats > 1)  || (numSkipOnlyFormats > 1) || ...
                                (numPrimitiveFormats == numSkipOnlyFormats)
    error(message('MATLAB:datastoreio:tabulartextdatastore:tooManyFormats'));   
end

% set the output logical vector only if there is a skipped non-literal
if any(xor(tempStruct.IsSkipped, tempStruct.IsLiteral))
    skippedVec(prev) = 1; 
end
end

function skippedVec = setSkippedVec(skipLog, inputIdx, outputIdx, skippedVec)
%SETSKIPPEDVEC sets the skipped vector
%   This function sets the skipped vector based on the whether a particular
%   input format is skipped or not. This function is called whenever a
%   concatenation with the next format happens or when there is no
%   concatenation.

%   Copyright 2014 The MathWorks, Inc.

if skipLog(inputIdx)
    skippedVec(outputIdx) = 1;
end
end

function outCellStr = combineWithPrev(prev, inStr, outCellStr)
%COMBINEWITHPREV combines 2 formats with a space
%   This function combines the input format string and the current output
%   format with a space.

%   Copyright 2014 The MathWorks, Inc.

outCellStr{prev} = [outCellStr{prev}, ' ', inStr];
end