Browse code

data structures skeleton

Dario Rodriguez authored on 25/02/2019 22:04:09
Showing 5 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,2 @@
1
+*.o
2
+re
0 3
new file mode 100644
... ...
@@ -0,0 +1,15 @@
1
+CC=gcc
2
+CFLAGS=-g -Wall -I/usr/include/SDL2
3
+LDFLAGS=-lSDL2 -lSDL2_image
4
+
5
+all: re
6
+
7
+recenteditor_data.o: recenteditor_data.c recenteditor_data.h
8
+
9
+recenteditor.o: recenteditor.c recenteditor_data.h
10
+
11
+re: recenteditor.o recenteditor_data.o
12
+	$(CC) $(LDFLAGS) -o re recenteditor.o recenteditor_data.o
13
+
14
+clean:
15
+	rm -f recenteditor.o recenteditor_data.o re
0 16
new file mode 100644
... ...
@@ -0,0 +1,92 @@
1
+/*
2
+ * recenteditor.c
3
+ *
4
+ * A programmers editor
5
+ *
6
+ * Author: Dario Rodriguez dario@softhome.net
7
+ * This program is licensed under the terms of GNU GPL v2.1+
8
+ */
9
+
10
+#include <stdio.h>
11
+#include <stdlib.h>
12
+#include <unistd.h>
13
+#include <string.h>
14
+#include <limits.h>
15
+
16
+#include "recenteditor_data.h"
17
+
18
+typedef struct re_t {
19
+        redata_t *redata;
20
+        int flag_newfile;
21
+        char filename[PATH_MAX];
22
+} re_t;
23
+
24
+re_t *re_init(void);
25
+void re_free(re_t *re);
26
+
27
+int re_setfilename(re_t *re, char *filename);
28
+
29
+int
30
+main(int argc, char *argv[])
31
+{
32
+        re_t *re;
33
+        if(argc!=2 || strcmp(argv[argc-1],"--help")==0) {
34
+                fprintf(stderr,"Syntax: %s filename\n",argv[0]);
35
+                return(1);
36
+        }
37
+        if((re=re_init())==NULL) {
38
+                fprintf(stderr,"ERROR: couldn't init structs.\n");
39
+                return(2);
40
+        }
41
+        if(re_setfilename(re,argv[argc-1])!=0) {
42
+                fprintf(stderr,"ERROR: filename too long.\n");
43
+                re_free(re),re=NULL;
44
+                return(2);
45
+        }
46
+        if((redata_load(re->redata,re->filename))!=0)
47
+                re->flag_newfile=1;
48
+        else
49
+                re->flag_newfile=0;
50
+#warning TODO
51
+        re_free(re),re=NULL;
52
+        return(0);
53
+}
54
+
55
+re_t *
56
+re_init(void)
57
+{
58
+        re_t *re;
59
+        if((re=malloc(sizeof(re_t)))==NULL)
60
+                return(NULL); /* insuf. mem. */
61
+        memset(re,0,sizeof(re_t));
62
+        if((re->redata=redata_init())==NULL) {
63
+                re_free(re),re=NULL;
64
+                return(NULL); /* insuf. mem. */
65
+        }
66
+        return(re);
67
+}
68
+
69
+void
70
+re_free(re_t *re)
71
+{
72
+        if(re==NULL)
73
+                return; /* all done */
74
+        if(re->redata!=NULL)
75
+                redata_free(re->redata),re->redata=NULL;
76
+        free(re),re=NULL;
77
+        return;
78
+}
79
+
80
+int
81
+re_setfilename(re_t *re, char *filename)
82
+{
83
+        if(re==NULL || filename==NULL)
84
+                return(-1);
85
+        strncpy(re->filename,filename,sizeof(re->filename));
86
+        re->filename[sizeof(re->filename)-1]='\0';
87
+        if(strcmp(filename,re->filename)!=0)
88
+                return(-1); /* filename too long */
89
+        return(0);
90
+}
91
+
92
+
0 93
new file mode 100644
... ...
@@ -0,0 +1,194 @@
1
+/*
2
+ * recenteditor_data.c
3
+ *
4
+ * A programmers editor
5
+ *
6
+ * Structures to hold the current file contents.
7
+ *
8
+ * Author: Dario Rodriguez dario@softhome.net
9
+ * This program is licensed under the terms of GNU GPL v2.1+
10
+ */
11
+
12
+#include <stdio.h>
13
+#include <stdlib.h>
14
+#include <unistd.h>
15
+#include <string.h>
16
+#include <sys/types.h>
17
+#include <sys/stat.h>
18
+#include <fcntl.h>
19
+
20
+#include "recenteditor_data.h"
21
+
22
+#define CHUNKSIZE 32768
23
+
24
+
25
+redata_t *
26
+redata_init(void)
27
+{
28
+        redata_t *redata;
29
+        if((redata=malloc(sizeof(redata_t)))==NULL)
30
+                return(NULL); /* sanity check failed */
31
+        memset(redata,0,sizeof(redata_t));
32
+        redata->sizechunks=0;
33
+        redata->chunks=NULL;
34
+        redata->chunkdatasize=CHUNKSIZE;
35
+        redata->available=0;
36
+        return(redata);
37
+}
38
+
39
+void
40
+redata_free(redata_t *redata)
41
+{
42
+        int i;
43
+        if(redata==NULL)
44
+                return; /* nothing to do */
45
+        for(i=0;i<redata->sizechunks;i++) {
46
+                if(redata->chunks[i]!=NULL)
47
+                        free(redata->chunks[i]),redata->chunks[i]=NULL;
48
+        }
49
+        redata->sizechunks=0;
50
+        if(redata->chunks!=NULL)
51
+                free(redata->chunks),redata->chunks=NULL;
52
+        free(redata),redata=NULL;
53
+        return;
54
+}
55
+
56
+int
57
+redata_getsize(redata_t *redata)
58
+{
59
+        if(redata==NULL)
60
+                return(0); /* sanity check failed */
61
+        return(redata->chunkdatasize*redata->sizechunks);
62
+}
63
+
64
+int
65
+redata_getused(redata_t *redata)
66
+{
67
+        if(redata==NULL)
68
+                return(0); /* sanity check failed */
69
+        return(redata_getsize(redata)-redata_getavailable(redata));
70
+}
71
+
72
+int
73
+redata_getavailable(redata_t *redata)
74
+{
75
+        if(redata==NULL)
76
+                return(0); /* sanity check failed */
77
+        return(redata->available);
78
+}
79
+
80
+int
81
+redata_wipe(redata_t *redata)
82
+{
83
+        int i;
84
+        if(redata==NULL)
85
+                return(-1); /* sanity check failed */
86
+        for(i=0;i<redata->sizechunks;i++) {
87
+                redata->chunks[i]->useddata=0;
88
+                memset(&(redata->chunks[i]->whatin),0,sizeof(whatin_t));
89
+        }
90
+        redata->available=redata_getsize(redata);
91
+        return(0);
92
+}
93
+
94
+int
95
+redata_preallocate(redata_t *redata, int newsize)
96
+{
97
+        int cursize;
98
+        int nchunks;
99
+        int i;
100
+        int rechunksize;
101
+        rechunk_t *newchunks,*chunk;
102
+        int oldsizechunks;
103
+        if(redata==NULL || redata->chunkdatasize==0 || newsize<0)
104
+                return(-1); /* sanity check failed */
105
+        if((cursize=redata_getsize(redata))>=newsize)
106
+                return(0); /* all done */
107
+        nchunks=(newsize-cursize+redata->chunkdatasize-1)/redata->chunkdatasize;
108
+        rechunksize=sizeof(rechunk_t)-1+redata->chunkdatasize;
109
+        if((newchunks=realloc(redata->chunks,sizeof(rechunk_t *)*(redata->sizechunks+nchunks)))==NULL)
110
+                return(-1); /* insuf. mem. */
111
+        redata->chunks=newchunks;
112
+        memset(redata->chunks+redata->sizechunks,0,sizeof(rechunk_t *)*nchunks);
113
+        oldsizechunks=redata->sizechunks;
114
+        for(i=0;i<nchunks;i++) {
115
+                if((chunk=malloc(rechunksize))==NULL)
116
+                        return(-1);  /* insuf. mem. */
117
+                memset(chunk,0,rechunksize);
118
+                chunk->useddata=0;
119
+                redata->chunks[oldsizechunks+i]=chunk;
120
+                redata->sizechunks++;
121
+                redata->available+=redata->chunkdatasize;
122
+        }
123
+        return(0);
124
+}
125
+
126
+int
127
+redata_fill_whatin(redata_t *redata, int chunkno)
128
+{
129
+        rechunk_t *chunk;
130
+        int nlcount;
131
+        int i,lim;
132
+        if(redata==NULL || chunkno<0 || chunkno>=redata->sizechunks || redata->chunks[chunkno]==NULL)
133
+                return(-1); /* sanity check failed */
134
+        chunk=redata->chunks[chunkno];
135
+        memset(&(chunk->whatin),0,sizeof(whatin_t));
136
+        nlcount=0;
137
+        for(i=0,lim=chunk->useddata;i<lim;i++) {
138
+                nlcount+=(chunk->data[i]=='\n')?1:0;
139
+        }
140
+        chunk->whatin.nlcount=nlcount;
141
+        return(0);
142
+}
143
+
144
+
145
+int
146
+redata_load(redata_t *redata, char *filename)
147
+{
148
+        int fd,nread,totalread;
149
+        int chunkno, avail;
150
+        struct stat statbuf;
151
+        rechunk_t *chunk;
152
+        redata_wipe(redata);
153
+        if((fd=open(filename,O_RDONLY))==-1 || fstat(fd,&statbuf)!=0 || !S_ISREG(statbuf.st_mode)) {
154
+                if(fd!=-1)
155
+                        close(fd),fd=-1;
156
+                return(-1); /* file not found, couldn't query size or not regular file */
157
+        }
158
+        if(redata_preallocate(redata,statbuf.st_size)) {
159
+                if(fd!=-1)
160
+                        close(fd),fd=-1;
161
+                return(-1); /* insuf. mem. */
162
+        }
163
+        for(totalread=0,chunkno=0,nread=0;totalread<statbuf.st_size;totalread+=nread,nread=0) {
164
+                if(chunkno>=redata->sizechunks || redata->chunks[chunkno]==NULL) {
165
+                        if(fd!=-1)
166
+                                close(fd),fd=-1;
167
+                        fprintf(stderr,"redata_load: INTERNAL ERROR\n");
168
+                        return(-2); /* internal error */
169
+                }
170
+                chunk=redata->chunks[chunkno];
171
+                avail=redata->chunkdatasize-chunk->useddata;
172
+                avail=((totalread+avail)>statbuf.st_size)?statbuf.st_size-totalread:avail;
173
+                if(avail==0) {
174
+                        chunkno++; /* full, try next */
175
+                        continue;
176
+                }
177
+                if((nread=read(fd,chunk->data+chunk->useddata,avail))<=0) {
178
+                        if(fd!=-1)
179
+                                close(fd),fd=-1;
180
+                        return(-1); /* short read */
181
+                }
182
+                chunk->useddata+=nread;
183
+                redata->available-=nread;
184
+                redata_fill_whatin(redata,chunkno);
185
+        }
186
+        return(0);
187
+}
188
+
189
+int
190
+redata_save(redata_t *redata, char *filename)
191
+{
192
+#warning TODO
193
+        return(-1);
194
+}
0 195
new file mode 100644
... ...
@@ -0,0 +1,44 @@
1
+/*
2
+ * recenteditor_data.c
3
+ *
4
+ * A programmers editor
5
+ *
6
+ * Structures to hold the current file contents.
7
+ *
8
+ * HEADER FILE
9
+ *
10
+ * Author: Dario Rodriguez dario@softhome.net
11
+ * This program is licensed under the terms of GNU GPL v2.1+
12
+ */
13
+
14
+
15
+typedef struct whatin_t {
16
+        int nlcount;
17
+} whatin_t;
18
+
19
+typedef struct rechunk_t {
20
+        whatin_t whatin;
21
+        int useddata;
22
+        unsigned char data[1];
23
+} rechunk_t;
24
+
25
+typedef struct redata_t {
26
+        int chunkdatasize;
27
+        int sizechunks;
28
+        rechunk_t **chunks;
29
+        int available;
30
+} redata_t;
31
+
32
+redata_t *redata_init(void);
33
+void redata_free(redata_t *redata);
34
+
35
+int redata_getsize(redata_t *redata);
36
+int redata_getused(redata_t *redata);
37
+int redata_getavailable(redata_t *redata);
38
+
39
+int redata_wipe(redata_t *redata);
40
+int redata_preallocate(redata_t *redata, int size);
41
+int redata_fill_whatin(redata_t *redata, int chunkno);
42
+
43
+int redata_load(redata_t *redata, char *filename);
44
+int redata_save(redata_t *redata, char *filename);