1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdarg.h>
5 #include <stdint.h>
6 #include <errno.h>
7 
8 #include "shadowdive/internal/writer.h"
9 
10 struct sd_writer_t {
11     FILE *handle;
12     int sd_errno;
13 };
14 
sd_writer_open(const char * file)15 sd_writer* sd_writer_open(const char *file) {
16     sd_writer *writer = malloc(sizeof(sd_writer));
17 
18     writer->handle = fopen(file, "wb");
19     writer->sd_errno = 0;
20     if(!writer->handle) {
21         free(writer);
22         return 0;
23     }
24 
25     return writer;
26 }
27 
sd_writer_errno(const sd_writer * writer)28 int sd_writer_errno(const sd_writer *writer) {
29     return writer->sd_errno;
30 }
31 
sd_writer_close(sd_writer * writer)32 void sd_writer_close(sd_writer *writer) {
33     fclose(writer->handle);
34     free(writer);
35 }
36 
sd_writer_pos(sd_writer * writer)37 long sd_writer_pos(sd_writer *writer) {
38     long res = ftell(writer->handle);
39     if (res == -1) {
40         writer->sd_errno = errno;
41     }
42     return res;
43 }
44 
sd_writer_seek_start(const sd_writer * writer,long offset)45 int sd_writer_seek_start(const sd_writer *writer, long offset) {
46     return fseek(writer->handle, offset, SEEK_SET);
47 }
48 
sd_writer_seek_cur(const sd_writer * writer,long offset)49 int sd_writer_seek_cur(const sd_writer *writer, long offset) {
50     return fseek(writer->handle, offset, SEEK_CUR);
51 }
52 
sd_writer_seek_end(const sd_writer * writer,long offset)53 int sd_writer_seek_end(const sd_writer *writer, long offset) {
54     return fseek(writer->handle, offset, SEEK_END);
55 }
56 
sd_write_buf(sd_writer * writer,const char * buf,int len)57 int sd_write_buf(sd_writer *writer, const char *buf, int len) {
58     if(fwrite(buf, 1, len, writer->handle) != len) {
59         writer->sd_errno = ferror(writer->handle);
60         return 0;
61     }
62     return 1;
63 }
64 
sd_write_fprintf(const sd_writer * writer,const char * format,...)65 int sd_write_fprintf(const sd_writer *writer, const char *format, ...) {
66     va_list argp;
67     va_start(argp, format);
68     int ret = vfprintf(writer->handle, format, argp);
69     va_end(argp);
70     return ret;
71 }
72 
sd_write_ubyte(sd_writer * writer,uint8_t data)73 void sd_write_ubyte(sd_writer *writer, uint8_t data) {
74     sd_write_buf(writer, (char*)&data, 1);
75 }
76 
sd_write_uword(sd_writer * writer,uint16_t data)77 void sd_write_uword(sd_writer *writer, uint16_t data) {
78     sd_write_buf(writer, (char*)&data, 2);
79 }
80 
sd_write_udword(sd_writer * writer,uint32_t data)81 void sd_write_udword(sd_writer *writer, uint32_t data) {
82     sd_write_buf(writer, (char*)&data, 4);
83 }
84 
sd_write_byte(sd_writer * writer,int8_t data)85 void sd_write_byte(sd_writer *writer, int8_t data) {
86     sd_write_buf(writer, (char*)&data, 1);
87 }
88 
sd_write_word(sd_writer * writer,int16_t data)89 void sd_write_word(sd_writer *writer, int16_t data) {
90     sd_write_buf(writer, (char*)&data, 2);
91 }
92 
sd_write_dword(sd_writer * writer,int32_t data)93 void sd_write_dword(sd_writer *writer, int32_t data) {
94     sd_write_buf(writer, (char*)&data, 4);
95 }
96 
sd_write_float(sd_writer * writer,float data)97 void sd_write_float(sd_writer *writer, float data) {
98     sd_write_buf(writer, (char*)&data, sizeof(float));
99 }
100 
sd_write_fill(sd_writer * writer,char content,int len)101 void sd_write_fill(sd_writer *writer, char content, int len) {
102     int left = len;
103     int now = 0;
104     char buffer[1024];
105 
106     memset(buffer, content, 1024);
107     while(left > 0) {
108         now = (left > 1024) ? 1024 : left;
109         if (fwrite(buffer, 1, now, writer->handle) != now) {
110             writer->sd_errno = ferror(writer->handle);
111             return;
112         }
113         left -= now;
114     }
115 }
116 
sd_write_variable_str(sd_writer * w,const char * str)117 void sd_write_variable_str(sd_writer *w, const char *str) {
118     if(str == NULL) {
119         sd_write_uword(w, 0);
120         return;
121     }
122     uint16_t len = strlen(str) + 1;
123     sd_write_uword(w, len);
124     sd_write_buf(w, str, len);
125 }
126