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