1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include <stdio.h>
6 #include <cstdlib>
7
8 #define MAX_IO_BLOCK_SIZE (1024 * 1024)
9
fread_fixed(FILE * f,void * _buf,unsigned num_bytes)10 void fread_fixed(FILE *f, void * _buf, unsigned num_bytes) {
11 char * buf = (char *)_buf;
12
13 while (num_bytes != 0)
14 {
15 unsigned block_size = num_bytes;
16 if (block_size > MAX_IO_BLOCK_SIZE) block_size = MAX_IO_BLOCK_SIZE;
17
18 size_t r = fread(buf, 1, block_size, f);
19 if (r != block_size)
20 {
21 static char read_error_message[128];
22 sprintf (read_error_message, "read error: fread_fixed(block_size=%u) != %u", block_size, (unsigned)r);
23 throw read_error_message;
24 }
25 buf += block_size;
26 num_bytes -= block_size;
27 }
28 }
29
fwrite_fixed(FILE * f,const void * _buf,unsigned num_bytes)30 void fwrite_fixed(FILE *f, const void * _buf, unsigned num_bytes) {
31 const char * buf = (const char *)_buf;
32
33 while (num_bytes != 0)
34 {
35 unsigned block_size = num_bytes;
36 if (block_size > MAX_IO_BLOCK_SIZE) block_size = MAX_IO_BLOCK_SIZE;
37
38 size_t r = fwrite(buf, 1, block_size, f);
39 if (r != block_size)
40 {
41 static char write_error_message[128];
42 sprintf (write_error_message, "write error: fwrite_fixed(num_bytes=%u) != %u", block_size, (unsigned)r);
43 throw write_error_message;
44 }
45 buf += block_size;
46 num_bytes -= block_size;
47 }
48 }
49
read_word(FILE * f)50 unsigned read_word(FILE *f) {
51 unsigned char b, b2;
52 fread_fixed(f, &b, 1);
53 fread_fixed(f, &b2, 1);
54 return (b2 << 8) + b;
55 }
56
read_dword(FILE * f)57 unsigned read_dword(FILE *f) {
58 unsigned low = read_word(f);
59 return (read_word(f) << 16) + low;
60 }
61
scan_varint(const char * in,size_t len,unsigned long long * n)62 static size_t scan_varint(const char* in,size_t len, unsigned long long* n) {
63 size_t i;
64 unsigned long long l;
65 if (len==0) return 0;
66 for (l=0, i=0; i<len; ++i) {
67 l+=(unsigned long long)(in[i]&0x7f) << (i*7);
68 if (!(in[i]&0x80)) {
69 *n=l;
70 return i+1;
71 }
72 }
73 return 0;
74 }
75
scan_pb_type0_sint(const char * in,size_t len,signed long long * l)76 size_t scan_pb_type0_sint(const char* in,size_t len,signed long long* l) {
77 unsigned long long m;
78 size_t n=scan_varint(in,len,&m);
79 if (!n) return 0;
80 *l=(-(m&1)) ^ (m>>1);
81 return n;
82 }
83
read_varint(FILE * f)84 long long read_varint(FILE* f) {
85 char buf[20];
86 size_t i;
87 long long l;
88 for (i=0; i<sizeof(buf); ++i) {
89 fread_fixed(f,buf+i,1);
90 if (!(buf[i]&0x80)) {
91 if (scan_pb_type0_sint(buf,i+1,&l)!=i+1) break;
92 return l;
93 }
94 }
95 static char read_error_message[128];
96 strcpy(read_error_message, "parse error: read_varint() failed");
97 throw read_error_message;
98 }
99
write_word(FILE * f,unsigned number)100 void write_word(FILE *f, unsigned number) {
101 unsigned char b = number & 255,
102 b2 = number >> 8;
103 fwrite_fixed(f, &b, 1);
104 fwrite_fixed(f, &b2, 1);
105 }
106
write_dword(FILE * f,unsigned number)107 void write_dword(FILE *f, unsigned number) {
108 write_word(f, number & 65535);
109 write_word(f, number >> 16);
110 }
111
112
113 /* write int in least amount of bytes, return number of bytes */
114 /* as used in varints from Google protocol buffers */
fmt_varint(char * dest,unsigned long long l)115 static size_t fmt_varint(char* dest,unsigned long long l) {
116 /* high bit says if more bytes are coming, lower 7 bits are payload; little endian */
117 size_t i;
118 for (i=0; l; ++i, l>>=7) {
119 if (dest) dest[i]=(l&0x7f) | ((!!(l&~0x7f))<<7);
120 }
121 if (!i) { /* l was 0 */
122 if (dest) dest[0]=0;
123 ++i;
124 }
125 return i;
126 }
127
fmt_pb_type0_sint(char * dest,signed long long l)128 static size_t fmt_pb_type0_sint(char* dest,signed long long l) {
129 return fmt_varint(dest,(l << 1) ^ (l >> (sizeof(l)*8-1)));
130 }
131
write_varint(FILE * f,long long number)132 void write_varint(FILE* f, long long number) {
133 char tmp[20];
134 fwrite_fixed(f,tmp,fmt_pb_type0_sint(tmp,number));
135 }
136
fileExists(char * fname)137 bool fileExists(char *fname) {
138 FILE *f = fopen(fname, "rb");
139 bool exists = (f != NULL);
140 if (exists) fclose(f);
141 return exists;
142 }
143
getLenOfFile(char * fname)144 unsigned getLenOfFile(char *fname) {
145 FILE *f = fopen(fname, "rb");
146 fseek(f, 0, SEEK_END);
147 unsigned len = ftell(f);
148 fclose(f);
149 return len;
150 }
151