blob: 466c02aff02944cdd7fc3204cae5f4605129c148 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/*
2 * qrencode - QR Code encoder
3 *
4 * Copyright (C) 2006-2012 Kentaro Fukuchi <kentaro@fukuchi.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "config.h"
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <errno.h>
26
27#include "qrencode.h"
28#include "qrspec.h"
29#include "mqrspec.h"
30#include "bitstream.h"
31#include "qrinput.h"
32#include "rscode.h"
33#include "split.h"
34#include "mask.h"
35#include "mmask.h"
36
37/******************************************************************************
38 * Raw code
39 *****************************************************************************/
40
41typedef struct {
42 int dataLength;
43 unsigned char *data;
44 int eccLength;
45 unsigned char *ecc;
46} RSblock;
47
48typedef struct {
49 int version;
50 int dataLength;
51 int eccLength;
52 unsigned char *datacode;
53 unsigned char *ecccode;
54 int b1;
55 int blocks;
56 RSblock *rsblock;
57 int count;
58} QRRawCode;
59
60static void RSblock_initBlock(RSblock *block, int dl, unsigned char *data, int el, unsigned char *ecc, RS *rs)
61{
62 block->dataLength = dl;
63 block->data = data;
64 block->eccLength = el;
65 block->ecc = ecc;
66
67 encode_rs_char(rs, data, ecc);
68}
69
70static int RSblock_init(RSblock *blocks, int spec[5], unsigned char *data, unsigned char *ecc)
71{
72 int i;
73 RSblock *block;
74 unsigned char *dp, *ep;
75 RS *rs;
76 int el, dl;
77
78 dl = QRspec_rsDataCodes1(spec);
79 el = QRspec_rsEccCodes1(spec);
80 rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el);
81 if(rs == NULL) return -1;
82
83 block = blocks;
84 dp = data;
85 ep = ecc;
86 for(i=0; i<QRspec_rsBlockNum1(spec); i++) {
87 RSblock_initBlock(block, dl, dp, el, ep, rs);
88 dp += dl;
89 ep += el;
90 block++;
91 }
92
93 if(QRspec_rsBlockNum2(spec) == 0) return 0;
94
95 dl = QRspec_rsDataCodes2(spec);
96 el = QRspec_rsEccCodes2(spec);
97 rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el);
98 if(rs == NULL) return -1;
99 for(i=0; i<QRspec_rsBlockNum2(spec); i++) {
100 RSblock_initBlock(block, dl, dp, el, ep, rs);
101 dp += dl;
102 ep += el;
103 block++;
104 }
105
106 return 0;
107}
108
109static void QRraw_free(QRRawCode *raw);
110static QRRawCode *QRraw_new(QRinput *input)
111{
112 QRRawCode *raw;
113 int spec[5], ret;
114
115 raw = (QRRawCode *)malloc(sizeof(QRRawCode));
116 if(raw == NULL) return NULL;
117
118 raw->datacode = QRinput_getByteStream(input);
119 if(raw->datacode == NULL) {
120 free(raw);
121 return NULL;
122 }
123
124 QRspec_getEccSpec(input->version, input->level, spec);
125
126 raw->version = input->version;
127 raw->b1 = QRspec_rsBlockNum1(spec);
128 raw->dataLength = QRspec_rsDataLength(spec);
129 raw->eccLength = QRspec_rsEccLength(spec);
130 raw->ecccode = (unsigned char *)malloc(raw->eccLength);
131 if(raw->ecccode == NULL) {
132 free(raw->datacode);
133 free(raw);
134 return NULL;
135 }
136
137 raw->blocks = QRspec_rsBlockNum(spec);
138 raw->rsblock = (RSblock *)calloc(raw->blocks, sizeof(RSblock));
139 if(raw->rsblock == NULL) {
140 QRraw_free(raw);
141 return NULL;
142 }
143 ret = RSblock_init(raw->rsblock, spec, raw->datacode, raw->ecccode);
144 if(ret < 0) {
145 QRraw_free(raw);
146 return NULL;
147 }
148
149 raw->count = 0;
150
151 return raw;
152}
153
154/**
155 * Return a code (byte).
156 * This function can be called iteratively.
157 * @param raw raw code.
158 * @return code
159 */
160static unsigned char QRraw_getCode(QRRawCode *raw)
161{
162 int col, row;
163 unsigned char ret;
164
165 if(raw->count < raw->dataLength) {
166 row = raw->count % raw->blocks;
167 col = raw->count / raw->blocks;
168 if(col >= raw->rsblock[0].dataLength) {
169 row += raw->b1;
170 }
171 ret = raw->rsblock[row].data[col];
172 } else if(raw->count < raw->dataLength + raw->eccLength) {
173 row = (raw->count - raw->dataLength) % raw->blocks;
174 col = (raw->count - raw->dataLength) / raw->blocks;
175 ret = raw->rsblock[row].ecc[col];
176 } else {
177 return 0;
178 }
179 raw->count++;
180 return ret;
181}
182
183static void QRraw_free(QRRawCode *raw)
184{
185 if(raw != NULL) {
186 free(raw->datacode);
187 free(raw->ecccode);
188 free(raw->rsblock);
189 free(raw);
190 }
191}
192
193/******************************************************************************
194 * Raw code for Micro QR Code
195 *****************************************************************************/
196
197typedef struct {
198 int version;
199 int dataLength;
200 int eccLength;
201 unsigned char *datacode;
202 unsigned char *ecccode;
203 RSblock *rsblock;
204 int oddbits;
205 int count;
206} MQRRawCode;
207
208static void MQRraw_free(MQRRawCode *raw);
209static MQRRawCode *MQRraw_new(QRinput *input)
210{
211 MQRRawCode *raw;
212 RS *rs;
213
214 raw = (MQRRawCode *)malloc(sizeof(MQRRawCode));
215 if(raw == NULL) return NULL;
216
217 raw->version = input->version;
218 raw->dataLength = MQRspec_getDataLength(input->version, input->level);
219 raw->eccLength = MQRspec_getECCLength(input->version, input->level);
220 raw->oddbits = raw->dataLength * 8 - MQRspec_getDataLengthBit(input->version, input->level);
221 raw->datacode = QRinput_getByteStream(input);
222 if(raw->datacode == NULL) {
223 free(raw);
224 return NULL;
225 }
226 raw->ecccode = (unsigned char *)malloc(raw->eccLength);
227 if(raw->ecccode == NULL) {
228 free(raw->datacode);
229 free(raw);
230 return NULL;
231 }
232
233 raw->rsblock = (RSblock *)calloc(1, sizeof(RSblock));
234 if(raw->rsblock == NULL) {
235 MQRraw_free(raw);
236 return NULL;
237 }
238
239 rs = init_rs(8, 0x11d, 0, 1, raw->eccLength, 255 - raw->dataLength - raw->eccLength);
240 if(rs == NULL) {
241 MQRraw_free(raw);
242 return NULL;
243 }
244
245 RSblock_initBlock(raw->rsblock, raw->dataLength, raw->datacode, raw->eccLength, raw->ecccode, rs);
246
247 raw->count = 0;
248
249 return raw;
250}
251
252/**
253 * Return a code (byte).
254 * This function can be called iteratively.
255 * @param raw raw code.
256 * @return code
257 */
258static unsigned char MQRraw_getCode(MQRRawCode *raw)
259{
260 unsigned char ret;
261
262 if(raw->count < raw->dataLength) {
263 ret = raw->datacode[raw->count];
264 } else if(raw->count < raw->dataLength + raw->eccLength) {
265 ret = raw->ecccode[raw->count - raw->dataLength];
266 } else {
267 return 0;
268 }
269 raw->count++;
270 return ret;
271}
272
273static void MQRraw_free(MQRRawCode *raw)
274{
275 if(raw != NULL) {
276 free(raw->datacode);
277 free(raw->ecccode);
278 free(raw->rsblock);
279 free(raw);
280 }
281}
282
283
284/******************************************************************************
285 * Frame filling
286 *****************************************************************************/
287
288typedef struct {
289 int width;
290 unsigned char *frame;
291 int x, y;
292 int dir;
293 int bit;
294 int mqr;
295} FrameFiller;
296
297static FrameFiller *FrameFiller_new(int width, unsigned char *frame, int mqr)
298{
299 FrameFiller *filler;
300
301 filler = (FrameFiller *)malloc(sizeof(FrameFiller));
302 if(filler == NULL) return NULL;
303 filler->width = width;
304 filler->frame = frame;
305 filler->x = width - 1;
306 filler->y = width - 1;
307 filler->dir = -1;
308 filler->bit = -1;
309 filler->mqr = mqr;
310
311 return filler;
312}
313
314static unsigned char *FrameFiller_next(FrameFiller *filler)
315{
316 unsigned char *p;
317 int x, y, w;
318
319 if(filler->bit == -1) {
320 filler->bit = 0;
321 return filler->frame + filler->y * filler->width + filler->x;
322 }
323
324 x = filler->x;
325 y = filler->y;
326 p = filler->frame;
327 w = filler->width;
328
329 if(filler->bit == 0) {
330 x--;
331 filler->bit++;
332 } else {
333 x++;
334 y += filler->dir;
335 filler->bit--;
336 }
337
338 if(filler->dir < 0) {
339 if(y < 0) {
340 y = 0;
341 x -= 2;
342 filler->dir = 1;
343 if(!filler->mqr && x == 6) {
344 x--;
345 y = 9;
346 }
347 }
348 } else {
349 if(y == w) {
350 y = w - 1;
351 x -= 2;
352 filler->dir = -1;
353 if(!filler->mqr && x == 6) {
354 x--;
355 y -= 8;
356 }
357 }
358 }
359 if(x < 0 || y < 0) return NULL;
360
361 filler->x = x;
362 filler->y = y;
363
364 if(p[y * w + x] & 0x80) {
365 // This tail recursion could be optimized.
366 return FrameFiller_next(filler);
367 }
368 return &p[y * w + x];
369}
370
371#ifdef WITH_TESTS
372extern unsigned char *FrameFiller_test(int version)
373{
374 int width;
375 unsigned char *frame, *p;
376 FrameFiller *filler;
377 int i, length;
378
379 width = QRspec_getWidth(version);
380 frame = QRspec_newFrame(version);
381 if(frame == NULL) return NULL;
382 filler = FrameFiller_new(width, frame, 0);
383 if(filler == NULL) {
384 free(frame);
385 return NULL;
386 }
387 length = QRspec_getDataLength(version, QR_ECLEVEL_L) * 8
388 + QRspec_getECCLength(version, QR_ECLEVEL_L) * 8
389 + QRspec_getRemainder(version);
390 for(i=0; i<length; i++) {
391 p = FrameFiller_next(filler);
392 if(p == NULL) {
393 free(filler);
394 free(frame);
395 return NULL;
396 }
397 *p = (unsigned char)(i & 0x7f) | 0x80;
398 }
399 free(filler);
400 return frame;
401}
402
403extern unsigned char *FrameFiller_testMQR(int version)
404{
405 int width;
406 unsigned char *frame, *p;
407 FrameFiller *filler;
408 int i, length;
409
410 width = MQRspec_getWidth(version);
411 frame = MQRspec_newFrame(version);
412 if(frame == NULL) return NULL;
413 filler = FrameFiller_new(width, frame, 1);
414 if(filler == NULL) {
415 free(frame);
416 return NULL;
417 }
418 length = MQRspec_getDataLengthBit(version, QR_ECLEVEL_L)
419 + MQRspec_getECCLength(version, QR_ECLEVEL_L) * 8;
420 for(i=0; i<length; i++) {
421 p = FrameFiller_next(filler);
422 if(p == NULL) {
423 fprintf(stderr, "Frame filler run over the frame!\n");
424 free(filler);
425 return frame;
426 }
427 *p = (unsigned char)(i & 0x7f) | 0x80;
428 }
429 free(filler);
430 return frame;
431}
432#endif
433
434
435/******************************************************************************
436 * QR-code encoding
437 *****************************************************************************/
438
439static QRcode *QRcode_new(int version, int width, unsigned char *data)
440{
441 QRcode *qrcode;
442
443 qrcode = (QRcode *)malloc(sizeof(QRcode));
444 if(qrcode == NULL) return NULL;
445
446 qrcode->version = version;
447 qrcode->width = width;
448 qrcode->data = data;
449
450 return qrcode;
451}
452
453void QRcode_free(QRcode *qrcode)
454{
455 if(qrcode != NULL) {
456 free(qrcode->data);
457 free(qrcode);
458 }
459}
460
461static QRcode *QRcode_encodeMask(QRinput *input, int mask)
462{
463 int width, version;
464 QRRawCode *raw;
465 unsigned char *frame, *masked, *p, code, bit;
466 FrameFiller *filler;
467 int i, j;
468 QRcode *qrcode = NULL;
469
470 if(input->mqr) {
471 errno = EINVAL;
472 return NULL;
473 }
474 if(input->version < 0 || input->version > QRSPEC_VERSION_MAX) {
475 errno = EINVAL;
476 return NULL;
477 }
478 if(input->level > QR_ECLEVEL_H) {
479 errno = EINVAL;
480 return NULL;
481 }
482
483 raw = QRraw_new(input);
484 if(raw == NULL) return NULL;
485
486 version = raw->version;
487 width = QRspec_getWidth(version);
488 frame = QRspec_newFrame(version);
489 if(frame == NULL) {
490 QRraw_free(raw);
491 return NULL;
492 }
493 filler = FrameFiller_new(width, frame, 0);
494 if(filler == NULL) {
495 QRraw_free(raw);
496 free(frame);
497 return NULL;
498 }
499
500 /* inteleaved data and ecc codes */
501 for(i=0; i<raw->dataLength + raw->eccLength; i++) {
502 code = QRraw_getCode(raw);
503 bit = 0x80;
504 for(j=0; j<8; j++) {
505 p = FrameFiller_next(filler);
506 if(p == NULL) goto EXIT;
507 *p = 0x02 | ((bit & code) != 0);
508 bit = bit >> 1;
509 }
510 }
511 QRraw_free(raw);
512 raw = NULL;
513 /* remainder bits */
514 j = QRspec_getRemainder(version);
515 for(i=0; i<j; i++) {
516 p = FrameFiller_next(filler);
517 if(p == NULL) goto EXIT;
518 *p = 0x02;
519 }
520
521 /* masking */
522 if(mask == -2) { // just for debug purpose
523 masked = (unsigned char *)malloc(width * width);
524 memcpy(masked, frame, width * width);
525 } else if(mask < 0) {
526 masked = Mask_mask(width, frame, input->level);
527 } else {
528 masked = Mask_makeMask(width, frame, mask, input->level);
529 }
530 if(masked == NULL) {
531 goto EXIT;
532 }
533 qrcode = QRcode_new(version, width, masked);
534
535EXIT:
536 QRraw_free(raw);
537 free(filler);
538 free(frame);
539 return qrcode;
540}
541
542static QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask)
543{
544 int width, version;
545 MQRRawCode *raw;
546 unsigned char *frame, *masked, *p, code, bit;
547 FrameFiller *filler;
548 int i, j;
549 QRcode *qrcode = NULL;
550
551 if(!input->mqr) {
552 errno = EINVAL;
553 return NULL;
554 }
555 if(input->version <= 0 || input->version > MQRSPEC_VERSION_MAX) {
556 errno = EINVAL;
557 return NULL;
558 }
559 if(input->level > QR_ECLEVEL_Q) {
560 errno = EINVAL;
561 return NULL;
562 }
563
564 raw = MQRraw_new(input);
565 if(raw == NULL) return NULL;
566
567 version = raw->version;
568 width = MQRspec_getWidth(version);
569 frame = MQRspec_newFrame(version);
570 if(frame == NULL) {
571 MQRraw_free(raw);
572 return NULL;
573 }
574 filler = FrameFiller_new(width, frame, 1);
575 if(filler == NULL) {
576 MQRraw_free(raw);
577 free(frame);
578 return NULL;
579 }
580
581 /* inteleaved data and ecc codes */
582 for(i=0; i<raw->dataLength + raw->eccLength; i++) {
583 code = MQRraw_getCode(raw);
584 if(raw->oddbits && i == raw->dataLength - 1) {
585 bit = 1 << (raw->oddbits - 1);
586 for(j=0; j<raw->oddbits; j++) {
587 p = FrameFiller_next(filler);
588 if(p == NULL) goto EXIT;
589 *p = 0x02 | ((bit & code) != 0);
590 bit = bit >> 1;
591 }
592 } else {
593 bit = 0x80;
594 for(j=0; j<8; j++) {
595 p = FrameFiller_next(filler);
596 if(p == NULL) goto EXIT;
597 *p = 0x02 | ((bit & code) != 0);
598 bit = bit >> 1;
599 }
600 }
601 }
602 MQRraw_free(raw);
603 raw = NULL;
604
605 /* masking */
606 if(mask < 0) {
607 masked = MMask_mask(version, frame, input->level);
608 } else {
609 masked = MMask_makeMask(version, frame, mask, input->level);
610 }
611 if(masked == NULL) {
612 goto EXIT;
613 }
614
615 qrcode = QRcode_new(version, width, masked);
616
617EXIT:
618 MQRraw_free(raw);
619 free(filler);
620 free(frame);
621 return qrcode;
622}
623
624QRcode *QRcode_encodeInput(QRinput *input)
625{
626 if(input->mqr) {
627 return QRcode_encodeMaskMQR(input, -1);
628 } else {
629 return QRcode_encodeMask(input, -1);
630 }
631}
632
633static QRcode *QRcode_encodeStringReal(const char *string, int version, QRecLevel level, int mqr, QRencodeMode hint, int casesensitive)
634{
635 QRinput *input;
636 QRcode *code;
637 int ret;
638
639 if(string == NULL) {
640 errno = EINVAL;
641 return NULL;
642 }
643 if(hint != QR_MODE_8 && hint != QR_MODE_KANJI) {
644 errno = EINVAL;
645 return NULL;
646 }
647
648 if(mqr) {
649 input = QRinput_newMQR(version, level);
650 } else {
651 input = QRinput_new2(version, level);
652 }
653 if(input == NULL) return NULL;
654
655 ret = Split_splitStringToQRinput(string, input, hint, casesensitive);
656 if(ret < 0) {
657 QRinput_free(input);
658 return NULL;
659 }
660 code = QRcode_encodeInput(input);
661 QRinput_free(input);
662
663 return code;
664}
665
666QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
667{
668 return QRcode_encodeStringReal(string, version, level, 0, hint, casesensitive);
669}
670
671QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
672{
673 return QRcode_encodeStringReal(string, version, level, 1, hint, casesensitive);
674}
675
676static QRcode *QRcode_encodeDataReal(const unsigned char *data, int length, int version, QRecLevel level, int mqr)
677{
678 QRinput *input;
679 QRcode *code;
680 int ret;
681
682 if(data == NULL || length == 0) {
683 errno = EINVAL;
684 return NULL;
685 }
686
687 if(mqr) {
688 input = QRinput_newMQR(version, level);
689 } else {
690 input = QRinput_new2(version, level);
691 }
692 if(input == NULL) return NULL;
693
694 ret = QRinput_append(input, QR_MODE_8, length, data);
695 if(ret < 0) {
696 QRinput_free(input);
697 return NULL;
698 }
699 code = QRcode_encodeInput(input);
700 QRinput_free(input);
701
702 return code;
703}
704
705QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level)
706{
707 return QRcode_encodeDataReal(data, size, version, level, 0);
708}
709
710QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level)
711{
712 if(string == NULL) {
713 errno = EINVAL;
714 return NULL;
715 }
716 return QRcode_encodeDataReal((unsigned char *)string, strlen(string), version, level, 0);
717}
718
719QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level)
720{
721 return QRcode_encodeDataReal(data, size, version, level, 1);
722}
723
724QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level)
725{
726 if(string == NULL) {
727 errno = EINVAL;
728 return NULL;
729 }
730 return QRcode_encodeDataReal((unsigned char *)string, strlen(string), version, level, 1);
731}
732
733
734/******************************************************************************
735 * Structured QR-code encoding
736 *****************************************************************************/
737
738static QRcode_List *QRcode_List_newEntry(void)
739{
740 QRcode_List *entry;
741
742 entry = (QRcode_List *)malloc(sizeof(QRcode_List));
743 if(entry == NULL) return NULL;
744
745 entry->next = NULL;
746 entry->code = NULL;
747
748 return entry;
749}
750
751static void QRcode_List_freeEntry(QRcode_List *entry)
752{
753 if(entry != NULL) {
754 QRcode_free(entry->code);
755 free(entry);
756 }
757}
758
759void QRcode_List_free(QRcode_List *qrlist)
760{
761 QRcode_List *list = qrlist, *next;
762
763 while(list != NULL) {
764 next = list->next;
765 QRcode_List_freeEntry(list);
766 list = next;
767 }
768}
769
770int QRcode_List_size(QRcode_List *qrlist)
771{
772 QRcode_List *list = qrlist;
773 int size = 0;
774
775 while(list != NULL) {
776 size++;
777 list = list->next;
778 }
779
780 return size;
781}
782
783#if 0
784static unsigned char QRcode_parity(const char *str, int size)
785{
786 unsigned char parity = 0;
787 int i;
788
789 for(i=0; i<size; i++) {
790 parity ^= str[i];
791 }
792
793 return parity;
794}
795#endif
796
797QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s)
798{
799 QRcode_List *head = NULL;
800 QRcode_List *tail = NULL;
801 QRcode_List *entry;
802 QRinput_InputList *list = s->head;
803
804 while(list != NULL) {
805 if(head == NULL) {
806 entry = QRcode_List_newEntry();
807 if(entry == NULL) goto ABORT;
808 head = entry;
809 tail = head;
810 } else {
811 entry = QRcode_List_newEntry();
812 if(entry == NULL) goto ABORT;
813 tail->next = entry;
814 tail = tail->next;
815 }
816 tail->code = QRcode_encodeInput(list->input);
817 if(tail->code == NULL) {
818 goto ABORT;
819 }
820 list = list->next;
821 }
822
823 return head;
824ABORT:
825 QRcode_List_free(head);
826 return NULL;
827}
828
829static QRcode_List *QRcode_encodeInputToStructured(QRinput *input)
830{
831 QRinput_Struct *s;
832 QRcode_List *codes;
833
834 s = QRinput_splitQRinputToStruct(input);
835 if(s == NULL) return NULL;
836
837 codes = QRcode_encodeInputStructured(s);
838 QRinput_Struct_free(s);
839
840 return codes;
841}
842
843static QRcode_List *QRcode_encodeDataStructuredReal(
844 int size, const unsigned char *data,
845 int version, QRecLevel level,
846 int eightbit, QRencodeMode hint, int casesensitive)
847{
848 QRinput *input;
849 QRcode_List *codes;
850 int ret;
851
852 if(version <= 0) {
853 errno = EINVAL;
854 return NULL;
855 }
856 if(!eightbit && (hint != QR_MODE_8 && hint != QR_MODE_KANJI)) {
857 errno = EINVAL;
858 return NULL;
859 }
860
861 input = QRinput_new2(version, level);
862 if(input == NULL) return NULL;
863
864 if(eightbit) {
865 ret = QRinput_append(input, QR_MODE_8, size, data);
866 } else {
867 ret = Split_splitStringToQRinput((char *)data, input, hint, casesensitive);
868 }
869 if(ret < 0) {
870 QRinput_free(input);
871 return NULL;
872 }
873 codes = QRcode_encodeInputToStructured(input);
874 QRinput_free(input);
875
876 return codes;
877}
878
879QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level) {
880 return QRcode_encodeDataStructuredReal(size, data, version, level, 1, QR_MODE_NUL, 0);
881}
882
883QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level) {
884 if(string == NULL) {
885 errno = EINVAL;
886 return NULL;
887 }
888 return QRcode_encodeDataStructured(strlen(string), (unsigned char *)string, version, level);
889}
890
891QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
892{
893 if(string == NULL) {
894 errno = EINVAL;
895 return NULL;
896 }
897 return QRcode_encodeDataStructuredReal(strlen(string), (unsigned char *)string, version, level, 0, hint, casesensitive);
898}
899
900/******************************************************************************
901 * System utilities
902 *****************************************************************************/
903
904void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version)
905{
906 if(major_version != NULL) {
907 *major_version = MAJOR_VERSION;
908 }
909 if(minor_version != NULL) {
910 *minor_version = MINOR_VERSION;
911 }
912 if(micro_version != NULL) {
913 *micro_version = MICRO_VERSION;
914 }
915}
916
917char *QRcode_APIVersionString(void)
918{
919 return VERSION;
920}
921
922void QRcode_clearCache(void)
923{
924 QRspec_clearCache();
925 MQRspec_clearCache();
926 free_rs_cache();
927}