fix sprintf to take care of %%
[scilab.git] / scilab / modules / output_stream / sci_gateway / cpp / sci_msprintf.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) INRIA
4  * Copyright (C) 2010 - DIGITEO - ELIAS Antoine
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 "funcmanager.hxx"
15 #include "output_stream_gw.hxx"
16 #include "scilab_sprintf.hxx"
17 #include "function.hxx"
18 #include "string.hxx"
19 #include "overload.hxx"
20 #include "execvisitor.hxx"
21
22 extern "C"
23 {
24 #include "Scierror.h"
25 #include "localization.h"
26 }
27
28 /*--------------------------------------------------------------------------*/
29 types::Callable::ReturnValue sci_msprintf(types::typed_list &in, int _iRetCount, types::typed_list &out)
30 {
31     //Structure to store, link between % and input value
32     ArgumentPosition* pArgs = NULL;
33
34     if (in.size() < 1)
35     {
36         Scierror(999, _("%s: Wrong number of input arguments: at least %d expected.\n"), "msprintf", 1);
37         return types::Function::Error;
38     }
39
40     if (in[0]->isString() == false || in[0]->getAs<types::String>()->getSize() != 1)
41     {
42         Scierror(999, _("%s: Wrong type for input argument #%d: A string expected.\n"), "msprintf" , 1);
43         return types::Function::Error;
44     }
45
46     for (int i = 1 ; i < in.size() ; i++)
47     {
48         if (in[i]->isDouble() == false && in[i]->isString() == false)
49         {
50             std::wstring wstFuncName = L"%"  + in[i]->getShortTypeStr() + L"_msprintf";
51             return Overload::call(wstFuncName, in, _iRetCount, out, new ast::ExecVisitor());
52         }
53     }
54
55     wchar_t* pwstInput = in[0]->getAs<types::String>()->get()[0];
56     int iNumberPercent = 0;
57     int iNumberPercentPercent = 0;
58     for (int i = 0; i < wcslen(pwstInput); i++)
59     {
60         if (pwstInput[i] == L'%')
61         {
62             iNumberPercent++;
63             if (pwstInput[i + 1] == L'%')
64             {
65                 //it is a %%, not a %_
66                 iNumberPercentPercent++;
67                 //force incremantation to bypass the second % of %%
68                 i++;
69             }
70         }
71     }
72
73     //Input values must be less or equal than excepted
74     if ((in.size() - 1) > iNumberPercent - iNumberPercentPercent)
75     {
76         Scierror(999, _("%s: Wrong number of input arguments: at most %d expected.\n"), "msprintf", iNumberPercent);
77         return types::Function::Error;
78     }
79
80     //determine if imput values are ... multiple values
81     int iNumberCols = 0;
82     if ( in.size() > 1 )
83     {
84         int iRefRows = in[1]->getAs<GenericType>()->getRows();
85         for (int i = 1 ; i < in.size() ; i++)
86         {
87             //all arguments must have the same numbers of rows !
88             if (iRefRows != in[i]->getAs<GenericType>()->getRows())
89             {
90                 Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), "msprintf");
91                 return types::Function::Error;
92             }
93
94             iNumberCols += in[i]->getAs<GenericType>()->getCols();
95         }
96     }
97
98     if (iNumberCols != iNumberPercent - iNumberPercentPercent)
99     {
100         Scierror(999, _("%s: Wrong number of input arguments: data doesn't fit with format.\n"), "msprintf");
101         return types::Function::Error;
102     }
103
104
105     //fill ArgumentPosition structure
106     pArgs = new ArgumentPosition[iNumberPercent - iNumberPercentPercent];
107     int idx = 0;
108     for (int i = 1 ; i < in.size() ; i++)
109     {
110         for (int j = 0 ; j < in[i]->getAs<GenericType>()->getCols() ; j++)
111         {
112             pArgs[idx].iArg = i;
113             pArgs[idx].iPos = j;
114             pArgs[idx].type = in[i]->getType();
115             idx++;
116         }
117     }
118
119     int iOutputRows = 0;
120     int iNewLine = 0;
121     wchar_t** pwstOutput = scilab_sprintf("msprintf", pwstInput, in, pArgs, iNumberPercent, &iOutputRows, &iNewLine);
122
123     if (pwstOutput == NULL)
124     {
125         delete[] pArgs;
126         return types::Function::Error;
127     }
128
129     types::String* pOut = new types::String(iOutputRows, 1);
130     pOut->set(pwstOutput);
131     out.push_back(pOut);
132
133     for (int i = 0 ; i < iOutputRows ; i++)
134     {
135         FREE(pwstOutput[i]);
136     }
137     FREE(pwstOutput);
138     return types::Function::OK;
139 }
140 /*--------------------------------------------------------------------------*/