#include <google/protobuf/util/message_differencer.h>
namespace google::protobuf::util
Esse arquivo define métodos e classes estáticos para comparar mensagens de protocolo.
Agosto de 2008: comparação de campos desconhecidos para mensagens. Agosto de 2009: foram adicionadas opções diferentes para comparar campos repetidos. Abril de 2010: mudança de campo em comparação com FieldComparator, setembro de 2020: opção adicionada para gerar chaves de mapa no caminho.
Turmas neste arquivo | |
---|---|
Um diferencial básico que pode ser usado para determinar as diferenças entre duas mensagens de protocolo especificadas. | |
Classe base abstrata da qual todos os IgnoreCritérios são derivados. | |
MapKeyComparator é usado para determinar se dois elementos têm a mesma chave ao comparar elementos de um campo repetido como um mapa. | |
Classe base abstrata da qual todos os repórteres MessageDifferencer derivam. | |
Identifica um campo individual em uma instância de mensagem. | |
Uma implementação do MessageDifferencer Reporter que gera qualquer diferença encontrada em formato legível para o ZeroCopyOutputStream ou impressora fornecido. | |
Classe para processar qualquer desserialização. | |
Essa classe fornece informações extras para a função FieldComparator::Compare. |
Participantes do arquivoEssas definições não fazem parte de nenhuma classe. | |
---|---|
typedef | std::vector< const FieldDescriptor * > FieldDescriptorArray Define uma coleção de descritores de campo. mais… |
typedef util::FieldDescriptorArray
Define uma coleção de descritores de campo.
No caso da base de código interna do Google, estamos usando absl::FixedArray em vez de vetores. Acelera significativamente a comparação de protótipos (cerca de 30%) reduzindo o número de operações malloc/free
classe MessageDifferencer
#include <google/protobuf/util/message_differencer.h>
namespace google::protobuf::util
Um diferencial básico que pode ser usado para determinar as diferenças entre duas mensagens de protocolo especificadas.
Se forem encontradas diferenças, o método "Comparar" retornará "false", e os relatórios de diferença especificados por "ReportDifferencesTo" terão seus métodos de geração de relatórios chamados (veja abaixo a implementação do relatório). Com base na implementação original do ProtocolDifferencer em //net/proto/protocol-differencer.h (Obrigado, Todd!).
MessageDifferencer requer que mensagens comparadas sejam do mesmo tipo, definidas como mensagens que compartilham o mesmo descritor. Caso contrário, o comportamento dessa classe é indefinido.
As pessoas discordam sobre o que o MessageDifferencer deve fazer ao comparar mensagens com diferentes descritores. Algumas pessoas acham que ele deve sempre retornar "false". Outros esperam que ele tente procurar campos semelhantes e os comparar mesmo assim, principalmente se os descritores forem idênticos. Se escolhermos um desses comportamentos, algumas pessoas vão se surpreender e talvez escrevam códigos esperando o outro comportamento sem perceber o erro. Portanto, proibimos esse uso.
Essa classe é implementada com base na reflexão proto2. A performance precisa ser boa o suficiente para usos normais. No entanto, para locais em que o desempenho é extremamente sensível, existem várias alternativas:
- Comparação da string serializada de lado: falsos negativos (há mensagens que são as mesmas, mas as strings serializadas são diferentes).
- Igual ao gerador de código por plug-in do compilador (net/proto2/contrib/equals_plugin) desvantagem: código mais gerado, sobrecarga de manutenção para a regra adicional (precisa estar em sincronia com a proto_library original).
Observação sobre o processamento do google.protobuf.Any: o MessageDifferencer descompacta automaticamente Any::value em uma Message e compara os campos individuais dele. Mensagens codificadas em qualquer Any repetido não podem ser comparadas usando TreatAsMap.
Observação sobre a segurança de linhas de execução: MessageDifferencer não é thread-safe. Você precisa protegê-la com um bloqueio para usar a mesma instância MessageDifferencer em várias linhas de execução. Não há problema em chamar métodos de comparação estáticos (como MessageDifferencer::Equals) simultaneamente, mas isso não é recomendável para códigos críticos de desempenho, já que eles levam a alocações extras.
Participantes | |
---|---|
enum | MessageFieldComparison |
enum | Scope |
enum | FloatComparison OBSOLETO. Use FieldComparator::FloatComparison mais… |
enum | RepeatedFieldComparison |
DefaultFieldComparator * | default_impl |
FieldComparator * | base |
static bool | Determina se as mensagens fornecidas são iguais. mais… |
static bool | Determina se as mensagens fornecidas são equivalentes. mais… |
static bool | Determina se as mensagens fornecidas são aproximadamente iguais. mais… |
static bool | Determina se as mensagens fornecidas são aproximadamente equivalentes. mais… |
explicit | MessageDifferencer() Para adicionar um Reporter, construa aqui o padrão e use ReportDifferencesTo ou ReportDifferencesToString. |
| ~MessageDifferencer() |
void | TreatAsSet(const FieldDescriptor * field) Os elementos do campo repetido serão tratados como um conjunto para fins de diferenciação. Portanto, ordens diferentes dos mesmos elementos serão consideradas iguais. mais… |
void | TreatAsSmartSet(const FieldDescriptor * field) |
void | TreatAsList(const FieldDescriptor * field) Os elementos do campo repetido serão tratados como uma lista para fins de diferenciação. Sendo assim, ordens diferentes dos mesmos elementos NÃO serão consideradas iguais. mais… |
void | TreatAsSmartList(const FieldDescriptor * field) A complexidade é semelhante ao tratamento como SET. |
void | TreatAsMap(const FieldDescriptor * field, const FieldDescriptor * key) Os elementos do campo repetido serão tratados como um mapa para fins de diferenciação, em que |key| será a chave do mapa. mais… |
void | TreatAsMapWithMultipleFieldsAsKey(const FieldDescriptor * field, const std::vector< const FieldDescriptor * > & key_fields) O mesmo que o TreatAsMap, mas esse método vai usar vários campos como chave em comparação. mais… |
void | TreatAsMapWithMultipleFieldPathsAsKey(const FieldDescriptor * field, const std::vector< std::vector< const FieldDescriptor * > > & key_field_paths) Igual a TreatAsMapWithMultipleFieldsAsKey, exceto que cada campo não precisa necessariamente ser um subcampo direto. mais… |
void | TreatAsMapUsingKeyComparator(const FieldDescriptor * field, const MapKeyComparator * key_comparator) Usa um MapKeyComparator personalizado para determinar se dois elementos têm a mesma chave ao comparar um campo repetido como um mapa. mais... |
MapKeyComparator * | CreateMultipleFieldsMapKeyComparator(const std::vector< std::vector< const FieldDescriptor * > > & key_field_paths) Inicia e retorna uma nova instância de MultipleFieldsMapKeyComparator. |
void | AddIgnoreCriteria(IgnoreCriteria * ignore_criteria) Adicione um critério personalizado "ignore" que é avaliado, além dos campos ignorados adicionados com IgnoreField. mais… |
void | IgnoreField(const FieldDescriptor * field) Indica que qualquer campo com o descritor especificado deve ser ignorado para comparar duas mensagens. mais… |
void | set_field_comparator(FieldComparator * comparator) Define o comparador de campo usado para determinar as diferenças entre os campos de buffer de protocolo. mais… |
void | SetFractionAndMargin(const FieldDescriptor * field, double fraction, double margin) OBSOLETO. mais… |
void | set_message_field_comparison(MessageFieldComparison comparison) Define o tipo de comparação (conforme definido na enumeração MessageFieldComparison acima) que é usada por esse diferencial ao determinar como comparar campos em mensagens. |
void | set_report_matches(bool report_matches) Informa ao diferencial se deve ou não informar as correspondências. mais… |
void | set_report_moves(bool report_moves) Informa ao diferencial se deve ou não informar os movimentos (em um campo repetido de "set" ou "map"). mais… |
void | set_report_ignores(bool report_ignores) Informa ao diferencial se deve ou não informar os valores ignorados. mais… |
void | set_scope(Scope scope) Define o escopo da comparação (conforme definido na enumeração de escopo acima) que é usada por este diferencial ao determinar quais campos serão comparados entre as mensagens. |
Scope | scope() Retorna o escopo atual usado por este diferencial. |
void | set_float_comparison(FloatComparison comparison) OBSOLETO. mais… |
void | set_repeated_field_comparison(RepeatedFieldComparison comparison) Define o tipo de comparação para o campo repetido (conforme definido na enumeração RepitaedFieldComparison acima) que é usado por este diferenciador ao comparar campos repetidos em mensagens. |
RepeatedFieldComparison | repeated_field_comparison() Retorna a comparação de campos repetidos atual usada por esse diferencial. |
bool | Compara as duas mensagens especificadas, retornando "true" se elas forem iguais; caso contrário, retorna "false". mais… |
bool | CompareWithFields(const Message & message1, const Message & message2, const std::vector< const FieldDescriptor * > & message1_fields, const std::vector< const FieldDescriptor * > & message2_fields) Igual ao anterior, mas comparando apenas a lista de campos especificados pelos dois vetores de FieldDescriptors. |
void | ReportDifferencesToString(std::string * output) Cria automaticamente um gerador de relatórios que gera as diferenças encontradas (se houver) no ponteiro de string de saída especificado. mais… |
void | ReportDifferencesTo(Reporter * reporter) Informa ao MessageDifferencer para informar as diferenças usando o especificador. mais... |
enum MessageDifferencer::MessageFieldComparison {
EQUAL,
EQUIVALENT
}
EQUAL,
EQUIVALENT
}
EQUAL | Os campos precisam estar presentes nas duas mensagens para que as mensagens sejam consideradas iguais. |
EQUIVALENTE | Os campos com valores padrão são considerados definidos para fins de comparação, mesmo que não sejam definidos explicitamente nas próprias mensagens. Os campos desconhecidos são ignorados. |
enum MessageDifferencer::Scope {
FULL,
PARTIAL
}
FULL,
PARTIAL
}
FULL | Todos os campos das duas mensagens são considerados na comparação. |
PARTIAL | Somente os campos presentes na primeira mensagem são considerados. Os campos definidos apenas na segunda mensagem serão ignorados durante a comparação. |
enum MessageDifferencer::FloatComparison {
EXACT,
APPROXIMATE
}
EXACT,
APPROXIMATE
}
OBSOLETO. Use FieldComparator::FloatComparison
EXACT | Os pontos flutuantes e duplos são comparados exatamente. |
APROXIMAR | Os pontos flutuantes e duplos são comparados usando o método MathUtil::EqualEquals. |
enum MessageDifferencer::RepeatedFieldComparison {
AS_LIST,
AS_SET,
AS_SMART_LIST,
AS_SMART_SET
}
AS_LIST,
AS_SET,
AS_SMART_LIST,
AS_SMART_SET
}
LISTA_DE_AS | Os campos repetidos são comparados em ordem. Valores diferentes no mesmo índice são informados usando ReportModified(). Se os campos repetidos tiverem números diferentes de elementos, os elementos não pareados serão informados usando ReportAdded() ou ReportDeleted(). |
CONFIGURAÇÃO AS | Trate todos os campos repetidos como conjuntos. Consulte TreatAsSet(), como abaixo. |
LISTA_SMART_LIST | Semelhante a AS_SET, mas preserva a ordem e encontra a sequência de correspondência mais longa do primeiro elemento correspondente. Para usar uma solução ideal, chame SetMatchIndicesForSmartListCallback() para transmiti-la. |
SET_SMART_SET | Semelhante a AS_SET, mas corresponde a elementos com menos diferenças. |
static bool MessageDifferencer::Equals(
const Message & message1,
const Message & message2)
const Message & message1,
const Message & message2)
Determina se as mensagens fornecidas são iguais.
Igualdade é definida como todos os campos dentro das duas mensagens que estão sendo definidos com o mesmo valor. Os campos e strings primitivos são comparados por valor, enquanto as mensagens/grupos incorporados são comparados como se fossem uma chamada recursiva. Use Compare() com IgnoreField() caso alguns campos sejam ignorados na comparação. Use Compare() com TreatAsSet() se houver campos repetidos em que a ordem não é importante.
Esse método requer que as duas mensagens tenham o mesmo Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
static bool MessageDifferencer::Equivalent(
const Message & message1,
const Message & message2)
const Message & message1,
const Message & message2)
Determina se as mensagens fornecidas são equivalentes.
A equivalência é definida como todos os campos dentro das duas mensagens que têm o mesmo valor. Isso é diferente do método "Equals" acima, em que os campos com valores padrão são considerados definidos automaticamente para esse valor. Veja mais detalhes sobre como os valores padrão são definidos para cada tipo de campo em . Além disso, Equivalent() ignora campos desconhecidos. Use IgnoreField() e Compare() se alguns campos forem ignorados na comparação.
Esse método requer que as duas mensagens tenham o mesmo Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
static bool MessageDifferencer::ApproximatelyEquals(
const Message & message1,
const Message & message2)
const Message & message1,
const Message & message2)
Determina se as mensagens fornecidas são aproximadamente iguais.
A igualdade aproximada é definida como todos os campos dentro das duas mensagens que são aproximadamente iguais. Os campos e strings primitivos (não flutuantes) são comparados por valor, os flutuantes são comparados usando MathUtil::QuaseEquals() e mensagens/grupos incorporados como se fossem uma chamada recursiva. Use IgnoreField() e Compare() se alguns campos forem ignorados na comparação.
Esse método requer que as duas mensagens tenham o mesmo Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
static bool MessageDifferencer::ApproximatelyEquivalent(
const Message & message1,
const Message & message2)
const Message & message1,
const Message & message2)
Determina se as mensagens fornecidas são aproximadamente equivalentes.
A equivalência aproximada é definida como todos os campos nas duas mensagens sendo aproximadamente equivalentes. Assim como em MessageDifferencer::RelativelyEquals, os campos e strings primitivos (não flutuantes) são comparados por valor, os flutuantes são comparados usando MathUtil::QuaseEquals() e mensagens/grupos incorporados como se fossem uma chamada recursiva. No entanto, os campos com valores padrão são considerados definidos como esse valor, de acordo com o MessageDiffencer::Equivalent. Use IgnoreField() e Compare() se alguns campos forem ignorados na comparação.
Esse método requer que as duas mensagens tenham o mesmo Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
void MessageDifferencer::TreatAsSet(
const FieldDescriptor * field)
const FieldDescriptor * field)
Os elementos do campo repetido serão tratados como um conjunto para fins de diferenciação. Portanto, ordens diferentes dos mesmos elementos serão consideradas iguais.
Os elementos que estão presentes nos dois lados da comparação, mas que mudaram de posição, são informados com ReportMudança(). Os elementos que existem apenas de um lado ou do outro são informados com ReportAdded() e ReportDeleted(), independentemente das posições deles. ReportModified() nunca é usado para esse campo repetido. Se as únicas diferenças entre as mensagens comparadas forem que alguns campos foram movidos, a comparação retornará "true".
Observe que, apesar do nome desse método, isso é na verdade uma comparação de vários conjuntos: se um lado da comparação tiver uma cópia no campo repetido, mas o outro não, isso contará como uma incompatibilidade.
Se o escopo da comparação for definido como PARCIAL, além do que foi mencionado acima, os valores extras adicionados aos campos repetidos da segunda mensagem não farão a comparação falhar.
A comparação definida é O(k * n^2) (em que n é o número total de elementos e k é o tamanho médio de cada elemento). Teoricamente, seria possível usar O(n * k) com uma implementação de hash mais complexa. Fique à vontade para contribuir se a implementação atual estiver lenta demais para você. Se a correspondência parcial também estiver ativada, a complexidade de tempo será O(k * n^2
- n^3) em que n^3 é a complexidade de tempo do algoritmo de correspondência máxima.
REQUISITOS: field->is_Repeated() e campo não registrado em TreatAsMap*
void MessageDifferencer::TreatAsList(
const FieldDescriptor * field)
const FieldDescriptor * field)
Os elementos do campo repetido serão tratados como uma lista para fins de diferenciação. Sendo assim, ordens diferentes dos mesmos elementos NÃO serão consideradas iguais.
REQUISITOS: field->is_Repeated() e campo não registrado em TreatAsMap*
void MessageDifferencer::TreatAsMap(
const FieldDescriptor * field,
const FieldDescriptor * key)
const FieldDescriptor * field,
const FieldDescriptor * key)
Os elementos do campo repetido serão tratados como um mapa para fins de diferenciação, em que |key| será a chave do mapa.
Assim, elementos com a mesma chave serão comparados mesmo que não apareçam no mesmo índice. As diferenças são relatadas de maneira semelhante a TreatAsSet(), exceto pelo fato de ReportModified() ser usado para relatar elementos com a mesma chave, mas valores diferentes. Se um elemento for movido e modificado, somente o ReportModified() será chamado. Assim como no TreatAsSet, se as únicas diferenças entre as mensagens comparadas forem que alguns campos foram movidos, a comparação retornará "true". Consulte TreatAsSet para ver observações sobre o desempenho.
REQUISITOS: field->is_Repeated() REQUIRES: field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE REQUISITOS: key->containing_type() == field->message_type()
void MessageDifferencer::TreatAsMapWithMultipleFieldsAsKey(
const FieldDescriptor * field,
const std::vector< const FieldDescriptor * > & key_fields)
const FieldDescriptor * field,
const std::vector< const FieldDescriptor * > & key_fields)
O mesmo que o TreatAsMap, mas esse método vai usar vários campos como chave em comparação.
Todos os campos especificados em "key_fields" precisam estar presentes nos elementos comparados. Dois elementos serão tratados como tendo a mesma chave se eles tiverem o mesmo valor para cada campo especificado. Há duas etapas no processo de comparação. A primeira é a correspondência de chaves. Cada elemento de uma mensagem será comparado a todos os elementos da outra. Somente os campos de "key_fields" são comparados nesta etapa para decidir se dois elementos têm a mesma chave. A segunda etapa é a comparação de valores. Os pares de elementos com a mesma chave (com valor igual para cada campo em "key_fields") serão comparados nesta etapa. A complexidade temporal da primeira etapa é O(s * m * n ^ 2), em que s é o tamanho médio dos campos especificados em "key_fields", m é o número de campos em "key_fields" e n é o número de elementos. Se a correspondência parcial estiver ativada, um algoritmo O(n^3) extra será gerado pelo algoritmo de correspondência máxima. A segunda etapa é O(k * n), em que k é o tamanho médio de cada elemento.
void MessageDifferencer::TreatAsMapWithMultipleFieldPathsAsKey(
const FieldDescriptor * field,
const std::vector< std::vector< const FieldDescriptor * > > & key_field_paths)
const FieldDescriptor * field,
const std::vector< std::vector< const FieldDescriptor * > > & key_field_paths)
Igual a TreatAsMapWithMultipleFieldsAsKey, exceto que cada campo não precisa necessariamente ser um subcampo direto.
Cada elemento em key_field_paths indica um caminho da mensagem que está sendo comparada, listando um subcampo sucessivo para chegar ao campo chave.
REQUISITOS:
for key_field_path in key_field_paths: key_field_path[[]0]->containing_type() == field->message_type() for i in [[]0, key_field_path.size() - 1): key_field_path[[]i+1]->containing_type() == key_field_path[[]i]->message_type() key_field_path[[]i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE !key_field_path[[]i]->is_repeated()
void MessageDifferencer::TreatAsMapUsingKeyComparator(
const FieldDescriptor * field,
const MapKeyComparator * key_comparator)
const FieldDescriptor * field,
const MapKeyComparator * key_comparator)
Usa um MapKeyComparator personalizado para determinar se dois elementos têm a mesma chave ao comparar um campo repetido como um mapa.
O autor da chamada é responsável por excluir o key_comparator. Esse método varia em TreatAsMapWithMultipleFieldsAsKey apenas na primeira etapa de correspondência de chave. Em vez de comparar alguns campos especificados, ele invoca o método IsMatch do "key_comparator" determinado para decidir se dois elementos têm a mesma chave.
void MessageDifferencer::AddIgnoreCriteria(
IgnoreCriteria * ignore_criteria)
IgnoreCriteria * ignore_criteria)
Adicione um critério personalizado "ignore" que é avaliado, além dos campos ignorados adicionados com IgnoreField.
Assumiu a propriedade de ignore_criteria.
void MessageDifferencer::IgnoreField(
const FieldDescriptor * field)
const FieldDescriptor * field)
Indica que qualquer campo com o descritor especificado deve ser ignorado para comparar duas mensagens.
Isso se aplica a campos aninhados na estrutura da mensagem, bem como aos de nível superior. Quando MessageDifferencer encontra um campo ignorado, o ReportIgnored é chamado no gerador de relatórios, se especificado.
O único status em que o status "ignorado" do campo não é aplicado é quando ele está sendo usado como chave em um campo transmitido para TreatAsMap ou é um dos campos transmitidos para TreatAsMapWithMultipleFieldsAsKey. Nesse caso, ele é comparado na correspondência de chaves, mas depois é ignorado na comparação de valores.
void MessageDifferencer::set_field_comparator(
FieldComparator * comparator)
FieldComparator * comparator)
Define o comparador de campo usado para determinar as diferenças entre os campos de buffer de protocolo.
Por padrão, ele é definido como uma instância DefaultFieldComparator. MessageDifferencer não assume a propriedade do objeto transmitido. Esse método precisa ser chamado antes de "Comparar" para que o comparador seja usado.
void MessageDifferencer::SetFractionAndMargin(
const FieldDescriptor * field,
double fraction,
double margin)
const FieldDescriptor * field,
double fraction,
double margin)
OBSOLETO.
Passe uma instância DefaultFieldComparator. Define a fração e a margem para a comparação de ponto flutuante de um determinado campo. Usa MathUtil::WithinFractionOrMargin para comparar os valores. OBSERVAÇÃO: esse método não fará nada se o comparador de campo do diferencial tiver sido
set to a custom object.
EXIGEM: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE ou
field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT
EXIGEM: float_comparison_ == APPROXIMATE
void MessageDifferencer::set_report_matches(
bool report_matches)
bool report_matches)
Informa ao diferencial se deve ou não informar as correspondências.
Esse método precisa ser chamado antes da comparação. O padrão para um novo diferencial é falso.
void MessageDifferencer::set_report_moves(
bool report_moves)
bool report_moves)
Informa ao diferencial se deve ou não informar os movimentos (em um campo repetido de "set" ou "map").
Esse método precisa ser chamado antes da comparação. O padrão para um novo diferencial é verdadeiro.
void MessageDifferencer::set_report_ignores(
bool report_ignores)
bool report_ignores)
Informa ao diferencial se deve ou não informar os valores ignorados.
Esse método precisa ser chamado antes da comparação. O padrão para um novo diferencial é verdadeiro.
void MessageDifferencer::set_float_comparison(
FloatComparison comparison)
FloatComparison comparison)
OBSOLETO.
Passe uma instância DefaultFieldComparator. Define o tipo de comparação, conforme definido na enumeração FloatComparison acima, usada por este diferencial na comparação de campos flutuantes (e duplos) em mensagens. OBSERVAÇÃO: esse método não fará nada se o comparador de campo do diferencial tiver sido
set to a custom object.
bool MessageDifferencer::Compare(
const Message & message1,
const Message & message2)
const Message & message1,
const Message & message2)
Compara as duas mensagens especificadas, retornando "true" se elas forem iguais; caso contrário, retorna "false".
Se esse método retornar "false", todas as alterações entre as duas mensagens serão informadas se um Reporter tiver sido especificado por ReportDifferencesTo. Veja também ReportDifferencesToString.
Esse método requer que as duas mensagens tenham o mesmo Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
void MessageDifferencer::ReportDifferencesToString(
std::string * output)
std::string * output)
Cria automaticamente um gerador de relatórios que gera as diferenças encontradas (se houver) no ponteiro de string de saída especificado.
Esse método precisa ser chamado antes da comparação.
void MessageDifferencer::ReportDifferencesTo(
Reporter * reporter)
Reporter * reporter)
Informa ao MessageDifferencer para informar as diferenças usando o especificador.
Esse método precisa ser chamado antes de "Comparar" para que o repórter seja usado. É responsabilidade do autor da chamada excluir esse objeto. Se o ponteiro fornecido for igual a NULL, o MessageDifferencer vai interromper as diferenças de relatórios para qualquer repórter ou string de saída definido anteriormente.
classe MessageDifferencer::IgnoreCriteria
#include <google/protobuf/util/message_differencer.h>
namespace google::protobuf::util
Classe base abstrata da qual todos os IgnoreCritérios são derivados.
Ao adicionar IgnoreCriteria, é possível implementar uma lógica de ignorar mais complexa. IgnoreCriteria são registrados em AddIgnoreCriteria. Em cada campo comparado, IsIgnored é chamado em cada IgnoreCriteria adicionado até que um retorne "true" ou todos retornem "false". IsIgnored é chamado para campos em que pelo menos um lado tenha um valor.
Participantes | |
---|---|
| IgnoreCriteria() |
virtual | ~IgnoreCriteria() |
virtual bool | IsIgnored(const Message & , const Message & , const FieldDescriptor * , const std::vector< SpecificField > & ) = 0 Retornará "true" se o campo precisar ser ignorado. |
virtual bool | IsUnknownFieldIgnored(const Message & , const Message & , const SpecificField & , const std::vector< SpecificField > & ) Retornará "true" se o campo desconhecido precisar ser ignorado. mais… |
virtual bool IgnoreCriteria::IsUnknownFieldIgnored(
const Message & ,
const Message & ,
const SpecificField & ,
const std::vector< SpecificField > & )
const Message & ,
const Message & ,
const SpecificField & ,
const std::vector< SpecificField > & )
Retornará "true" se o campo desconhecido precisar ser ignorado.
Observação: isso também será chamado para os campos desconhecidos. Nesse caso,
field.field will be null.
classe MessageDifferencer::MapKeyComparator
#include <google/protobuf/util/message_differencer.h>
namespace google::protobuf::util
MapKeyComparator é usado para determinar se dois elementos têm a mesma chave ao comparar elementos de um campo repetido como um mapa.
Participantes | |
---|---|
| MapKeyComparator() |
virtual | ~MapKeyComparator() |
virtual bool | IsMatch(const Message & , const Message & , const std::vector< SpecificField > & ) const |
classe MessageDifferencer::Reporter
#include <google/protobuf/util/message_differencer.h>
namespace google::protobuf::util
Classe base abstrata da qual todos os repórteres MessageDifferencer derivam.
Os cinco métodos* abaixo serão chamados quando um campo for adicionado, excluído, modificado, movido ou correspondido. O terceiro argumento é um vetor de ponteiros de FieldDescriptor que descreve a cadeia de campos usada para encontrar o campo atual. Por exemplo, para um campo encontrado em uma mensagem incorporada, o vetor conterá dois FieldDescriptors. O primeiro será o campo da mensagem incorporada e o segundo será o campo da mensagem incorporada que foi adicionado, excluído/modificado. Os campos serão informados em PostTraversalOrder. Por exemplo, considerando o proto a seguir, se baz e quux forem alterados. foo {
bar { baz: 1 quux: 2 }
} ReportModified será invocado com a seguinte ordem:
- foo.bar.baz ou foo.bar.quux
- foo.bar.quux ou foo.bar.baz
- foo.bar
- foo
Subclasses conhecidas:
Participantes | |
---|---|
| Reporter() |
virtual | ~Reporter() |
virtual void | ReportAdded(const Message & message1, const Message & message2, const std::vector< SpecificField > & field_path) = 0 Informa que um campo foi adicionado à Message2. |
virtual void | ReportDeleted(const Message & message1, const Message & message2, const std::vector< SpecificField > & field_path) = 0 Informa que um campo foi excluído da mensagem 1. |
virtual void | ReportModified(const Message & message1, const Message & message2, const std::vector< SpecificField > & field_path) = 0 Informa que o valor de um campo foi modificado. |
virtual void | ReportMoved(const Message & , const Message & , const std::vector< SpecificField > & ) Informa que um campo repetido foi movido para outro local. mais… |
virtual void | ReportMatched(const Message & , const Message & , const std::vector< SpecificField > & ) Informa que dois campos coincidem. mais… |
virtual void | ReportIgnored(const Message & , const Message & , const std::vector< SpecificField > & ) Informa que dois campos seriam comparados, mas a comparação foi ignorada porque o campo foi marcado como "ignore" usando IgnoreField(). mais... |
virtual void | ReportUnknownFieldIgnored(const Message & , const Message & , const std::vector< SpecificField > & ) Informar que um campo desconhecido é ignorado. mais… |
virtual void Reporter::ReportMoved(
const Message & ,
const Message & ,
const std::vector< SpecificField > & )
const Message & ,
const Message & ,
const std::vector< SpecificField > & )
Informa que um campo repetido foi movido para outro local.
Isso se aplica somente ao usar TreatAsSet ou TreatAsMap(). Veja abaixo. Observe também que, para qualquer campo, ReportModified e ReportMudanças são mutuamente exclusivos. Se um campo tiver sido movido e modificado, somente o ReportModified será chamado.
virtual void Reporter::ReportMatched(
const Message & ,
const Message & ,
const std::vector< SpecificField > & )
const Message & ,
const Message & ,
const std::vector< SpecificField > & )
Informa que dois campos coincidem.
Útil para fazer diferenças lado a lado. Essa função é mutuamente exclusiva com ReportModified e ReportMudança. É necessário chamar set_report_matches(true) antes de chamar "Comparar" para usar essa função.
virtual void Reporter::ReportIgnored(
const Message & ,
const Message & ,
const std::vector< SpecificField > & )
const Message & ,
const Message & ,
const std::vector< SpecificField > & )
Informa que dois campos teriam sido comparados, mas a comparação foi ignorada porque foi marcado como "ignorado" usando IgnoreField().
Essa função é mutuamente exclusiva com todas as outras funções Report().
O contrato de ReportIgnored é um pouco diferente das outras funções Report(), em que |field_path.back().index| é sempre igual a -1, mesmo que o último campo seja repetido. Isso acontece porque, enquanto as outras funções Report() indicam onde a ação (Adição, Exclusão etc.) aconteceu em um campo repetido, quando um campo repetido é "ignorado", o diferencial simplesmente chama ReportIgnored no campo repetido como um todo e prossegue sem examinar os elementos individuais dele.
Além disso, ReportIgnored() não indica se os campos foram realmente iguais ou não, já que Compare() não inspeciona esses campos. Cabe ao Relator decidir se os campos são iguais ou não (talvez com uma segunda chamada para Compare()), se for importante.
virtual void Reporter::ReportUnknownFieldIgnored(
const Message & ,
const Message & ,
const std::vector< SpecificField > & )
const Message & ,
const Message & ,
const std::vector< SpecificField > & )
Informar que um campo desconhecido é ignorado.
Veja o comentário acima. Essa é uma função diferente, porque o último SpecificField no caminho do campo tem um campo nulo. Isso pode interromper o Repórter existente.
struct MessageDifferencer::SpecificField
#include <google/protobuf/util/message_differencer.h>
namespace google::protobuf::util
Identifica um campo individual em uma instância de mensagem.
Usado em field_path, abaixo.
Participantes | |
---|---|
const FieldDescriptor * | field = = nullptr Para campos conhecidos, o campo é preenchido e "Unknown_field_number" é -1. mais… |
int | unknown_field_number = = -1 |
UnknownField::Type | unknown_field_type = = UnknownField::Type::TYPE_VARINT |
int | index = = -1 Se for um campo repetido, "índice" será o índice dentro dele. mais… |
int | new_index = = -1 Se "campo" for um campo repetido que está sendo tratado como um mapa ou conjunto (consulte TreatAsMap() e TreatAsSet() abaixo), new_index indica a posição para a qual o elemento foi movido. mais... |
const UnknownFieldSet * | unknown_field_set1 = = nullptr Para campos desconhecidos, eles são os ponteiros para o UnknownFieldSet que contém os campos desconhecidos. mais... |
const UnknownFieldSet * | unknown_field_set2 = = nullptr |
int | unknown_field_index1 = = -1 Para campos desconhecidos, eles são o índice do campo em UnknownFieldSets. mais… |
int | unknown_field_index2 = = -1 |
const FieldDescriptor * SpecificField::field = = nullptr
Para campos conhecidos, o campo é preenchido e "Unknown_field_number" é -1.
Para campos desconhecidos, "field" é NULL, "Unknown_field_number" é o número de campo e "Unknown_field_type" é o tipo.
int SpecificField::index = = -1
Se for um campo repetido, "índice" será o índice dentro dele.
Para campos desconhecidos, este é o índice do campo entre todos os campos desconhecidos do mesmo número de campo e tipo.
int SpecificField::new_index = = -1
Se "campo" for um campo repetido que está sendo tratado como um mapa ou conjunto (consulte TreatAsMap() e TreatAsSet() abaixo), new_index indica a posição para a qual o elemento foi movido.
Se o elemento não tiver sido movido, o "new_index" terá o mesmo valor que "index".
const UnknownFieldSet * SpecificField::unknown_field_set1 = = nullptr
Para campos desconhecidos, eles são os ponteiros para o UnknownFieldSet que contém os campos desconhecidos.
Em determinados casos (por exemplo, MessageSet do proto1 ou grupos aninhados de campos desconhecidos), eles podem ser diferentes dos NativeFieldSets internos das mensagens.
int SpecificField::unknown_field_index1 = = -1
Para campos desconhecidos, eles são o índice do campo em UnknownFieldSets.
Um deles será -1 ao informar uma adição ou exclusão.
classe MessageDifferencer::StreamReporter: Reporter público
#include <google/protobuf/util/message_differencer.h>
namespace google::protobuf::util
Uma implementação do MessageDifferencer Reporter que gera qualquer diferença encontrada em formato legível para o ZeroCopyOutputStream ou impressora fornecido.
Se uma impressora for usada, o delimitador precisa ser "$".
AVISO: este repórter não necessariamente esvazia a saída até ser destruído. Como resultado, não é seguro presumir que o resultado seja válido ou completo até você destruir o repórter. Por exemplo, se você usar um StreamReporter para gravar em um StringOutputStream, a string de destino poderá conter dados não inicializados até que o repórter seja destruído.
Participantes | |
---|---|
explicit | StreamReporter(io::ZeroCopyOutputStream * output) |
explicit | StreamReporter(io::Printer * printer) delimitador "$" |
| ~StreamReporter() |
void | set_report_modified_aggregates(bool report) Quando definido como verdadeiro, o relatório de stream também gerará nós agregados (ou seja, mais... |
virtual void | ReportAdded(const Message & message1, const Message & message2, const std::vector< SpecificField > & field_path) Informa que um campo foi adicionado à Message2. |
virtual void | ReportDeleted(const Message & message1, const Message & message2, const std::vector< SpecificField > & field_path) Informa que um campo foi excluído da mensagem 1. |
virtual void | ReportModified(const Message & message1, const Message & message2, const std::vector< SpecificField > & field_path) Informa que o valor de um campo foi modificado. |
virtual void | ReportMoved(const Message & , const Message & , const std::vector< SpecificField > & ) Informa que um campo repetido foi movido para outro local. mais… |
virtual void | ReportMatched(const Message & , const Message & , const std::vector< SpecificField > & ) Informa que dois campos coincidem. mais… |
virtual void | ReportIgnored(const Message & , const Message & , const std::vector< SpecificField > & ) Informa que dois campos seriam comparados, mas a comparação foi ignorada porque o campo foi marcado como "ignore" usando IgnoreField(). mais... |
virtual void | ReportUnknownFieldIgnored(const Message & , const Message & , const std::vector< SpecificField > & ) Informar que um campo desconhecido é ignorado. mais… |
void | As mensagens que estão sendo comparadas precisam ser fornecidas a StreamReporter antes do processamento. |
protected virtual void | PrintPath(const std::vector< SpecificField > & field_path, bool left_side) Exibe o caminho especificado dos campos para o buffer. |
protected virtual void | PrintValue(const Message & message, const std::vector< SpecificField > & field_path, bool left_side) Mostra o valor dos campos no buffer. mais… |
protected virtual void | PrintUnknownFieldValue(const UnknownField * unknown_field) Mostra o caminho especificado dos campos desconhecidos no buffer. |
protected void | Print(const std::string & str) É só imprimir uma string. |
protected void | PrintMapKey(const std::vector< SpecificField > & field_path, bool left_side, const SpecificField & specific_field, size_t target_field_index) função auxiliar para PrintPath que contém a lógica para imprimir mapas |
void StreamReporter::set_report_modified_aggregates(
bool report)
bool report)
Quando definido como verdadeiro, o relatório de stream também gera nós agregados (ou seja,
mensagens e grupos) cujos subcampos tenham sido modificados. Quando falso, somente os subcampos individuais serão informados. O padrão é "false".
virtual void StreamReporter::ReportMoved(
const Message & ,
const Message & ,
const std::vector< SpecificField > & )
const Message & ,
const Message & ,
const std::vector< SpecificField > & )
Informa que um campo repetido foi movido para outro local.
Isso se aplica somente ao usar TreatAsSet ou TreatAsMap(). Veja abaixo. Observe também que, para qualquer campo, ReportModified e ReportMudanças são mutuamente exclusivos. Se um campo tiver sido movido e modificado, somente o ReportModified será chamado.
virtual void StreamReporter::ReportMatched(
const Message & ,
const Message & ,
const std::vector< SpecificField > & )
const Message & ,
const Message & ,
const std::vector< SpecificField > & )
Informa que dois campos coincidem.
Útil para fazer diferenças lado a lado. Essa função é mutuamente exclusiva com ReportModified e ReportMudança. É necessário chamar set_report_matches(true) antes de chamar "Comparar" para usar essa função.
virtual void StreamReporter::ReportIgnored(
const Message & ,
const Message & ,
const std::vector< SpecificField > & )
const Message & ,
const Message & ,
const std::vector< SpecificField > & )
Informa que dois campos teriam sido comparados, mas a comparação foi ignorada porque foi marcado como "ignorado" usando IgnoreField().
Essa função é mutuamente exclusiva com todas as outras funções Report().
O contrato de ReportIgnored é um pouco diferente das outras funções Report(), em que |field_path.back().index| é sempre igual a -1, mesmo que o último campo seja repetido. Isso acontece porque, enquanto as outras funções Report() indicam onde a ação (Adição, Exclusão etc.) aconteceu em um campo repetido, quando um campo repetido é "ignorado", o diferencial simplesmente chama ReportIgnored no campo repetido como um todo e prossegue sem examinar os elementos individuais dele.
Além disso, ReportIgnored() não indica se os campos foram realmente iguais ou não, já que Compare() não inspeciona esses campos. Cabe ao Relator decidir se os campos são iguais ou não (talvez com uma segunda chamada para Compare()), se for importante.
virtual void StreamReporter::ReportUnknownFieldIgnored(
const Message & ,
const Message & ,
const std::vector< SpecificField > & )
const Message & ,
const Message & ,
const std::vector< SpecificField > & )
Informar que um campo desconhecido é ignorado.
Veja o comentário acima. Essa é uma função diferente, porque o último SpecificField no caminho do campo tem um campo nulo. Isso pode interromper o Repórter existente.
protected virtual void StreamReporter::PrintValue(
const Message & message,
const std::vector< SpecificField > & field_path,
bool left_side)
const Message & message,
const std::vector< SpecificField > & field_path,
bool left_side)
Mostra o valor dos campos no buffer.
left_side será verdadeiro se a mensagem especificada for do lado esquerdo da comparação e falso se for a direita. Isso é relevante apenas para decidir se você precisa seguir desconhecido_field_index1 ou desconhecido_field_index2 quando um campo desconhecido é encontrado em field_path.
classe MessageDifferencer::UnpackAnyField
#include <google/protobuf/util/message_differencer.h>
namespace google::protobuf::util
Classe para processar qualquer desserialização.
Essa lógica é usada pelas classes MessageDifferencer e StreamReporter.
Participantes | |
---|---|
| UnpackAnyField() |
| ~UnpackAnyField() |
bool | Se "any" for do tipo google.protobuf.Any, extraia o payload dela usando DynamicMessageFactory e armazene-a em "data". |
classe FieldContext
#include <google/protobuf/util/message_differencer.h>
namespace google::protobuf::util
Essa classe fornece informações extras para a função FieldComparator::Compare.
Participantes | |
---|---|
explicit | FieldContext(std::vector< MessageDifferencer::SpecificField > * parent_fields) |
std::vector< MessageDifferencer::SpecificField > * | parent_fields() const |