~ubuntu-branches/ubuntu/oneiric/protobuf/oneiric

« back to all changes in this revision

Viewing changes to src/google/protobuf/stubs/substitute.cc

  • Committer: Bazaar Package Importer
  • Author(s): Iustin Pop
  • Date: 2008-08-03 11:01:44 UTC
  • Revision ID: james.westby@ubuntu.com-20080803110144-uyiw41bf1m2oe17t
Tags: upstream-2.0.0~b
ImportĀ upstreamĀ versionĀ 2.0.0~b

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Protocol Buffers - Google's data interchange format
 
2
// Copyright 2008 Google Inc.
 
3
// http://code.google.com/p/protobuf/
 
4
//
 
5
// Licensed under the Apache License, Version 2.0 (the "License");
 
6
// you may not use this file except in compliance with the License.
 
7
// You may obtain a copy of the License at
 
8
//
 
9
//      http://www.apache.org/licenses/LICENSE-2.0
 
10
//
 
11
// Unless required by applicable law or agreed to in writing, software
 
12
// distributed under the License is distributed on an "AS IS" BASIS,
 
13
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
14
// See the License for the specific language governing permissions and
 
15
// limitations under the License.
 
16
 
 
17
// Author: kenton@google.com (Kenton Varda)
 
18
 
 
19
#include <google/protobuf/stubs/substitute.h>
 
20
#include <google/protobuf/stubs/strutil.h>
 
21
#include <google/protobuf/stubs/stl_util-inl.h>
 
22
 
 
23
namespace google {
 
24
namespace protobuf {
 
25
namespace strings {
 
26
 
 
27
using internal::SubstituteArg;
 
28
 
 
29
// Returns the number of args in arg_array which were passed explicitly
 
30
// to Substitute().
 
31
static int CountSubstituteArgs(const SubstituteArg* const* args_array) {
 
32
  int count = 0;
 
33
  while (args_array[count] != NULL && args_array[count]->size() != -1) {
 
34
    ++count;
 
35
  }
 
36
  return count;
 
37
}
 
38
 
 
39
string Substitute(
 
40
    const char* format,
 
41
    const SubstituteArg& arg0, const SubstituteArg& arg1,
 
42
    const SubstituteArg& arg2, const SubstituteArg& arg3,
 
43
    const SubstituteArg& arg4, const SubstituteArg& arg5,
 
44
    const SubstituteArg& arg6, const SubstituteArg& arg7,
 
45
    const SubstituteArg& arg8, const SubstituteArg& arg9) {
 
46
  string result;
 
47
  SubstituteAndAppend(&result, format, arg0, arg1, arg2, arg3, arg4,
 
48
                                       arg5, arg6, arg7, arg8, arg9);
 
49
  return result;
 
50
}
 
51
 
 
52
void SubstituteAndAppend(
 
53
    string* output, const char* format,
 
54
    const SubstituteArg& arg0, const SubstituteArg& arg1,
 
55
    const SubstituteArg& arg2, const SubstituteArg& arg3,
 
56
    const SubstituteArg& arg4, const SubstituteArg& arg5,
 
57
    const SubstituteArg& arg6, const SubstituteArg& arg7,
 
58
    const SubstituteArg& arg8, const SubstituteArg& arg9) {
 
59
  const SubstituteArg* const args_array[] = {
 
60
    &arg0, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8, &arg9, NULL
 
61
  };
 
62
 
 
63
  // Determine total size needed.
 
64
  int size = 0;
 
65
  for (int i = 0; format[i] != '\0'; i++) {
 
66
    if (format[i] == '$') {
 
67
      if (ascii_isdigit(format[i+1])) {
 
68
        int index = format[i+1] - '0';
 
69
        if (args_array[index]->size() == -1) {
 
70
          GOOGLE_LOG(DFATAL)
 
71
            << "strings::Substitute format string invalid: asked for \"$"
 
72
            << index << "\", but only " << CountSubstituteArgs(args_array)
 
73
            << " args were given.  Full format string was: \""
 
74
            << CEscape(format) << "\".";
 
75
          return;
 
76
        }
 
77
        size += args_array[index]->size();
 
78
        ++i;  // Skip next char.
 
79
      } else if (format[i+1] == '$') {
 
80
        ++size;
 
81
        ++i;  // Skip next char.
 
82
      } else {
 
83
        GOOGLE_LOG(DFATAL)
 
84
          << "Invalid strings::Substitute() format string: \""
 
85
          << CEscape(format) << "\".";
 
86
        return;
 
87
      }
 
88
    } else {
 
89
      ++size;
 
90
    }
 
91
  }
 
92
 
 
93
  if (size == 0) return;
 
94
 
 
95
  // Build the string.
 
96
  int original_size = output->size();
 
97
  STLStringResizeUninitialized(output, original_size + size);
 
98
  char* target = string_as_array(output) + original_size;
 
99
  for (int i = 0; format[i] != '\0'; i++) {
 
100
    if (format[i] == '$') {
 
101
      if (ascii_isdigit(format[i+1])) {
 
102
        const SubstituteArg* src = args_array[format[i+1] - '0'];
 
103
        memcpy(target, src->data(), src->size());
 
104
        target += src->size();
 
105
        ++i;  // Skip next char.
 
106
      } else if (format[i+1] == '$') {
 
107
        *target++ = '$';
 
108
        ++i;  // Skip next char.
 
109
      }
 
110
    } else {
 
111
      *target++ = format[i];
 
112
    }
 
113
  }
 
114
 
 
115
  GOOGLE_DCHECK_EQ(target - output->data(), output->size());
 
116
}
 
117
 
 
118
}  // namespace strings
 
119
}  // namespace protobuf
 
120
}  // namespace google