1 /*
2  * Copyright (c) 2007 - 2015 Joseph Gaeddert
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 
23 //
24 // shift_array.c
25 //
26 // byte-wise array shifting
27 //
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 
33 #include "liquid.internal.h"
34 
35 
36 // shift array to the left _b bytes, filling in zeros
37 //  _src        :   source address [size: _n x 1]
38 //  _n          :   input data array size
39 //  _b          :   number of bytes to shift
liquid_lshift(unsigned char * _src,unsigned int _n,unsigned int _b)40 void liquid_lshift(unsigned char * _src,
41                    unsigned int _n,
42                    unsigned int _b)
43 {
44     // shift amount exceeds buffer size; fill with zeros
45     if (_b >= _n) {
46         memset(_src, 0x00, _n*sizeof(unsigned char));
47         return;
48     }
49 
50     // move memory
51     memmove(_src, &_src[_b], (_n-_b)*sizeof(unsigned char));
52 
53     // fill remaining buffer with zeros
54     memset(&_src[_n-_b], 0x00, _b*sizeof(unsigned char));
55 }
56 
57 // shift array to the right _b bytes, filling in zeros
58 //  _src        :   source address [size: _n x 1]
59 //  _n          :   input data array size
60 //  _b          :   number of bytes to shift
liquid_rshift(unsigned char * _src,unsigned int _n,unsigned int _b)61 void liquid_rshift(unsigned char * _src,
62                    unsigned int _n,
63                    unsigned int _b)
64 {
65     // shift amount exceeds buffer size; fill with zeros
66     if (_b >= _n) {
67         memset(_src, 0x00, _n*sizeof(unsigned char));
68         return;
69     }
70 
71     // move memory
72     memmove(&_src[_b], _src, (_n-_b)*sizeof(unsigned char));
73 
74     // fill remaining buffer with zeros
75     memset(_src, 0x00, _b*sizeof(unsigned char));
76 }
77 
78 
79 // circular shift array to the left _n bytes
80 //  _src        :   source address [size: _n x 1]
81 //  _n          :   input data array size
82 //  _b          :   number of bytes to shift
liquid_lcircshift(unsigned char * _src,unsigned int _n,unsigned int _b)83 void liquid_lcircshift(unsigned char * _src,
84                        unsigned int _n,
85                        unsigned int _b)
86 {
87     // validate input
88     if (_n == 0)
89         return;
90 
91     // ensure 0 <= _b < _n
92     _b = _b % _n;
93 
94     // check if less memory is used with rcircshift
95     if (_b > (_n>>1)) {
96         liquid_rcircshift(_src, _n, _n-_b);
97         return;
98     }
99 
100     // allocate memory for temporary array
101     unsigned char * tmp = (unsigned char*) malloc(_b*sizeof(unsigned char));
102 
103     // copy to temporary array
104     memmove(tmp, _src, _b*sizeof(unsigned char));
105 
106     // shift left
107     memmove(_src, &_src[_b], (_n-_b)*sizeof(unsigned char));
108 
109     // copy from temporary array
110     memmove(&_src[_n-_b], tmp, _b*sizeof(unsigned char));
111 
112     // free temporary array
113     free(tmp);
114 }
115 
116 
117 // circular shift array to the right _n bytes
118 //  _src        :   source address [size: _n x 1]
119 //  _n          :   input data array size
120 //  _b          :   number of bytes to shift
liquid_rcircshift(unsigned char * _src,unsigned int _n,unsigned int _b)121 void liquid_rcircshift(unsigned char * _src,
122                        unsigned int _n,
123                        unsigned int _b)
124 {
125     // validate input
126     if (_n == 0)
127         return;
128 
129     // ensure 0 <= _b < _n
130     _b = _b % _n;
131 
132     // check if less memory is used with lcircshift
133     if (_b > (_n>>1)) {
134         liquid_lcircshift(_src, _n, _n-_b);
135         return;
136     }
137 
138     // allocate memory for temporary array
139     unsigned char * tmp = (unsigned char*) malloc(_b*sizeof(unsigned char));
140 
141     // copy to temporary array
142     memmove(tmp, &_src[_n-_b], _b*sizeof(unsigned char));
143 
144     // shift right
145     memmove(&_src[_b], _src, (_n-_b)*sizeof(unsigned char));
146 
147     // copy from temporary array
148     memmove(_src, tmp, _b*sizeof(unsigned char));
149 
150     // free temporary array
151     free(tmp);
152 }
153 
154