Domanda

scrissi Un'estensione di Ruby C ++ avvolgere Libreria di espressione regolare Re2 di Google ma a recente aggiornamento alla biblioteca ha modificato l'interfaccia del Match() funzione da:

bool Match(const StringPiece& text,
           int startpos,
           Anchor anchor,
           StringPiece *match,
           int nmatch) const;

Per:

bool Match(const StringPiece& text,
           int startpos,
           int endpos,
           Anchor anchor,
           StringPiece *match,
           int nmatch) const;

(Nota il nuovo int endpos discussione.)

La mia domanda è: è possibile per me supportare entrambe le versioni di questa biblioteca in un'estensione nonostante il fatto che RE2 non sembri specificare alcun tipo di VERSION costante che posso introspettare?

Idealmente, voglio essere in grado di provare la versione più recente (con 6 argomenti) e, fallendo, rientrare alla versione precedente (poiché sono in grado di riempire il endpos argomento facilmente).

Al momento il mio codice è così:

matched = p->pattern->Match(text_as_string_piece, 0, (int)RSTRING_LEN(text), RE2::UNANCHORED, 0, 0);

Ma se hai la versione precedente di RE2, deve essere:

matched = p->pattern->Match(text_as_string_piece, 0, RE2::UNANCHORED, 0, 0);
È stato utile?

Soluzione

La risposta tradizionale è generare a config.h o qualsiasi altra cosa al momento dell'installazione.

Cioè, durante l'installazione rileverai quale versione di re2 è installato e quindi definire un simbolo in config.h A seconda di questo:

// config.h
#ifndef CONFIG_H_INCLUDED
#define CONFIG_H_INCLUDED

#define RE2_MATCH_6_ARGS 1

#endif // CONFIG_H_INCLUDED

E poi, puoi usarlo:

#if defined(RE2_MATCH_6_ARGS) && RE2_MATCH_6_ARGS == 1
  matched = p->pattern->Match(text_as_string_piece, 0, (int)RSTRING_LEN(text), RE2::UNANCHORED, 0, 0);
#else
  matched = p->pattern->Match(text_as_string_piece, 0, RE2::UNANCHORED, 0, 0);
#endif

Questa è una soluzione stabile e dovrebbe funzionare bene.


Un'altra possibilità è quella di hackerare il sistema ...

Fornire una definizione di entrambi Match Funzioni in una libreria wrapper:

  • Match5 lancia un errore (si prega di collegamento a RE2)
  • Match6 in avanti a Match5.

Il fatto è (nel mondo di Unix ...), se un simbolo è già stato caricato, non sarà sovrascritto da una nuova definizione. Quindi fino a quando re2 viene caricato per primo finisci in uno di quei due scenari:

  • vecchio re2: La tua libreria (wrapper) fornisce una definizione di Match6 che inoltra al re2 Definizione fornita di Match5
  • nuovo re2: la chiamata va direttamente alla definizione di Match6 Quello re2 fornito

Tanto più fragile. Richiede a Biblioteca wrapper intorno a re2. È improbabile che funzioni con il collegamento statico (mai provato però ...). Ma non richiede un file ./configure fare un passo.

Altri suggerimenti

Da quello che so, non puoi. Ciò richiederebbe di collegarti con le versioni vecchie e nuove di RE2, il che renderebbe le spazi dei nomi.

A meno che non esista una versione di questo metodo che riprende la vecchia versione, sei bloccato con la nuova versione.

Se vuoi essere in grado di farlo compilare La tua estensione per entrambe le versioni, quindi devi modificare i passaggi di compilazione per definire un po 'di flag voi controllo.

#ifdef RE2_ODLFORMAT
matched = p->pattern->Match(text_as_string_piece, 0, RE2::UNANCHORED, 0, 0);
#else
matched = p->pattern->Match(text_as_string_piece, 0, (int)RSTRING_LEN(text), RE2::UNANCHORED, 0, 0);
#endif

Quindi per compilare il tuo codice, faresti qualcosa su queste righe:

make RE2_OLDFORMAT=1 all # compile for old version
make all # default target is for new version
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top