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