summaryrefslogtreecommitdiff
path: root/ace/Read_Buffer.cpp
blob: b203f3b8d0ea2aa26bc3e0e6cdb043acb8ca4de7 (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// $Id$

#define ACE_BUILD_DLL
#include "ace/Read_Buffer.h"
#include "ace/Service_Config.h"

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

ACE_RCSID(ace, Read_Buffer, "$Id$")

void
ACE_Read_Buffer::dump (void) const
{
  ACE_TRACE ("ACE_Read_Buffer::dump");
  ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
  ACE_DEBUG ((LM_DEBUG,  ASYS_TEXT ("size_ = %d"), this->size_));
  ACE_DEBUG ((LM_DEBUG,  ASYS_TEXT ("\noccurrences_ = %d"), this->occurrences_));
  ACE_DEBUG ((LM_DEBUG,  ASYS_TEXT ("\nstream_ = %x"), this->stream_));
  ACE_DEBUG ((LM_DEBUG,  ASYS_TEXT ("\nallocator_ = %x"), this->allocator_));
  ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
}

ACE_Read_Buffer::ACE_Read_Buffer (FILE *fp,
                                  int close_on_delete,
                                  ACE_Allocator *alloc)
  : stream_ (fp),
    close_on_delete_ (close_on_delete),
    allocator_ (alloc)
{
  ACE_TRACE ("ACE_Read_Buffer::ACE_Read_Buffer");
  if (this->allocator_ == 0)
    this->allocator_ = ACE_Allocator::instance ();
}

ACE_Read_Buffer::ACE_Read_Buffer (ACE_HANDLE handle,
                                  int close_on_delete,
                                  ACE_Allocator *alloc)
  : stream_ (ACE_OS::fdopen (handle, "r")),
    close_on_delete_ (close_on_delete),
    allocator_ (alloc)
{
  ACE_TRACE ("ACE_Read_Buffer::ACE_Read_Buffer");

  if (this->allocator_ == 0)
    this->allocator_ = ACE_Allocator::instance ();
}

ACE_Read_Buffer::~ACE_Read_Buffer (void)
{
  ACE_TRACE ("ACE_Read_Buffer::~ACE_Read_Buffer");

  if (this->close_on_delete_)
    ACE_OS::fclose (this->stream_);
}

// Input: term        the character to terminate on
//        search      the character to search for
//        replace     the character with which to replace search
// Output: a buffer containing the contents of stream
// Method: call the recursive helper function read_helper

char *
ACE_Read_Buffer::read (int term, int search, int replace)
{
  ACE_TRACE ("ACE_Read_Buffer::read");
  this->occurrences_ = 0;
  this->size_ = 0;
  return this->rec_read (term, search, replace);
}

// Input: term       the termination character
//        search     the character to search for
//        replace    the character with which to replace search
// Purpose: read in a file to a buffer using only a single dynamic
//          allocation.
// Method: read until the local buffer is full and then recurse.
//         Must continue until the termination character is reached.
//         Allocate the final buffer based on the number of local
//         buffers read and as the recursive calls bottom out,
//         copy them in reverse order into the allocated buffer.

char *
ACE_Read_Buffer::rec_read (int term, int search, int replace)
{
  ACE_TRACE ("ACE_Read_Buffer::rec_read");
  // This is our temporary workspace.
  char buf[BUFSIZ];

  int c = EOF;
  size_t slot = 0;
  int done = 0;

  // Read in the file char by char
  while (slot < BUFSIZ)
    {
      c = getc (this->stream_);

      // Don't insert EOF into the buffer...
      if (c == EOF)
        {
          if (slot == 0)
            return 0;
          else
            {
              ungetc (c, this->stream_);
              break;
            }
        }
      else if (c == term)
        done = 1;

      // Check for possible substitutions.
      if (c == search)
        {
          this->occurrences_++;

          if (replace >= 0)
            c = replace;
        }

      buf[slot++] = (char) c;

      // Substitutions must be made before checking for termination.
      if (done)
        break;
    }

  // Increment the number of bytes.
  this->size_ += slot;

  char *result;

  // Recurse, when the recursion bottoms out, allocate the result
  // buffer.
  if (done || c == EOF)
    {
      // Use the allocator to acquire the memory.  The + 1 allows
      // space for the null terminator.
      result = (char *) this->allocator_->malloc (this->size_ + 1);

      if (result == 0)
        {
          errno = ENOMEM;
          return 0;
        }
      result += this->size_;
    }
  else if ((result = this->rec_read (term, search, replace)) == 0)
    return 0;

  // Null terminate the buffer.
  *result = '\0';

  // Copy buf into the appropriate location starting from end of
  // buffer.  Peter says this is confusing and that we should use
  // memcpy() ;-)
  for (size_t j = slot; j > 0; j--)
    *--result = buf[j - 1];

  return result;
}