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