1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 #include "KFileHelper.h"
28 #include <string.h>
29
BufferedKFileGets(KDataBuffer * buf,unsigned offset,unsigned * nread,BufferedKFile * strm)30 rc_t BufferedKFileGets(KDataBuffer *buf, unsigned offset, unsigned *nread, BufferedKFile *strm) {
31 unsigned i;
32 unsigned n;
33 int ch;
34 rc_t rc;
35
36 do {
37 if (strm->cur != strm->inbuf) {
38 ch = strm->buf[strm->cur];
39
40 if (ch == '\r' || ch == '\n')
41 ++strm->cur;
42 else
43 break;
44 }
45 else {
46 size_t numread;
47
48 rc = KFileRead(strm->kfp, strm->fpos, strm->buf, sizeof(strm->buf), &numread);
49 if (rc) return -1;
50
51 strm->cur = 0;
52 strm->inbuf = numread;
53 strm->fpos += numread;
54 if (numread == 0) {
55 *nread = 0;
56 return 0;
57 }
58 }
59 } while (1);
60
61 for (n = 0, i = offset; ; ++i, ++n) {
62 if (strm->cur != strm->inbuf) {
63 ch = strm->buf[strm->cur++];
64 }
65 else {
66 size_t numread;
67
68 rc = KFileRead(strm->kfp, strm->fpos, strm->buf, sizeof(strm->buf), &numread);
69 if (rc) return rc;
70
71 strm->cur = 0;
72 strm->inbuf = numread;
73 if (numread == 0) break;
74 strm->fpos += numread;
75 ch = strm->buf[strm->cur++];
76 }
77 if (ch == '\r' || ch == '\n') break;
78 if (i >= buf->elem_count) {
79 rc = KDataBufferResize(buf, buf->elem_count ? buf->elem_count * 2 : 1024);
80 if (rc) return rc;
81 }
82 ((char *)buf->base)[i] = ch;
83 }
84 *nread = n;
85 return 0;
86 }
87
BufferedKFileOpen(const KDirectory * directory,BufferedKFile * rslt,const char * fileName,...)88 rc_t BufferedKFileOpen(const KDirectory *directory, BufferedKFile *rslt, const char *fileName, ...) {
89 va_list va;
90 rc_t rc;
91
92 memset(rslt, 0, sizeof(rslt) - sizeof(rslt->buf));
93
94 va_start(va, fileName);
95 rc = KDirectoryVOpenFileRead(directory, &rslt->kfp, fileName, va);
96 va_end(va);
97
98 return rc;
99 }
100
BufferedKFileClose(BufferedKFile * strm)101 rc_t BufferedKFileClose(BufferedKFile *strm) {
102 return KFileRelease(strm->kfp);
103 }
104
LoadFile(KDataBuffer * dst,uint64_t * lineCount,const KDirectory * dir,const char * fileName,...)105 rc_t LoadFile(KDataBuffer *dst, uint64_t *lineCount, const KDirectory *dir, const char *fileName, ...) {
106 BufferedKFile strm;
107 rc_t rc;
108 unsigned line = 0;
109
110 memset(&strm, 0, sizeof(strm) - sizeof(strm.buf));
111 {
112 va_list va;
113
114 va_start(va, fileName);
115 rc = KDirectoryVOpenFileRead(dir, &strm.kfp, fileName, va);
116 va_end(va);
117 }
118 if (rc == 0) {
119 unsigned offset = 0;
120 unsigned i;
121
122 while ((rc = BufferedKFileGets(dst, offset, &i, &strm)) == 0 && i) {
123 offset += i;
124 if (offset + 1 >= dst->elem_count) {
125 rc = KDataBufferResize(dst, offset + 1);
126 if (rc)
127 break;
128 }
129 ((char *)dst->base)[offset++] = '\0';
130 ++line;
131 }
132 BufferedKFileClose(&strm);
133 if (rc == 0)
134 rc = KDataBufferResize(dst, offset);
135 }
136 if (rc != 0) {
137 KDataBufferResize(dst, 0);
138 line = 0;
139 }
140 if (lineCount) *lineCount = line;
141 return rc;
142 }
143