summaryrefslogtreecommitdiff
path: root/ace/Read_Buffer.h
blob: 11176ef34df789ddbcdde9d797c4b297086e3c2e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// -*- C++ -*-

//==========================================================================
/**
 *  @file    Read_Buffer.h
 *
 *  $Id$
 *
 *  @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
 *  @author Seth Widoff
 */
//==========================================================================

#ifndef ACE_READ_BUFFER_H
#define ACE_READ_BUFFER_H

#include /**/ "ace/pre.h"

#include "ace/ACE_export.h"

#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */

#include "ace/Global_Macros.h"
#include "ace/os_include/os_stdio.h"

ACE_BEGIN_VERSIONED_NAMESPACE_DECL

class ACE_Allocator;

/**
 * @class ACE_Read_Buffer
 *
 * @brief Efficiently reads an artibrarily large buffer from an input
 * stream up to and including a termination character.  Also
 * performs search/replace on single occurrences a character in
 * the buffer using the principles of Integrated Layer
 * Processing.
 *
 * This implementation is optimized to do a single dynamic
 * allocation and make only one copy of the data.  It uses
 * recursion and the run-time stack to accomplish this
 * efficiently.
 */
class ACE_Export ACE_Read_Buffer
{
public:
  // = Initialization and termination methods.
  /// Read from a FILE *.
  ACE_Read_Buffer (FILE *fp,
                   int close_on_delete = 0,
                   ACE_Allocator * = 0);

#if !defined (ACE_HAS_WINCE)
  // Note that ACE_HANDLE = FILE under CE.

  /// Read from an open HANDLE.
  ACE_Read_Buffer (ACE_HANDLE handle,
                   int close_on_delete = 0,
                   ACE_Allocator * = 0);
#endif  // ACE_HAS_WINCE

  /// Closes the FILE *.
  ~ACE_Read_Buffer (void);

  /**
   * Returns a pointer dynamically allocated with
   * <ACE_Allocator::malloc> to data from the input stream up to (and
   * including) the <terminator>.  If <search> is >= 0 then all
   * occurrences of the <search> value are substituted with the
   * <replace> value.  The last of the byte of data is a 0, so that
   * <strlen> can be used on it.  The caller is responsible for
   * freeing the pointer returned from this method using the
   * <ACE_Allocator::free>.
   */
  char *read (int terminator = EOF,
              int search = '\n',
              int replace = '\0');

  /// Returns the number of characters replaced during a <read>.
  size_t replaced (void) const;

  /// Returns the size of the allocated buffer obtained during a
  /// @c read, not including the null terminator.
  size_t size (void) const;

  /// Returns a pointer to its allocator.
  ACE_Allocator *alloc (void) const;

  /// Dump the state of the object.
  void dump (void) const;

private:

  // Disallow copying and assignment...
  void operator= (const ACE_Read_Buffer &);
  ACE_Read_Buffer (const ACE_Read_Buffer &);

private:
  /// Recursive helper method that does the work...
  char *rec_read (int term, int search, int replace);

  /// The total number of characters in the buffer.
  size_t size_;

  /// The total number of characters replaced.
  size_t occurrences_;

  /// The stream we are reading from.
  FILE *stream_;

  /// Keeps track of whether we should close the FILE in the
  /// destructor.
  int close_on_delete_;

  /// Pointer to the allocator.
  ACE_Allocator *allocator_;

};

ACE_END_VERSIONED_NAMESPACE_DECL

#if defined (__ACE_INLINE__)
# include "ace/Read_Buffer.inl"
#endif /* __ACE_INLINE__ */

#include /**/ "ace/post.h"

#endif /* ACE_READ_BUFFER_H */