/************************************************************************************************* * Comparator functions * Copyright (C) 2009-2012 FAL Labs * This file is part of Kyoto Cabinet. * This program is free software: you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by the Free Software Foundation, either version * 3 of the License, or any later version. * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * You should have received a copy of the GNU General Public License along with this program. * If not, see . *************************************************************************************************/ #ifndef _KCCOMPARE_H // duplication check #define _KCCOMPARE_H #include #include namespace kyotocabinet { // common namespace /** * Interfrace of comparator of record keys. */ class Comparator { public: /** * Destructor. */ virtual ~Comparator() {} /** * Compare two keys. * @param akbuf the pointer to the region of one key. * @param aksiz the size of the region of one key. * @param bkbuf the pointer to the region of the other key. * @param bksiz the size of the region of the other key. * @return positive if the former is big, negative if the latter is big, 0 if both are * equivalent. */ virtual int32_t compare(const char* akbuf, size_t aksiz, const char* bkbuf, size_t bksiz) = 0; }; /** * Comparator in the lexical order. */ class LexicalComparator : public Comparator { public: explicit LexicalComparator() {} int32_t compare(const char* akbuf, size_t aksiz, const char* bkbuf, size_t bksiz) { _assert_(akbuf && bkbuf); size_t msiz = aksiz < bksiz ? aksiz : bksiz; for (size_t i = 0; i < msiz; i++) { if (((uint8_t*)akbuf)[i] != ((uint8_t*)bkbuf)[i]) return ((uint8_t*)akbuf)[i] - ((uint8_t*)bkbuf)[i]; } return (int32_t)aksiz - (int32_t)bksiz; } }; /** * Comparator in the lexical descending order. */ class LexicalDescendingComparator : public Comparator { public: explicit LexicalDescendingComparator() : comp_() {} int32_t compare(const char* akbuf, size_t aksiz, const char* bkbuf, size_t bksiz) { return -comp_.compare(akbuf, aksiz, bkbuf, bksiz); } private: LexicalComparator comp_; }; /** * Comparator in the decimal order. */ class DecimalComparator : public Comparator { public: explicit DecimalComparator() {} int32_t compare(const char* akbuf, size_t aksiz, const char* bkbuf, size_t bksiz) { _assert_(akbuf && bkbuf); const int32_t LDBLCOLMAX = 16; const unsigned char* arp = (unsigned char*)akbuf; int32_t alen = aksiz; while (alen > 0 && (*arp <= ' ' || *arp == 0x7f)) { arp++; alen--; } int64_t anum = 0; int32_t asign = 1; if (alen > 0 && *arp == '-') { arp++; alen--; asign = -1; } while (alen > 0) { int32_t c = *arp; if (c < '0' || c > '9') break; anum = anum * 10 + c - '0'; arp++; alen--; } anum *= asign; const unsigned char* brp = (unsigned char*)bkbuf; int32_t blen = bksiz; while (blen > 0 && (*brp <= ' ' || *brp == 0x7f)) { brp++; blen--; } int64_t bnum = 0; int32_t bsign = 1; if (blen > 0 && *brp == '-') { brp++; blen--; bsign = -1; } while (blen > 0) { int32_t c = *brp; if (c < '0' || c > '9') break; bnum = bnum * 10 + c - '0'; brp++; blen--; } bnum *= bsign; if (anum < bnum) return -1; if (anum > bnum) return 1; if ((alen > 1 && *arp == '.') || (blen > 1 && *brp == '.')) { long double aflt = 0; if (alen > 1 && *arp == '.') { arp++; alen--; if (alen > LDBLCOLMAX) alen = LDBLCOLMAX; long double base = 10; while (alen > 0) { if (*arp < '0' || *arp > '9') break; aflt += (*arp - '0') / base; arp++; alen--; base *= 10; } aflt *= asign; } long double bflt = 0; if (blen > 1 && *brp == '.') { brp++; blen--; if (blen > LDBLCOLMAX) blen = LDBLCOLMAX; long double base = 10; while (blen > 0) { if (*brp < '0' || *brp > '9') break; bflt += (*brp - '0') / base; brp++; blen--; base *= 10; } bflt *= bsign; } if (aflt < bflt) return -1; if (aflt > bflt) return 1; } LexicalComparator lexcomp; int32_t rv = lexcomp.compare(akbuf, aksiz, bkbuf, bksiz); return rv; } }; /** * Comparator in the decimal descending order. */ class DecimalDescendingComparator : public Comparator { public: explicit DecimalDescendingComparator() : comp_() {} int32_t compare(const char* akbuf, size_t aksiz, const char* bkbuf, size_t bksiz) { return -comp_.compare(akbuf, aksiz, bkbuf, bksiz); } private: DecimalComparator comp_; }; /** * Prepared pointer of the comparator in the lexical order. */ extern LexicalComparator* const LEXICALCOMP; /** * Prepared pointer of the comparator in the lexical descending order. */ extern LexicalDescendingComparator* const LEXICALDESCCOMP; /** * Prepared pointer of the comparator in the decimal order. */ extern DecimalComparator* const DECIMALCOMP; /** * Prepared pointer of the comparator in the decimal descending order. */ extern DecimalDescendingComparator* const DECIMALDESCCOMP; } // common namespace #endif // duplication check // END OF FILE