/[pcre]/code/trunk/pcrecpp.cc
ViewVC logotype

Diff of /code/trunk/pcrecpp.cc

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 253 by ph10, Mon Sep 17 10:51:30 2007 UTC revision 594 by ph10, Sun May 1 08:22:12 2011 UTC
# Line 1  Line 1 
1  // Copyright (c) 2005, Google Inc.  // Copyright (c) 2010, Google Inc.
2  // All rights reserved.  // All rights reserved.
3  //  //
4  // Redistribution and use in source and binary forms, with or without  // Redistribution and use in source and binary forms, with or without
# Line 33  Line 33 
33  #include "config.h"  #include "config.h"
34  #endif  #endif
35    
 #ifdef HAVE_WINDOWS_H  
 #define HAVE_STRTOQ 1  
 #define strtoll     _strtoui64  
 #define strtoull    _strtoi64  
 #endif  
   
36  #include <stdlib.h>  #include <stdlib.h>
37  #include <stdio.h>  #include <stdio.h>
38  #include <ctype.h>  #include <ctype.h>
39  #include <limits.h>      /* for SHRT_MIN, USHRT_MAX, etc */  #include <limits.h>      /* for SHRT_MIN, USHRT_MAX, etc */
40    #include <string.h>      /* for memcpy */
41  #include <assert.h>  #include <assert.h>
42  #include <errno.h>  #include <errno.h>
43  #include <string>  #include <string>
# Line 61  static const int kMaxArgs = 16; Line 56  static const int kMaxArgs = 16;
56  static const int kVecSize = (1 + kMaxArgs) * 3;  // results + PCRE workspace  static const int kVecSize = (1 + kMaxArgs) * 3;  // results + PCRE workspace
57    
58  // Special object that stands-in for no argument  // Special object that stands-in for no argument
59  PCRECPP_EXP_DEFN Arg no_arg((void*)NULL);  Arg RE::no_arg((void*)NULL);
60    
61    // This is for ABI compatibility with old versions of pcre (pre-7.6),
62    // which defined a global no_arg variable instead of putting it in the
63    // RE class.  This works on GCC >= 3, at least.  It definitely works
64    // for ELF, but may not for other object formats (Mach-O, for
65    // instance, does not support aliases.)  We could probably have a more
66    // inclusive test if we ever needed it.  (Note that not only the
67    // __attribute__ syntax, but also __USER_LABEL_PREFIX__, are
68    // gnu-specific.)
69    #if defined(__GNUC__) && __GNUC__ >= 3 && defined(__ELF__)
70    # define ULP_AS_STRING(x)            ULP_AS_STRING_INTERNAL(x)
71    # define ULP_AS_STRING_INTERNAL(x)   #x
72    # define USER_LABEL_PREFIX_STR       ULP_AS_STRING(__USER_LABEL_PREFIX__)
73    extern Arg no_arg
74      __attribute__((alias(USER_LABEL_PREFIX_STR "_ZN7pcrecpp2RE6no_argE")));
75    #endif
76    
77  // If a regular expression has no error, its error_ field points here  // If a regular expression has no error, its error_ field points here
78  static const string empty_string;  static const string empty_string;
# Line 321  bool RE::FindAndConsume(StringPiece* inp Line 332  bool RE::FindAndConsume(StringPiece* inp
332  bool RE::Replace(const StringPiece& rewrite,  bool RE::Replace(const StringPiece& rewrite,
333                   string *str) const {                   string *str) const {
334    int vec[kVecSize];    int vec[kVecSize];
335    int matches = TryMatch(*str, 0, UNANCHORED, vec, kVecSize);    int matches = TryMatch(*str, 0, UNANCHORED, true, vec, kVecSize);
336    if (matches == 0)    if (matches == 0)
337      return false;      return false;
338    
# Line 360  static int NewlineMode(int pcre_options) Line 371  static int NewlineMode(int pcre_options)
371      else if (newline == -1)      else if (newline == -1)
372        newline_mode = PCRE_NEWLINE_ANY;        newline_mode = PCRE_NEWLINE_ANY;
373      else if (newline == -2)      else if (newline == -2)
374        newline_mode = PCRE_NEWLINE_ANYCRLF;        newline_mode = PCRE_NEWLINE_ANYCRLF;
375      else      else
376        assert("" == "Unexpected return value from pcre_config(NEWLINE)");        assert(NULL == "Unexpected return value from pcre_config(NEWLINE)");
377    }    }
378    return newline_mode;    return newline_mode;
379  }  }
# Line 374  int RE::GlobalReplace(const StringPiece& Line 385  int RE::GlobalReplace(const StringPiece&
385    string out;    string out;
386    int start = 0;    int start = 0;
387    int lastend = -1;    int lastend = -1;
388      bool last_match_was_empty_string = false;
389    
390    for (; start <= static_cast<int>(str->length()); count++) {    while (start <= static_cast<int>(str->length())) {
391      int matches = TryMatch(*str, start, UNANCHORED, vec, kVecSize);      // If the previous match was for the empty string, we shouldn't
392      if (matches <= 0)      // just match again: we'll match in the same way and get an
393        break;      // infinite loop.  Instead, we do the match in a special way:
394      int matchstart = vec[0], matchend = vec[1];      // anchored -- to force another try at the same position --
395      assert(matchstart >= start);      // and with a flag saying that this time, ignore empty matches.
396      assert(matchend >= matchstart);      // If this special match returns, that means there's a non-empty
397      if (matchstart == matchend && matchstart == lastend) {      // match at this position as well, and we can continue.  If not,
398        // advance one character if we matched an empty string at the same      // we do what perl does, and just advance by one.
399        // place as the last match occurred      // Notice that perl prints '@@@' for this;
400        matchend = start + 1;      //    perl -le '$_ = "aa"; s/b*|aa/@/g; print'
401        // If the current char is CR and we're in CRLF mode, skip LF too.      int matches;
402        // Note it's better to call pcre_fullinfo() than to examine      if (last_match_was_empty_string) {
403        // all_options(), since options_ could have changed bewteen        matches = TryMatch(*str, start, ANCHOR_START, false, vec, kVecSize);
404        // compile-time and now, but this is simpler and safe enough.        if (matches <= 0) {
405        // Modified by PH to add ANY and ANYCRLF.          int matchend = start + 1;     // advance one character.
406        if (start+1 < static_cast<int>(str->length()) &&          // If the current char is CR and we're in CRLF mode, skip LF too.
407            (*str)[start] == '\r' && (*str)[start+1] == '\n' &&          // Note it's better to call pcre_fullinfo() than to examine
408            (NewlineMode(options_.all_options()) == PCRE_NEWLINE_CRLF ||          // all_options(), since options_ could have changed bewteen
409             NewlineMode(options_.all_options()) == PCRE_NEWLINE_ANY ||          // compile-time and now, but this is simpler and safe enough.
410             NewlineMode(options_.all_options()) == PCRE_NEWLINE_ANYCRLF)          // Modified by PH to add ANY and ANYCRLF.
411            ) {          if (matchend < static_cast<int>(str->length()) &&
412          matchend++;              (*str)[start] == '\r' && (*str)[matchend] == '\n' &&
413        }              (NewlineMode(options_.all_options()) == PCRE_NEWLINE_CRLF ||
414        // We also need to advance more than one char if we're in utf8 mode.               NewlineMode(options_.all_options()) == PCRE_NEWLINE_ANY ||
415  #ifdef SUPPORT_UTF8               NewlineMode(options_.all_options()) == PCRE_NEWLINE_ANYCRLF)) {
       if (options_.utf8()) {  
         while (matchend < static_cast<int>(str->length()) &&  
                ((*str)[matchend] & 0xc0) == 0x80)  
416            matchend++;            matchend++;
417        }          }
418            // We also need to advance more than one char if we're in utf8 mode.
419    #ifdef SUPPORT_UTF8
420            if (options_.utf8()) {
421              while (matchend < static_cast<int>(str->length()) &&
422                     ((*str)[matchend] & 0xc0) == 0x80)
423                matchend++;
424            }
425  #endif  #endif
426        if (matchend <= static_cast<int>(str->length()))          if (start < static_cast<int>(str->length()))
427          out.append(*str, start, matchend - start);            out.append(*str, start, matchend - start);
428        start = matchend;          start = matchend;
429            last_match_was_empty_string = false;
430            continue;
431          }
432      } else {      } else {
433        out.append(*str, start, matchstart - start);        matches = TryMatch(*str, start, UNANCHORED, true, vec, kVecSize);
434        Rewrite(&out, rewrite, *str, vec, matches);        if (matches <= 0)
435        start = matchend;          break;
       lastend = matchend;  
       count++;  
436      }      }
437        int matchstart = vec[0], matchend = vec[1];
438        assert(matchstart >= start);
439        assert(matchend >= matchstart);
440        out.append(*str, start, matchstart - start);
441        Rewrite(&out, rewrite, *str, vec, matches);
442        start = matchend;
443        lastend = matchend;
444        count++;
445        last_match_was_empty_string = (matchstart == matchend);
446    }    }
447    
448    if (count == 0)    if (count == 0)
# Line 432  bool RE::Extract(const StringPiece& rewr Line 458  bool RE::Extract(const StringPiece& rewr
458                   const StringPiece& text,                   const StringPiece& text,
459                   string *out) const {                   string *out) const {
460    int vec[kVecSize];    int vec[kVecSize];
461    int matches = TryMatch(text, 0, UNANCHORED, vec, kVecSize);    int matches = TryMatch(text, 0, UNANCHORED, true, vec, kVecSize);
462    if (matches == 0)    if (matches == 0)
463      return false;      return false;
464    out->erase();    out->erase();
# Line 447  bool RE::Extract(const StringPiece& rewr Line 473  bool RE::Extract(const StringPiece& rewr
473    // Note that it's legal to escape a character even if it has no    // Note that it's legal to escape a character even if it has no
474    // special meaning in a regular expression -- so this function does    // special meaning in a regular expression -- so this function does
475    // that.  (This also makes it identical to the perl function of the    // that.  (This also makes it identical to the perl function of the
476    // same name; see `perldoc -f quotemeta`.)    // same name; see `perldoc -f quotemeta`.)  The one exception is
477      // escaping NUL: rather than doing backslash + NUL, like perl does,
478      // we do '\0', because pcre itself doesn't take embedded NUL chars.
479    for (int ii = 0; ii < unquoted.size(); ++ii) {    for (int ii = 0; ii < unquoted.size(); ++ii) {
480      // Note that using 'isalnum' here raises the benchmark time from      // Note that using 'isalnum' here raises the benchmark time from
481      // 32ns to 58ns:      // 32ns to 58ns:
482      if ((unquoted[ii] < 'a' || unquoted[ii] > 'z') &&      if (unquoted[ii] == '\0') {
483          (unquoted[ii] < 'A' || unquoted[ii] > 'Z') &&        result += "\\0";
484          (unquoted[ii] < '0' || unquoted[ii] > '9') &&      } else if ((unquoted[ii] < 'a' || unquoted[ii] > 'z') &&
485          unquoted[ii] != '_' &&                 (unquoted[ii] < 'A' || unquoted[ii] > 'Z') &&
486          // If this is the part of a UTF8 or Latin1 character, we need                 (unquoted[ii] < '0' || unquoted[ii] > '9') &&
487          // to copy this byte without escaping.  Experimentally this is                 unquoted[ii] != '_' &&
488          // what works correctly with the regexp library.                 // If this is the part of a UTF8 or Latin1 character, we need
489          !(unquoted[ii] & 128)) {                 // to copy this byte without escaping.  Experimentally this is
490                   // what works correctly with the regexp library.
491                   !(unquoted[ii] & 128)) {
492        result += '\\';        result += '\\';
493          result += unquoted[ii];
494        } else {
495          result += unquoted[ii];
496      }      }
     result += unquoted[ii];  
497    }    }
498    
499    return result;    return result;
# Line 472  bool RE::Extract(const StringPiece& rewr Line 504  bool RE::Extract(const StringPiece& rewr
504  int RE::TryMatch(const StringPiece& text,  int RE::TryMatch(const StringPiece& text,
505                   int startpos,                   int startpos,
506                   Anchor anchor,                   Anchor anchor,
507                     bool empty_ok,
508                   int *vec,                   int *vec,
509                   int vecsize) const {                   int vecsize) const {
510    pcre* re = (anchor == ANCHOR_BOTH) ? re_full_ : re_partial_;    pcre* re = (anchor == ANCHOR_BOTH) ? re_full_ : re_partial_;
# Line 489  int RE::TryMatch(const StringPiece& text Line 522  int RE::TryMatch(const StringPiece& text
522      extra.flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;      extra.flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
523      extra.match_limit_recursion = options_.match_limit_recursion();      extra.match_limit_recursion = options_.match_limit_recursion();
524    }    }
525    
526      int options = 0;
527      if (anchor != UNANCHORED)
528        options |= PCRE_ANCHORED;
529      if (!empty_ok)
530        options |= PCRE_NOTEMPTY;
531    
532    int rc = pcre_exec(re,              // The regular expression object    int rc = pcre_exec(re,              // The regular expression object
533                       &extra,                       &extra,
534                       (text.data() == NULL) ? "" : text.data(),                       (text.data() == NULL) ? "" : text.data(),
535                       text.size(),                       text.size(),
536                       startpos,                       startpos,
537                       (anchor == UNANCHORED) ? 0 : PCRE_ANCHORED,                       options,
538                       vec,                       vec,
539                       vecsize);                       vecsize);
540    
# Line 524  bool RE::DoMatchImpl(const StringPiece& Line 564  bool RE::DoMatchImpl(const StringPiece&
564                       int* vec,                       int* vec,
565                       int vecsize) const {                       int vecsize) const {
566    assert((1 + n) * 3 <= vecsize);  // results + PCRE workspace    assert((1 + n) * 3 <= vecsize);  // results + PCRE workspace
567    int matches = TryMatch(text, 0, anchor, vec, vecsize);    int matches = TryMatch(text, 0, anchor, true, vec, vecsize);
568    assert(matches >= 0);  // TryMatch never returns negatives    assert(matches >= 0);  // TryMatch never returns negatives
569    if (matches == 0)    if (matches == 0)
570      return false;      return false;
# Line 566  bool RE::DoMatch(const StringPiece& text Line 606  bool RE::DoMatch(const StringPiece& text
606                                         // (as for kVecSize)                                         // (as for kVecSize)
607    int space[21];   // use stack allocation for small vecsize (common case)    int space[21];   // use stack allocation for small vecsize (common case)
608    int* vec = vecsize <= 21 ? space : new int[vecsize];    int* vec = vecsize <= 21 ? space : new int[vecsize];
609    bool retval = DoMatchImpl(text, anchor, consumed, args, n, vec, vecsize);    bool retval = DoMatchImpl(text, anchor, consumed, args, n, vec, (int)vecsize);
610    if (vec != space) delete [] vec;    if (vec != space) delete [] vec;
611    return retval;    return retval;
612  }  }
# Line 589  bool RE::Rewrite(string *out, const Stri Line 629  bool RE::Rewrite(string *out, const Stri
629          if (start >= 0)          if (start >= 0)
630            out->append(text.data() + start, vec[2 * n + 1] - start);            out->append(text.data() + start, vec[2 * n + 1] - start);
631        } else if (c == '\\') {        } else if (c == '\\') {
632          out->push_back('\\');          *out += '\\';
633        } else {        } else {
634          //fprintf(stderr, "invalid rewrite pattern: %.*s\n",          //fprintf(stderr, "invalid rewrite pattern: %.*s\n",
635          //        rewrite.size(), rewrite.data());          //        rewrite.size(), rewrite.data());
636          return false;          return false;
637        }        }
638      } else {      } else {
639        out->push_back(c);        *out += c;
640      }      }
641    }    }
642    return true;    return true;
# Line 624  bool Arg::parse_null(const char* str, in Line 664  bool Arg::parse_null(const char* str, in
664  }  }
665    
666  bool Arg::parse_string(const char* str, int n, void* dest) {  bool Arg::parse_string(const char* str, int n, void* dest) {
667      if (dest == NULL) return true;
668    reinterpret_cast<string*>(dest)->assign(str, n);    reinterpret_cast<string*>(dest)->assign(str, n);
669    return true;    return true;
670  }  }
671    
672  bool Arg::parse_stringpiece(const char* str, int n, void* dest) {  bool Arg::parse_stringpiece(const char* str, int n, void* dest) {
673      if (dest == NULL) return true;
674    reinterpret_cast<StringPiece*>(dest)->set(str, n);    reinterpret_cast<StringPiece*>(dest)->set(str, n);
675    return true;    return true;
676  }  }
677    
678  bool Arg::parse_char(const char* str, int n, void* dest) {  bool Arg::parse_char(const char* str, int n, void* dest) {
679    if (n != 1) return false;    if (n != 1) return false;
680      if (dest == NULL) return true;
681    *(reinterpret_cast<char*>(dest)) = str[0];    *(reinterpret_cast<char*>(dest)) = str[0];
682    return true;    return true;
683  }  }
684    
685  bool Arg::parse_uchar(const char* str, int n, void* dest) {  bool Arg::parse_uchar(const char* str, int n, void* dest) {
686    if (n != 1) return false;    if (n != 1) return false;
687      if (dest == NULL) return true;
688    *(reinterpret_cast<unsigned char*>(dest)) = str[0];    *(reinterpret_cast<unsigned char*>(dest)) = str[0];
689    return true;    return true;
690  }  }
# Line 689  bool Arg::parse_long_radix(const char* s Line 733  bool Arg::parse_long_radix(const char* s
733    long r = strtol(str, &end, radix);    long r = strtol(str, &end, radix);
734    if (end != str + n) return false;   // Leftover junk    if (end != str + n) return false;   // Leftover junk
735    if (errno) return false;    if (errno) return false;
736      if (dest == NULL) return true;
737    *(reinterpret_cast<long*>(dest)) = r;    *(reinterpret_cast<long*>(dest)) = r;
738    return true;    return true;
739  }  }
# Line 706  bool Arg::parse_ulong_radix(const char* Line 751  bool Arg::parse_ulong_radix(const char*
751    unsigned long r = strtoul(str, &end, radix);    unsigned long r = strtoul(str, &end, radix);
752    if (end != str + n) return false;   // Leftover junk    if (end != str + n) return false;   // Leftover junk
753    if (errno) return false;    if (errno) return false;
754      if (dest == NULL) return true;
755    *(reinterpret_cast<unsigned long*>(dest)) = r;    *(reinterpret_cast<unsigned long*>(dest)) = r;
756    return true;    return true;
757  }  }
# Line 717  bool Arg::parse_short_radix(const char* Line 763  bool Arg::parse_short_radix(const char*
763    long r;    long r;
764    if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse    if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse
765    if (r < SHRT_MIN || r > SHRT_MAX) return false;       // Out of range    if (r < SHRT_MIN || r > SHRT_MAX) return false;       // Out of range
766    *(reinterpret_cast<short*>(dest)) = r;    if (dest == NULL) return true;
767      *(reinterpret_cast<short*>(dest)) = static_cast<short>(r);
768    return true;    return true;
769  }  }
770    
# Line 728  bool Arg::parse_ushort_radix(const char* Line 775  bool Arg::parse_ushort_radix(const char*
775    unsigned long r;    unsigned long r;
776    if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse    if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse
777    if (r > USHRT_MAX) return false;                      // Out of range    if (r > USHRT_MAX) return false;                      // Out of range
778    *(reinterpret_cast<unsigned short*>(dest)) = r;    if (dest == NULL) return true;
779      *(reinterpret_cast<unsigned short*>(dest)) = static_cast<unsigned short>(r);
780    return true;    return true;
781  }  }
782    
# Line 739  bool Arg::parse_int_radix(const char* st Line 787  bool Arg::parse_int_radix(const char* st
787    long r;    long r;
788    if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse    if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse
789    if (r < INT_MIN || r > INT_MAX) return false;         // Out of range    if (r < INT_MIN || r > INT_MAX) return false;         // Out of range
790      if (dest == NULL) return true;
791    *(reinterpret_cast<int*>(dest)) = r;    *(reinterpret_cast<int*>(dest)) = r;
792    return true;    return true;
793  }  }
# Line 750  bool Arg::parse_uint_radix(const char* s Line 799  bool Arg::parse_uint_radix(const char* s
799    unsigned long r;    unsigned long r;
800    if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse    if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse
801    if (r > UINT_MAX) return false;                       // Out of range    if (r > UINT_MAX) return false;                       // Out of range
802      if (dest == NULL) return true;
803    *(reinterpret_cast<unsigned int*>(dest)) = r;    *(reinterpret_cast<unsigned int*>(dest)) = r;
804    return true;    return true;
805  }  }
# Line 770  bool Arg::parse_longlong_radix(const cha Line 820  bool Arg::parse_longlong_radix(const cha
820    long long r = strtoq(str, &end, radix);    long long r = strtoq(str, &end, radix);
821  #elif defined HAVE_STRTOLL  #elif defined HAVE_STRTOLL
822    long long r = strtoll(str, &end, radix);    long long r = strtoll(str, &end, radix);
823    #elif defined HAVE__STRTOI64
824      long long r = _strtoi64(str, &end, radix);
825    #elif defined HAVE_STRTOIMAX
826      long long r = strtoimax(str, &end, radix);
827  #else  #else
828  #error parse_longlong_radix: cannot convert input to a long-long  #error parse_longlong_radix: cannot convert input to a long-long
829  #endif  #endif
830    if (end != str + n) return false;   // Leftover junk    if (end != str + n) return false;   // Leftover junk
831    if (errno) return false;    if (errno) return false;
832      if (dest == NULL) return true;
833    *(reinterpret_cast<long long*>(dest)) = r;    *(reinterpret_cast<long long*>(dest)) = r;
834    return true;    return true;
835  #endif   /* HAVE_LONG_LONG */  #endif   /* HAVE_LONG_LONG */
# Line 797  bool Arg::parse_ulonglong_radix(const ch Line 852  bool Arg::parse_ulonglong_radix(const ch
852    unsigned long long r = strtouq(str, &end, radix);    unsigned long long r = strtouq(str, &end, radix);
853  #elif defined HAVE_STRTOLL  #elif defined HAVE_STRTOLL
854    unsigned long long r = strtoull(str, &end, radix);    unsigned long long r = strtoull(str, &end, radix);
855    #elif defined HAVE__STRTOI64
856      unsigned long long r = _strtoui64(str, &end, radix);
857    #elif defined HAVE_STRTOIMAX
858      unsigned long long r = strtoumax(str, &end, radix);
859  #else  #else
860  #error parse_ulonglong_radix: cannot convert input to a long-long  #error parse_ulonglong_radix: cannot convert input to a long-long
861  #endif  #endif
862    if (end != str + n) return false;   // Leftover junk    if (end != str + n) return false;   // Leftover junk
863    if (errno) return false;    if (errno) return false;
864      if (dest == NULL) return true;
865    *(reinterpret_cast<unsigned long long*>(dest)) = r;    *(reinterpret_cast<unsigned long long*>(dest)) = r;
866    return true;    return true;
867  #endif   /* HAVE_UNSIGNED_LONG_LONG */  #endif   /* HAVE_UNSIGNED_LONG_LONG */
# Line 819  bool Arg::parse_double(const char* str, Line 879  bool Arg::parse_double(const char* str,
879    double r = strtod(buf, &end);    double r = strtod(buf, &end);
880    if (end != buf + n) return false;   // Leftover junk    if (end != buf + n) return false;   // Leftover junk
881    if (errno) return false;    if (errno) return false;
882      if (dest == NULL) return true;
883    *(reinterpret_cast<double*>(dest)) = r;    *(reinterpret_cast<double*>(dest)) = r;
884    return true;    return true;
885  }  }
# Line 826  bool Arg::parse_double(const char* str, Line 887  bool Arg::parse_double(const char* str,
887  bool Arg::parse_float(const char* str, int n, void* dest) {  bool Arg::parse_float(const char* str, int n, void* dest) {
888    double r;    double r;
889    if (!parse_double(str, n, &r)) return false;    if (!parse_double(str, n, &r)) return false;
890      if (dest == NULL) return true;
891    *(reinterpret_cast<float*>(dest)) = static_cast<float>(r);    *(reinterpret_cast<float*>(dest)) = static_cast<float>(r);
892    return true;    return true;
893  }  }

Legend:
Removed from v.253  
changed lines
  Added in v.594

  ViewVC Help
Powered by ViewVC 1.1.5