1 /********************************************************************************
2 * *
3 * X M L - F i l e I / O *
4 * *
5 *********************************************************************************
6 * Copyright (C) 2016,2021 by Jeroen van der Zijp. All Rights Reserved. *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU Lesser General Public License as published by *
10 * the Free Software Foundation; either version 3 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public License *
19 * along with this program. If not, see <http://www.gnu.org/licenses/> *
20 ********************************************************************************/
21 #include "xincs.h"
22 #include "fxver.h"
23 #include "fxdefs.h"
24 #include "fxmath.h"
25 #include "fxascii.h"
26 #include "FXElement.h"
27 #include "FXArray.h"
28 #include "FXString.h"
29 #include "FXIO.h"
30 #include "FXIODevice.h"
31 #include "FXStat.h"
32 #include "FXFile.h"
33 #include "FXException.h"
34 #include "FXStringDictionary.h"
35 #include "FXCallback.h"
36 #include "FXXML.h"
37 #include "FXXMLFile.h"
38
39
40 /*
41 Notes:
42
43 - XML serialization to a file.
44 - To fill buffer, move unread bytes to start, then load as from file as will fit;
45 thus, wptr==endptr indicates the file is not fully loaded yet, while wptr<endptr
46 means we've reached end of file.
47 - To flush buffer, try write all bytes from buffer; if not able to write it all,
48 move unwritten bytes to start to have maximum of free space in buffer.
49 */
50
51
52 using namespace FX;
53
54 namespace FX {
55
56 /*******************************************************************************/
57
58 // Create XML file i/o object
FXXMLFile()59 FXXMLFile::FXXMLFile(){
60 FXTRACE((100,"FXXMLFile::FXXMLFile\n"));
61 }
62
63
64 // Create XML file i/o object and open it
FXXMLFile(const FXString & filename,Direction d,FXuval sz)65 FXXMLFile::FXXMLFile(const FXString& filename,Direction d,FXuval sz){
66 FXTRACE((100,"FXXMLFile::FXXMLFile(\"%s\",%s,%lu)\n",filename.text(),(d==Save)?"Save":(d==Load)?"Load":"Stop",sz));
67 open(filename,d,sz);
68 }
69
70
71 // Open archive for operation
open(FXInputHandle h,Direction d,FXuval sz)72 FXbool FXXMLFile::open(FXInputHandle h,Direction d,FXuval sz){
73 FXTRACE((101,"FXXMLFile::open(%lx,%s,%lu)\n",h,(d==Save)?"Save":(d==Load)?"Load":"Stop",sz));
74 FXchar *buffer;
75 if(allocElms(buffer,sz)){
76 if(file.open(h,(d==Save)?FXIO::Writing:FXIO::Reading)){
77 if(FXXML::open(buffer,sz,d)){
78 rptr=endptr;
79 sptr=endptr;
80 wptr=endptr;
81 return true;
82 }
83 file.close();
84 }
85 freeElms(buffer);
86 }
87 return false;
88 }
89
90
91 // Open archive for operation
open(const FXString & filename,Direction d,FXuval sz)92 FXbool FXXMLFile::open(const FXString& filename,Direction d,FXuval sz){
93 FXTRACE((101,"FXXMLFile::open(\"%s\",%s,%lu)\n",filename.text(),(d==Save)?"Save":(d==Load)?"Load":"Stop",sz));
94 FXchar *buffer;
95 FXASSERT(dir==Stop);
96 if(allocElms(buffer,sz)){
97 if(file.open(filename,(d==Save)?FXIO::Writing:FXIO::Reading,FXIO::AllReadWrite)){
98 if(FXXML::open(buffer,sz,d)){
99 rptr=endptr;
100 sptr=endptr;
101 wptr=endptr;
102 return true;
103 }
104 file.close();
105 }
106 freeElms(buffer);
107 }
108 return false;
109 }
110
111
112 // Read at least count bytes into buffer; return bytes available, or -1 for error
fill(FXival)113 FXival FXXMLFile::fill(FXival){
114 FXival nbytes;
115 FXASSERT(dir==Load);
116 if(file.isReadable()){
117 moveElms(begptr,rptr,wptr-rptr);
118 wptr=begptr+(wptr-rptr);
119 sptr=begptr+(sptr-rptr);
120 rptr=begptr;
121 nbytes=file.readBlock(wptr,endptr-wptr);
122 if(0<=nbytes){
123 wptr+=nbytes;
124 if(wptr<endptr){ wptr[0]='\0'; }
125 return wptr-sptr; // Input left to read
126 }
127 }
128 return -1;
129 }
130
131
132 // Write at least count bytes from buffer; return space available, or -1 for error
flush(FXival)133 FXival FXXMLFile::flush(FXival){
134 FXival nbytes;
135 FXASSERT(dir==Save);
136 if(file.isWritable()){
137 nbytes=file.writeBlock(rptr,wptr-rptr);
138 if(0<=nbytes){
139 rptr+=nbytes;
140 moveElms(begptr,rptr,wptr-rptr);
141 wptr=begptr+(wptr-rptr);
142 rptr=begptr;
143 return endptr-wptr; // Space left to write
144 }
145 }
146 return -1;
147 }
148
149
150 // Close stream and delete buffers
close()151 FXbool FXXMLFile::close(){
152 FXTRACE((101,"FXXMLFile::close()\n"));
153 FXchar *buffer=begptr;
154 if(FXXML::close()){
155 freeElms(buffer);
156 return file.close();
157 }
158 return false;
159 }
160
161
162 // Close XML file
~FXXMLFile()163 FXXMLFile::~FXXMLFile(){
164 FXTRACE((100,"FXXMLFile::~FXXMLFile\n"));
165 close();
166 }
167
168 }
169