156a0246e6fd5f351cf9b9308147d2a3eb77950c
[scilab.git] / scilab / modules / core / src / cpp / namstr.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010 - DIGITEO - Bernard HUGUENEY
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12 #ifdef _MSC_VER
13 #include <Windows.h>
14 #endif
15 #include <algorithm>
16 #include "machine.h" /* C2F */
17 #include "stack-def.h" /* nsiz, nlgh */
18
19 extern "C"
20 {
21     void C2F(namstr)(int* id, int* str, int* n, char* job);
22 }
23
24 namespace
25 {
26     int const blank=40; /* a scilab encoded blank character: used for padding id when name has < nsiz*6 characters*/
27 /*  constant below are used for fast padding 1->4 blanks at once */
28     int const one_blank= (blank<<24);
29     int const two_blanks= one_blank + (blank<<16);
30     int const three_blanks= two_blanks + (blank<<8);
31     int const four_blanks= three_blanks + blank;
32 }
33
34 /*
35  * convert id (array of nsiz ints) <-> str (array of n <= nlgh=4*nsiz ints)
36  * each element of str is stored in 8 bits of an id. The reming bytes (after n)
37  * are filled with blanks.
38  *
39  *
40  * @param  id contains the id of nsiz ints
41  * @param  str contains the string of nlgh ints
42  * @param  n contains the address of the (int) length of the string input for str->id, output for id->str
43  * @param job 0 => str->id, id-> str otherwise
44  *
45  * TODO: now that function search has been ported to C++, should expose a saner API that would not require strlen call nor a job arg.
46  */
47 void C2F(namstr)(int* id,int* str, int* n, char* job)
48 {
49     if (*job)  /* id -> str */
50     {
51
52         unsigned int i1(0); /* starting character from constructed str when processing an int from id */
53
54         for (unsigned int j= 0; j != nsiz; ++j, i1 += 4) /* processing id[j] into str[i1...ii+4] */
55         {
56             int id_j(id[j]);/* caching id[j] because we could not tell the compiler that id and str do not alias */
57             for (unsigned int i(i1); i!=i1+4; ++i, id_j >>= 8)/* processing each byte from id[j] into an int in str*/
58             {
59                 /* extracting the *signed* lower byte: & 0x80 tests the 7th bit (sign bit of the byte)
60                  * |0xffffff00 : lower <0, byte & 0xff : lower >0 byte */
61                 int ch((id_j & 0x80) ? (id_j |0xffffff00) :  (id_j & 0xff));
62                 if (ch == blank)/* we encounter a blank -> end of string. */
63                 {
64                     *n = i;
65                     return;
66                 }
67                 id_j += 128;/* propagate sign bit to upper bits */
68                 str[i]= ch;
69             }
70         }
71
72         *n= nlgh;/* no blank encountered str length is nlgh= nsiz*8 */
73
74     }
75     else
76     { /* str -> id */
77         /* n (<= nsiz*4 = nlgh) int in str packed into id */
78         unsigned int j;
79         /* a full id contains 4 ints from str, so we have *n/4 full ids the remaing are padded with blanks
80          we can get *n > nlgh (we  truncate @ nsiz ids) */
81 #ifndef _MSC_VER
82         unsigned const int full_ids(std::min(*n/4, nsiz));
83 #else
84         unsigned const int full_ids(min(*n/4, nsiz));
85 #endif
86
87         for (j= 0; j!=full_ids; ++j)
88         { /* str int are signed bytes in fact, we pack them using shifts */
89             id[j]= str[4*j+0] +(str[4*j+1]<<8)+(str[4*j+2]<<16)+(str[4*j+3]<<24);
90         }
91         if (j!= nsiz)/* we had < nsiz int in str : padd with blank chars */
92         {
93             switch ((*n ) & 0x3)  /* pad partial id int according modulo 4= nb of remaining ints in str */
94             {
95             case 3: /* three remaining ints and one blank */
96             {
97                 id[j]= one_blank + (str[4*j+2] << 16) + (str[4*j+1] << 8) + str[4*j + 0];
98                 ++j;
99                 break;
100             }
101             case 2: /* two remaining ints and two blanks */
102             {
103                 id[j]= two_blanks + (str[4*j+1]<<8) + str[4*j+0];
104                 ++j;
105                 break;
106             }
107             case 1:/* one remaining int and three blanks*/
108             {
109                 id[j]= three_blanks + str[4*j+0];
110                 ++j;
111                 break;
112             }
113             }
114
115             for (;j != nsiz; ++j) /* pad empty ints in id with four blanks at once */
116             {
117                 id[j]= four_blanks;
118             }
119         }
120     }
121     return;
122 }