FileBuffer.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. //---------------------------------------------------------------------------
  2. #include <CorePCH.h>
  3. #pragma hdrstop
  4. #include "FileBuffer.h"
  5. //---------------------------------------------------------------------------
  6. const wchar_t * EOLTypeNames = L"LF;CRLF;CR";
  7. //---------------------------------------------------------------------------
  8. const char * __fastcall EOLToStr(TEOLType EOLType)
  9. {
  10. switch (EOLType) {
  11. case eolLF: return "\n";
  12. case eolCRLF: return "\r\n";
  13. case eolCR: return "\r";
  14. default: DebugFail(); return "";
  15. }
  16. }
  17. //---------------------------------------------------------------------------
  18. __fastcall TFileBuffer::TFileBuffer()
  19. {
  20. FMemory = new TMemoryStream();
  21. FSize = 0;
  22. }
  23. //---------------------------------------------------------------------------
  24. __fastcall TFileBuffer::~TFileBuffer()
  25. {
  26. delete FMemory;
  27. }
  28. //---------------------------------------------------------------------------
  29. void __fastcall TFileBuffer::SetSize(int value)
  30. {
  31. if (FSize != value)
  32. {
  33. FMemory->Size = value;
  34. FSize = value;
  35. }
  36. }
  37. //---------------------------------------------------------------------------
  38. void TFileBuffer::Reset()
  39. {
  40. FMemory->Position = 0;
  41. }
  42. //---------------------------------------------------------------------------
  43. void __fastcall TFileBuffer::ProcessRead(DWORD Len, DWORD Result)
  44. {
  45. if (Result != Len)
  46. {
  47. Size = Size - Len + Result;
  48. }
  49. FMemory->Seek(Result, soCurrent);
  50. }
  51. //---------------------------------------------------------------------------
  52. void TFileBuffer::NeedSpace(DWORD Len)
  53. {
  54. Size = GetPosition() + Len;
  55. }
  56. //---------------------------------------------------------------------------
  57. DWORD __fastcall TFileBuffer::ReadStream(TStream * Stream, const DWORD Len, bool ForceLen)
  58. {
  59. DWORD Result;
  60. try
  61. {
  62. NeedSpace(Len);
  63. if (ForceLen)
  64. {
  65. Stream->ReadBuffer(GetPointer(), Len);
  66. Result = Len;
  67. }
  68. else
  69. {
  70. Result = Stream->Read(GetPointer(), Len);
  71. }
  72. ProcessRead(Len, Result);
  73. }
  74. catch(EReadError &)
  75. {
  76. RaiseLastOSError();
  77. }
  78. return Result;
  79. }
  80. //---------------------------------------------------------------------------
  81. DWORD __fastcall TFileBuffer::LoadStream(TStream * Stream, const DWORD Len, bool ForceLen)
  82. {
  83. FMemory->Seek(0, soFromBeginning);
  84. return ReadStream(Stream, Len, ForceLen);
  85. }
  86. //---------------------------------------------------------------------------
  87. DWORD __fastcall TFileBuffer::LoadFromIn(TTransferInEvent OnTransferIn, TObject * Sender, DWORD Len)
  88. {
  89. FMemory->Seek(0, soFromBeginning);
  90. DebugAssert(GetPosition() == 0);
  91. NeedSpace(Len);
  92. size_t Result = OnTransferIn(Sender, reinterpret_cast<unsigned char *>(GetPointer()), Len);
  93. ProcessRead(Len, Result);
  94. return Result;
  95. }
  96. //---------------------------------------------------------------------------
  97. void __fastcall TFileBuffer::Convert(const char * Source, const char * Dest, int Params,
  98. bool & Token)
  99. {
  100. DebugAssert(strlen(Source) <= 2);
  101. DebugAssert(strlen(Dest) <= 2);
  102. if (FLAGSET(Params, cpRemoveBOM) && (Size >= 3) &&
  103. (memcmp(Data, Bom, strlen(Bom)) == 0))
  104. {
  105. Delete(0, 3);
  106. }
  107. if (FLAGSET(Params, cpRemoveCtrlZ) && (Size > 0) && ((*(Data + Size - 1)) == '\x1A'))
  108. {
  109. Delete(Size-1, 1);
  110. }
  111. if (strcmp(Source, Dest) == 0)
  112. {
  113. return;
  114. }
  115. char * Ptr = Data;
  116. // one character source EOL
  117. if (!Source[1])
  118. {
  119. bool PrevToken = Token;
  120. Token = false;
  121. for (int Index = 0; Index < Size; Index++)
  122. {
  123. // EOL already in destination format, make sure to pass it unmodified
  124. if ((Index < Size - 1) && (*Ptr == Dest[0]) && (*(Ptr+1) == Dest[1]))
  125. {
  126. Index++;
  127. Ptr++;
  128. }
  129. // last buffer ended with the first char of destination 2-char EOL format,
  130. // which got expanded to full destination format.
  131. // now we got the second char, so get rid of it.
  132. else if ((Index == 0) && PrevToken && (*Ptr == Dest[1]))
  133. {
  134. Delete(Index, 1);
  135. Index--;
  136. Ptr = Data + Index;
  137. }
  138. // we are ending with the first char of destination 2-char EOL format,
  139. // append the second char and make sure we strip it from the next buffer, if any
  140. else if ((*Ptr == Dest[0]) && (Index == Size - 1) && Dest[1])
  141. {
  142. Token = true;
  143. Insert(Index+1, Dest+1, 1);
  144. Index++;
  145. Ptr = Data + Index;
  146. }
  147. else if (*Ptr == Source[0])
  148. {
  149. *Ptr = Dest[0];
  150. if (Dest[1])
  151. {
  152. Insert(Index+1, Dest+1, 1);
  153. Index++;
  154. Ptr = Data + Index;
  155. }
  156. }
  157. Ptr++;
  158. }
  159. }
  160. // two character source EOL
  161. else
  162. {
  163. int Index;
  164. for (Index = 0; Index < Size - 1; Index++)
  165. {
  166. if ((*Ptr == Source[0]) && (*(Ptr+1) == Source[1]))
  167. {
  168. *Ptr = Dest[0];
  169. if (Dest[1])
  170. {
  171. *(Ptr+1) = Dest[1];
  172. Index++; Ptr++;
  173. }
  174. else
  175. {
  176. Delete(Index+1, 1);
  177. Ptr = Data + Index;
  178. }
  179. }
  180. Ptr++;
  181. }
  182. if ((Index < Size) && (*Ptr == Source[0]))
  183. {
  184. Delete(Index, 1);
  185. }
  186. }
  187. }
  188. //---------------------------------------------------------------------------
  189. void __fastcall TFileBuffer::Convert(TEOLType Source, TEOLType Dest, int Params,
  190. bool & Token)
  191. {
  192. Convert(EOLToStr(Source), EOLToStr(Dest), Params, Token);
  193. }
  194. //---------------------------------------------------------------------------
  195. void __fastcall TFileBuffer::Convert(const char * Source, TEOLType Dest, int Params,
  196. bool & Token)
  197. {
  198. Convert(Source, EOLToStr(Dest), Params, Token);
  199. }
  200. //---------------------------------------------------------------------------
  201. void __fastcall TFileBuffer::Convert(TEOLType Source, const char * Dest, int Params,
  202. bool & Token)
  203. {
  204. Convert(EOLToStr(Source), Dest, Params, Token);
  205. }
  206. //---------------------------------------------------------------------------
  207. void __fastcall TFileBuffer::Insert(int Index, const char * Buf, int Len)
  208. {
  209. Size += Len;
  210. memmove(Data + Index + Len, Data + Index, Size - Index - Len);
  211. memmove(Data + Index, Buf, Len);
  212. }
  213. //---------------------------------------------------------------------------
  214. void __fastcall TFileBuffer::Delete(int Index, int Len)
  215. {
  216. memmove(Data + Index, Data + Index + Len, Size - Index - Len);
  217. Size -= Len;
  218. }
  219. //---------------------------------------------------------------------------
  220. void __fastcall TFileBuffer::WriteToStream(TStream * Stream, const DWORD Len)
  221. {
  222. try
  223. {
  224. Stream->WriteBuffer(GetPointer(), Len);
  225. FMemory->Seek(Len, soCurrent);
  226. }
  227. catch(EWriteError &)
  228. {
  229. RaiseLastOSError();
  230. }
  231. }
  232. //---------------------------------------------------------------------------
  233. void __fastcall TFileBuffer::WriteToOut(TTransferOutEvent OnTransferOut, TObject * Sender, const DWORD Len)
  234. {
  235. OnTransferOut(Sender, reinterpret_cast<const unsigned char *>(GetPointer()), Len);
  236. FMemory->Seek(Len, soCurrent);
  237. }
  238. //---------------------------------------------------------------------------
  239. //---------------------------------------------------------------------------
  240. __fastcall TSafeHandleStream::TSafeHandleStream(int AHandle) :
  241. THandleStream(AHandle),
  242. FSource(NULL)
  243. {
  244. }
  245. //---------------------------------------------------------------------------
  246. __fastcall TSafeHandleStream::TSafeHandleStream(THandleStream * Source, bool Own) :
  247. THandleStream(Source->Handle)
  248. {
  249. FSource = Own ? Source : NULL;
  250. }
  251. //---------------------------------------------------------------------------
  252. TSafeHandleStream * TSafeHandleStream::CreateFromFile(const UnicodeString & FileName, unsigned short Mode)
  253. {
  254. return new TSafeHandleStream(new TFileStream(ApiPath(FileName), Mode), true);
  255. }
  256. //---------------------------------------------------------------------------
  257. __fastcall TSafeHandleStream::~TSafeHandleStream()
  258. {
  259. SAFE_DESTROY(FSource);
  260. }
  261. //---------------------------------------------------------------------------
  262. int __fastcall TSafeHandleStream::Read(void * Buffer, int Count)
  263. {
  264. int Result = FileRead(FHandle, Buffer, Count);
  265. if (Result == -1)
  266. {
  267. RaiseLastOSError();
  268. }
  269. return Result;
  270. }
  271. //---------------------------------------------------------------------------
  272. int __fastcall TSafeHandleStream::Write(const void * Buffer, int Count)
  273. {
  274. int Result = FileWrite(FHandle, Buffer, Count);
  275. if (Result == -1)
  276. {
  277. RaiseLastOSError();
  278. }
  279. return Result;
  280. }
  281. //---------------------------------------------------------------------------
  282. int __fastcall TSafeHandleStream::Read(System::DynamicArray<System::Byte> Buffer, int Offset, int Count)
  283. {
  284. // This is invoked for example via CopyFrom from TParallelOperation::Done
  285. int Result = FileRead(FHandle, Buffer, Offset, Count);
  286. if (Result == -1)
  287. {
  288. RaiseLastOSError();
  289. }
  290. return Result;
  291. }
  292. //---------------------------------------------------------------------------
  293. int __fastcall TSafeHandleStream::Write(const System::DynamicArray<System::Byte> Buffer, int Offset, int Count)
  294. {
  295. // This is invoked for example by TIniFileStorage::Flush or via CopyFrom from TParallelOperation::Done
  296. int Result = FileWrite(FHandle, Buffer, Offset, Count);
  297. if (Result == -1)
  298. {
  299. RaiseLastOSError();
  300. }
  301. return Result;
  302. }