1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1994-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29
30 #include "error.h"
31 #include "ovl.h"
32
33 // We are likely to have a lot of octave_value_list objects to allocate,
34 // so make the grow_size large.
35
octave_value_list(const std::list<octave_value> & lst)36 octave_value_list::octave_value_list (const std::list<octave_value>& lst)
37 {
38 std::size_t nel = lst.size ();
39
40 if (nel > 0)
41 {
42 m_data.resize (nel);
43 octave_idx_type k = 0;
44 for (const auto& ov : lst)
45 m_data[k++] = ov;
46 }
47 }
48
octave_value_list(const std::list<octave_value_list> & lst)49 octave_value_list::octave_value_list (const std::list<octave_value_list>& lst)
50 {
51 octave_idx_type n = 0;
52 octave_idx_type nel = 0;
53
54 // Determine number.
55 for (const auto& ovl : lst)
56 {
57 n++;
58 nel += ovl.length ();
59 }
60
61 // Optimize single-element case
62 if (n == 1)
63 m_data = lst.front ().m_data;
64 else if (nel > 0)
65 {
66 m_data.resize (nel);
67 octave_idx_type k = 0;
68 for (const auto& ovl : lst)
69 {
70 for (octave_idx_type i = 0; i < ovl.length (); i++)
71 m_data[k++] = ovl(i);
72 }
73
74 assert (k == nel);
75 }
76
77 }
78
79 octave_value_list&
prepend(const octave_value & val)80 octave_value_list::prepend (const octave_value& val)
81 {
82 octave_idx_type n = length ();
83
84 resize (n + 1);
85
86 while (n > 0)
87 {
88 elem (n) = elem (n - 1);
89 n--;
90 }
91
92 elem (0) = val;
93
94 return *this;
95 }
96
97 octave_value_list&
append(const octave_value & val)98 octave_value_list::append (const octave_value& val)
99 {
100 octave_idx_type n = length ();
101
102 resize (n + 1);
103
104 elem (n) = val;
105
106 return *this;
107 }
108
109 octave_value_list&
append(const octave_value_list & lst)110 octave_value_list::append (const octave_value_list& lst)
111 {
112 octave_idx_type len = length ();
113 octave_idx_type lst_len = lst.length ();
114
115 resize (len + lst_len);
116
117 for (octave_idx_type i = 0; i < lst_len; i++)
118 elem (len + i) = lst (i);
119
120 return *this;
121 }
122
123 octave_value_list&
reverse(void)124 octave_value_list::reverse (void)
125 {
126 octave_idx_type n = length ();
127
128 for (octave_idx_type i = 0; i < n / 2; i++)
129 {
130 octave_value tmp = elem (i);
131 elem (i) = elem (n - i - 1);
132 elem (n - i - 1) = tmp;
133 }
134
135 return *this;
136 }
137
138 octave_value_list
splice(octave_idx_type offset,octave_idx_type rep_length,const octave_value_list & lst) const139 octave_value_list::splice (octave_idx_type offset, octave_idx_type rep_length,
140 const octave_value_list& lst) const
141 {
142 octave_value_list retval;
143
144 octave_idx_type len = length ();
145
146 if (offset < 0 || offset >= len)
147 {
148 if (! (rep_length == 0 && offset == len))
149 error ("octave_value_list::splice: invalid OFFSET");
150 }
151
152 if (rep_length < 0 || rep_length + offset > len)
153 error ("octave_value_list::splice: invalid LENGTH");
154
155 octave_idx_type lst_len = lst.length ();
156
157 octave_idx_type new_len = len - rep_length + lst_len;
158
159 retval.resize (new_len);
160
161 octave_idx_type k = 0;
162
163 for (octave_idx_type i = 0; i < offset; i++)
164 retval(k++) = elem (i);
165
166 for (octave_idx_type i = 0; i < lst_len; i++)
167 retval(k++) = lst (i);
168
169 for (octave_idx_type i = offset + rep_length; i < len; i++)
170 retval(k++) = elem (i);
171
172 return retval;
173 }
174
175 bool
all_strings_p(void) const176 octave_value_list::all_strings_p (void) const
177 {
178 octave_idx_type n = length ();
179
180 for (octave_idx_type i = 0; i < n; i++)
181 if (! elem(i).is_string ())
182 return false;
183
184 return true;
185 }
186
187 bool
all_scalars(void) const188 octave_value_list::all_scalars (void) const
189 {
190 octave_idx_type n = length ();
191
192 for (octave_idx_type i = 0; i < n; i++)
193 {
194 dim_vector dv = elem(i).dims ();
195 if (! dv.all_ones ())
196 return false;
197 }
198
199 return true;
200 }
201
202 bool
any_cell(void) const203 octave_value_list::any_cell (void) const
204 {
205 octave_idx_type n = length ();
206
207 for (octave_idx_type i = 0; i < n; i++)
208 if (elem (i).iscell ())
209 return true;
210
211 return false;
212 }
213
214 bool
has_magic_colon(void) const215 octave_value_list::has_magic_colon (void) const
216 {
217 octave_idx_type n = length ();
218
219 for (octave_idx_type i = 0; i < n; i++)
220 if (elem(i).is_magic_colon ())
221 return true;
222
223 return false;
224 }
225
226 string_vector
make_argv(const std::string & fcn_name) const227 octave_value_list::make_argv (const std::string& fcn_name) const
228 {
229 string_vector argv;
230
231 if (! all_strings_p ())
232 error ("%s: all arguments must be strings", fcn_name.c_str ());
233
234 octave_idx_type len = length ();
235
236 octave_idx_type total_nr = 0;
237
238 for (octave_idx_type i = 0; i < len; i++)
239 {
240 // An empty std::string ("") has zero columns and zero rows
241 // (a change that was made for Matlab contemptibility.
242
243 octave_idx_type n = elem (i).rows ();
244
245 total_nr += n ? n : 1;
246 }
247
248 octave_idx_type k = 0;
249 if (! fcn_name.empty ())
250 {
251 argv.resize (total_nr+1);
252 argv[0] = fcn_name;
253 k = 1;
254 }
255 else
256 argv.resize (total_nr);
257
258 for (octave_idx_type i = 0; i < len; i++)
259 {
260 octave_idx_type nr = elem (i).rows ();
261
262 if (nr < 2)
263 argv[k++] = elem (i).string_value ();
264 else
265 {
266 string_vector tmp = elem (i).string_vector_value ();
267
268 for (octave_idx_type j = 0; j < nr; j++)
269 argv[k++] = tmp[j];
270 }
271 }
272
273 return argv;
274 }
275
276 void
make_storable_values(void)277 octave_value_list::make_storable_values (void)
278 {
279 octave_idx_type len = length ();
280 const std::vector<octave_value>& cdata = m_data;
281
282 for (octave_idx_type i = 0; i < len; i++)
283 {
284 // This is optimized so that we don't force a copy unless necessary.
285 octave_value tmp = cdata[i].storable_value ();
286 if (! tmp.is_copy_of (cdata[i]))
287 m_data[i] = tmp;
288 }
289 }
290