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