Free cookie consent management tool by TermsFeed Policy Generator

source: branches/WebJobManager/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/2.4.1/ProtobufCS/src/ProtocolBuffers/TextFormat.cs

Last change on this file was 8295, checked in by abeham, 12 years ago

#1897:

  • Removed protocol buffers 0.9.1
  • Added protocol buffers 2.4.1
  • Updated proto processing command
File size: 33.0 KB
Line 
1#region Copyright notice and license
2
3// Protocol Buffers - Google's data interchange format
4// Copyright 2008 Google Inc.  All rights reserved.
5// http://github.com/jskeet/dotnet-protobufs/
6// Original C++/Java/Python code:
7// http://code.google.com/p/protobuf/
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions are
11// met:
12//
13//     * Redistributions of source code must retain the above copyright
14// notice, this list of conditions and the following disclaimer.
15//     * Redistributions in binary form must reproduce the above
16// copyright notice, this list of conditions and the following disclaimer
17// in the documentation and/or other materials provided with the
18// distribution.
19//     * Neither the name of Google Inc. nor the names of its
20// contributors may be used to endorse or promote products derived from
21// this software without specific prior written permission.
22//
23// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35#endregion
36
37using System;
38using System.Collections;
39using System.Collections.Generic;
40using System.Globalization;
41using System.IO;
42using System.Text;
43using Google.ProtocolBuffers.Descriptors;
44
45namespace Google.ProtocolBuffers
46{
47    /// <summary>
48    /// Provides ASCII text formatting support for messages.
49    /// TODO(jonskeet): Support for alternative line endings.
50    /// (Easy to print, via TextGenerator. Not sure about parsing.)
51    /// </summary>
52    public static class TextFormat
53    {
54        /// <summary>
55        /// Outputs a textual representation of the Protocol Message supplied into
56        /// the parameter output.
57        /// </summary>
58        public static void Print(IMessage message, TextWriter output)
59        {
60            TextGenerator generator = new TextGenerator(output, "\n");
61            Print(message, generator);
62        }
63
64        /// <summary>
65        /// Outputs a textual representation of <paramref name="fields" /> to <paramref name="output"/>.
66        /// </summary>
67        public static void Print(UnknownFieldSet fields, TextWriter output)
68        {
69            TextGenerator generator = new TextGenerator(output, "\n");
70            PrintUnknownFields(fields, generator);
71        }
72
73        public static string PrintToString(IMessage message)
74        {
75            StringWriter text = new StringWriter();
76            Print(message, text);
77            return text.ToString();
78        }
79
80        public static string PrintToString(UnknownFieldSet fields)
81        {
82            StringWriter text = new StringWriter();
83            Print(fields, text);
84            return text.ToString();
85        }
86
87        private static void Print(IMessage message, TextGenerator generator)
88        {
89            foreach (KeyValuePair<FieldDescriptor, object> entry in message.AllFields)
90            {
91                PrintField(entry.Key, entry.Value, generator);
92            }
93            PrintUnknownFields(message.UnknownFields, generator);
94        }
95
96        internal static void PrintField(FieldDescriptor field, object value, TextGenerator generator)
97        {
98            if (field.IsRepeated)
99            {
100                // Repeated field.  Print each element.
101                foreach (object element in (IEnumerable) value)
102                {
103                    PrintSingleField(field, element, generator);
104                }
105            }
106            else
107            {
108                PrintSingleField(field, value, generator);
109            }
110        }
111
112        private static void PrintSingleField(FieldDescriptor field, Object value, TextGenerator generator)
113        {
114            if (field.IsExtension)
115            {
116                generator.Print("[");
117                // We special-case MessageSet elements for compatibility with proto1.
118                if (field.ContainingType.Options.MessageSetWireFormat
119                    && field.FieldType == FieldType.Message
120                    && field.IsOptional
121                    // object equality (TODO(jonskeet): Work out what this comment means!)
122                    && field.ExtensionScope == field.MessageType)
123                {
124                    generator.Print(field.MessageType.FullName);
125                }
126                else
127                {
128                    generator.Print(field.FullName);
129                }
130                generator.Print("]");
131            }
132            else
133            {
134                if (field.FieldType == FieldType.Group)
135                {
136                    // Groups must be serialized with their original capitalization.
137                    generator.Print(field.MessageType.Name);
138                }
139                else
140                {
141                    generator.Print(field.Name);
142                }
143            }
144
145            if (field.MappedType == MappedType.Message)
146            {
147                generator.Print(" {\n");
148                generator.Indent();
149            }
150            else
151            {
152                generator.Print(": ");
153            }
154
155            PrintFieldValue(field, value, generator);
156
157            if (field.MappedType == MappedType.Message)
158            {
159                generator.Outdent();
160                generator.Print("}");
161            }
162            generator.Print("\n");
163        }
164
165        private static void PrintFieldValue(FieldDescriptor field, object value, TextGenerator generator)
166        {
167            switch (field.FieldType)
168            {
169                    // The Float and Double types must specify the "r" format to preserve their precision, otherwise,
170                    // the double to/from string will trim the precision to 6 places.  As with other numeric formats
171                    // below, always use the invariant culture so it's predictable.
172                case FieldType.Float:
173                    generator.Print(((float) value).ToString("r", CultureInfo.InvariantCulture));
174                    break;
175                case FieldType.Double:
176                    generator.Print(((double) value).ToString("r", CultureInfo.InvariantCulture));
177                    break;
178
179                case FieldType.Int32:
180                case FieldType.Int64:
181                case FieldType.SInt32:
182                case FieldType.SInt64:
183                case FieldType.SFixed32:
184                case FieldType.SFixed64:
185                case FieldType.UInt32:
186                case FieldType.UInt64:
187                case FieldType.Fixed32:
188                case FieldType.Fixed64:
189                    // The simple Object.ToString converts using the current culture.
190                    // We want to always use the invariant culture so it's predictable.
191                    generator.Print(((IConvertible) value).ToString(CultureInfo.InvariantCulture));
192                    break;
193                case FieldType.Bool:
194                    // Explicitly use the Java true/false
195                    generator.Print((bool) value ? "true" : "false");
196                    break;
197
198                case FieldType.String:
199                    generator.Print("\"");
200                    generator.Print(EscapeText((string) value));
201                    generator.Print("\"");
202                    break;
203
204                case FieldType.Bytes:
205                    {
206                        generator.Print("\"");
207                        generator.Print(EscapeBytes((ByteString) value));
208                        generator.Print("\"");
209                        break;
210                    }
211
212                case FieldType.Enum:
213                    {
214                        if (value is IEnumLite && !(value is EnumValueDescriptor))
215                        {
216                            throw new NotSupportedException("Lite enumerations are not supported.");
217                        }
218                        generator.Print(((EnumValueDescriptor) value).Name);
219                        break;
220                    }
221
222                case FieldType.Message:
223                case FieldType.Group:
224                    if (value is IMessageLite && !(value is IMessage))
225                    {
226                        throw new NotSupportedException("Lite messages are not supported.");
227                    }
228                    Print((IMessage) value, generator);
229                    break;
230            }
231        }
232
233        private static void PrintUnknownFields(UnknownFieldSet unknownFields, TextGenerator generator)
234        {
235            foreach (KeyValuePair<int, UnknownField> entry in unknownFields.FieldDictionary)
236            {
237                String prefix = entry.Key.ToString() + ": ";
238                UnknownField field = entry.Value;
239
240                foreach (ulong value in field.VarintList)
241                {
242                    generator.Print(prefix);
243                    generator.Print(value.ToString());
244                    generator.Print("\n");
245                }
246                foreach (uint value in field.Fixed32List)
247                {
248                    generator.Print(prefix);
249                    generator.Print(string.Format("0x{0:x8}", value));
250                    generator.Print("\n");
251                }
252                foreach (ulong value in field.Fixed64List)
253                {
254                    generator.Print(prefix);
255                    generator.Print(string.Format("0x{0:x16}", value));
256                    generator.Print("\n");
257                }
258                foreach (ByteString value in field.LengthDelimitedList)
259                {
260                    generator.Print(entry.Key.ToString());
261                    generator.Print(": \"");
262                    generator.Print(EscapeBytes(value));
263                    generator.Print("\"\n");
264                }
265                foreach (UnknownFieldSet value in field.GroupList)
266                {
267                    generator.Print(entry.Key.ToString());
268                    generator.Print(" {\n");
269                    generator.Indent();
270                    PrintUnknownFields(value, generator);
271                    generator.Outdent();
272                    generator.Print("}\n");
273                }
274            }
275        }
276
277        [CLSCompliant(false)]
278        public static ulong ParseUInt64(string text)
279        {
280            return (ulong) ParseInteger(text, false, true);
281        }
282
283        public static long ParseInt64(string text)
284        {
285            return ParseInteger(text, true, true);
286        }
287
288        [CLSCompliant(false)]
289        public static uint ParseUInt32(string text)
290        {
291            return (uint) ParseInteger(text, false, false);
292        }
293
294        public static int ParseInt32(string text)
295        {
296            return (int) ParseInteger(text, true, false);
297        }
298
299        public static float ParseFloat(string text)
300        {
301            switch (text)
302            {
303                case "-inf":
304                case "-infinity":
305                case "-inff":
306                case "-infinityf":
307                    return float.NegativeInfinity;
308                case "inf":
309                case "infinity":
310                case "inff":
311                case "infinityf":
312                    return float.PositiveInfinity;
313                case "nan":
314                case "nanf":
315                    return float.NaN;
316                default:
317                    return float.Parse(text, CultureInfo.InvariantCulture);
318            }
319        }
320
321        public static double ParseDouble(string text)
322        {
323            switch (text)
324            {
325                case "-inf":
326                case "-infinity":
327                    return double.NegativeInfinity;
328                case "inf":
329                case "infinity":
330                    return double.PositiveInfinity;
331                case "nan":
332                    return double.NaN;
333                default:
334                    return double.Parse(text, CultureInfo.InvariantCulture);
335            }
336        }
337
338        /// <summary>
339        /// Parses an integer in hex (leading 0x), decimal (no prefix) or octal (leading 0).
340        /// Only a negative sign is permitted, and it must come before the radix indicator.
341        /// </summary>
342        private static long ParseInteger(string text, bool isSigned, bool isLong)
343        {
344            string original = text;
345            bool negative = false;
346            if (text.StartsWith("-"))
347            {
348                if (!isSigned)
349                {
350                    throw new FormatException("Number must be positive: " + original);
351                }
352                negative = true;
353                text = text.Substring(1);
354            }
355
356            int radix = 10;
357            if (text.StartsWith("0x"))
358            {
359                radix = 16;
360                text = text.Substring(2);
361            }
362            else if (text.StartsWith("0"))
363            {
364                radix = 8;
365            }
366
367            ulong result;
368            try
369            {
370                // Workaround for https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=278448
371                // We should be able to use Convert.ToUInt64 for all cases.
372                result = radix == 10 ? ulong.Parse(text) : Convert.ToUInt64(text, radix);
373            }
374            catch (OverflowException)
375            {
376                // Convert OverflowException to FormatException so there's a single exception type this method can throw.
377                string numberDescription = string.Format("{0}-bit {1}signed integer", isLong ? 64 : 32,
378                                                         isSigned ? "" : "un");
379                throw new FormatException("Number out of range for " + numberDescription + ": " + original);
380            }
381
382            if (negative)
383            {
384                ulong max = isLong ? 0x8000000000000000UL : 0x80000000L;
385                if (result > max)
386                {
387                    string numberDescription = string.Format("{0}-bit signed integer", isLong ? 64 : 32);
388                    throw new FormatException("Number out of range for " + numberDescription + ": " + original);
389                }
390                return -((long) result);
391            }
392            else
393            {
394                ulong max = isSigned
395                                ? (isLong ? (ulong) long.MaxValue : int.MaxValue)
396                                : (isLong ? ulong.MaxValue : uint.MaxValue);
397                if (result > max)
398                {
399                    string numberDescription = string.Format("{0}-bit {1}signed integer", isLong ? 64 : 32,
400                                                             isSigned ? "" : "un");
401                    throw new FormatException("Number out of range for " + numberDescription + ": " + original);
402                }
403                return (long) result;
404            }
405        }
406
407        /// <summary>
408        /// Tests a character to see if it's an octal digit.
409        /// </summary>
410        private static bool IsOctal(char c)
411        {
412            return '0' <= c && c <= '7';
413        }
414
415        /// <summary>
416        /// Tests a character to see if it's a hex digit.
417        /// </summary>
418        private static bool IsHex(char c)
419        {
420            return ('0' <= c && c <= '9') ||
421                   ('a' <= c && c <= 'f') ||
422                   ('A' <= c && c <= 'F');
423        }
424
425        /// <summary>
426        /// Interprets a character as a digit (in any base up to 36) and returns the
427        /// numeric value.
428        /// </summary>
429        private static int ParseDigit(char c)
430        {
431            if ('0' <= c && c <= '9')
432            {
433                return c - '0';
434            }
435            else if ('a' <= c && c <= 'z')
436            {
437                return c - 'a' + 10;
438            }
439            else
440            {
441                return c - 'A' + 10;
442            }
443        }
444
445        /// <summary>
446        /// Unescapes a text string as escaped using <see cref="EscapeText(string)" />.
447        /// Two-digit hex escapes (starting with "\x" are also recognised.
448        /// </summary>
449        public static string UnescapeText(string input)
450        {
451            return UnescapeBytes(input).ToStringUtf8();
452        }
453
454        /// <summary>
455        /// Like <see cref="EscapeBytes" /> but escapes a text string.
456        /// The string is first encoded as UTF-8, then each byte escaped individually.
457        /// The returned value is guaranteed to be entirely ASCII.
458        /// </summary>
459        public static string EscapeText(string input)
460        {
461            return EscapeBytes(ByteString.CopyFromUtf8(input));
462        }
463
464        /// <summary>
465        /// Escapes bytes in the format used in protocol buffer text format, which
466        /// is the same as the format used for C string literals.  All bytes
467        /// that are not printable 7-bit ASCII characters are escaped, as well as
468        /// backslash, single-quote, and double-quote characters.  Characters for
469        /// which no defined short-hand escape sequence is defined will be escaped
470        /// using 3-digit octal sequences.
471        /// The returned value is guaranteed to be entirely ASCII.
472        /// </summary>
473        public static String EscapeBytes(ByteString input)
474        {
475            StringBuilder builder = new StringBuilder(input.Length);
476            foreach (byte b in input)
477            {
478                switch (b)
479                {
480                        // C# does not use \a or \v
481                    case 0x07:
482                        builder.Append("\\a");
483                        break;
484                    case (byte) '\b':
485                        builder.Append("\\b");
486                        break;
487                    case (byte) '\f':
488                        builder.Append("\\f");
489                        break;
490                    case (byte) '\n':
491                        builder.Append("\\n");
492                        break;
493                    case (byte) '\r':
494                        builder.Append("\\r");
495                        break;
496                    case (byte) '\t':
497                        builder.Append("\\t");
498                        break;
499                    case 0x0b:
500                        builder.Append("\\v");
501                        break;
502                    case (byte) '\\':
503                        builder.Append("\\\\");
504                        break;
505                    case (byte) '\'':
506                        builder.Append("\\\'");
507                        break;
508                    case (byte) '"':
509                        builder.Append("\\\"");
510                        break;
511                    default:
512                        if (b >= 0x20 && b < 128)
513                        {
514                            builder.Append((char) b);
515                        }
516                        else
517                        {
518                            builder.Append('\\');
519                            builder.Append((char) ('0' + ((b >> 6) & 3)));
520                            builder.Append((char) ('0' + ((b >> 3) & 7)));
521                            builder.Append((char) ('0' + (b & 7)));
522                        }
523                        break;
524                }
525            }
526            return builder.ToString();
527        }
528
529        /// <summary>
530        /// Performs string unescaping from C style (octal, hex, form feeds, tab etc) into a byte string.
531        /// </summary>
532        public static ByteString UnescapeBytes(string input)
533        {
534            byte[] result = new byte[input.Length];
535            int pos = 0;
536            for (int i = 0; i < input.Length; i++)
537            {
538                char c = input[i];
539                if (c > 127 || c < 32)
540                {
541                    throw new FormatException("Escaped string must only contain ASCII");
542                }
543                if (c != '\\')
544                {
545                    result[pos++] = (byte) c;
546                    continue;
547                }
548                if (i + 1 >= input.Length)
549                {
550                    throw new FormatException("Invalid escape sequence: '\\' at end of string.");
551                }
552
553                i++;
554                c = input[i];
555                if (c >= '0' && c <= '7')
556                {
557                    // Octal escape.
558                    int code = ParseDigit(c);
559                    if (i + 1 < input.Length && IsOctal(input[i + 1]))
560                    {
561                        i++;
562                        code = code*8 + ParseDigit(input[i]);
563                    }
564                    if (i + 1 < input.Length && IsOctal(input[i + 1]))
565                    {
566                        i++;
567                        code = code*8 + ParseDigit(input[i]);
568                    }
569                    result[pos++] = (byte) code;
570                }
571                else
572                {
573                    switch (c)
574                    {
575                        case 'a':
576                            result[pos++] = 0x07;
577                            break;
578                        case 'b':
579                            result[pos++] = (byte) '\b';
580                            break;
581                        case 'f':
582                            result[pos++] = (byte) '\f';
583                            break;
584                        case 'n':
585                            result[pos++] = (byte) '\n';
586                            break;
587                        case 'r':
588                            result[pos++] = (byte) '\r';
589                            break;
590                        case 't':
591                            result[pos++] = (byte) '\t';
592                            break;
593                        case 'v':
594                            result[pos++] = 0x0b;
595                            break;
596                        case '\\':
597                            result[pos++] = (byte) '\\';
598                            break;
599                        case '\'':
600                            result[pos++] = (byte) '\'';
601                            break;
602                        case '"':
603                            result[pos++] = (byte) '\"';
604                            break;
605
606                        case 'x':
607                            // hex escape
608                            int code;
609                            if (i + 1 < input.Length && IsHex(input[i + 1]))
610                            {
611                                i++;
612                                code = ParseDigit(input[i]);
613                            }
614                            else
615                            {
616                                throw new FormatException("Invalid escape sequence: '\\x' with no digits");
617                            }
618                            if (i + 1 < input.Length && IsHex(input[i + 1]))
619                            {
620                                ++i;
621                                code = code*16 + ParseDigit(input[i]);
622                            }
623                            result[pos++] = (byte) code;
624                            break;
625
626                        default:
627                            throw new FormatException("Invalid escape sequence: '\\" + c + "'");
628                    }
629                }
630            }
631
632            return ByteString.CopyFrom(result, 0, pos);
633        }
634
635        public static void Merge(string text, IBuilder builder)
636        {
637            Merge(text, ExtensionRegistry.Empty, builder);
638        }
639
640        public static void Merge(TextReader reader, IBuilder builder)
641        {
642            Merge(reader, ExtensionRegistry.Empty, builder);
643        }
644
645        public static void Merge(TextReader reader, ExtensionRegistry registry, IBuilder builder)
646        {
647            Merge(reader.ReadToEnd(), registry, builder);
648        }
649
650        public static void Merge(string text, ExtensionRegistry registry, IBuilder builder)
651        {
652            TextTokenizer tokenizer = new TextTokenizer(text);
653
654            while (!tokenizer.AtEnd)
655            {
656                MergeField(tokenizer, registry, builder);
657            }
658        }
659
660        /// <summary>
661        /// Parses a single field from the specified tokenizer and merges it into
662        /// the builder.
663        /// </summary>
664        private static void MergeField(TextTokenizer tokenizer, ExtensionRegistry extensionRegistry,
665                                       IBuilder builder)
666        {
667            FieldDescriptor field;
668            MessageDescriptor type = builder.DescriptorForType;
669            ExtensionInfo extension = null;
670
671            if (tokenizer.TryConsume("["))
672            {
673                // An extension.
674                StringBuilder name = new StringBuilder(tokenizer.ConsumeIdentifier());
675                while (tokenizer.TryConsume("."))
676                {
677                    name.Append(".");
678                    name.Append(tokenizer.ConsumeIdentifier());
679                }
680
681                extension = extensionRegistry.FindByName(type, name.ToString());
682
683                if (extension == null)
684                {
685                    throw tokenizer.CreateFormatExceptionPreviousToken("Extension \"" + name +
686                                                                       "\" not found in the ExtensionRegistry.");
687                }
688                else if (extension.Descriptor.ContainingType != type)
689                {
690                    throw tokenizer.CreateFormatExceptionPreviousToken("Extension \"" + name +
691                                                                       "\" does not extend message type \"" +
692                                                                       type.FullName + "\".");
693                }
694
695                tokenizer.Consume("]");
696
697                field = extension.Descriptor;
698            }
699            else
700            {
701                String name = tokenizer.ConsumeIdentifier();
702                field = type.FindDescriptor<FieldDescriptor>(name);
703
704                // Group names are expected to be capitalized as they appear in the
705                // .proto file, which actually matches their type names, not their field
706                // names.
707                if (field == null)
708                {
709                    // Explicitly specify the invariant culture so that this code does not break when
710                    // executing in Turkey.
711                    String lowerName = name.ToLower(CultureInfo.InvariantCulture);
712                    field = type.FindDescriptor<FieldDescriptor>(lowerName);
713                    // If the case-insensitive match worked but the field is NOT a group,
714                    // TODO(jonskeet): What? Java comment ends here!
715                    if (field != null && field.FieldType != FieldType.Group)
716                    {
717                        field = null;
718                    }
719                }
720                // Again, special-case group names as described above.
721                if (field != null && field.FieldType == FieldType.Group && field.MessageType.Name != name)
722                {
723                    field = null;
724                }
725
726                if (field == null)
727                {
728                    throw tokenizer.CreateFormatExceptionPreviousToken(
729                        "Message type \"" + type.FullName + "\" has no field named \"" + name + "\".");
730                }
731            }
732
733            object value = null;
734
735            if (field.MappedType == MappedType.Message)
736            {
737                tokenizer.TryConsume(":"); // optional
738
739                String endToken;
740                if (tokenizer.TryConsume("<"))
741                {
742                    endToken = ">";
743                }
744                else
745                {
746                    tokenizer.Consume("{");
747                    endToken = "}";
748                }
749
750                IBuilder subBuilder;
751                if (extension == null)
752                {
753                    subBuilder = builder.CreateBuilderForField(field);
754                }
755                else
756                {
757                    subBuilder = extension.DefaultInstance.WeakCreateBuilderForType() as IBuilder;
758                    if (subBuilder == null)
759                    {
760                        throw new NotSupportedException("Lite messages are not supported.");
761                    }
762                }
763
764                while (!tokenizer.TryConsume(endToken))
765                {
766                    if (tokenizer.AtEnd)
767                    {
768                        throw tokenizer.CreateFormatException("Expected \"" + endToken + "\".");
769                    }
770                    MergeField(tokenizer, extensionRegistry, subBuilder);
771                }
772
773                value = subBuilder.WeakBuild();
774            }
775            else
776            {
777                tokenizer.Consume(":");
778
779                switch (field.FieldType)
780                {
781                    case FieldType.Int32:
782                    case FieldType.SInt32:
783                    case FieldType.SFixed32:
784                        value = tokenizer.ConsumeInt32();
785                        break;
786
787                    case FieldType.Int64:
788                    case FieldType.SInt64:
789                    case FieldType.SFixed64:
790                        value = tokenizer.ConsumeInt64();
791                        break;
792
793                    case FieldType.UInt32:
794                    case FieldType.Fixed32:
795                        value = tokenizer.ConsumeUInt32();
796                        break;
797
798                    case FieldType.UInt64:
799                    case FieldType.Fixed64:
800                        value = tokenizer.ConsumeUInt64();
801                        break;
802
803                    case FieldType.Float:
804                        value = tokenizer.ConsumeFloat();
805                        break;
806
807                    case FieldType.Double:
808                        value = tokenizer.ConsumeDouble();
809                        break;
810
811                    case FieldType.Bool:
812                        value = tokenizer.ConsumeBoolean();
813                        break;
814
815                    case FieldType.String:
816                        value = tokenizer.ConsumeString();
817                        break;
818
819                    case FieldType.Bytes:
820                        value = tokenizer.ConsumeByteString();
821                        break;
822
823                    case FieldType.Enum:
824                        {
825                            EnumDescriptor enumType = field.EnumType;
826
827                            if (tokenizer.LookingAtInteger())
828                            {
829                                int number = tokenizer.ConsumeInt32();
830                                value = enumType.FindValueByNumber(number);
831                                if (value == null)
832                                {
833                                    throw tokenizer.CreateFormatExceptionPreviousToken(
834                                        "Enum type \"" + enumType.FullName +
835                                        "\" has no value with number " + number + ".");
836                                }
837                            }
838                            else
839                            {
840                                String id = tokenizer.ConsumeIdentifier();
841                                value = enumType.FindValueByName(id);
842                                if (value == null)
843                                {
844                                    throw tokenizer.CreateFormatExceptionPreviousToken(
845                                        "Enum type \"" + enumType.FullName +
846                                        "\" has no value named \"" + id + "\".");
847                                }
848                            }
849
850                            break;
851                        }
852
853                    case FieldType.Message:
854                    case FieldType.Group:
855                        throw new InvalidOperationException("Can't get here.");
856                }
857            }
858
859            if (field.IsRepeated)
860            {
861                builder.WeakAddRepeatedField(field, value);
862            }
863            else
864            {
865                builder.SetField(field, value);
866            }
867        }
868    }
869}
Note: See TracBrowser for help on using the repository browser.