1 /*************************************************************************** 2 Copyright (C) 2002-2009 Robby Stephenson <robby@periapsis.org> 3 ***************************************************************************/ 4 5 /*************************************************************************** 6 * * 7 * This program is free software; you can redistribute it and/or * 8 * modify it under the terms of the GNU General Public License as * 9 * published by the Free Software Foundation; either version 2 of * 10 * the License or (at your option) version 3 or any later version * 11 * accepted by the membership of KDE e.V. (or its successor approved * 12 * by the membership of KDE e.V.), which shall act as a proxy * 13 * defined in Section 14 of version 3 of the license. * 14 * * 15 * This program is distributed in the hope that it will be useful, * 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 18 * GNU General Public License for more details. * 19 * * 20 * You should have received a copy of the GNU General Public License * 21 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 22 * * 23 ***************************************************************************/ 24 25 #ifndef TELLICO_ISBNVALIDATOR_H 26 #define TELLICO_ISBNVALIDATOR_H 27 28 #include <QValidator> 29 30 namespace Tellico { 31 32 /** 33 * @author Robby Stephenson 34 * 35 * @see https://web.archive.org/web/20130126042049/http://www.isbn.org/standards/home/isbn/international/hyphenation-instructions.asp 36 * @see https://www.eblong.com/zarf/bookscan/ 37 * @see https://doc.qt.io/archives/qq/qq01-seriously-weird-qregexp.html 38 */ 39 class ISBNValidator : public QValidator { 40 Q_OBJECT 41 42 public: 43 ISBNValidator(QObject* parent = nullptr); 44 45 /** 46 * Certain conditions are checked. Character, length and position 47 * restrictions are checked. Certain cases where the user is deleting 48 * characters are caught and compensated for. The string is then passed to 49 * @ref fixup. Finally, the text is @ref Valid if it is a certain length and 50 * @ref Intermediate if not. 51 * 52 * @param input The text to validate 53 * @param pos The position of the cursor 54 * @return The condition of the text 55 */ 56 virtual QValidator::State validate(QString& input, int& pos) const Q_DECL_OVERRIDE; 57 58 /** 59 * The input string is examined. Hyphens are inserted appropriately, 60 * and the checksum is calculated. 61 * 62 * For correct presentation, the 10 digits of an ISBN must 63 * be divided, by hyphens, into four parts: 64 * @li Part 1: The country or group of countries identifier 65 * @li Part 2: The publisher identifier 66 * @li Part 3: The title identifier 67 * @li Part 4: The check digit 68 * For details 69 * @see https://web.archive.org/web/20130126042049/http://www.isbn.org/standards/home/isbn/international/hyphenation-instructions.asp 70 * For details on ranges 71 * @see https://www.isbn-international.org/range_file_generation 72 * For info on group codes 73 * @see https://web.archive.org/web/20030609050408/http://www.isbn.spk-berlin.de/html/prefix/allpref.htm 74 * For info on French language publisher codes 75 * @see https://www.afnil.org/ 76 * <pre> 77 * Group Identifiers First Hyphen After 78 * ----------------------------------------- 79 * 0........7 1st digit 80 * 80.......94 2nd " 81 * 950......993 3rd " 82 * 9940.....9989 4th " 83 * 99900....99999 5th " 84 * 85 * Group Insert Hyphens 86 * Identifier "0" After 87 * ----------------------------------------- 88 * 00.......19 1st 3rd 9th digit 89 * 200......699 " 4th " 90 * 7000.....8499 " 5th " 91 * 85000....89999 " 6th " 92 * 900000...949999 " 7th " 93 * 9500000..9999999 " 8th " 94 * 95 * 96 * Group Insert Hyphens 97 * Identifier "1" After 98 * ---------------------------------------- 99 * 0........54999 illegal 100 * 55000....86979 1st 6th 9th digit 101 * 869800...998999 " 7th " 102 * 9990000..9999999 " 8th " 103 * 104 * 105 * Group Insert Hyphens 106 * Identifier "2" After 107 * ----------------------------------------- 108 * 00.......19 1st 3rd 9th digit 109 * 200......349 " 4th " 110 * 34000....39999 " 6th " 111 * 400......699 " 4th " 112 * 7000.....8399 " 5th " 113 * 84000....89999 " 6th " 114 * 900000...949999 " 7th " 115 * 9500000..9999999 " 8th " 116 * 117 * The position of the hyphens are determined by the publisher 118 * prefix range established by each national agency in accordance 119 * with the industry needs. The knowledge of the prefix ranges for 120 * each country or group of countries is necessary to develop the 121 * hyphenation output program. For groups 3 through 99999, the hyphenation 122 * rules are currently unknown. So just leave out the hyphen between 123 * the publisher and title for now, but allow it if the user inserts it. 124 * </pre> 125 * 126 * @param input The raw string, hyphens included 127 */ 128 virtual void fixup(QString& input) const Q_DECL_OVERRIDE; 129 130 static void staticFixup(QString& input); 131 static void fixup10(QString& input); 132 static void fixup13(QString& input); 133 134 static QString isbn10(QString isbn13); 135 static QString isbn13(QString isbn10); 136 static QString cleanValue(QString isbn); 137 // returns the values in list1 that are not in list2 138 static QStringList listDifference(const QStringList& list1, const QStringList& list2); 139 140 private: 141 static struct isbn_band { 142 unsigned long MaxValue; 143 int First; 144 int Mid; 145 int Last; 146 } bands[]; 147 148 QValidator::State validate10(QString& input, int& pos) const; 149 QValidator::State validate13(QString& input, int& pos) const; 150 151 /** 152 * This function calculates and returns the ISBN checksum. The 153 * algorithm is based on some code by Andrew Plotkin, available at 154 * https://www.eblong.com/zarf/bookscan/ 155 * 156 * @see https://www.eblong.com/zarf/bookscan/ 157 * 158 * @param input The raw string, with no hyphens 159 */ 160 static QChar checkSum10(const QString& input); 161 static QChar checkSum13(const QString& input); 162 }; 163 164 class ISBNComparison { 165 public: 166 bool operator()(const QString& value1, const QString& value2) const; 167 }; 168 169 } // end namespace 170 #endif 171