| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 Pattern.CASE_INSENSITIVE); | 654 Pattern.CASE_INSENSITIVE); |
| 655 | 655 |
| 656 /** Construct a tokenizer that parses tokens from the given text. */ | 656 /** Construct a tokenizer that parses tokens from the given text. */ |
| 657 private Tokenizer(final CharSequence text) { | 657 private Tokenizer(final CharSequence text) { |
| 658 this.text = text; | 658 this.text = text; |
| 659 this.matcher = WHITESPACE.matcher(text); | 659 this.matcher = WHITESPACE.matcher(text); |
| 660 skipWhitespace(); | 660 skipWhitespace(); |
| 661 nextToken(); | 661 nextToken(); |
| 662 } | 662 } |
| 663 | 663 |
| 664 int getPreviousLine() { | |
| 665 return previousLine; | |
| 666 } | |
| 667 | |
| 668 int getPreviousColumn() { | |
| 669 return previousColumn; | |
| 670 } | |
| 671 | |
| 672 int getLine() { | 664 int getLine() { |
| 673 return line; | 665 return line; |
| 674 } | 666 } |
| 675 | 667 |
| 676 int getColumn() { | 668 int getColumn() { |
| 677 return column; | 669 return column; |
| 678 } | 670 } |
| 679 | 671 |
| 680 /** Are we at the end of the input? */ | 672 /** Are we at the end of the input? */ |
| 681 public boolean atEnd() { | 673 public boolean atEnd() { |
| (...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1375 final int n = input.read(buffer); | 1367 final int n = input.read(buffer); |
| 1376 if (n == -1) { | 1368 if (n == -1) { |
| 1377 break; | 1369 break; |
| 1378 } | 1370 } |
| 1379 buffer.flip(); | 1371 buffer.flip(); |
| 1380 text.append(buffer, 0, n); | 1372 text.append(buffer, 0, n); |
| 1381 } | 1373 } |
| 1382 return text; | 1374 return text; |
| 1383 } | 1375 } |
| 1384 | 1376 |
| 1385 // Check both unknown fields and unknown extensions and log warming messages | |
| 1386 // or throw exceptions according to the flag. | |
| 1387 private void checkUnknownFields(final List<String> unknownFields) | |
| 1388 throws ParseException { | |
| 1389 if (unknownFields.isEmpty()) { | |
| 1390 return; | |
| 1391 } | |
| 1392 | |
| 1393 StringBuilder msg = new StringBuilder("Input contains unknown fields and/o
r extensions:"); | |
| 1394 for (String field : unknownFields) { | |
| 1395 msg.append('\n').append(field); | |
| 1396 } | |
| 1397 | |
| 1398 if (allowUnknownFields) { | |
| 1399 logger.warning(msg.toString()); | |
| 1400 } else { | |
| 1401 String[] lineColumn = unknownFields.get(0).split(":"); | |
| 1402 throw new ParseException(Integer.valueOf(lineColumn[0]), | |
| 1403 Integer.valueOf(lineColumn[1]), msg.toString()); | |
| 1404 } | |
| 1405 } | |
| 1406 | |
| 1407 /** | 1377 /** |
| 1408 * Parse a text-format message from {@code input} and merge the contents | 1378 * Parse a text-format message from {@code input} and merge the contents |
| 1409 * into {@code builder}. Extensions will be recognized if they are | 1379 * into {@code builder}. Extensions will be recognized if they are |
| 1410 * registered in {@code extensionRegistry}. | 1380 * registered in {@code extensionRegistry}. |
| 1411 */ | 1381 */ |
| 1412 public void merge(final CharSequence input, | 1382 public void merge(final CharSequence input, |
| 1413 final ExtensionRegistry extensionRegistry, | 1383 final ExtensionRegistry extensionRegistry, |
| 1414 final Message.Builder builder) | 1384 final Message.Builder builder) |
| 1415 throws ParseException { | 1385 throws ParseException { |
| 1416 final Tokenizer tokenizer = new Tokenizer(input); | 1386 final Tokenizer tokenizer = new Tokenizer(input); |
| 1417 MessageReflection.BuilderAdapter target = | 1387 MessageReflection.BuilderAdapter target = |
| 1418 new MessageReflection.BuilderAdapter(builder); | 1388 new MessageReflection.BuilderAdapter(builder); |
| 1419 | 1389 |
| 1420 List<String> unknownFields = new ArrayList<String>(); | |
| 1421 | |
| 1422 while (!tokenizer.atEnd()) { | 1390 while (!tokenizer.atEnd()) { |
| 1423 mergeField(tokenizer, extensionRegistry, target, unknownFields); | 1391 mergeField(tokenizer, extensionRegistry, target); |
| 1424 } | 1392 } |
| 1425 | |
| 1426 checkUnknownFields(unknownFields); | |
| 1427 } | 1393 } |
| 1428 | 1394 |
| 1429 | 1395 |
| 1430 /** | 1396 /** |
| 1431 * Parse a single field from {@code tokenizer} and merge it into | 1397 * Parse a single field from {@code tokenizer} and merge it into |
| 1432 * {@code builder}. | 1398 * {@code builder}. |
| 1433 */ | 1399 */ |
| 1434 private void mergeField(final Tokenizer tokenizer, | 1400 private void mergeField(final Tokenizer tokenizer, |
| 1435 final ExtensionRegistry extensionRegistry, | 1401 final ExtensionRegistry extensionRegistry, |
| 1436 final MessageReflection.MergeTarget target, | 1402 final MessageReflection.MergeTarget target) |
| 1437 List<String> unknownFields) | |
| 1438 throws ParseException { | 1403 throws ParseException { |
| 1439 mergeField(tokenizer, extensionRegistry, target, parseInfoTreeBuilder, | 1404 mergeField(tokenizer, extensionRegistry, target, parseInfoTreeBuilder); |
| 1440 unknownFields); | |
| 1441 } | 1405 } |
| 1442 | 1406 |
| 1443 /** | 1407 /** |
| 1444 * Parse a single field from {@code tokenizer} and merge it into | 1408 * Parse a single field from {@code tokenizer} and merge it into |
| 1445 * {@code builder}. | 1409 * {@code builder}. |
| 1446 */ | 1410 */ |
| 1447 private void mergeField(final Tokenizer tokenizer, | 1411 private void mergeField(final Tokenizer tokenizer, |
| 1448 final ExtensionRegistry extensionRegistry, | 1412 final ExtensionRegistry extensionRegistry, |
| 1449 final MessageReflection.MergeTarget target, | 1413 final MessageReflection.MergeTarget target, |
| 1450 TextFormatParseInfoTree.Builder parseTreeBuilder, | 1414 TextFormatParseInfoTree.Builder parseTreeBuilder) |
| 1451 List<String> unknownFields) | |
| 1452 throws ParseException { | 1415 throws ParseException { |
| 1453 FieldDescriptor field = null; | 1416 FieldDescriptor field = null; |
| 1454 int startLine = tokenizer.getLine(); | 1417 int startLine = tokenizer.getLine(); |
| 1455 int startColumn = tokenizer.getColumn(); | 1418 int startColumn = tokenizer.getColumn(); |
| 1456 final Descriptor type = target.getDescriptorForType(); | 1419 final Descriptor type = target.getDescriptorForType(); |
| 1457 ExtensionRegistry.ExtensionInfo extension = null; | 1420 ExtensionRegistry.ExtensionInfo extension = null; |
| 1458 | 1421 |
| 1459 if (tokenizer.tryConsume("[")) { | 1422 if (tokenizer.tryConsume("[")) { |
| 1460 // An extension. | 1423 // An extension. |
| 1461 final StringBuilder name = | 1424 final StringBuilder name = |
| 1462 new StringBuilder(tokenizer.consumeIdentifier()); | 1425 new StringBuilder(tokenizer.consumeIdentifier()); |
| 1463 while (tokenizer.tryConsume(".")) { | 1426 while (tokenizer.tryConsume(".")) { |
| 1464 name.append('.'); | 1427 name.append('.'); |
| 1465 name.append(tokenizer.consumeIdentifier()); | 1428 name.append(tokenizer.consumeIdentifier()); |
| 1466 } | 1429 } |
| 1467 | 1430 |
| 1468 extension = target.findExtensionByName( | 1431 extension = target.findExtensionByName( |
| 1469 extensionRegistry, name.toString()); | 1432 extensionRegistry, name.toString()); |
| 1470 | 1433 |
| 1471 if (extension == null) { | 1434 if (extension == null) { |
| 1472 unknownFields.add((tokenizer.getPreviousLine() + 1) + ":" + | 1435 if (!allowUnknownFields) { |
| 1473 (tokenizer.getPreviousColumn() + 1) + ":\t" + | 1436 throw tokenizer.parseExceptionPreviousToken( |
| 1474 type.getFullName() + ".[" + name + "]"); | 1437 "Extension \"" + name + "\" not found in the ExtensionRegistry."); |
| 1438 } else { |
| 1439 logger.warning( |
| 1440 "Extension \"" + name + "\" not found in the ExtensionRegistry."); |
| 1441 } |
| 1475 } else { | 1442 } else { |
| 1476 if (extension.descriptor.getContainingType() != type) { | 1443 if (extension.descriptor.getContainingType() != type) { |
| 1477 throw tokenizer.parseExceptionPreviousToken( | 1444 throw tokenizer.parseExceptionPreviousToken( |
| 1478 "Extension \"" + name + "\" does not extend message type \"" | 1445 "Extension \"" + name + "\" does not extend message type \"" |
| 1479 + type.getFullName() + "\"."); | 1446 + type.getFullName() + "\"."); |
| 1480 } | 1447 } |
| 1481 field = extension.descriptor; | 1448 field = extension.descriptor; |
| 1482 } | 1449 } |
| 1483 | 1450 |
| 1484 tokenizer.consume("]"); | 1451 tokenizer.consume("]"); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1499 field = null; | 1466 field = null; |
| 1500 } | 1467 } |
| 1501 } | 1468 } |
| 1502 // Again, special-case group names as described above. | 1469 // Again, special-case group names as described above. |
| 1503 if (field != null && field.getType() == FieldDescriptor.Type.GROUP | 1470 if (field != null && field.getType() == FieldDescriptor.Type.GROUP |
| 1504 && !field.getMessageType().getName().equals(name)) { | 1471 && !field.getMessageType().getName().equals(name)) { |
| 1505 field = null; | 1472 field = null; |
| 1506 } | 1473 } |
| 1507 | 1474 |
| 1508 if (field == null) { | 1475 if (field == null) { |
| 1509 unknownFields.add((tokenizer.getPreviousLine() + 1) + ":" + | 1476 if (!allowUnknownFields) { |
| 1510 (tokenizer.getPreviousColumn() + 1) + ":\t" + | 1477 throw tokenizer.unknownFieldParseExceptionPreviousToken( |
| 1511 type.getFullName() + "." + name); | 1478 name, |
| 1479 "Message type \"" + type.getFullName() |
| 1480 + "\" has no field named \"" + name + "\"."); |
| 1481 } else { |
| 1482 logger.warning( |
| 1483 "Message type \"" + type.getFullName() |
| 1484 + "\" has no field named \"" + name + "\"."); |
| 1485 } |
| 1512 } | 1486 } |
| 1513 } | 1487 } |
| 1514 | 1488 |
| 1515 // Skips unknown fields. | 1489 // Skips unknown fields. |
| 1516 if (field == null) { | 1490 if (field == null) { |
| 1517 // Try to guess the type of this field. | 1491 // Try to guess the type of this field. |
| 1518 // If this field is not a message, there should be a ":" between the | 1492 // If this field is not a message, there should be a ":" between the |
| 1519 // field name and the field value and also the field value should not | 1493 // field name and the field value and also the field value should not |
| 1520 // start with "{" or "<" which indicates the beginning of a message body
. | 1494 // start with "{" or "<" which indicates the beginning of a message body
. |
| 1521 // If there is no ":" or there is a "{" or "<" after ":", this field has | 1495 // If there is no ":" or there is a "{" or "<" after ":", this field has |
| 1522 // to be a message or the input is ill-formed. | 1496 // to be a message or the input is ill-formed. |
| 1523 if (tokenizer.tryConsume(":") | 1497 if (tokenizer.tryConsume(":") |
| 1524 && !tokenizer.lookingAt("{") | 1498 && !tokenizer.lookingAt("{") |
| 1525 && !tokenizer.lookingAt("<")) { | 1499 && !tokenizer.lookingAt("<")) { |
| 1526 skipFieldValue(tokenizer); | 1500 skipFieldValue(tokenizer); |
| 1527 } else { | 1501 } else { |
| 1528 skipFieldMessage(tokenizer); | 1502 skipFieldMessage(tokenizer); |
| 1529 } | 1503 } |
| 1530 return; | 1504 return; |
| 1531 } | 1505 } |
| 1532 | 1506 |
| 1533 // Handle potential ':'. | 1507 // Handle potential ':'. |
| 1534 if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { | 1508 if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { |
| 1535 tokenizer.tryConsume(":"); // optional | 1509 tokenizer.tryConsume(":"); // optional |
| 1536 if (parseTreeBuilder != null) { | 1510 if (parseTreeBuilder != null) { |
| 1537 TextFormatParseInfoTree.Builder childParseTreeBuilder = | 1511 TextFormatParseInfoTree.Builder childParseTreeBuilder = |
| 1538 parseTreeBuilder.getBuilderForSubMessageField(field); | 1512 parseTreeBuilder.getBuilderForSubMessageField(field); |
| 1539 consumeFieldValues(tokenizer, extensionRegistry, target, field, extens
ion, | 1513 consumeFieldValues(tokenizer, extensionRegistry, target, field, extens
ion, |
| 1540 childParseTreeBuilder, unknownFields); | 1514 childParseTreeBuilder); |
| 1541 } else { | 1515 } else { |
| 1542 consumeFieldValues(tokenizer, extensionRegistry, target, field, extens
ion, | 1516 consumeFieldValues(tokenizer, extensionRegistry, target, field, extens
ion, |
| 1543 parseTreeBuilder, unknownFields); | 1517 parseTreeBuilder); |
| 1544 } | 1518 } |
| 1545 } else { | 1519 } else { |
| 1546 tokenizer.consume(":"); // required | 1520 tokenizer.consume(":"); // required |
| 1547 consumeFieldValues(tokenizer, extensionRegistry, target, field, | 1521 consumeFieldValues( |
| 1548 extension, parseTreeBuilder, unknownFields); | 1522 tokenizer, extensionRegistry, target, field, extension, parseTreeBui
lder); |
| 1549 } | 1523 } |
| 1550 | 1524 |
| 1551 if (parseTreeBuilder != null) { | 1525 if (parseTreeBuilder != null) { |
| 1552 parseTreeBuilder.setLocation( | 1526 parseTreeBuilder.setLocation( |
| 1553 field, TextFormatParseLocation.create(startLine, startColumn)); | 1527 field, TextFormatParseLocation.create(startLine, startColumn)); |
| 1554 } | 1528 } |
| 1555 | 1529 |
| 1556 // For historical reasons, fields may optionally be separated by commas or | 1530 // For historical reasons, fields may optionally be separated by commas or |
| 1557 // semicolons. | 1531 // semicolons. |
| 1558 if (!tokenizer.tryConsume(";")) { | 1532 if (!tokenizer.tryConsume(";")) { |
| 1559 tokenizer.tryConsume(","); | 1533 tokenizer.tryConsume(","); |
| 1560 } | 1534 } |
| 1561 } | 1535 } |
| 1562 | 1536 |
| 1563 /** | 1537 /** |
| 1564 * Parse a one or more field values from {@code tokenizer} and merge it into | 1538 * Parse a one or more field values from {@code tokenizer} and merge it into |
| 1565 * {@code builder}. | 1539 * {@code builder}. |
| 1566 */ | 1540 */ |
| 1567 private void consumeFieldValues( | 1541 private void consumeFieldValues( |
| 1568 final Tokenizer tokenizer, | 1542 final Tokenizer tokenizer, |
| 1569 final ExtensionRegistry extensionRegistry, | 1543 final ExtensionRegistry extensionRegistry, |
| 1570 final MessageReflection.MergeTarget target, | 1544 final MessageReflection.MergeTarget target, |
| 1571 final FieldDescriptor field, | 1545 final FieldDescriptor field, |
| 1572 final ExtensionRegistry.ExtensionInfo extension, | 1546 final ExtensionRegistry.ExtensionInfo extension, |
| 1573 final TextFormatParseInfoTree.Builder parseTreeBuilder, | 1547 final TextFormatParseInfoTree.Builder parseTreeBuilder) |
| 1574 List<String> unknownFields) | |
| 1575 throws ParseException { | 1548 throws ParseException { |
| 1576 // Support specifying repeated field values as a comma-separated list. | 1549 // Support specifying repeated field values as a comma-separated list. |
| 1577 // Ex."foo: [1, 2, 3]" | 1550 // Ex."foo: [1, 2, 3]" |
| 1578 if (field.isRepeated() && tokenizer.tryConsume("[")) { | 1551 if (field.isRepeated() && tokenizer.tryConsume("[")) { |
| 1579 if (!tokenizer.tryConsume("]")) { // Allow "foo: []" to be treated as e
mpty. | 1552 while (true) { |
| 1580 while (true) { | 1553 consumeFieldValue(tokenizer, extensionRegistry, target, field, extensi
on, |
| 1581 consumeFieldValue( | 1554 parseTreeBuilder); |
| 1582 tokenizer, | 1555 if (tokenizer.tryConsume("]")) { |
| 1583 extensionRegistry, | 1556 // End of list. |
| 1584 target, | 1557 break; |
| 1585 field, | |
| 1586 extension, | |
| 1587 parseTreeBuilder, | |
| 1588 unknownFields); | |
| 1589 if (tokenizer.tryConsume("]")) { | |
| 1590 // End of list. | |
| 1591 break; | |
| 1592 } | |
| 1593 tokenizer.consume(","); | |
| 1594 } | 1558 } |
| 1559 tokenizer.consume(","); |
| 1595 } | 1560 } |
| 1596 } else { | 1561 } else { |
| 1597 consumeFieldValue(tokenizer, extensionRegistry, target, field, | 1562 consumeFieldValue( |
| 1598 extension, parseTreeBuilder, unknownFields); | 1563 tokenizer, extensionRegistry, target, field, extension, parseTreeBui
lder); |
| 1599 } | 1564 } |
| 1600 } | 1565 } |
| 1601 | 1566 |
| 1602 /** | 1567 /** |
| 1603 * Parse a single field value from {@code tokenizer} and merge it into | 1568 * Parse a single field value from {@code tokenizer} and merge it into |
| 1604 * {@code builder}. | 1569 * {@code builder}. |
| 1605 */ | 1570 */ |
| 1606 private void consumeFieldValue( | 1571 private void consumeFieldValue( |
| 1607 final Tokenizer tokenizer, | 1572 final Tokenizer tokenizer, |
| 1608 final ExtensionRegistry extensionRegistry, | 1573 final ExtensionRegistry extensionRegistry, |
| 1609 final MessageReflection.MergeTarget target, | 1574 final MessageReflection.MergeTarget target, |
| 1610 final FieldDescriptor field, | 1575 final FieldDescriptor field, |
| 1611 final ExtensionRegistry.ExtensionInfo extension, | 1576 final ExtensionRegistry.ExtensionInfo extension, |
| 1612 final TextFormatParseInfoTree.Builder parseTreeBuilder, | 1577 final TextFormatParseInfoTree.Builder parseTreeBuilder) |
| 1613 List<String> unknownFields) | |
| 1614 throws ParseException { | 1578 throws ParseException { |
| 1615 Object value = null; | 1579 Object value = null; |
| 1616 | 1580 |
| 1617 if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { | 1581 if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { |
| 1618 final String endToken; | 1582 final String endToken; |
| 1619 if (tokenizer.tryConsume("<")) { | 1583 if (tokenizer.tryConsume("<")) { |
| 1620 endToken = ">"; | 1584 endToken = ">"; |
| 1621 } else { | 1585 } else { |
| 1622 tokenizer.consume("{"); | 1586 tokenizer.consume("{"); |
| 1623 endToken = "}"; | 1587 endToken = "}"; |
| 1624 } | 1588 } |
| 1625 | 1589 |
| 1626 final MessageReflection.MergeTarget subField; | 1590 final MessageReflection.MergeTarget subField; |
| 1627 subField = target.newMergeTargetForField(field, | 1591 subField = target.newMergeTargetForField(field, |
| 1628 (extension == null) ? null : extension.defaultInstance); | 1592 (extension == null) ? null : extension.defaultInstance); |
| 1629 | 1593 |
| 1630 while (!tokenizer.tryConsume(endToken)) { | 1594 while (!tokenizer.tryConsume(endToken)) { |
| 1631 if (tokenizer.atEnd()) { | 1595 if (tokenizer.atEnd()) { |
| 1632 throw tokenizer.parseException( | 1596 throw tokenizer.parseException( |
| 1633 "Expected \"" + endToken + "\"."); | 1597 "Expected \"" + endToken + "\"."); |
| 1634 } | 1598 } |
| 1635 mergeField(tokenizer, extensionRegistry, subField, parseTreeBuilder, | 1599 mergeField(tokenizer, extensionRegistry, subField, parseTreeBuilder); |
| 1636 unknownFields); | |
| 1637 } | 1600 } |
| 1638 | 1601 |
| 1639 value = subField.finish(); | 1602 value = subField.finish(); |
| 1640 | 1603 |
| 1641 } else { | 1604 } else { |
| 1642 switch (field.getType()) { | 1605 switch (field.getType()) { |
| 1643 case INT32: | 1606 case INT32: |
| 1644 case SINT32: | 1607 case SINT32: |
| 1645 case SFIXED32: | 1608 case SFIXED32: |
| 1646 value = tokenizer.consumeInt32(); | 1609 value = tokenizer.consumeInt32(); |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2099 } | 2062 } |
| 2100 } | 2063 } |
| 2101 } | 2064 } |
| 2102 | 2065 |
| 2103 result = bigValue.longValue(); | 2066 result = bigValue.longValue(); |
| 2104 } | 2067 } |
| 2105 | 2068 |
| 2106 return result; | 2069 return result; |
| 2107 } | 2070 } |
| 2108 } | 2071 } |
| OLD | NEW |