split.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * qrencode - QR Code encoder
  3. *
  4. * Input data splitter.
  5. * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
  6. *
  7. * The following data / specifications are taken from
  8. * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
  9. * or
  10. * "Automatic identification and data capture techniques --
  11. * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
  12. *
  13. * This library is free software; you can redistribute it and/or
  14. * modify it under the terms of the GNU Lesser General Public
  15. * License as published by the Free Software Foundation; either
  16. * version 2.1 of the License, or any later version.
  17. *
  18. * This library is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  21. * Lesser General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU Lesser General Public
  24. * License along with this library; if not, write to the Free Software
  25. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  26. */
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <errno.h>
  30. #include "qrencode.h"
  31. #include "qrinput.h"
  32. #include "qrspec.h"
  33. #include "split.h"
  34. #define isdigit(__c__) ((unsigned char)((signed char)(__c__) - '0') < 10)
  35. #define isalnum(__c__) (QRinput_lookAnTable(__c__) >= 0)
  36. static QRencodeMode Split_identifyMode(const char *string, QRencodeMode hint)
  37. {
  38. unsigned char c, d;
  39. unsigned int word;
  40. c = string[0];
  41. if(c == '\0') return QR_MODE_NUL;
  42. if(isdigit(c)) {
  43. return QR_MODE_NUM;
  44. } else if(isalnum(c)) {
  45. return QR_MODE_AN;
  46. } else if(hint == QR_MODE_KANJI) {
  47. d = string[1];
  48. if(d != '\0') {
  49. word = ((unsigned int)c << 8) | d;
  50. if((word >= 0x8140 && word <= 0x9ffc) || (word >= 0xe040 && word <= 0xebbf)) {
  51. return QR_MODE_KANJI;
  52. }
  53. }
  54. }
  55. return QR_MODE_8;
  56. }
  57. static int Split_eatNum(const char *string, QRinput *input, QRencodeMode hint);
  58. static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint);
  59. static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint);
  60. static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint);
  61. static int Split_eatNum(const char *string, QRinput *input,QRencodeMode hint)
  62. {
  63. const char *p;
  64. int ret;
  65. int run;
  66. int dif;
  67. int ln;
  68. QRencodeMode mode;
  69. ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
  70. p = string;
  71. while(isdigit(*p)) {
  72. p++;
  73. }
  74. run = p - string;
  75. mode = Split_identifyMode(p, hint);
  76. if(mode == QR_MODE_8) {
  77. dif = QRinput_estimateBitsModeNum(run) + 4 + ln
  78. + QRinput_estimateBitsMode8(1) /* + 4 + l8 */
  79. - QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */;
  80. if(dif > 0) {
  81. return Split_eat8(string, input, hint);
  82. }
  83. }
  84. if(mode == QR_MODE_AN) {
  85. dif = QRinput_estimateBitsModeNum(run) + 4 + ln
  86. + QRinput_estimateBitsModeAn(1) /* + 4 + la */
  87. - QRinput_estimateBitsModeAn(run + 1) /* - 4 - la */;
  88. if(dif > 0) {
  89. return Split_eatAn(string, input, hint);
  90. }
  91. }
  92. ret = QRinput_append(input, QR_MODE_NUM, run, (unsigned char *)string);
  93. if(ret < 0) return -1;
  94. return run;
  95. }
  96. static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint)
  97. {
  98. const char *p, *q;
  99. int ret;
  100. int run;
  101. int dif;
  102. int la, ln;
  103. la = QRspec_lengthIndicator(QR_MODE_AN, input->version);
  104. ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
  105. p = string;
  106. while(isalnum(*p)) {
  107. if(isdigit(*p)) {
  108. q = p;
  109. while(isdigit(*q)) {
  110. q++;
  111. }
  112. dif = QRinput_estimateBitsModeAn(p - string) /* + 4 + la */
  113. + QRinput_estimateBitsModeNum(q - p) + 4 + ln
  114. - QRinput_estimateBitsModeAn(q - string) /* - 4 - la */;
  115. if(dif < 0) {
  116. break;
  117. } else {
  118. p = q;
  119. }
  120. } else {
  121. p++;
  122. }
  123. }
  124. run = p - string;
  125. if(*p && !isalnum(*p)) {
  126. dif = QRinput_estimateBitsModeAn(run) + 4 + la
  127. + QRinput_estimateBitsMode8(1) /* + 4 + l8 */
  128. - QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */;
  129. if(dif > 0) {
  130. return Split_eat8(string, input, hint);
  131. }
  132. }
  133. ret = QRinput_append(input, QR_MODE_AN, run, (unsigned char *)string);
  134. if(ret < 0) return -1;
  135. return run;
  136. }
  137. static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint)
  138. {
  139. const char *p;
  140. int ret;
  141. int run;
  142. p = string;
  143. while(Split_identifyMode(p, hint) == QR_MODE_KANJI) {
  144. p += 2;
  145. }
  146. run = p - string;
  147. ret = QRinput_append(input, QR_MODE_KANJI, run, (unsigned char *)string);
  148. if(ret < 0) return -1;
  149. return run;
  150. }
  151. static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint)
  152. {
  153. const char *p, *q;
  154. QRencodeMode mode;
  155. int ret;
  156. int run;
  157. int dif;
  158. int la, ln;
  159. la = QRspec_lengthIndicator(QR_MODE_AN, input->version);
  160. ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
  161. p = string + 1;
  162. while(*p != '\0') {
  163. mode = Split_identifyMode(p, hint);
  164. if(mode == QR_MODE_KANJI) {
  165. break;
  166. }
  167. if(mode == QR_MODE_NUM) {
  168. q = p;
  169. while(isdigit(*q)) {
  170. q++;
  171. }
  172. dif = QRinput_estimateBitsMode8(p - string) /* + 4 + l8 */
  173. + QRinput_estimateBitsModeNum(q - p) + 4 + ln
  174. - QRinput_estimateBitsMode8(q - string) /* - 4 - l8 */;
  175. if(dif < 0) {
  176. break;
  177. } else {
  178. p = q;
  179. }
  180. } else if(mode == QR_MODE_AN) {
  181. q = p;
  182. while(isalnum(*q)) {
  183. q++;
  184. }
  185. dif = QRinput_estimateBitsMode8(p - string) /* + 4 + l8 */
  186. + QRinput_estimateBitsModeAn(q - p) + 4 + la
  187. - QRinput_estimateBitsMode8(q - string) /* - 4 - l8 */;
  188. if(dif < 0) {
  189. break;
  190. } else {
  191. p = q;
  192. }
  193. } else {
  194. p++;
  195. }
  196. }
  197. run = p - string;
  198. ret = QRinput_append(input, QR_MODE_8, run, (unsigned char *)string);
  199. if(ret < 0) return -1;
  200. return run;
  201. }
  202. static int Split_splitString(const char *string, QRinput *input,
  203. QRencodeMode hint)
  204. {
  205. int length;
  206. QRencodeMode mode;
  207. if(*string == '\0') return 0;
  208. mode = Split_identifyMode(string, hint);
  209. if(mode == QR_MODE_NUM) {
  210. length = Split_eatNum(string, input, hint);
  211. } else if(mode == QR_MODE_AN) {
  212. length = Split_eatAn(string, input, hint);
  213. } else if(mode == QR_MODE_KANJI && hint == QR_MODE_KANJI) {
  214. length = Split_eatKanji(string, input, hint);
  215. } else {
  216. length = Split_eat8(string, input, hint);
  217. }
  218. if(length == 0) return 0;
  219. if(length < 0) return -1;
  220. return Split_splitString(&string[length], input, hint);
  221. }
  222. static char *dupAndToUpper(const char *str, QRencodeMode hint)
  223. {
  224. char *newstr, *p;
  225. QRencodeMode mode;
  226. newstr = strdup(str);
  227. if(newstr == NULL) return NULL;
  228. p = newstr;
  229. while(*p != '\0') {
  230. mode = Split_identifyMode(p, hint);
  231. if(mode == QR_MODE_KANJI) {
  232. p += 2;
  233. } else {
  234. if (*p >= 'a' && *p <= 'z') {
  235. *p = (char)((int)*p - 32);
  236. }
  237. p++;
  238. }
  239. }
  240. return newstr;
  241. }
  242. int Split_splitStringToQRinput(const char *string, QRinput *input,
  243. QRencodeMode hint, int casesensitive)
  244. {
  245. char *newstr;
  246. int ret;
  247. if(string == NULL || *string == '\0') {
  248. errno = EINVAL;
  249. return -1;
  250. }
  251. if(!casesensitive) {
  252. newstr = dupAndToUpper(string, hint);
  253. if(newstr == NULL) return -1;
  254. ret = Split_splitString(newstr, input, hint);
  255. free(newstr);
  256. } else {
  257. ret = Split_splitString(string, input, hint);
  258. }
  259. return ret;
  260. }