1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Copyright 2014 PDFium Authors. All rights reserved.
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Use of this source code is governed by a BSD-style license that can be
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// found in the LICENSE file.
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef _FX_STREAM_H_
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define _FX_STREAM_H_
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef _FX_MEMORY_H_
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "fx_memory.h"
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* FX_OpenFolder(FX_LPCSTR path);
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* FX_OpenFolder(FX_LPCWSTR path);
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL FX_GetNextFile(void* handle, CFX_ByteString& filename, FX_BOOL& bFolder);
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL FX_GetNextFile(void* handle, CFX_WideString& filename, FX_BOOL& bFolder);
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid FX_CloseFolder(void* handle);
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_WCHAR FX_GetFolderSeparator();
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_DEFINEHANDLE(FX_HFILE)
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FX_FILESIZE			FX_INT32
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else
22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <fcntl.h>
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <unistd.h>
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <sys/stat.h>
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef O_BINARY
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define O_BINARY 		0
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef O_LARGEFILE
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define O_LARGEFILE		0
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FX_FILESIZE			off_t
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FX_GETBYTEOFFSET32(a)	0
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FX_GETBYTEOFFSET40(a)	0
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FX_GETBYTEOFFSET48(a)	0
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FX_GETBYTEOFFSET56(a)	0
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FX_GETBYTEOFFSET24(a)  ((FX_BYTE)(a>>24))
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FX_GETBYTEOFFSET16(a)  ((FX_BYTE)(a>>16))
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FX_GETBYTEOFFSET8(a)   ((FX_BYTE)(a>>8))
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FX_GETBYTEOFFSET0(a)   ((FX_BYTE)(a))
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FX_FILEMODE_Write		0
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FX_FILEMODE_ReadOnly	1
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FX_FILEMODE_Truncate	2
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_HFILE	FX_File_Open(FX_BSTR fileName, FX_DWORD dwMode, IFX_Allocator* pAllocator = NULL);
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_HFILE	FX_File_Open(FX_WSTR fileName, FX_DWORD dwMode, IFX_Allocator* pAllocator = NULL);
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid		FX_File_Close(FX_HFILE hFile, IFX_Allocator* pAllocator = NULL);
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_FILESIZE	FX_File_GetSize(FX_HFILE hFile);
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_FILESIZE	FX_File_GetPosition(FX_HFILE hFile);
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_FILESIZE	FX_File_SetPosition(FX_HFILE hFile, FX_FILESIZE pos);
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovsize_t		FX_File_Read(FX_HFILE hFile, void* pBuffer, size_t szBuffer);
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovsize_t		FX_File_ReadPos(FX_HFILE hFile, void* pBuffer, size_t szBuffer, FX_FILESIZE pos);
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovsize_t		FX_File_Write(FX_HFILE hFile, const void* pBuffer, size_t szBuffer);
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovsize_t		FX_File_WritePos(FX_HFILE hFile, const void* pBuffer, size_t szBuffer, FX_FILESIZE pos);
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL		FX_File_Flush(FX_HFILE hFile);
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL		FX_File_Truncate(FX_HFILE hFile, FX_FILESIZE szFile);
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL		FX_File_Exist(FX_BSTR fileName);
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL		FX_File_Exist(FX_WSTR fileName);
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL		FX_File_Delete(FX_BSTR fileName);
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL		FX_File_Delete(FX_WSTR fileName);
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL		FX_File_Copy(FX_BSTR fileNameSrc, FX_BSTR fileNameDst);
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL		FX_File_Copy(FX_WSTR fileNameSrc, FX_WSTR fileNameDst);
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL		FX_File_Move(FX_BSTR fileNameSrc, FX_BSTR fileNameDst);
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL		FX_File_Move(FX_WSTR fileNameSrc, FX_WSTR fileNameDst);
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovclass IFX_StreamWrite
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovpublic:
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual void		Release() = 0;
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual	FX_BOOL		WriteBlock(const void* pData, size_t size) = 0;
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovclass IFX_FileWrite : public IFX_StreamWrite
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovpublic:
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual void			Release() = 0;
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_FILESIZE		GetSize() = 0;
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_BOOL			Flush() = 0;
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual	FX_BOOL			WriteBlock(const void* pData, FX_FILESIZE offset, size_t size) = 0;
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual	FX_BOOL			WriteBlock(const void* pData, size_t size)
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return WriteBlock(pData, GetSize(), size);
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovIFX_FileWrite* FX_CreateFileWrite(FX_LPCSTR filename, IFX_Allocator* pAllocator = NULL);
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovIFX_FileWrite* FX_CreateFileWrite(FX_LPCWSTR filename, IFX_Allocator* pAllocator = NULL);
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovclass IFX_StreamRead
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovpublic:
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual void			Release() = 0;
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_BOOL			IsEOF() = 0;
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_FILESIZE		GetPosition() = 0;
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual size_t			ReadBlock(void* buffer, size_t size) = 0;
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovclass IFX_FileRead : IFX_StreamRead
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovpublic:
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual void			Release() = 0;
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_FILESIZE		GetSize() = 0;
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_BOOL			IsEOF()
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_FILESIZE		GetPosition()
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 0;
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_BOOL			SetRange(FX_FILESIZE offset, FX_FILESIZE size)
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual void			ClearRange() {}
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_BOOL			ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) = 0;
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual size_t			ReadBlock(void* buffer, size_t size)
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 0;
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovIFX_FileRead* FX_CreateFileRead(FX_LPCSTR filename, IFX_Allocator* pAllocator = NULL);
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovIFX_FileRead* FX_CreateFileRead(FX_LPCWSTR filename, IFX_Allocator* pAllocator = NULL);
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovclass IFX_FileStream : public IFX_FileRead, public IFX_FileWrite
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovpublic:
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual IFX_FileStream*		Retain() = 0;
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual void				Release() = 0;
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_FILESIZE			GetSize() = 0;
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_BOOL				IsEOF() = 0;
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_FILESIZE			GetPosition() = 0;
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_BOOL				ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) = 0;
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual size_t				ReadBlock(void* buffer, size_t size) = 0;
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual	FX_BOOL				WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) = 0;
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual	FX_BOOL				WriteBlock(const void* buffer, size_t size)
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return WriteBlock(buffer, GetSize(), size);
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_BOOL				Flush() = 0;
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovIFX_FileStream*		FX_CreateFileStream(FX_LPCSTR filename, FX_DWORD dwModes, IFX_Allocator* pAllocator = NULL);
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovIFX_FileStream*		FX_CreateFileStream(FX_LPCWSTR filename, FX_DWORD dwModes, IFX_Allocator* pAllocator = NULL);
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovclass IFX_MemoryStream : public IFX_FileStream
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovpublic:
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_BOOL			IsConsecutive() const = 0;
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual void			EstimateSize(size_t nInitSize, size_t nGrowSize) = 0;
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_LPBYTE		GetBuffer() const = 0;
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual void			AttachBuffer(FX_LPBYTE pBuffer, size_t nSize, FX_BOOL bTakeOver = FALSE) = 0;
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual void			DetachBuffer() = 0;
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovIFX_MemoryStream*	FX_CreateMemoryStream(FX_LPBYTE pBuffer, size_t nSize, FX_BOOL bTakeOver = FALSE, IFX_Allocator* pAllocator = NULL);
179ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovIFX_MemoryStream*	FX_CreateMemoryStream(FX_BOOL bConsecutive = FALSE, IFX_Allocator* pAllocator = NULL);
180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovclass IFX_BufferRead : public IFX_StreamRead
181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovpublic:
183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual void			Release() = 0;
185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_BOOL			IsEOF() = 0;
187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_FILESIZE		GetPosition() = 0;
189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual size_t			ReadBlock(void* buffer, size_t size) = 0;
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_BOOL			ReadNextBlock(FX_BOOL bRestart = FALSE) = 0;
193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_LPCBYTE		GetBlockBuffer() = 0;
195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual size_t			GetBlockSize() = 0;
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    virtual FX_FILESIZE		GetBlockOffset() = 0;
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
201