NCBI C++ ToolKit
strbuffer.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: strbuffer.cpp 98247 2022-10-17 18:01:55Z gouriano $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Eugene Vasilchenko
27 *
28 * File Description:
29 * Input buffer
30 */
31 
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbistre.hpp>
34 #include <corelib/ncbi_limits.hpp>
35 #include <util/strbuffer.hpp>
36 #include <util/bytesrc.hpp>
37 #include <util/error_codes.hpp>
38 #include <algorithm>
39 
40 
41 #define NCBI_USE_ERRCODE_X Util_Stream
42 
44 
45 
46 static const size_t KInitialBufferSize = 4096;
47 
48 static inline
50 {
51  return size * 2;
52 }
53 
54 
56  THROWS1((bad_alloc))
57  : m_Error(0), m_BufferPos(0),
58  m_BufferSize(0), m_Buffer(0),
59  m_CurrentPos(0), m_DataEndPos(0),
60  m_Line(1),
61  m_CollectPos(0),
62  m_CanceledCallback(0),
63  m_BufferLockSize(0)
64 {
65 }
66 
67 
69  : m_Error(0), m_BufferPos(0),
70  m_BufferSize(0), m_Buffer(const_cast<char*>(buffer)),
71  m_CurrentPos(buffer), m_DataEndPos(buffer+size),
72  m_Line(1),
73  m_CollectPos(0),
74  m_CanceledCallback(0),
75  m_BufferLockSize(0)
76 {
77 }
78 
79 
81 {
82  try {
83  Close();
84  }
85  NCBI_CATCH_X(1, "~CIStreamBuffer: exception while closing");
86  if ( m_BufferSize ) {
87  delete[] m_Buffer;
88  }
89 }
90 
91 
93 {
94  Close();
95  if (reader.IsMultiPart()) {
96  m_BufferSize = reader.GetNextPart(&m_Buffer, 0);
99  m_BufferSize = 0;
100  } else {
101  if ( !m_BufferSize ) {
104  }
105  }
106  m_Input = &reader;
107  m_Error = 0;
108 }
109 
110 
111 void CIStreamBuffer::Open(const char* buffer, size_t size)
112 {
113  Close();
114  if ( m_BufferSize ) {
115  delete[] m_Buffer;
116  }
117  m_BufferSize = 0;
118  m_Buffer = const_cast<char*>(buffer);
121  m_Error = 0;
122 }
123 
124 
126 {
127  if ( m_Input ) {
128  size_t unused = m_DataEndPos - m_CurrentPos;
129  if ( unused ) {
131  }
132  m_Input.Reset();
133  }
134  m_BufferPos = 0;
137  m_Line = 1;
138  m_Error = 0;
139 }
140 
141 
142 void CIStreamBuffer::SetCanceledCallback(const ICanceled* canceled_callback)
143 {
144  m_CanceledCallback = canceled_callback;
145 }
146 
147 
149 {
150  _ASSERT(size > 0);
151  size_t pos = m_CurrentPos - m_Buffer;
152  m_BufferLockSize = pos + size;
153  return pos;
154 }
155 
156 
158 {
159  _ASSERT(m_Buffer+pos <= m_CurrentPos);
160  m_BufferLockSize = 0;
161  m_CurrentPos = m_Buffer+pos;
162 }
163 
164 
166 {
167  if ( m_Collector ) {
168  // update current collector data
170  size_t count = m_CurrentPos - m_CollectPos;
171  if ( count )
173  }
175  if ( m_Input ) {
176  m_Collector =
178  }
179  else {
180  m_Collector =
182  }
183 }
184 
185 
187 {
190 
192  size_t count = m_CurrentPos - m_CollectPos;
193  if ( count )
195 
197 
199  if ( parent ) {
200  m_Collector = parent;
202  }
203  else {
204  m_Collector = null;
205  m_CollectPos = 0;
206  }
207 
208  return source;
209 }
210 
211 
212 // this method is highly optimized
215 {
216  // cache pointers
217  const char* pos = m_CurrentPos;
218  const char* end = m_DataEndPos;
219  // make sure thire is at least one char in buffer
220  if ( pos == end ) {
221  // fill buffer
222  pos = FillBuffer(pos);
223  // cache m_DataEndPos
224  end = m_DataEndPos;
225  }
226  // main cycle
227  // at the beginning:
228  // pos == m_CurrentPos
229  // end == m_DataEndPos
230  // pos < end
231  for (;;) {
232  // we use do{}while() cycle because
233  // condition is true at the beginning ( pos < end )
234  do {
235  // cache current char
236  char c = *pos;
237  if ( c != ' ' ) { // it's not space (' ')
238  // point m_CurrentPos to first non space char
239  m_CurrentPos = pos;
240  // return char value
241  return c;
242  }
243  // skip space char
244  } while ( ++pos < end );
245  // here pos == end == m_DataEndPos
246  // point m_CurrentPos to end of buffer
247  m_CurrentPos = pos;
248  // fill next portion
249  pos = FillBuffer(pos);
250  // cache m_DataEndPos
251  end = m_DataEndPos;
252  }
253 }
254 
255 
256 // this method is highly optimized
259 {
260  // cache pointers
261  const char* pos = m_CurrentPos;
262  const char* end = m_DataEndPos;
263  // make sure thire is at least one char in buffer
264  if ( pos == end ) {
265  // fill buffer
266  pos = FillBuffer(pos);
267  // cache m_DataEndPos
268  end = m_DataEndPos;
269  }
270  // main cycle
271  // at the beginning:
272  // pos == m_CurrentPos
273  // end == m_DataEndPos
274  // pos < end
275  for (;;) {
276  const void* found = memchr(pos, c, end - pos);
277  if ( found ) {
278  m_CurrentPos = static_cast<const char*>(found);
279  return;
280  }
281  // point m_CurrentPos to end of buffer
282  m_CurrentPos = end;
283  // fill next portion
284  pos = FillBuffer(end);
285  // cache m_DataEndPos
286  end = m_DataEndPos;
287  }
288 }
289 
290 
291 // this method is highly optimized
292 size_t CIStreamBuffer::PeekFindChar(char c, size_t limit)
294 {
295  _ASSERT(limit > 0);
296  PeekCharNoEOF(limit - 1);
297  // cache pointers
298  const char* pos = m_CurrentPos;
299  size_t bufferSize = m_DataEndPos - pos;
300  if ( bufferSize != 0 ) {
301  const void* found = memchr(pos, c, min(limit, bufferSize));
302  if ( found )
303  return static_cast<const char*>(found) - pos;
304  }
305  return limit;
306 }
307 
308 
309 bool CIStreamBuffer::TrySetCurrentPos(const char* pos)
310 {
311  if (m_BufferPos == 0 && pos >= m_Buffer && pos <= m_DataEndPos) {
312  m_CurrentPos = pos;
313  return true;
314  }
315  return false;
316 }
317 
318 
319 const char* CIStreamBuffer::FillBuffer(const char* pos, bool noEOF)
320  THROWS1((CIOException, bad_alloc))
321 {
322  if ( const ICanceled* callback = m_CanceledCallback ) {
323  if ( callback->IsCanceled() ) {
324  m_Error = "canceled";
326  }
327  }
328  _ASSERT(pos >= m_DataEndPos);
329  // remove unused portion of buffer at the beginning
330  _ASSERT(m_CurrentPos >= m_Buffer);
331  if ( m_BufferSize == 0 ) {
332  if (m_Input.NotNull() && m_Input->IsMultiPart()) {
333 
334  if ( m_Collector ) {
335  _ASSERT(m_CollectPos);
336  size_t count = m_CurrentPos - m_CollectPos;
337  if ( count > 0 )
338  m_Collector->AddChunk(m_CollectPos, count);
339  }
340  m_BufferPos += (m_DataEndPos - m_Buffer);
341  m_BufferSize = m_Input->GetNextPart(&m_Buffer, m_DataEndPos - m_CurrentPos);
342  m_CurrentPos = m_Buffer;
343  m_DataEndPos = m_Buffer + m_BufferSize;
344  if ( m_Collector ) {
345  m_CollectPos = m_CurrentPos;
346  }
347  m_BufferSize = 0;
348  if (m_CurrentPos != m_DataEndPos) {
349  return m_CurrentPos;
350  }
351  }
352  // buffer is external -> no more data
353  if ( noEOF ) {
354  return pos;
355  }
356  else {
357  m_Error = "end of file";
358  NCBI_THROW(CEofException,eEof,m_Error);
359  }
360  }
361  size_t newPosOffset = pos - m_Buffer;
362  if ( m_BufferLockSize == 0 &&
363  (newPosOffset >= m_BufferSize || m_DataEndPos == m_CurrentPos) ) {
364  // if new position is out of buffer, or if there is no data left
365  // move pointers to the beginning
366  size_t erase = m_CurrentPos - m_Buffer;
367  if ( erase > 0 ) {
368  const char* newPos = m_CurrentPos - erase;
369  if ( m_Collector ) {
370  _ASSERT(m_CollectPos);
371  size_t count = m_CurrentPos - m_CollectPos;
372  if ( count > 0 )
373  m_Collector->AddChunk(m_CollectPos, count);
374  m_CollectPos = newPos;
375  }
376  size_t copy_count = m_DataEndPos - m_CurrentPos;
377  if ( copy_count )
378  memmove(const_cast<char*>(newPos), m_CurrentPos, copy_count);
379  m_CurrentPos = newPos;
380  m_DataEndPos -= erase;
381  m_BufferPos += CT_OFF_TYPE(erase);
382  pos -= erase;
383  newPosOffset -= erase;
384  }
385  }
386  size_t dataSize = m_DataEndPos - m_Buffer;
387  if ( newPosOffset >= m_BufferSize ) {
388  // reallocate buffer
389  size_t newSize = BiggerBufferSize(m_BufferSize);
390  while ( newPosOffset >= newSize ) {
391  newSize = BiggerBufferSize(newSize);
392  }
393  if ( m_BufferLockSize != 0 ) {
394  newSize = min(newSize, m_BufferLockSize);
395  if ( newPosOffset >= newSize ) {
396  NCBI_THROW(CIOException, eOverflow, "Locked buffer overflow");
397  }
398  }
399  char* newBuffer = new char[newSize];
400  memcpy(newBuffer, m_Buffer, dataSize);
401  m_CurrentPos = newBuffer + (m_CurrentPos - m_Buffer);
402  if ( m_CollectPos )
403  m_CollectPos = newBuffer + (m_CollectPos - m_Buffer);
404  pos = newBuffer + newPosOffset;
405  m_DataEndPos = newBuffer + dataSize;
406  delete[] m_Buffer;
407  m_Buffer = newBuffer;
408  m_BufferSize = newSize;
409  }
410  size_t load = m_BufferSize - dataSize;
411  while ( load > 0 && pos >= m_DataEndPos ) {
412  if ( !m_Input ) {
413  if ( noEOF ) {
414  return pos;
415  }
416  m_Error = "end of file";
417  NCBI_THROW(CEofException,eEof,m_Error);
418  }
419  size_t count = m_Input->Read(const_cast<char*>(m_DataEndPos), load);
420  if ( count == 0 ) {
421  if ( pos < m_DataEndPos )
422  return pos;
423  if ( m_Input->EndOfData() ) {
424  if ( noEOF ) {
425  // ignore EOF
426  _ASSERT(m_Buffer <= m_CurrentPos);
427  _ASSERT(m_CurrentPos <= pos);
428  _ASSERT(m_DataEndPos <= m_Buffer + m_BufferSize);
429  _ASSERT(!m_CollectPos ||
430  (m_CollectPos>=m_Buffer &&
431  m_CollectPos<=m_CurrentPos));
432  return pos;
433  }
434  m_Error = "end of file";
435  NCBI_THROW(CEofException,eEof,m_Error);
436  }
437  else {
438  m_Error = "read fault";
439  NCBI_THROW(CIOException,eRead,m_Error);
440  }
441  }
442  m_DataEndPos += count;
443  load -= count;
444  }
445  _ASSERT(m_Buffer <= m_CurrentPos);
446  _ASSERT(m_CurrentPos <= pos);
447  _ASSERT(pos < m_DataEndPos);
448  _ASSERT(m_DataEndPos <= m_Buffer + m_BufferSize);
449  _ASSERT(!m_CollectPos ||
450  (m_CollectPos>=m_Buffer && m_CollectPos<=m_CurrentPos));
451  return pos;
452 }
453 
454 
455 char CIStreamBuffer::FillBufferNoEOF(const char* pos)
456 {
457  pos = FillBuffer(pos, true);
458  if ( pos >= m_DataEndPos )
459  return 0;
460  else
461  return *pos;
462 }
463 
464 
466 {
467  return FillBuffer(m_CurrentPos, true) < m_DataEndPos;
468 }
469 
470 
473 {
474  // cache pos
475  const char* pos = m_CurrentPos;
476  for ( ;; ) {
477  size_t c = m_DataEndPos - pos;
478  if ( c >= count ) {
479  // all data is already in buffer -> copy it
480  memcpy(buffer, pos, count);
481  m_CurrentPos = pos + count;
482  return;
483  }
484  else {
485  memcpy(buffer, pos, c);
486  buffer += c;
487  count -= c;
488  m_CurrentPos = pos += c;
489  pos = FillBuffer(pos);
490  }
491  }
492 }
493 
494 
495 void CIStreamBuffer::GetChars(string& str, size_t count)
497 {
498  // cache pos
499  const char* pos = m_CurrentPos;
500  size_t in_buffer = m_DataEndPos - pos;
501  if ( in_buffer >= count ) {
502  // simplest case - plain copy
503  str.assign(pos, count);
504  m_CurrentPos = pos + count;
505  return;
506  }
507  str.reserve(count);
508  str.assign(pos, in_buffer);
509  for ( ;; ) {
510  count -= in_buffer;
511  m_CurrentPos = pos += in_buffer;
512  pos = FillBuffer(pos);
513  in_buffer = m_DataEndPos - pos;
514  if ( in_buffer >= count ) {
515  // all data is already in buffer -> copy it
516  str.append(pos, count);
517  m_CurrentPos = pos + count;
518  return;
519  }
520  str.append(pos, in_buffer);
521  }
522 }
523 
524 
525 void CIStreamBuffer::SkipEndOfLine(char lastChar)
527 {
528  _ASSERT(lastChar == '\n' || lastChar == '\r');
529  _ASSERT(m_CurrentPos > m_Buffer && m_CurrentPos[-1] == lastChar);
530  m_Line++;
531  char nextChar = PeekCharNoEOF();
532  // lastChar either '\r' or \n'
533  // if nextChar is compliment, skip it
534  if ( (lastChar + nextChar) == ('\r' + '\n') )
535  SkipChar();
536 }
537 
538 
539 size_t CIStreamBuffer::ReadLine(char* buff, size_t size)
541 {
542  size_t count = 0;
543  try {
544  while ( size > 0 ) {
545  char c = *buff++ = GetChar();
546  count++;
547  size--;
548  switch ( c ) {
549  case '\r':
550  // replace leading '\r' by '\n'
551  buff[-1] = '\n';
552  if ( PeekChar() == '\n' )
553  SkipChar();
554  return count;
555  case '\n':
556  if ( PeekChar() == '\r' )
557  SkipChar();
558  return count;
559  }
560  }
561  return count;
562  }
563  catch ( CEofException& /*ignored*/ ) {
564  return count;
565  }
566 }
567 
568 
571 {
572  m_Error = "bad number";
573  NCBI_THROW_FMT(CUtilException, eWrongData,
574  "bad number in line " << GetLine());
575 }
576 
577 
580 {
581  m_Error = "number overflow";
582  NCBI_THROW_FMT(CUtilException, eWrongData,
583  "number overflow in line " << GetLine());
584 }
585 
586 
588 {
589  SetStreamPos(pos);
590 }
591 
592 
594 {
595  if ( m_Input ) {
596  m_Line = 1;
597  if (m_Input->IsMultiPart() && TrySetCurrentPos(m_Buffer + (size_t)pos)) {
598  return;
599  }
600  m_Input->Seekg(pos);
601  m_BufferPos = pos;
604  }
605  else {
606  if ( pos < 0 || pos > m_DataEndPos - m_Buffer ) {
607  NCBI_THROW(CIOException,eRead,"stream position is out of buffer");
608  }
609  m_BufferPos = pos;
610  m_CurrentPos = m_Buffer + (size_t)pos;
611  m_Line = 1;
612  }
613 }
614 
615 
617 {
618  char c;
619  while (isspace((unsigned char)(c = GetChar())))
620  ;
621  return c;
622 }
623 
624 
627 {
628  bool sign;
629  char c = SkipWs();
630  switch ( c ) {
631  case '-':
632  sign = true;
633  c = GetChar();
634  break;
635  case '+':
636  sign = false;
637  c = GetChar();
638  break;
639  default:
640  sign = false;
641  break;
642  }
643 
644  Uint4 n = c - '0';
645  if ( n > 9 )
646  BadNumber();
647 
648  // overflow limits
649  const Uint4 kMaxBeforeMul = kMax_I4/10;
650  const Uint1 kMaxLimitAdd = Uint1(kMax_I4%10 + sign);
651 
652  for ( ;; ) {
653  Uint1 d = (Uint1)(PeekCharNoEOF() - '0');
654  if ( d > 9 )
655  break;
656  SkipChar();
657 
658  // check multiplication overflow
659  if ( n > kMaxBeforeMul || (n == kMaxBeforeMul && d > kMaxLimitAdd) )
660  NumberOverflow();
661 
662  n = n * 10 + d;
663  }
664  if ( sign )
665  return -Int4(n);
666  else
667  return n;
668 }
669 
670 
673 {
674  char c = SkipWs();
675  if ( c == '+' )
676  c = GetChar();
677 
678  Uint4 n = c - '0';
679  if ( n > 9 )
680  BadNumber();
681 
682  // overflow limits
683  const Uint4 kMaxBeforeMul = kMax_UI4/10;
684  const Uint1 kMaxLimitAdd = Uint1(kMax_UI4%10);
685 
686  for ( ;; ) {
687  Uint1 d = (Uint1)(PeekCharNoEOF() - '0');
688  if ( d > 9 )
689  break;
690  SkipChar();
691 
692  // check multiplication overflow
693  if ( n > kMaxBeforeMul || (n == kMaxBeforeMul && d > kMaxLimitAdd) )
694  NumberOverflow();
695 
696  n = n * 10 + d;
697  }
698  return n;
699 }
700 
701 
704 {
705  bool sign;
706  char c = SkipWs();
707  switch ( c ) {
708  case '-':
709  sign = true;
710  c = GetChar();
711  break;
712  case '+':
713  sign = false;
714  c = GetChar();
715  break;
716  default:
717  sign = false;
718  break;
719  }
720 
721  Uint8 n = c - '0';
722  if ( n > 9 )
723  BadNumber();
724 
725  // overflow limits
726  const Uint8 kMaxBeforeMul = kMax_I8/10;
727  const Uint1 kMaxLimitAdd = Uint1(kMax_I8%10 + sign);
728 
729  for ( ;; ) {
730  Uint1 d = (Uint1)(PeekCharNoEOF() - '0');
731  if ( d > 9 )
732  break;
733  SkipChar();
734 
735  // check multiplication overflow
736  if ( n > kMaxBeforeMul || (n == kMaxBeforeMul && d > kMaxLimitAdd) )
737  NumberOverflow();
738 
739  n = n * 10 + d;
740  }
741  if ( sign )
742  return -Int8(n);
743  else
744  return n;
745 }
746 
747 
750 {
751  char c = SkipWs();
752  if ( c == '+' )
753  c = GetChar();
754  Uint1 d = (Uint1)(c - '0');
755  if ( d > 9 )
756  BadNumber();
757 
758  Uint8 n = d;
759 
760  // overflow limits
761  const Uint8 kMaxBeforeMul = kMax_UI8/10;
762 
763  for ( ;; ) {
764  d = (Uint1)(PeekCharNoEOF() - '0');
765  if ( d > 9 )
766  break;
767  SkipChar();
768 
769  // check multiplication overflow
770  if ( n > kMaxBeforeMul )
771  NumberOverflow();
772 
773  n = n * 10 + d;
774 
775  if ( n < d )
776  NumberOverflow();
777  }
778  return n;
779 }
780 
781 
783  THROWS1((bad_alloc))
784  : m_Output(out), m_DeleteOutput(deleteOut), m_Closed(false), m_Error(0),
785  m_IndentLevel(0), m_BufferPos(0),
786  m_Buffer(new char[KInitialBufferSize]),
787  m_CurrentPos(m_Buffer),
788  m_BufferEnd(m_Buffer + KInitialBufferSize),
789  m_Line(1), m_LineLength(0),
790  m_BackLimit(0), m_UseIndentation(true), m_UseEol(true),
791  m_CanceledCallback(0)
792 {
793 }
794 
795 
797 {
798  try {
799  Close();
800  }
801  NCBI_CATCH_X(2, "~COStreamBuffer: exception while closing");
802  if ( m_DeleteOutput ) {
803  try {
804  delete &m_Output;
805  }
806  NCBI_CATCH_X(2, "~COStreamBuffer: exception deleting output stream");
807  m_DeleteOutput = false;
808  }
809  delete[] m_Buffer;
810 }
811 
812 
814 
816 {
818  : m_Stream(stream),
819  m_State(stream.rdstate())
820  {
821  m_Stream.clear();
822  }
824  {
825  try {
826  m_Stream.setstate(m_State);
827  }
828  catch ( ios_base::failure& /*ignored*/ ) {
829  // stream may throw exception of type failure if instructed so
830  // the exception should've been already thrown
831  // we only restore the stream state
832  }
833  }
834 
835  ios& m_Stream;
836  IOS_BASE::iostate m_State;
837 };
838 
840 
841 
843 {
844  if ( !m_Closed && m_Output ) {
845  m_Closed = true;
846  if ( m_DeleteOutput ) {
847  Flush();
848  delete &m_Output;
849  m_DeleteOutput = false;
850  }
851  else {
853  FlushBuffer();
854  }
855  }
856  m_Error = 0;
857  m_IndentLevel = 0;
859  m_Line = 1;
860  m_LineLength = 0;
861 }
862 
863 
865 {
866  m_CanceledCallback = callback;
867 }
868 
869 
870 void COStreamBuffer::FlushBuffer(bool fullBuffer)
872 {
873  if ( const ICanceled* callback = m_CanceledCallback ) {
874  if ( callback->IsCanceled() ) {
875  m_Error = "canceled";
877  }
878  }
879  size_t used = GetUsedSpace();
880  size_t count;
881  size_t leave;
882  if ( fullBuffer ) {
883  count = used;
884  leave = 0;
885  }
886  else {
887  leave = m_BackLimit;
888  if ( used < leave )
889  return; // none to flush
890  count = used - leave;
891  }
892  if ( count != 0 ) {
893  if ( !m_Output.write(m_Buffer, count) ) {
894  m_Error = "write fault";
895  NCBI_THROW(CIOException,eWrite,m_Error);
896  }
897  if ( leave != 0 ) {
898  memmove(m_Buffer, m_Buffer + count, leave);
899  m_CurrentPos -= count;
900  }
901  else {
902  m_CurrentPos = m_Buffer;
903  }
904  m_BufferPos += CT_OFF_TYPE(count);
905  }
906 }
907 
908 
911 {
913  FlushBuffer();
914  if ( !m_Output.flush() ) {
915  NCBI_THROW(CIOException,eFlush,"COStreamBuffer::Flush: failed");
916  }
917 }
918 
919 
921  THROWS1((CIOException, bad_alloc))
922 {
923  FlushBuffer(false);
924  size_t usedSize = m_CurrentPos - m_Buffer;
925  size_t needSize = usedSize + count;
926  size_t bufferSize = m_BufferEnd - m_Buffer;
927  if ( bufferSize < needSize ) {
928  // realloc too small buffer
929  do {
930  bufferSize = BiggerBufferSize(bufferSize);
931  } while ( bufferSize < needSize );
932  if ( usedSize == 0 ) {
933  delete[] m_Buffer;
934  m_CurrentPos = m_Buffer = new char[bufferSize];
935  m_BufferEnd = m_Buffer + bufferSize;
936  }
937  else {
938  char* oldBuffer = m_Buffer;
939  m_Buffer = new char[bufferSize];
940  m_BufferEnd = m_Buffer + bufferSize;
941  memcpy(m_Buffer, oldBuffer, usedSize);
942  delete[] oldBuffer;
943  m_CurrentPos = m_Buffer + usedSize;
944  }
945  }
946  return m_CurrentPos;
947 }
948 
949 
951  THROWS1((CIOException, bad_alloc))
952 {
953  const size_t BSIZE = (sizeof(v)*CHAR_BIT) / 3 + 2;
954  char b[BSIZE];
955  Int4 n = v;
956  if ( n < 0 ) {
957  n = -n;
958  }
959  char* pos = b + BSIZE;
960  do {
961  Int4 a = '0'+n;
962  *--pos = char(a-10*(n/=Uint4(10)));
963  } while ( n );
964  if ( v < 0 ) {
965  *--pos = '-';
966  }
967  int len = (int)(b + BSIZE - pos);
968  char* dst = Skip(len);
969  for ( int i = 0; i < len; ++i ) {
970  dst[i] = pos[i];
971  }
972 }
973 
974 
976  THROWS1((CIOException, bad_alloc))
977 {
978  const size_t BSIZE = (sizeof(v)*CHAR_BIT) / 3 + 2;
979  char b[BSIZE];
980  Uint4 n = v;
981  char* pos = b + BSIZE;
982  do {
983  Uint4 a = '0'+n;
984  *--pos = char(a-10*(n/=Uint4(10)));
985  } while ( n );
986  int len = (int)(b + BSIZE - pos);
987  char* dst = Skip(len);
988  for ( int i = 0; i < len; ++i ) {
989  dst[i] = pos[i];
990  }
991 }
992 
993 
994 // On some platforms division of Int8 is very slow,
995 // so will try to optimize it working with chunks.
996 // Works only for radix base == 10.
997 
998 #define PRINT_INT8_CHUNK 1000000000
999 #define PRINT_INT8_CHUNK_SIZE 9
1000 
1002  THROWS1((CIOException, bad_alloc))
1003 {
1004  const size_t BSIZE = (sizeof(v)*CHAR_BIT) / 3 + 2;
1005  char b[BSIZE];
1006  Int8 n = v;
1007  if ( n < 0 ) {
1008  n = -n;
1009  }
1010  char* pos = b + BSIZE;
1011 #ifdef PRINT_INT8_CHUNK
1012  // while n doesn't fit in Int4 process it by 9-digit chunks with 32 bits
1013  while ( n & ~Uint8(Uint4(~0)) ) {
1014  Uint4 m = Uint4(n);
1016  char* end = pos - PRINT_INT8_CHUNK_SIZE;
1017  do {
1018  Uint4 a = '0'+m;
1019  *--pos = char(a-10*(m/=10));
1020  } while ( pos != end );
1021  }
1022  // process all remaining digits in 32-bit number
1023  Uint4 m = Uint4(n);
1024  do {
1025  Uint4 a = '0'+m;
1026  *--pos = char(a-10*(m/=10));
1027  } while ( m );
1028 #else
1029  do {
1030  Uint8 a = '0'+n;
1031  *--pos = char(a-10*(n/=Uint8(10)));
1032  } while ( n );
1033 #endif
1034  if ( v < 0 ) {
1035  *--pos = '-';
1036  }
1037  int len = (int)(b + BSIZE - pos);
1038  char* dst = Skip(len);
1039  for ( int i = 0; i < len; ++i ) {
1040  dst[i] = pos[i];
1041  }
1042 }
1043 
1044 
1046  THROWS1((CIOException, bad_alloc))
1047 {
1048  const size_t BSIZE = (sizeof(v)*CHAR_BIT) / 3 + 2;
1049  char b[BSIZE];
1050  Uint8 n = v;
1051  char* pos = b + BSIZE;
1052 #ifdef PRINT_INT8_CHUNK
1053  // while n doesn't fit in Uint4 process it by 9-digit chunks with 32 bits
1054  while ( n & ~Uint8(Uint4(~0)) ) {
1055  Uint4 m = Uint4(n);
1057  char* end = pos - PRINT_INT8_CHUNK_SIZE;
1058  do {
1059  Uint4 a = '0'+m;
1060  *--pos = char(a-10*(m/=10));
1061  } while ( pos != end );
1062  }
1063  // process all remaining digits in 32-bit number
1064  Uint4 m = Uint4(n);
1065  do {
1066  Uint4 a = '0'+m;
1067  *--pos = char(a-10*(m/=10));
1068  } while ( m );
1069 #else
1070  do {
1071  Uint8 a = '0'+n;
1072  *--pos = char(a-10*(n/=10));
1073  } while ( n );
1074 #endif
1075  int len = (int)(b + BSIZE - pos);
1076  char* dst = Skip(len);
1077  for ( int i = 0; i < len; ++i ) {
1078  dst[i] = pos[i];
1079  }
1080 }
1081 
1082 
1083 void COStreamBuffer::PutEolAtWordEnd(size_t lineLength)
1084  THROWS1((CIOException, bad_alloc))
1085 {
1086  if (!GetUseEol()) {
1087  return;
1088  }
1089  Reserve(1);
1090  size_t linePos = m_LineLength;
1091  char* pos = m_CurrentPos;
1092  bool goodPlace = false;
1093  while ( pos > m_Buffer && linePos > 0 ) {
1094  --pos;
1095  --linePos;
1096  if ( linePos <= lineLength && (isspace((unsigned char) (*pos)) ||
1097  *pos == '\'') ) {
1098  goodPlace = true;
1099  break;
1100  }
1101  else if ( *pos == '\n' || *pos == '"' ) {
1102  // no suitable space found
1103  break;
1104  }
1105  }
1106 
1107  // Prevent insertion of more than one '\n'
1108  if (pos > m_Buffer && *(pos-1) == '\n') {
1109  goodPlace = false;
1110  }
1111 
1112  if ( !goodPlace ) {
1113  // no suitable space found
1114  if ( linePos < lineLength ) {
1115  pos += lineLength - linePos;
1116  linePos = lineLength;
1117  }
1118  // assure we will not break double ""
1119  while ( pos > m_Buffer && *(pos - 1) == '"' ) {
1120  --pos;
1121  --linePos;
1122  }
1123  if ( pos == m_Buffer ) {
1124  // it's possible that we already put some " before...
1125  while ( pos < m_CurrentPos && *pos == '"' ) {
1126  ++pos;
1127  ++linePos;
1128  }
1129  }
1130  }
1131  // split there
1132  // insert '\n'
1133  size_t count = m_CurrentPos - pos;
1134  memmove(pos + 1, pos, count);
1135  m_LineLength = count;
1136  ++m_CurrentPos;
1137  *pos = '\n';
1138  ++m_Line;
1139 }
1140 
1141 
1142 void COStreamBuffer::Write(const char* data, size_t dataLength)
1143  THROWS1((CIOException, bad_alloc))
1144 {
1145  while ( dataLength > 0 ) {
1146  size_t available = GetAvailableSpace();
1147  if ( available == 0 ) {
1148  FlushBuffer(false);
1149  available = GetAvailableSpace();
1150  }
1151  if ( available >= dataLength )
1152  break; // current chunk will fit in buffer
1153  memcpy(m_CurrentPos, data, available);
1154  m_CurrentPos += available;
1155  data += available;
1156  dataLength -= available;
1157  }
1158  memcpy(m_CurrentPos, data, dataLength);
1159  m_CurrentPos += dataLength;
1160 }
1161 
1162 
1164  THROWS1((CIOException, bad_alloc))
1165 {
1166  for ( ;; ) {
1167  size_t available = GetAvailableSpace();
1168  if ( available == 0 ) {
1169  FlushBuffer(false);
1170  available = GetAvailableSpace();
1171  }
1172  size_t count = reader.Read(m_CurrentPos, available);
1173  if ( count == 0 ) {
1174  if ( reader.EndOfData() )
1175  return;
1176  else
1177  NCBI_THROW(CIOException,eRead,"buffer read fault");
1178  }
1179  m_CurrentPos += count;
1180  }
1181 }
1182 
Interface for testing cancellation request in a long lasting operation.
Definition: icanceled.hpp:51
NLM_EXTERN Nlm_CharPtr LIBCALL SkipChar(char FAR *theString, char Char)
std::ofstream out("events_result.xml")
main entry point for tests
static int failure
Definition: t0019.c:11
#define true
Definition: bool.h:35
#define false
Definition: bool.h:36
static const char * str(char *buf, int n)
Definition: stats.c:84
char data[12]
Definition: iconv.c:80
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
#define NCBI_CATCH_X(err_subcode, message)
Catch CExceptions as well with default error code and given error subcode placed in diagnostics.
Definition: ncbiexpt.hpp:615
#define NCBI_THROW_FMT(exception_class, err_code, message)
The same as NCBI_THROW but with message processed as output to ostream.
Definition: ncbiexpt.hpp:719
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:773
#define kMax_UI8
Definition: ncbi_limits.h:222
uint8_t Uint1
1-byte (8-bit) unsigned integer
Definition: ncbitype.h:99
int32_t Int4
4-byte (32-bit) signed integer
Definition: ncbitype.h:102
uint32_t Uint4
4-byte (32-bit) unsigned integer
Definition: ncbitype.h:103
#define kMax_I8
Definition: ncbi_limits.h:221
int64_t Int8
8-byte (64-bit) signed integer
Definition: ncbitype.h:104
uint64_t Uint8
8-byte (64-bit) unsigned integer
Definition: ncbitype.h:105
#define kMax_UI4
Definition: ncbi_limits.h:219
#define kMax_I4
Definition: ncbi_limits.h:218
#define CHAR_BIT
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
Uint4 GetUint4(void)
Definition: strbuffer.cpp:671
COStreamBuffer(CNcbiOstream &out, bool deleteOut=false)
Definition: strbuffer.cpp:782
void ResetBufferLock(size_t pos)
Definition: strbuffer.cpp:157
virtual bool IsMultiPart(void) const
Definition: bytesrc.hpp:91
void Flush(void)
Definition: strbuffer.cpp:909
Int8 GetInt8(void)
Definition: strbuffer.cpp:702
virtual CRef< CByteSource > GetSource(void)=0
Get CByteSource implementation.
CIStreamBuffer(void)
Definition: strbuffer.cpp:55
void GetChars(char *buffer, size_t count)
Definition: strbuffer.cpp:471
const CRef< CSubSourceCollector > & GetParentCollector(void) const
Definition: bytesrc.hpp:141
char * DoReserve(size_t reserve=0)
Definition: strbuffer.cpp:920
Uint8 GetUint8(void)
Definition: strbuffer.cpp:748
size_t m_IndentLevel
Definition: strbuffer.hpp:326
bool TryToFillBuffer(void)
Definition: strbuffer.cpp:465
char SkipSpaces(void)
Definition: strbuffer.cpp:213
bool TrySetCurrentPos(const char *pos)
Definition: strbuffer.cpp:309
void PutEolAtWordEnd(size_t lineLength)
Definition: strbuffer.cpp:1083
Int4 GetInt4(void)
Definition: strbuffer.cpp:625
void Open(CByteSourceReader &reader)
Definition: strbuffer.cpp:92
const char * m_CurrentPos
Definition: strbuffer.hpp:204
size_t m_LineLength
Definition: strbuffer.hpp:333
void Close(void)
Definition: strbuffer.cpp:125
const char * m_Error
Definition: strbuffer.hpp:320
void BadNumber(void)
Definition: strbuffer.cpp:569
size_t PeekFindChar(char c, size_t limit)
Definition: strbuffer.cpp:292
void SetStreamOffset(CNcbiStreampos pos)
Definition: strbuffer.cpp:587
void StartSubSource(void)
Definition: strbuffer.cpp:165
void SetStreamPos(CNcbiStreampos pos)
Definition: strbuffer.cpp:593
virtual void Seekg(CNcbiStreampos pos)
Definition: bytesrc.cpp:96
#define THROWS1(arg)
Definition: strbuffer.hpp:56
virtual void AddChunk(const char *buffer, size_t bufferLength)
Add data to the sub-source.
Definition: bytesrc.cpp:125
virtual size_t GetNextPart(char **, size_t)
Definition: bytesrc.hpp:94
CNcbiOstream & m_Output
Definition: strbuffer.hpp:316
char SkipWs(void)
Definition: strbuffer.cpp:616
char * m_CurrentPos
Definition: strbuffer.hpp:330
CRef< CSubSourceCollector > m_Collector
Definition: strbuffer.hpp:209
void Write(const char *data, size_t dataLength)
Definition: strbuffer.cpp:1142
void SkipEndOfLine(char lastChar)
Definition: strbuffer.cpp:525
void SetCanceledCallback(const ICanceled *callback)
Definition: strbuffer.cpp:142
size_t SetBufferLock(size_t size)
Definition: strbuffer.cpp:148
CRef< CByteSourceReader > m_Input
Definition: strbuffer.hpp:197
CConstIRef< ICanceled > m_CanceledCallback
Definition: strbuffer.hpp:211
void PutInt8(Int8 v)
Definition: strbuffer.cpp:1001
size_t m_BufferSize
Definition: strbuffer.hpp:202
void FlushBuffer(bool fullBuffer=true)
Definition: strbuffer.cpp:870
char GetChar(void)
const char * m_CollectPos
Definition: strbuffer.hpp:208
char FillBufferNoEOF(const char *pos)
Definition: strbuffer.cpp:455
const char * FillBuffer(const char *pos, bool noEOF=false)
Definition: strbuffer.cpp:319
void NumberOverflow(void)
Definition: strbuffer.cpp:578
virtual bool Pushback(const char *data, size_t size)
Definition: bytesrc.cpp:86
void SetCanceledCallback(const ICanceled *callback)
Definition: strbuffer.cpp:864
CRef< CByteSource > EndSubSource(void)
Definition: strbuffer.cpp:186
size_t m_BufferLockSize
Definition: strbuffer.hpp:212
~COStreamBuffer(void)
Definition: strbuffer.cpp:796
void PutUint4(Uint4 v)
Definition: strbuffer.cpp:975
void FindChar(char c)
Definition: strbuffer.cpp:257
void Close(void)
Definition: strbuffer.cpp:842
CConstIRef< ICanceled > m_CanceledCallback
Definition: strbuffer.hpp:338
const char * m_Error
Definition: strbuffer.hpp:199
void PutUint8(Uint8 v)
Definition: strbuffer.cpp:1045
~CIStreamBuffer(void)
Definition: strbuffer.cpp:80
const char * m_DataEndPos
Definition: strbuffer.hpp:205
size_t ReadLine(char *buff, size_t size)
Definition: strbuffer.cpp:539
virtual CRef< CSubSourceCollector > SubSource(size_t prepend, CRef< CSubSourceCollector > parent)
Definition: bytesrc.cpp:102
#define THROWS1_NONE
Definition: strbuffer.hpp:57
void PutInt4(Int4 v)
Definition: strbuffer.cpp:950
#define CT_OFF_TYPE
Definition: ncbistre.hpp:731
IO_PREFIX::ostream CNcbiOstream
Portable alias for ostream.
Definition: ncbistre.hpp:149
IO_PREFIX::streampos CNcbiStreampos
Portable alias for streampos.
Definition: ncbistre.hpp:134
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
Definition of all error codes used in util (xutil.lib).
where boath are integers</td > n< td ></td > n</tr > n< tr > n< td > tse</td > n< td > optional</td > n< td > String</td > n< td class=\"description\"> TSE option controls what blob is smart and slim</td> n<td> orig</td> n</tr> n<tr> n<td> last_modified</td> n<td> optional</td> n<td> Integer</td> n<td class=\"description\"> The blob last modification If provided then the exact match will be requested with n the Cassandra storage corresponding field value</td> n<td> Positive integer Not provided means that the most recent match will be selected</td> n<td></td> n</tr> n<tr> n<td> use_cache</td> n<td> optional</td> n<td> String</td> n<td class=\"description\"> The option controls if the Cassandra LMDB cache and or database should be used It n affects the seq id resolution step and the blob properties lookup step The following n options are available
int i
yy_size_t n
int len
static const CS_INT unused
Definition: long_binary.c:20
const struct ncbi::grid::netcache::search::fields::SIZE size
const CharType(& source)[N]
Definition: pointer.h:1149
unsigned int a
Definition: ncbi_localip.c:102
int isspace(Uchar c)
Definition: ncbictype.hpp:69
NCBI C++ stream class wrappers for triggering between "new" and "old" C++ stream libraries.
T min(T x_, T y_)
@ eRead
Definition: ns_types.hpp:56
#define memmove(a, b, c)
#define count
static uint8_t * buffer
Definition: pcre2test.c:1016
@ eCanceled
Request canceled.
#define PRINT_INT8_CHUNK_SIZE
Definition: strbuffer.cpp:999
static size_t BiggerBufferSize(size_t size) THROWS1_NONE
Definition: strbuffer.cpp:49
BEGIN_LOCAL_NAMESPACE
Definition: strbuffer.cpp:813
END_LOCAL_NAMESPACE
Definition: strbuffer.cpp:839
#define PRINT_INT8_CHUNK
Definition: strbuffer.cpp:998
static const size_t KInitialBufferSize
Definition: strbuffer.cpp:46
IOS_BASE::iostate m_State
Definition: strbuffer.cpp:836
STemporarilyClearStreamState(ios &stream)
Definition: strbuffer.cpp:817
#define _ASSERT
Modified on Fri Sep 20 14:57:02 2024 by modify_doxy.py rev. 669887