From 7573a827a0993fbb795c3351140eb5427ac5692a Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Tue, 17 Jun 2014 23:48:13 -0400 Subject: Initial implementation of cat and friends This is intended to be a very basic subset (for now) of cat that will be more efficient for general I/O (mainly pipeines between shell functions) than spawning a process. Benchmarks do show that it is definitely not always worth the trade off, but those situations are less likely to occur (large inputs) and, if they do, the author can be aware of it and use a function that will prevent the builtin from being used (I'll provide that as well, instead of `command cat`). I'll be writing an article on this with benchmarks to rationalize and explain in depth my approach. --- src/coreutils/cat.sh | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/coreutils/cat.sh (limited to 'src') diff --git a/src/coreutils/cat.sh b/src/coreutils/cat.sh new file mode 100644 index 0000000..52c3a93 --- /dev/null +++ b/src/coreutils/cat.sh @@ -0,0 +1,97 @@ +#!/bin/bash +# Bash alternative to external cat call +# +# Copyright (C) 2014 Mike Gerwitz +# +# This file is part of pkgsh. +# +# pkgsh is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# N.B. While this shell implementation may be faster for most use cases, the +# external binary will likely be much faster for large streams. +# +# This also contains some convenience functions that are not part of +# GNU coreutils. +## + +[ -z $__PKGSH_INC_COREUTILS_CAT ] || return +__PKGSH_INC_COREUTILS_CAT=1 + + +## +# Echo characters from stdin up to (but not including) the provided +# delimiter +cat-until() +{ + local -r delim="${1?Missing terminating delimiter}" + local -r file="${2:-/dev/stdin}" + + read -rd "$delim" < "$file" + local -ri result=$? + + echo -n "$REPLY" + return $result +} + + +## +# Echo characters from stdin up to and including the provided delimiter +cat-until-incl() +{ + # `cat-until` will validate + local -r delim="$1" + cat-until "$@" \ + && echo -n "$delim" +} + + +## +# Proxies to either the shell implementation of cat or the system binary, +# depending on support +cat() +{ + [[ "$1" =~ ^-[^-\ ] ]] \ + && command cat "$@" \ + || quickcat "$@" +} + + +## +# Limited implementation of `cat` for performance +# +# TODO: The proper research has not yet gone into optimizing this; this is +# just an initial implementation to get things going. I will be addressing +# this shortly. +# +# TODO: Exit status. +quickcat() +{ + local in="${1:-/dev/stdin}" + [ "$in" == - ] && in=/dev/stdin + readonly in + + while true; do + IFS= read -r || { + echo -n "$REPLY" + break + } + + echo "$REPLY" + done < "$in" + + if shift && [ $# -ne 0 ]; then + quickcat "$@" + fi +} + -- cgit v1.2.1