ref: 1ef3c13acf54fafc080c2dfada62e13dddf1c75b
parent: 7cdd489f860382e9943999947f4c1c262d47715e
author: JeffBezanson <jeff.bezanson@gmail.com>
date: Sat Aug 30 00:53:59 EDT 2008
removing a proprietary file that should not be here; I was using it as a UTF-8 test case
--- a/llt/textread.m
+++ /dev/null
@@ -1,601 +1,0 @@
-function varargout = textread(filename, format, varargin)
-% textread Formatted file read to one or more variables
-%
-% Syntax:
-% [<variable-1> <<,variable-2>> <<,variable-N>> ] = ...
-% textread( <input-filename>, <format-specifiers> <<,number-of-lines-to-read>> )
-%
-% This function is available for task parallel processing.
-%
-% ************
-%
-% The Star-P M implementation of this function exhibits the same signature and output characteristics as the Matlab
-% function of the same name.
-%
-% For details, please see matlab:textread.
-%
-% ************************
-%
-%
-
-% DOC % A
- if nargin < 2, error('Not enough input arguments.'); end
-
- if ~ischar(filename), error('Filename must be a string.'); end
-
- ifExist = exist(filename, 'file');
- if ifExist ~= 2 && ifExist ~= 4, error('File not found'); end
-
- fid = fopen(filename, 'r');
- if fid == -1, error(lasterror()); end;
-
- formatin = formatread(format);
- argin = readvarargin(varargin{:});
-
-
- % Проверка количества исходящих аргументов
- count = 0;
- for k = 1:length(formatin),
- if ~isequal(formatin(k).symbol, '*'), count = count + 1; end;
- end
- if count ~= nargout, error('widthber of outputs must match the widthber of unskipped input fields.');end
-
- % Флаг flag_N - опредиляет сколько раз использовать строку формата
- % (N или пока не считаем весь файл)
- flag_N = 1;
- if ~isempty(argin.N)
- N = argin.N;
- else
- N = 1; flag_N = 0;
- end
-
- % Пропустить первые N == headerlines линий
- for i = 1:argin.headerlines
- text = fgets(fid);
- end
-
- % Если строка пустая считать следующую
- text = fgets(fid);
-
- t = 1;
- k = 1;
-
- maxlen = 1;
- vararginEmpty = 1;
-
- while N
-
- t = 1;
- if ~isempty(format)
- if passLine(text, argin)
- for j = 1:length(formatin)
- s = formatin(j);
-
- if s.type == 'c' && isempty(text)
- while 1
- text = fgets(fid);
- if ~ischar(text)
- fclose(fid);
- return;
- else
- if ~(text(1) == 13)
- break;
- end
- end
- end
- end
-
-
- % Удалить первые лишние пробелы
- text = removeAllFirstSpaces(text, argin.delimiter);
- % Считать следующее слово указанного типа
- [out, text] = switchType(text, s, argin, fid);
- % Пропустить слово если установлен параметр *
-
- if ~isequal(s.symbol, '*')
- if ~isempty(text) || ~(isempty(out) || isequal(out, {''}))
- out = setEmptyValue(out, s, argin);
- if vararginEmpty
- varargout{t}(1, :) = out;
- else
- varargout{t}(end + 1, :) = out;
- end
- end
- t = t + 1;
- end;
-
- % Убрать первый символ если он равен delimiter
- if ~isempty(argin.delimiter) && ~isempty(text) && isa(text, 'char')
- if find(argin.delimiter == text(1))
- text = text(2:end);
- end
- end;
- end
- vararginEmpty = 0;
- end
- else % Если строка формата не задана читать как double
-
- if passLine(text, argin)
- [out, text] = readDoubleArray(text, argin);
- curmaxlen = maxlen;
- if length(out) > maxlen, maxlen = length(out); end;
- for z = 1:k
- for q = curmaxlen+1:maxlen
- varargout{1}(z, q) = argin.emptyvalue;
- end
- end
- for q = length(out)+1:maxlen
- out(q) = argin.emptyvalue;
- end
-
- varargout{1}(k, :) = out;
- k = k + 1;
- end
-
-
- end
-
- text = removeAllFirstSpaces(text, argin.delimiter);
- % Если строка пустая считать следующую
- if isempty(text)
- text = fgets(fid);
- elseif find(text(1) == [10 13])
- text = fgets(fid);
- end
- % Выйти если не смогли считать строку
- if ~ischar(text), break; end;
-
- if flag_N, N = N - 1; end;
- end
-
- fclose(fid);
-
-end
-
-% -------- Работа с текстом ---------------------------
-
-% Удаляет все первые разделители
-function text = removeAllFirstSpaces(text, delimiter)
- %if ~isempty(delimiter), return; end;
- idx = [];
- for k = 1:length(text)
- idx = find(text(k) ~= ' ', 1);
- if ~isempty(idx), break; end;
- end
- if ~isempty(idx)
- text = text(k:end);
- else
- text = '';
- end
-end
-
-% Читает первые n - символов
-function [word, text] = readCharacters(text, n, fid)
- word = '';
- while n
- if n > length(text)
- word = [word text(1:end)];
- n = n - length(text);
- text = fgets(fid);
- if ~ischar(text), error(sprintf('Trouble reading characters from file: %s', text)); end
- else
- word = [word text(1:n)];
- text = text(n+1:end);
- n = 0;
- end
- end
-end
-
-% Читает первое слово до разделитель или первые n - символов
-function [word, text] = readString(text, n, delimiter)
- if isempty(delimiter), delimiter = [13, 10, 32];
- else
- delimiter = [delimiter, 13, 10];
- end
-
- word = '';
- if isempty(n) || n > length(text) , n = length(text); end;
- for k = 1:n
- if find(delimiter == text(k))
- word = text(1:k-1);
- text = text(k:end);
- return;
- end
- end
- word = text(1:k);
- text = text(k+1:end);
-
-end
-
-% Читает первые числа до разделителяили или первые n - символов
-function [word, text] = readNumber(text, n)
-
- if isempty(text), word = ''; end;
-
- word = [];
- if isempty(n) || length(text) < n, n = length(text); end;
-
- for k = 1:n
- if text(k) < 48 || text(k) > 57
- word = text(1:k-1);
- text = text(k:end);
- return;
- end
- end
- word = text(1:k);
- text = text(k+1:end);
-
-end
-
-% Читает число с точкой до разделителяили или первые n - символов
-function [word, text] = readFloat(text, s)
-
- if isempty(text), word = ''; return; end;
-
- if isempty(s), s.width = []; s.precision = []; end;
-
- if isempty(s.width) || length(text) < s.width
- n = length(text);
- else
- n = s.width;
- end;
-
- if isempty(s.precision), s.precision = n; end;
-
- % Чтение знака
- [sign, text] = getSign(text);
- if ~isempty(sign), n = n - 1; end;
-
- point = 0;
- npoint = 0;
- word = sign;
- for k = 1:n
- if point
- npoint = npoint + 1;
- end
- if text(k) == '.' && ~point
- point = 1;
- continue;
- end
- if text(k) < 48 || text(k) > 57 || npoint > s.precision
- word = [word text(1:k-1)];
- text = text(k:end);
- return;
- end
- end
- word = [word text(1:k)];
- text = text(k+1:end);
-
-end
-
-% Определяет знак
-function [sign, text] = getSign(text)
- if isempty(text), sign = ''; return; end;
- if text(1) == '+' || text(1) == '-'
- sign = text(1);
- text = text(2:end);
- if isempty(text) || text(1) < 48 || text(1) > 57, error(sprintf('Trouble reading double from file: %s', text)); end;
- else
- sign = [];
- end
-end
-
-% 0 - пропустить строку, 1 - обрабатывать
-function out = passLine(text, argin)
-
- isdelimiter = 0;
- if argin.delimiter
- if ~isempty(find(text == argin.delimiter, 1))
- isdelimiter = 1;
- end
- end
-
- isnewline = 0;
- if ~isempty(find(text(1) == [10 13], 1))
- isnewline = 1;
- end
- if ~isnewline || isdelimiter
- out = 1;
- else
- out = 0;
- end
-
-end
-
-
-% -------- Парс входящих параметров ---------------------------
-
-% Читает входящие параметры в структуру
-function argin = readvarargin(varargin)
-
-
- argin = struct();
- argin(1).N = [];
- argin(1).bufsize = 4095;
- argin(1).commentstyle = [];
- argin(1).delimiter = '';
- argin(1).emptyvalue = 0;
- argin(1).endofline = [];
- argin(1).expchars = [];
- argin(1).headerlines = 0;
- argin(1).whitespace = [];
-
- if nargin == 0, return; end;
-
- k = 1;
- if isnumeric(varargin{1})
- argin.N = varargin{1};
- k = k + 1;
- end
-
-
- count = (length(varargin(k:end)) / 2);
- if floor(count) - count ~= 0, error('Param/value pairs must come in pairs'); end;
-
- while k < nargin
- switch varargin{k}
-
- case 'bufsize'
- k = k + 1;
- if isinteger(varargin{k}) && isscalar(varargin{k})
- argin(1).bufsize = str2double(varargin{k});
- else
- error('Buffer size must be a scalar integer.');
- end
-
- case 'commentstyle'
- k = k + 1;
- switch varargin{k}
- case 'matlab'
- argin(1).commentstyle = '%';
- case 'shell'
- argin(1).commentstyle = '#';
- case 'c++'
- argin(1).commentstyle = '//';
- otherwise
- error('Invalid comment style.');
- end
-
- case 'delimiter'
- k = k + 1;
- switch varargin{k}
- case '\n'
- num = 10;
- case '\r'
- num = 13;
- otherwise
- num = double(varargin{k});
- end
- argin(1).delimiter = num;
-
- case 'emptyvalue'
- k = k + 1;
- if isnumeric(varargin{k}) && isscalar(varargin{k})
- argin(1).emptyvalue = varargin{k};
- else
- error('Emptyvalue must be a scalar double.');
- end
-
- case 'endofline'
- k = k + 1;
- if ischar(varargin{k})
- argin(1).endofline = varargin{k};
- else
- error('endofline must be a scalar double.');
- end
-
- case 'expchars'
-
- case 'headerlines'
- k = k + 1;
- if isnumeric(varargin{k}) && isscalar(varargin{k})
- argin(1).headerlines = varargin{k};
- else
- error('Headerlines must be a scalar integer.');
- end
-
- case 'whitespace'
-
- otherwise
- error('Unknown option');
- end
-
- k = k + 1;
-
- end
-
-end
-
-% Читает строку формата в структуру
-function R = formatread(format)
-
- formatType = ['d', 'u', 'f', 's', 'q', 'c'];
- k = 1;
- t = 1;
- s = struct();
- s(t).type = [];
- s(t).width = [];
- s(t).precision = [];
- s(t).symbol = [];
- s(t).text = [];
-
- while ~isempty(format)
-
- type = [];
- width = [];
- precision = [];
- symbol = [];
- text = [];
-
- format = removeAllFirstSpaces(format, '');
- if format(1) == '%'
- format = format(2:end);
-
-
- if format(1) == '*'
- symbol = '*';
- format = format(2:end);
- end;
-
- [width, format] = readNumber(format, []);
- if format(1) == '.'
- format = format(2:end);
- [precision, format] = readNumber(format, []);
- end
-
- type = format(1);
- format = format(2:end);
-
- % Check and save correct format
- idx = find( formatType == type );
- if isempty(idx)
- error('Incorrect format');
- end;
-
- % Save width
- if ~isempty(width), width = str2double(width);end;
- % Save precision
- if ~isempty(precision), precision = str2double(precision);end;
-
- else
-
- [text, format] = readString(format, [], [' ', '%']);
- symbol = '*';
- type = 'r';
- end
-
- s(t).type = type;
- s(t).width = width;
- s(t).precision = precision;
- s(t).symbol = symbol;
- s(t).text = text;
-
- t = t + 1;
-
- end
-
- R = s;
-
-end
-
-% ------------- Вспомагательные функции --------------------
-
-function [out, text] = switchType(text, s, argin, fid)
-
- switch s.type
-
- case 'd'
- width = s.width;
- % Чтение знака числа
- [sign, text] = getSign(text);
- if ~isempty(sign), width = width - 1; end;
- % Чиение числа
- [word, text] = readNumber(text, width);
- % Обьеденить знак и число
- out = [sign word];
- % Если опция emptyvalue установлена и число пустое то заменить на заданное
- if ~isempty(out)
- out = str2double(out);
- if isequalwithequalnans(out, NaN), error(sprintf('Trouble reading double from file: %s', text)); end;
- else
- if ~isempty(text) && isempty(find(text(1) == [13, 10], 1))
- error(sprintf('Trouble reading integer from file: %s', text));
- end
- end
-
- case 'u'
- if isempty(text) || ~isempty(find(text(1) == [13, 10], 1))
- out = []; return;
- end
- [out, text] = readNumber(text, s.width);
- % Если опция emptyvalue установлена и число пустое то заменить на заданное
- if ~isempty(out)
- out = str2double(out);
- if isequalwithequalnans(out, NaN), error(sprintf('Trouble reading integer from file: %s', text)); end;
- else
- if ~isempty(text) && isempty(find(text(1) == [13, 10], 1))
- error(sprintf('Trouble reading integer from file: %s', text));
- end
- end
-
- case 'f'
- % Чтение числа
- [out, text] = readFloat(text, s);
- % Если опция emptyvalue установлена и число пустое то заменить на заданное
- if ~isempty(out)
- out = str2double(out);
- if isequalwithequalnans(out, NaN), error(sprintf('Trouble reading double from file: %s', text)); end;
- else
- if ~isempty(text) && isempty(find(text(1) == [13, 10], 1))
- error(sprintf('Trouble reading integer from file: %s', text));
- end
- end
-
- case 's'
- [word, text] = readString(text, s.width, argin.delimiter);
- if isempty(word)
- out = {''};
- else
- out = {word};
- end
-
- case 'q'
-
- case 'c'
- n = 1;
- if ~isempty(s.width), n = s.width; end;
- [word, text] = readCharacters(text, n, fid);
- out = word(:);
-
- case 'r'
- [out, text] = readCharacters(text, length(s.text));
- if ~isequal(out, s.text), error('Trouble reading characters from file'); end;
-
- otherwise
- error('Error');
- end
-
-end
-
-function out = setEmptyValue(text, s, argin)
- out = text;
- if isempty(text)
- if find(['d', 'u', 'f'] == s.type)
- out = argin.emptyvalue;
- end
- end
-end
-
-function [out, text] = readDoubleArray(text, argin)
-
- if isempty(text); out = []; return; end;
- t = 1;
- while isempty(find(text(1) == [13 10], 1))
- % Чтение знака
- [sign, text] = getSign(text);
- % Чтение числа
- [word, text] = readFloat(text, []);
- % Обьеденить знак и число
- word = [sign word];
- % Если опция emptyvalue установлена и число пустое то заменить на заданное
- if ~isempty(argin.emptyvalue) && isempty(word)
- out(t) = argin.emptyvalue;
- else
- out(t) = str2double(word);
- if isequalwithequalnans(out(t), NaN), error('Trouble reading integer from file'); end;
- end
-
- % Убрать первый символ если он равен delimiter
- if ~isempty(argin.delimiter) && ~isempty(text)
- if find(argin.delimiter == text(1))
- text = text(2:end);
- end
- end;
-
- t = t + 1;
- if isempty(text); break; end;
- end
-
-end
-
-