1/*
2 * intfile - integer to file and file to integer conversion
3 *
4 * Copyright (C) 2001,2021  Landon Curt Noll
5 *
6 * Calc is open software; you can redistribute it and/or modify it under
7 * the terms of the version 2.1 of the GNU Lesser General Public License
8 * as published by the Free Software Foundation.
9 *
10 * Calc is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
13 * Public License for more details.
14 *
15 * A copy of version 2.1 of the GNU Lesser General Public License is
16 * distributed with calc under the filename COPYING-LGPL.  You should have
17 * received a copy with calc; if not, write to Free Software Foundation, Inc.
18 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 *
20 * Under source code control:   2001/03/31 08:13:11
21 * File existed as early as:    2001
22 *
23 * chongo <was here> /\oo/\     http://www.isthe.com/chongo/
24 * Share and enjoy!  :-)        http://www.isthe.com/chongo/tech/comp/calc/
25 */
26
27
28/*
29 * NOTE: Because leading HALF values are trimmed from integer, a file
30 *	 that begins with lots of 0 bits (in the case of big Endian)
31 *	 or that ends with lots of 0 bits (in the case of little Endian)
32 *	 will be changed when the subsequent integer is written back.
33 */
34
35
36/*
37 * file2be - convert a file into an big Endian integer
38 *
39 * given:
40 *	filename	filename to read
41 *
42 * returns:
43 *	integer read from its contents on big Endian order
44 */
45define file2be(filename)
46{
47    local fd;	/* open file */
48    local ret;	/* integer to return */
49    local c;	/* character read from the file */
50    local i;
51
52    /*
53     * open the file for reading
54     */
55    fd = fopen(filename, "rb");
56    if (!isfile(fd)) quit "file2be: cannot open file for reading";
57
58    /*
59     * read the contents of the file
60     *
61     * The first octets become the most significant bits of the integer.
62     */
63    ret = 0;
64    while (! isnull(c = fgetc(fd))) {
65	ret <<= 8;
66	ret += ord(c);
67    }
68
69    /*
70     * cleanup and return the integer
71     */
72    fclose(fd);
73    return ret;
74}
75
76
77/*
78 * file2le - convert a file into an little Endian integer
79 *
80 * given:
81 *	filename	filename to read
82 *
83 * returns:
84 *	integer read from its contents on little Endian order
85 */
86define file2le(filename)
87{
88    local fd;	/* open file */
89    local ret;	/* integer to return */
90    local c;	/* character read from the file */
91    local shft;	/* bit shift for the c value */
92    local i;
93
94    /*
95     * open the file for reading
96     */
97    fd = fopen(filename, "rb");
98    if (!isfile(fd)) quit "file2le: cannot open file for reading";
99
100    /*
101     * read the contents of the file into a string
102     *
103     * The first octets become are the least significant bits of the integer.
104     */
105    ret = 0;
106    shft = 0;
107    while (! isnull(c = fgetc(fd))) {
108	ret |= (ord(c) << shft);
109	shft += 8;
110    }
111
112    /*
113     * cleanup and return the integer
114     */
115    fclose(fd);
116    return ret;
117}
118
119
120/*
121 * be2file - convert a big Endian integer into a file
122 *
123 * given:
124 *	v		integer to write to the file
125 *	filename	filename to write
126 *
127 * returns:
128 *	The number of octets written to the file.
129 *
130 * NOTE: The absolute value of the integer is written to the file.
131 */
132define be2file(v, filename)
133{
134    local fd;		/* open file */
135    local octlen;	/* length of v in octets */
136    local i;
137
138    /*
139     * firewall
140     */
141    if (!isint(v)) {
142	quit "be2file: 1st arg not an integer";
143    }
144    v = abs(v);
145
146    /*
147     * open the file for writing
148     */
149    fd = fopen(filename, "wb");
150    if (!isfile(fd)) quit "be2file: cannot open file for writing";
151
152    /*
153     * write the octets to the file
154     *
155     * The most significant bits of the integer become the first file octets.
156     */
157    octlen = int((highbit(v)+8) / 8);
158    for (i=octlen-1; i >= 0; --i) {
159	fputc(fd, char(v >> (i*8)));
160    }
161
162    /*
163     * cleanup
164     */
165    fclose(fd);
166    return octlen;
167}
168
169
170/*
171 * le2file - convert a little Endian integer into a file
172 *
173 * given:
174 *	v		integer to write to the file
175 *	filename	filename to write
176 *
177 * returns:
178 *	The number of octets written to the file.
179 *
180 * NOTE: The absolute value of the integer is written to the file.
181 */
182define le2file(v, filename)
183{
184    local fd;	/* open file */
185    local cnt;	/* octets written */
186
187    /*
188     * firewall
189     */
190    if (!isint(v)) {
191	quit "be2file: 1st arg not an integer";
192    }
193    v = abs(v);
194
195    /*
196     * open the file for writing
197     */
198    fd = fopen(filename, "wb");
199    if (!isfile(fd)) quit "le2file: cannot open file for writing";
200
201    /*
202     * Write the octets to the file.
203     *
204     * The least significant bits of the integer become the first file octets.
205     */
206    cnt = 0;
207    while (v > 0) {
208	fputc(fd, char(v));
209	v >>= 8;
210	++cnt;
211    }
212
213    /*
214     * cleanup
215     */
216    fclose(fd);
217    return cnt;
218}
219