* Bug #13780 fixed - size with two input and output arguments must return an error.
[scilab.git] / scilab / modules / elementary_functions / sci_gateway / cpp / sci_size.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - DIGITEO - Antoine ELIAS
4  * Copyright (C) 2015 - Scilab Enterprises - Anais AUBERT
5  *
6  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at
10  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11  *
12  */
13 /*--------------------------------------------------------------------------*/
14 #include "elem_func_gw.hxx"
15 #include "types.hxx"
16 #include "string.hxx"
17 #include "container.hxx"
18 #include "getmode.hxx"
19 #include "overload.hxx"
20 #include "execvisitor.hxx"
21 #include "context.hxx"
22
23 extern "C"
24 {
25 #include "Scierror.h"
26 #include "localization.h"
27 #include "os_string.h"
28 }
29
30 using namespace types;
31 /*--------------------------------------------------------------------------*/
32 Function::ReturnValue sci_size(types::typed_list &in, int _iRetCount, types::typed_list &out)
33 {
34     if (in.size() < 1)
35     {
36         Scierror(999, _("%s: Wrong number of input arguments: At least %d expected.\n"), "size", 1);
37         return Function::Error;
38     }
39
40     switch (in[0]->getType())
41     {
42         // Dedicated case for lists.
43         case InternalType::ScilabMList:
44         {
45             ast::ExecVisitor exec;
46             std::wstring wstFuncName = L"%" + in[0]->getShortTypeStr() + L"_size";
47             Overload::call(wstFuncName, in, _iRetCount, out, &exec);
48             break;
49         }
50         case InternalType::ScilabTList:
51         {
52             // calls the overload if it exists.
53             std::wstring wstFuncName = L"%"  + in[0]->getTypeStr() + L"_size";
54             types::InternalType *pIT = symbol::Context::getInstance()->get(symbol::Symbol(wstFuncName));
55             if (pIT)
56             {
57                 ast::ExecVisitor exec;
58                 return Overload::call(wstFuncName, in, _iRetCount, out, &exec);
59             }
60         }
61         case InternalType::ScilabList:
62         {
63             if (in.size() > 1)
64             {
65                 Scierror(999, _("%s: Wrong number of input argument(s): %d expected.\n"), "size", 1);
66                 return Function::Error;
67             }
68
69             Double* pD = new Double(in[0]->getAs<Container>()->getSize());
70             out.push_back(pD);
71             break;
72         }
73         default :
74             // All types inherits of GenericType, so have this algorithm as default.
75         {
76             if (in[0]->isGenericType() == false)
77             {
78                 ast::ExecVisitor exec;
79                 std::wstring wstFuncName = L"%" + in[0]->getShortTypeStr() + L"_size";
80                 return Overload::call(wstFuncName, in, _iRetCount, out, &exec);
81             }
82             int iMode = -1;
83
84             if (in.size() > 2)
85             {
86                 Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "size", 1, 2);
87                 return Function::Error;
88             }
89
90             if (in.size() == 2)
91             {
92                 if (_iRetCount == 2)
93                 {
94                     Scierror(999, _("%s: Wrong number of output argument(s): %d expected.\n"), "size", 1);
95                     return Function::Error;
96                 }
97                 iMode = getMode(in, 1, 0);
98                 if (iMode == -2)
99                 {
100                     return Function::Error;
101                 }
102
103             }
104
105             int iDims   = in[0]->getAs<GenericType>()->getDims();
106             int* piDims = in[0]->getAs<GenericType>()->getDimsArray();
107
108             if (_iRetCount == 1)
109             {
110                 int iRowsOut = 1;
111                 int iColsOut = 0;
112                 double* pdblReal = NULL;
113
114                 switch (iMode)
115                 {
116                     case -1 : //lhs == 1
117                         iColsOut = iDims;
118                         break;
119                     default : //"*"
120                         iColsOut = 1;
121                         break;
122                 }
123
124                 Double* pD = new Double(iRowsOut, iColsOut);
125
126                 double* pdbl = pD->getReal();
127
128                 switch (iMode)
129                 {
130                     case -1 : //lhs == 1
131                         for (int i = 0 ; i < iDims ; i++)
132                         {
133                             pdbl[i] = piDims[i];
134                         }
135                         break;
136                     case 0 : //"*"
137                         pdbl[0] = in[0]->getAs<GenericType>()->getSize();
138                         break;
139                     default : //"r"
140                         if (iMode > iDims)
141                         {
142                             pdbl[0] = 1;
143                             out.push_back(pD);
144                             return Function::OK;
145                         }
146
147                         iColsOut = 1;
148                         pdbl[0] = piDims[iMode - 1];
149                         break;
150                 }
151                 out.push_back(pD);
152             }
153             else
154             {
155                 for (int i = 0 ; i < std::min(_iRetCount, iDims) ; i++)
156                 {
157                     Double* pD = new Double(piDims[i]);
158                     out.push_back(pD);
159                 }
160
161                 /* Multiple returns:
162                  * example: [a b c]=size(M) */
163                 if (_iRetCount > iDims)
164                 {
165                     for (int i = iDims ; i < _iRetCount ; i++)
166                     {
167                         Double* pD = new Double(1);
168                         out.push_back(pD);
169                     }
170                 }
171             }
172             break;
173         }
174     }
175     return Function::OK;
176 }
177 /*--------------------------------------------------------------------------*/