Skip to content

Commit ba84c00

Browse files
committed
Linear time list operations
Avoids quadratic string concatenation overhead in extend and preextend by processing incoming lists into local strings and appending them to the target list in a single operation. Signed-off-by: Harmen Stoppels <harmenstoppels@gmail.com>
1 parent 0b4308a commit ba84c00

1 file changed

Lines changed: 69 additions & 30 deletions

File tree

cc.sh

Lines changed: 69 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -94,23 +94,6 @@ setsep() {
9494
esac
9595
}
9696

97-
# prepend LISTNAME ELEMENT
98-
#
99-
# Prepend ELEMENT to the list stored in the variable LISTNAME.
100-
# Handles empty lists and single-element lists.
101-
prepend() {
102-
varname="$1"
103-
elt="$2"
104-
105-
if empty "$varname"; then
106-
eval "$varname=\"\${elt}\""
107-
else
108-
# Get the appropriate separator for the list we're appending to.
109-
setsep "$varname"
110-
eval "$varname=\"\${elt}${sep}\${$varname}\""
111-
fi
112-
}
113-
11497
# append LISTNAME ELEMENT [SEP]
11598
#
11699
# Append ELEMENT to the list stored in the variable LISTNAME,
@@ -135,13 +118,45 @@ append() {
135118
# to the list stored in LISTNAME1.
136119
# If PREFIX is provided, prepend it to each element.
137120
extend() {
138-
# Figure out the appropriate IFS for the list we're reading.
139-
setsep "$2"
121+
_listname="$1"
122+
_src_list="$2"
123+
_prefix="$3"
124+
125+
setsep "$_src_list"
140126
if [ "$sep" != " " ]; then
141127
IFS="$sep"
142128
fi
143-
eval "for elt in \${$2}; do append $1 \"$3\${elt}\"; done"
129+
# Turn list into positional parameters
130+
eval "set -- \${$_src_list}"
144131
unset IFS
132+
133+
if [ $# -eq 0 ]; then
134+
return
135+
fi
136+
137+
setsep "$_listname"
138+
_target_sep="$sep"
139+
140+
if [ -z "$_prefix" ]; then
141+
IFS="$_target_sep"
142+
_ext_str="$*"
143+
unset IFS
144+
else
145+
_ext_str=""
146+
for elt in "$@"; do
147+
if [ -z "$_ext_str" ]; then
148+
_ext_str="${_prefix}${elt}"
149+
else
150+
_ext_str="${_ext_str}${_target_sep}${_prefix}${elt}"
151+
fi
152+
done
153+
fi
154+
155+
if empty "$_listname"; then
156+
eval "$_listname=\"\${_ext_str}\""
157+
else
158+
eval "$_listname=\"\${$_listname}${_target_sep}\${_ext_str}\""
159+
fi
145160
}
146161

147162
# preextend LISTNAME1 LISTNAME2 [PREFIX]
@@ -150,20 +165,44 @@ extend() {
150165
# to the list at LISTNAME1, preserving order.
151166
# If PREFIX is provided, prepend it to each element.
152167
preextend() {
153-
# Figure out the appropriate IFS for the list we're reading.
154-
setsep "$2"
168+
_listname="$1"
169+
_src_list="$2"
170+
_prefix="$3"
171+
172+
setsep "$_src_list"
155173
if [ "$sep" != " " ]; then
156174
IFS="$sep"
157175
fi
176+
eval "set -- \${$_src_list}"
177+
unset IFS
158178

159-
# first, reverse the list to prepend
160-
_reversed_list=""
161-
eval "for elt in \${$2}; do prepend _reversed_list \"$3\${elt}\"; done"
179+
if [ $# -eq 0 ]; then
180+
return
181+
fi
162182

163-
# prepend reversed list to preextend in order
164-
IFS="${lsep}"
165-
for elt in $_reversed_list; do prepend "$1" "$3${elt}"; done
166-
unset IFS
183+
setsep "$_listname"
184+
_target_sep="$sep"
185+
186+
if [ -z "$_prefix" ]; then
187+
IFS="$_target_sep"
188+
_ext_str="$*"
189+
unset IFS
190+
else
191+
_ext_str=""
192+
for elt in "$@"; do
193+
if [ -z "$_ext_str" ]; then
194+
_ext_str="${_prefix}${elt}"
195+
else
196+
_ext_str="${_ext_str}${_target_sep}${_prefix}${elt}"
197+
fi
198+
done
199+
fi
200+
201+
if empty "$_listname"; then
202+
eval "$_listname=\"\${_ext_str}\""
203+
else
204+
eval "$_listname=\"\${_ext_str}${_target_sep}\${$_listname}\""
205+
fi
167206
}
168207

169208
execute() {
@@ -966,7 +1005,7 @@ fi
9661005
if [ -n "$SPACK_CCACHE_BINARY" ]; then
9671006
case "$lang_flags" in
9681007
C|CXX) # ccache only supports C languages
969-
prepend full_command_list "${SPACK_CCACHE_BINARY}"
1008+
full_command_list="${SPACK_CCACHE_BINARY}${lsep}${full_command_list}"
9701009
# workaround for stage being a temp folder
9711010
# see #3761#issuecomment-294352232
9721011
export CCACHE_NOHASHDIR=yes

0 commit comments

Comments
 (0)