Import Upstream version 4.1.1

This commit is contained in:
rtlhq 2022-09-24 21:43:58 +08:00
commit 472578fa9f
82 changed files with 70938 additions and 0 deletions

201
CMakeLists.txt Normal file
View File

@ -0,0 +1,201 @@
cmake_minimum_required(VERSION 3.1.0)
project(QRencode VERSION 4.1.1 LANGUAGES C)
option(WITH_TOOLS "Build utility tools" YES )
option(WITH_TESTS "Build tests" NO )
option(WITHOUT_PNG "Disable PNG support" NO)
option(GPROF "Generate extra code to write profile information" OFF)
option(COVERAGE "Generate extra code to write coverage information" OFF)
option(ASAN "Use AddressSanitizer" OFF)
option(BUILD_SHARED_LIBS "Enable build of shared libraries" NO)
if(BUILD_TESTING)
set(WITH_TESTS ON)
message(DEPRECATION "use WITH_TESTS option instead BUILD_TESTING")
endif()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
set(CMAKE_THREAD_PREFER_PTHREAD ON)
find_package(Threads)
find_package(PNG)
find_package(Iconv)
if(CMAKE_USE_PTHREADS_INIT)
add_definitions(-DHAVE_LIBPTHREAD=1)
# for libqrencode.pc
set(LIBPTHREAD ${CMAKE_THREAD_LIBS_INIT})
endif()
## Check for system include files
include(CheckIncludeFile)
include(CheckFunctionExists)
check_include_file(dlfcn.h HAVE_DLFCN_H )
check_include_file(inttypes.h HAVE_INTTYPES_H)
check_include_file(memory.h HAVE_MEMORY_H )
check_include_file(stdint.h HAVE_STDINT_H )
check_include_file(stdlib.h HAVE_STDLIB_H )
check_include_file(strings.h HAVE_STRINGS_H )
check_include_file(string.h HAVE_STRING_H )
check_include_file(getopt.h HAVE_GETOPT_H )
check_include_file(sys/time.h HAVE_SYS_TIME_H)
check_include_file(time.h HAVE_TIME_H )
check_include_file(pthread.h HAVE_PTHREAD_H )
check_function_exists(strdup HAVE_STRDUP)
if(HAVE_STRDUP)
add_definitions(-DHAVE_STRDUP=1)
endif()
if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
endif()
if(GPROF)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg")
endif()
if(COVERAGE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage")
endif()
if(ASAN)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls")
endif()
add_definitions(-DMAJOR_VERSION=${PROJECT_VERSION_MAJOR})
add_definitions(-DMINOR_VERSION=${PROJECT_VERSION_MINOR})
add_definitions(-DMICRO_VERSION=${PROJECT_VERSION_PATCH})
add_definitions(-DVERSION="${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
add_definitions(-DHAVE_SDL=0)
if(MSVC)
set(CMAKE_DEBUG_POSTFIX "d")
add_definitions(-Dstrcasecmp=_stricmp)
add_definitions(-Dstrncasecmp=_strnicmp)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
if(WITH_TOOLS)
find_path(GETOPT_INCLUDE_DIR getopt.h PATH_SUFFIXES include)
find_library(GETOPT_LIBRARIES getopt PATH_SUFFIXES lib)
include_directories(${GETOPT_INCLUDE_DIR})
endif(WITH_TOOLS)
endif(MSVC)
set(QRENCODE_SRCS qrencode.c
qrinput.c
bitstream.c
qrspec.c
rsecc.c
split.c
mask.c
mqrspec.c
mmask.c)
set(QRENCODE_HDRS qrencode_inner.h
qrinput.h
bitstream.h
qrspec.h
rsecc.h
split.h
mask.h
mqrspec.h
mmask.h)
if(BUILD_SHARED_LIBS)
if(MSVC)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif()
add_library(qrencode SHARED ${QRENCODE_SRCS} ${QRENCODE_HDRS})
set_target_properties(qrencode PROPERTIES VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} SOVERSION ${PROJECT_VERSION_MAJOR})
else()
add_library(qrencode ${QRENCODE_SRCS} ${QRENCODE_HDRS})
endif()
if(CMAKE_USE_PTHREADS_INIT)
target_link_libraries(qrencode Threads::Threads)
endif()
include(GNUInstallDirs)
set(prefix "${CMAKE_INSTALL_PREFIX}")
set(exec_prefix "${CMAKE_INSTALL_FULL_BINDIR}")
set(libdir "${CMAKE_INSTALL_FULL_LIBDIR}")
set(includedir "${CMAKE_INSTALL_FULL_INCLUDEDIR}")
set(VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
configure_file(qrencode.1.in qrencode.1 @ONLY)
configure_file(libqrencode.pc.in libqrencode.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qrencode.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libqrencode.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
install(FILES qrencode.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(TARGETS qrencode DESTINATION ${CMAKE_INSTALL_LIBDIR})
## Build utility tools
if(WITH_TOOLS)
if(NOT WITHOUT_PNG)
add_definitions(-DHAVE_PNG=1)
endif()
add_executable(qrenc qrenc.c)
set_target_properties(qrenc PROPERTIES OUTPUT_NAME qrencode)
if(NOT WITHOUT_PNG)
target_link_libraries(qrenc qrencode PNG::PNG)
else()
target_link_libraries(qrenc qrencode)
endif()
if(MSVC)
target_link_libraries(qrenc ${GETOPT_LIBRARIES})
endif(MSVC)
install(TARGETS qrenc DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if(WITH_TESTS)
enable_testing()
add_definitions(-DWITH_TESTS=)
add_definitions(-DSTATIC_IN_RELEASE=)
add_subdirectory(tests)
else()
add_definitions(-DSTATIC_IN_RELEASE=static)
endif()
## ==============================================================================
##
## Configuration summary
##
## ==============================================================================
message(STATUS "------------------------------------------------------------" )
message(STATUS "[QRencode] Configuration summary." )
message(STATUS "------------------------------------------------------------ ")
message(STATUS " System configuration:" )
message(STATUS " .. Processor type .............. = ${CMAKE_SYSTEM_PROCESSOR}")
message(STATUS " .. CMake executable ............ = ${CMAKE_COMMAND}" )
message(STATUS " .. CMake version ............... = ${CMAKE_VERSION}" )
message(STATUS " .. System name ................. = ${CMAKE_SYSTEM}" )
message(STATUS " .. C++ compiler ................ = ${CMAKE_CXX_COMPILER}" )
message(STATUS " .. C compiler .................. = ${CMAKE_C_COMPILER}" )
message(STATUS " .. size(void*) ................. = ${CMAKE_SIZEOF_VOID_P}" )
message(STATUS " Dependencies:" )
#message(STATUS " .. Doxygen ..................... = ${DOXYGEN_EXECUTABLE}" )
message(STATUS " .. Thread library of the system = ${CMAKE_THREAD_LIBS_INIT}")
message(STATUS " .. Iconv ....................... = ${ICONV_FOUND}" )
message(STATUS " .... Iconv includes ............ = ${ICONV_INCLUDE_DIR}" )
message(STATUS " .... Iconv library ............. = ${ICONV_LIBRARIES}" )
message(STATUS " .. ZLIB ........................ = ${ZLIB_FOUND}" )
message(STATUS " .. PNG ......................... = ${PNG_FOUND}" )
message(STATUS " .... PNG includes .............. = ${PNG_INCLUDE_DIR}" )
message(STATUS " .... PNG library ............... = ${PNG_LIBRARIES}" )
#message(STATUS " .. Memory checker .............. = ${MEMORYCHECK_COMMAND}" )
message(STATUS " Project configuration:" )
message(STATUS " .. Build test programs ........ = ${WITH_TESTS}" )
message(STATUS " .. Build utility tools ........ = ${WITH_TOOLS}" )
message(STATUS " .. Disable PNG support ........ = ${WITHOUT_PNG}" )
message(STATUS " .. Installation prefix ......... = ${CMAKE_INSTALL_PREFIX}" )
message(STATUS "------------------------------------------------------------ ")

510
COPYING Normal file
View File

@ -0,0 +1,510 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations
below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it
becomes a de-facto standard. To achieve this, non-free programs must
be allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control
compilation and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at least
three years, to give the same user the materials specified in
Subsection 6a, above, for a charge no more than the cost of
performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply, and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License
may add an explicit geographical distribution limitation excluding those
countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms
of the ordinary General Public License).
To apply these terms, attach the following notices to the library.
It is safest to attach them to the start of each source file to most
effectively convey the exclusion of warranty; and each file should
have at least the "copyright" line and a pointer to where the full
notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or
your school, if any, to sign a "copyright disclaimer" for the library,
if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James
Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

1730
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

1781
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

48
Makefile.am Normal file
View File

@ -0,0 +1,48 @@
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS=-I m4
SUBDIRS = .
if BUILD_TESTS
SUBDIRS += tests
endif
lib_LTLIBRARIES = libqrencode.la
libqrencode_la_SOURCES = qrencode.c qrencode_inner.h \
qrinput.c qrinput.h \
bitstream.c bitstream.h \
qrspec.c qrspec.h \
rsecc.c rsecc.h \
split.c split.h \
mask.c mask.h \
mqrspec.c mqrspec.h \
mmask.c mmask.h
libqrencode_la_LDFLAGS = -version-number $(MAJOR_VERSION):$(MINOR_VERSION):$(MICRO_VERSION)
include_HEADERS = qrencode.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libqrencode.pc
noinst_DATA = README
README_markdown_optional := $(wildcard README.md)
README: $(README_markdown_optional)
$(if $(README_markdown_optional), ./makeREADME.sh)
EXTRA_DIST = libqrencode.pc.in autogen.sh configure.ac acinclude.m4 \
Makefile.am tests/Makefile.am \
qrencode.1.in Doxyfile \
CMakeLists.txt cmake/FindIconv.cmake
if BUILD_TOOLS
bin_PROGRAMS = qrencode
qrencode_SOURCES = qrenc.c
qrencode_CFLAGS = $(png_CFLAGS)
qrencode_LDADD = libqrencode.la $(png_LIBS)
man1_MANS = qrencode.1
endif
if MINGW
libqrencode_la_LDFLAGS += -no-undefined -avoid-version -Wl,--nxcompat -Wl,--dynamicbase
endif

1234
Makefile.in Normal file

File diff suppressed because it is too large Load Diff

332
NEWS Normal file
View File

@ -0,0 +1,332 @@
libqrencode NEWS - Overview of changes
======================================
Version 4.1.1 (2020.9.28)
-------------------------
* Some minor bugs in Micro QR Code generation have been fixed.
* The data capacity calculations are now correct. These bugs probably did not
affect the Micro QR Code generation.
Version 4.1.0 (2020.8.29)
-------------------------
* Command line tool "qrencode" has been improved:
* New option "--inline" has been added. (Thanks to @jp-bennett)
* New option "--strict-version" has been added.
* UTF8 mode now supports ANSI256 color. (Thanks to András Veres-
Szentkirályi)
* Micro QR Code no longer requires to specify the version number.
* 'make check' allows to run the test programs. (Thanks to Jan Tojnar)
* Some compile time warnings have been fixed.
* Various CMake support improvements. (Thanks to @mgorny and @sdf5)
* Some minor bug fixes. (Thanks to Lonnie Abelbeck and Frédéric Wang)
* Some documentation/manpage improvements. (Thanks to Dan Jacobson)
* Some performance improvements. (Thanks to @4061N and Mika Lindqvist)
Release Note:
The internal representation of the output code has been slightly changed -
the second bit from LSB side now represents; 1:ECC bit / 0:data bit.
This change is only for debug purposes and does not affect user applications.
Version 4.0.2 (2018.6.6)
------------------------
* Build script fixes. (Thanks to @mgorny)
Version 4.0.1 (2018.6.4)
------------------------
* CMake support improved.
* New test scripts have been added.
* Some compile time warnings have been fixed.
Version 4.0.0 (2017.9.21)
-------------------------
* Memory efficiency has been improved.
* QRcode_clearCache() has been deprecated.
* Error correction code generating functions have been improved.
* Command line tool "qrencode" has been improved:
* XPM support. (Thanks to Tobias Klauser)
* PNG32 (direct color mode) support. (Thanks to Greg Hart)
* EPS output now supports foreground and background color.
* New options "-r" and "--svg-path" have been added.
(Thanks to Robert Petersen and @Oblomov)
* CMake support has been added. (optional) (Thanks to @misery)
* Various bug fixes.
* Various performance improvements.
Release Note:
While the API has not been changed since the previous major release, we
incremented the major version number of libqrencode to 4 because the
implementation of the library has been largely changed.
This release improves the performance and memory footprints of code generation.
Now you can build libqrencode with CMake.
If you build the test programs, please note that the required SDL version has
been changed from 1.2 to 2.0.
Version 3.4.4 (2014.7.24)
-------------------------
* Bug fix release. (Thanks to Yoshimichi Inoue)
* New option "--verbose" has been added to the command line tool.
Release Note:
When only one symbol is generated in structured-append mode, the library had
inserted unnecessary chunk to the symbol and some QR Code readers fail to read
it. Now the library omits the chunk and generate a symbol identical to non-
structured symbol.
Version 3.4.3 (2013.8.12)
-------------------------
* New option "--rle" has been added to the command line tool (Thanks to Daniel
Dörrhöfer)
* Bug fixes. (Thanks to Hassan Hajji, Emmanuel Blot, and ßlúèÇhîp)
Release Note:
This release contains a couple of bug fixes and a new minor feature of the
command line tool. Some minor bugs in the library have been fixed.
Run Length Encoding (RLE) for SVG output decreases the size of the output file,
but it makes complicated to edit the image by SVG editors. A newly introduced
command line option "--rle" enables RLE. RLE will not be applied if it is not
given.
Version 3.4.2 (2013.3.1)
------------------------
* Bug fix release. (Thanks to chisj, vlad417, Petr and Viona)
Release Note:
Micro QR Code encoder had a bug that caused incorrect output (issue #25). Now
the bug has been fixed. Memory leak bug (#24) and insufficient string splitting
bug have been fixed.
Version 3.4.1 (2012.10.17)
--------------------------
* Bug fix release.
Release Note:
Mutual exclusion did not work correctly since 3.3.1. If your application uses
libqrencode in multithreaded environment, it is strongly recommended to update
it.
Version 3.4.0 (2012.10.15)
--------------------------
* SVG, UTF8, and ANSIUTF8 output supports have been added to the command line
tool. (Thanks to Dan Storm, David Dahl, and Lennart Poettering)
* Colored QR Code support.
* Bug fixes. (Thanks to Terry Burton, Fred Steinhaeuser, and Yann Droneaud)
Release Note:
Three new output format, SVG, UTF8, and ANSIUTF8 have been added to the command
line tool. UTF8 and ANSIUTF8 are another text art mode, using Unicode block
elements for high-resolution text output. Long-awaited colored QR code has been
introduced. Try "--foreground" and "--background" options to set the colors.
Currently PNG and SVG supports colored output.
Version 3.3.1 (2012.4.18)
-------------------------
* Bugs in command line tool, manual, configure script, and libtool files have
been fixed. (Thanks to Yutaka Niibe and Rob Ryan)
Version 3.3.0 (2012.4.1)
-------------------------
* EPS, ANSI, and ASCII text output supports have been added.
(Thanks to Zapster, Colin, and Ralf)
* QRcode_APIVersion() and QRcode_APIVersionString() have been added.
Release Note:
Three new output format, EPS, ANSI, and ASCII text, have been added to the
command line tool. ANSI and ASCII mode ignore "-size" option. Give "-t ASCIIi"
to get an ASCII-mode symbol in inverted color.
QRcode_APIVersion() is requested by Matthew Baker for better support of Python
ctypes binding. Check them out at https://code.google.com/p/libqrencode-ctypes/
Version 3.2.1 (2012.4.1)
------------------------
* Bugs in configure script and libtool file has been fixed. (Thanks to Yutaka
Niibe)
Version 3.2.0 (2011.11.26)
--------------------------
* "--dpi" (or "-d") option has been added to qrencode. This option set DPI
information in an output PNG image. (Thanks to David Dahl)
* New option "--enable-thread-safety" has been added to the configure script
that makes the library thread-safe. It is enabled by default.
* QRcode_encodeData(), QRcode_encodeDataMQR, QRcode_encodeDataStructured() have
been added for binary data encoding including '\0'.
* Typo and bug fixes.
* Experimental Micro QR Code support has been added.
* "--micro" (or "-M") option for Micro QR Code has been added to qrencode.
(experimental)
Release Note:
Binary data including '\0' is now supported. To encode a binary data, give "-8"
option to qrencode, and let qrencode obtain data via standard input like
"qrencode -8 -o output.png < binary". "--dpi" and "-d" are also added to embed
DPI information to PNG file.
A bug in the mask pattern evaluation routine has been fixed. In some cases,
libqrencode may generate a different symbol from the one that was generated by
the prior libqrencode because of this bug fix, but the embedded data are not
affected. The symbols generated by the old libqrencode are valid.
Experimental support of Micro QR Code encoder has been added. Some functions
(QRcode_*MQR()) have been added to the library. The command line tool generates
Micro QR Code when "--micro" or "-M" is given.
Version 3.1.1 (2010.2.3)
------------------------
* A bug in the library has been fixed.
Release Note:
Libqrecode had generated incorrect QR Code in some cases. Symbols larger than
version 5 (error correction level Q and H) were affected. In many cases this
bug did not cause serious damage thanks to the error correction mechanism, but
we highly recommend you to encode symbols again using this release.
Version 3.1.0 (2009.6.6)
------------------------
* Various code cleanups and performance improves.
* Strict internal error checks have been added.
* "--without-tests" has become default setting. Specify "--with-tests" to
compile test programs.
* Some memory leak bugs have been fixed.
Release Note:
This release focuses on the code cleanup and performance improve. Encoding time
has been improved, drastically in large symbols. Basically this update only
changes its internal code. The API is not changed, no need to recompile user
applications that includes only qrencode.h. If your application refers the
internal data representation (not recommended), see ChangeLog for further
information.
Version 3.0.3 (2008.6.1)
------------------------
* Portability enhancement. (Thanks to Gavan Fantom)
* The command line tool "qrencode" now accepts long options. See the man page
for the detailed instruction.
Release Note:
This release improves the portability of our command line tool "qrencode".
The library is not changed so that any applications using libqrencode are not
affected.
From this release, qrencode accepts "long" options, such as "--help". See the
manpage for the detailed instructions.
Qrencode now uses getopt_long() instead of getopt_long_only() which is not
available in some operating systems. If the getopt_long() is not provided or
the implementation of it is not compatible with GNU's one, please try
qrencode-3.0.3-gnulib, that contains the source code of the getopt_long().
Gnulib version is a test release. If you feel happy with it, please let us know
and the future releases will include gnulib.
Version 3.0.2 (2008.5.18)
-------------------------
* Some compile-time warnings/errors with g++ have been fixed.
(Thanks to wangsai)
* The bit order of "Version information" has been corrected.
Symbols greater than version 6 were affected. (Thanks to Paul Janssesn)
* The "--without-tests" option has been added to the configure script.
Version 3.0.1 (2008.5.9)
------------------------
* A bug fix for non-POSIX platform. (Thanks to Paul Janssens)
* The RPM spec file now packages the man page correctly.
Version 3.0.0 (2008.4.30)
-------------------------
* The interface of QRencode_encodeInput() has been changed. User applications
using it must be modified.
* Structured append support has been added. (patches from Yusuke Mihara)
* The "-S" option for structured append has been added to qrencode and
view_qrcode.
* Some functions now set errno to indicate errors.
* Some bug fixes.
Release Note:
Now libqrencode supports "structured-append" of symbols. A large data set can
be split into multiple QR code symbols. The basic usage of structured-append
is not so different from the single symbol encoding: just call
QRcode_encodeStringStructured() or QRcode_encodeString8bitStructured() and
they return a list of symbols. Instead of giving a string, you can encode
an explicitly typed data. See the manual generated by Doxygen for the detailed
usage.
Many thanks to Yusuke Mihara, who contributed a patch to add support of
structured-append to version 1.0.2.
API changes:
* Incompatible API changes:
- QRencode_encodeInput
* New types:
- QRinput_Struct
- QRcode_List
* New functions:
- QRinput_new2
- QRinput_Struct_new
- QRinput_Struct_setParity
- QRinput_Struct_appendInput
- QRinput_Struct_free
- QRinput_Struct_insertStructuredAppendHeaders
- QRinput_splitQRinputToStruct
- QRcode_encodeStructuredInput
- QRcode_encodeStringStructured
- QRcode_encodeString8bitStructured
- QRcode_List_size
- QRcode_List_free
* Declarations moved to qrencode.h:
- QRinput_getErrorCorrectionLevel
- QRinput_setErrorCorrectionLevel
- QRinput_getVersion
- QRinput_setVersion
Version 2.0.0 (2008.1.24)
-------------------------
* "-i" option to ignore case distinctions has been added to qrencode and
view_qrcode.
* "-c" option (case-sensitive mode) of qrencode is now enabled by default and
has been improved. See details in Release Note section.
* "-8" option has been added to qrencode to encode whole data in 8-bit mode.
* tests/view_qrcode now accepts various options like qrencode.
* Man page has been added.
* Code cleanup.
* The mask evaluation bug has been fixed. (Philippe Delcroix)
* API changes
- QRcode_encodeString() now receives case-sensitive flag.
- QRcode_encodeStringCase() has been removed.
- QRcode_encodeString8bit() has been added.
Release Note:
Previously libqrencode encodes lower-case alphabet characters in Alphabet-
Numeric mode (upper-case alphabet and numeric) by default. According to the
specification of QR code, however, it is clearly claimed that Alphabet-Numeric
mode provides only upper-case alphabet (+ numeric and some symbol) characters.
Since this version, libqrencode distinguishes lower-case and upper-case of
alphabet characters by default. Because of that, "-c" option of qrencode
is now deprecated, and "-i" option has been added. By giving "-i", qrencode
converts lower-case characters to upper-case if possible, then encode a QR code
symbol. Please read qrencode.h for the details about API changes if you are
going to use this library.
Many thanks to NANKI Haruo for his suggestions.
Version 1.0.2 (2007.03.24)
--------------------------
* A small bug fix. (Thanks to NANKI Haruo)
* 'extern "C"' barrier has been added to qrencode.h.
Version 1.0.1 (2006.12.27)
--------------------------
* Added "force 8-bit encoding mode".
* Configure script finds libpng's header correctly.
Version 1.0.0 (2006.12.12)
--------------------------
* The first public release.

224
README Normal file
View File

@ -0,0 +1,224 @@
libqrencode - a fast and compact QR Code encoding library
GENERAL INFORMATION
===================
Libqrencode is a fast and compact library for encoding data in a QR Code,
a 2D symbology that can be scanned by handy terminals such as a smartphone.
The capacity of QR Code is up to 7000 digits or 4000 characters and has high
robustness.
Libqrencode accepts a string or a list of data chunks then encodes in a QR Code
symbol as a bitmap array. While other QR Code applications generate an image
file, using libqrencode allows applications to render QR Code symbols from raw
bitmap data directly. This library also contains a command-line utility outputs
QR Code images in various formats.
SPECIFICATION
=============
Libqrencode supports QR Code model 2, described in JIS (Japanese Industrial
Standards) X0510:2004 or ISO/IEC 18004. Most of features in the specification
are implemented such as:
- Numeric, alphabet, Japanese kanji (Shift-JIS) or any 8 bit code can be
embedded
- Optimized encoding of a string
- Structured-append of symbols
- Micro QR Code (experimental)
Currently the following features are not supported:
- ECI and FNC1 mode
- QR Code model 1 (deprecated)
INSTALL
=======
Requirements
------------
While the command-line utility and some test programs use libpng or SDL 2.0,
the libqrencode library itself has no dependencies. You can skip compiling
tests and/or tools if you want not to install programs using SDL or PNG.
Compile & install
-----------------
If there is no "configure" script in the source code directory, run
"autogen.sh" at first to generate it - this is mandatory if you downloaded the
source from GitHub. Some additional software is needed to complete this
process. For example, in Ubuntu, the following packages are needed:
- autoconf
- automake
- autotools-dev
- libtool
- pkg-config
- libpng12-dev
You can skip this process if you have "configure" script already (typically
when you downloaded the source tarball from fukuchi.org.)
Now you are ready to compile the library and tool. Type the following commands:
./configure
make
sudo make install
sudo ldconfig
This compiles and installs the library and header file to the appropriate
directories: by default, /usr/local/lib and /usr/local/include. You can change
the destination directory by passing some options to the configure script.
Run "./configure --help" to see the list of options.
It also installs a command line tool "qrencode" to /usr/local/bin. If you want
not to build it, give "--without-tools" option to the configure script.
If the configure script does not work well, try to use CMake.
cmake .
make
When you want to build the test programs, give "--with-tests" option to
configure, or "-DWITH_TESTS=YES" to cmake.
### Building libqrencode with vcpkg
You can download and install libqrencode using the
[vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install libqrencode
The libqrencode port in vcpkg is kept up to date by Microsoft team members and
community contributors. If the version is out of date, please
[create an issue or pull request](https://github.com/Microsoft/vcpkg) on the
vcpkg repository.
USAGE
=====
Basic usages of this library are written in the header file (qrencode.h).
You can generate a manual of the library by using Doxygen, or see
https://fukuchi.org/works/qrencode/manual/index.html
WARNINGS
========
The library is distributed WITHOUT ANY WARRANTY.
Micro QR Code support is EXPERIMENTAL.
Be careful to use the command line tool (qrencode) if it is used by a web
application (e.g. CGI script). For example, giving "-s" option with a large
number to qrencode may cause DoS. The parameters should be checked by the
application.
LICENSING INFORMATION
=====================
Copyright (C) 2006-2018 Kentaro Fukuchi
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or any later version.
This library 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this library; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
CONTACT
=======
Visit the homepage at:
https://fukuchi.org/works/qrencode/
for new releases. The git repository is available at:
https://github.com/fukuchi/libqrencode
Please mail any bug reports, suggestions, comments, and questions to:
Kentaro Fukuchi <kentaro@fukuchi.org>
or submit issues to:
https://github.com/fukuchi/libqrencode/issues
ACKNOWLEDGMENTS
===============
QR Code is registered trademarks of DENSO WAVE INCORPORATED in JAPAN and other
countries.
Reed-Solomon encoder included in this library is originally taken from FEC
library developed by Phil Karn (KA9Q) and distributed under the terms of the
GNU LGPL, then rewritten by Kentaro Fukuchi.
Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
* NANKI Haruo - improved lower-case characters encoding
* Katsumi Saito - SPEC file
* Philippe Delcroix - improved mask evaluation
* Yusuke Mihara - structured-append support
* David Dahl - DPI and SVG support patch
* Adam Shepherd - bug fix patch of the mask evaluation
* Josef Eisl (@zapster) - EPS support patch
* Colin (@moshen) - ANSI support patch
* Ralf Ertzinger - ASCII support patch
* Yutaka Niibe (@gniibe)- various bug fix patches
* Dan Storm (@Repox) - SVG support patch
* Lennart Poettering (@mezcalero)
- improved text art patch
* Yann Droneaud - improved input validation patch
* Viona - bug fix patch for string splitting
* Daniel Dörrhöfer (@d4ndo)
- RLE option, some bug fixes, Travis configuration
* Greg Hart - PNG32 support patch
* @siggi-heltau - bug fix patch
* Tobias Klauser (@tklauser)
- bug fix patch, XPM support patch
* Robert Petersen (@ripetersen)
- added ability to read input data from a file
* @Oblomov - improved SVG support patch
* Michał Górny (@mgorny)
- reverse mappings of UTF8 and ANSIUTF8, build script
fixes
* @EckoEdc - MinGW support patch
* Sebastian Buchwald (@UniQP)
- Various code cleanups
* André Klitzing (@misery)
- CMake support
* Alexey Nikolaev (@aleksey-nikolaev)
- improved CMake support
* Vilppu Vuorinen (@vilppuvuorinen)
- improved CMake support
* @vanillahsu - bug fix patch
* @Ation - bug fix patch
* Jonathan Bennett - Added "--inline" option to qrencode
* András Veres-Szentkirályi
- ANSI256UTF8 support
* @sdf5 - improved CMake support
* Lonnie Abelbeck (@abelbeck)
- bug fix patch
* @4061N - performance improvement patch
* Rosen Penev (@neheb) - CMake bug fix patch
* Mika Lindqvist (@mtl1979)
- replacement for gettimeofday() for Windows.
* Shigeyuki Hirai, Paul Janssens, wangsai, Gavan Fantom, Matthew Baker,
Rob Ryan, Fred Steinhaeuser, Terry Burton, @chisj, @vlad417, Petr,
Hassan Hajji, Emmanuel Blot, ßlúèÇhîp, Heiko Becker, Gavin Andresen,
David Binderman, @ralgozino, Sean McMurray, Vlad Bespalov (@win32asm),
Antenore Gatta, Yoshimichi Inoue, Sunil Maganally, Norman Gray,
Danomi Manchego, @minus7, Ian Sweet, @qianchenglenger, Ronald Michaels,
Yuji Ueno, Jakub Wilk, @KangLin, @c-273, @thebunnyrules, @NancyLi1013,
Frédéric Wang, Dan Jacobson, Jan Tojnar, @xiaoyur347, @charmander
- bug report / suggestion / typo fixes

5
TODO Normal file
View File

@ -0,0 +1,5 @@
Micro QR code encoding is not tested well.
Documents (not only the README, but also the manual of the library) needs
revision of grammar, spelling or to resolve ambiguity or incomplete descriptions.
Feel really free to send us your revision.

1391
acinclude.m4 Normal file

File diff suppressed because it is too large Load Diff

10466
aclocal.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

35
autogen.sh Executable file
View File

@ -0,0 +1,35 @@
#!/bin/sh
set -e
if [ `uname -s` = Darwin ]; then
LIBTOOLIZE=glibtoolize
else
LIBTOOLIZE=libtoolize
fi
ACLOCAL_OPT=""
if [ -d /usr/local/share/aclocal ]; then
ACLOCAL_OPT="-I /usr/local/share/aclocal"
elif [ -d /opt/local/share/aclocal ]; then
ACLOCAL_OPT="-I /opt/local/share/aclocal"
elif [ -d /usr/share/aclocal ]; then
ACLOCAL_OPT="-I /usr/share/aclocal"
fi
if [ ! -d use ]; then
mkdir use
fi
if [ ! -d m4 ]; then
mkdir m4
fi
autoheader
aclocal $ACLOCAL_OPT
$LIBTOOLIZE --automake --copy
automake --add-missing --copy
autoconf

231
bitstream.c Normal file
View File

@ -0,0 +1,231 @@
/*
* qrencode - QR Code encoder
*
* Binary sequence class.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bitstream.h"
#define DEFAULT_BUFSIZE (128)
BitStream *BitStream_new(void)
{
BitStream *bstream;
bstream = (BitStream *)malloc(sizeof(BitStream));
if(bstream == NULL) return NULL;
bstream->length = 0;
bstream->data = (unsigned char *)malloc(DEFAULT_BUFSIZE);
if(bstream->data == NULL) {
free(bstream);
return NULL;
}
bstream->datasize = DEFAULT_BUFSIZE;
return bstream;
}
#ifdef WITH_TESTS
BitStream *BitStream_newWithBits(size_t size, unsigned char *bits)
{
BitStream *bstream;
if(size == 0) return BitStream_new();
bstream = (BitStream *)malloc(sizeof(BitStream));
if(bstream == NULL) return NULL;
bstream->data = (unsigned char *)malloc(size);
if(bstream->data == NULL) {
free(bstream);
return NULL;
}
bstream->length = size;
bstream->datasize = size;
memcpy(bstream->data, bits, size);
return bstream;
}
#endif
static int BitStream_expand(BitStream *bstream)
{
unsigned char *data;
data = (unsigned char *)realloc(bstream->data, bstream->datasize * 2);
if(data == NULL) {
return -1;
}
bstream->data = data;
bstream->datasize *= 2;
return 0;
}
static void BitStream_writeNum(unsigned char *dest, size_t bits, unsigned int num)
{
unsigned int mask;
size_t i;
unsigned char *p;
p = dest;
mask = 1U << (bits - 1);
for(i = 0; i < bits; i++) {
if(num & mask) {
*p = 1;
} else {
*p = 0;
}
p++;
mask = mask >> 1;
}
}
static void BitStream_writeBytes(unsigned char *dest, size_t size, unsigned char *data)
{
unsigned char mask;
size_t i, j;
unsigned char *p;
p = dest;
for(i = 0; i < size; i++) {
mask = 0x80;
for(j = 0; j < 8; j++) {
if(data[i] & mask) {
*p = 1;
} else {
*p = 0;
}
p++;
mask = mask >> 1;
}
}
}
int BitStream_append(BitStream *bstream, BitStream *arg)
{
int ret;
if(arg == NULL) {
return -1;
}
if(arg->length == 0) {
return 0;
}
while(bstream->length + arg->length > bstream->datasize) {
ret = BitStream_expand(bstream);
if(ret < 0) return ret;
}
memcpy(bstream->data + bstream->length, arg->data, arg->length);
bstream->length += arg->length;
return 0;
}
int BitStream_appendNum(BitStream *bstream, size_t bits, unsigned int num)
{
int ret;
if(bits == 0) return 0;
while(bstream->datasize - bstream->length < bits) {
ret = BitStream_expand(bstream);
if(ret < 0) return ret;
}
BitStream_writeNum(bstream->data + bstream->length, bits, num);
bstream->length += bits;
return 0;
}
int BitStream_appendBytes(BitStream *bstream, size_t size, unsigned char *data)
{
int ret;
if(size == 0) return 0;
while(bstream->datasize - bstream->length < size * 8) {
ret = BitStream_expand(bstream);
if(ret < 0) return ret;
}
BitStream_writeBytes(bstream->data + bstream->length, size, data);
bstream->length += size * 8;
return 0;
}
unsigned char *BitStream_toByte(BitStream *bstream)
{
size_t i, j, size, bytes, oddbits;
unsigned char *data, v;
unsigned char *p;
size = BitStream_size(bstream);
if(size == 0) {
return NULL;
}
data = (unsigned char *)malloc((size + 7) / 8);
if(data == NULL) {
return NULL;
}
bytes = size / 8;
p = bstream->data;
for(i = 0; i < bytes; i++) {
v = 0;
for(j = 0; j < 8; j++) {
v = (unsigned char)(v << 1);
v |= *p;
p++;
}
data[i] = v;
}
oddbits = size & 7;
if(oddbits > 0) {
v = 0;
for(j = 0; j < oddbits; j++) {
v = (unsigned char)(v << 1);
v |= *p;
p++;
}
data[bytes] = (unsigned char)(v << (8 - oddbits));
}
return data;
}
void BitStream_free(BitStream *bstream)
{
if(bstream != NULL) {
free(bstream->data);
free(bstream);
}
}

43
bitstream.h Normal file
View File

@ -0,0 +1,43 @@
/*
* qrencode - QR Code encoder
*
* Binary sequence class.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef BITSTREAM_H
#define BITSTREAM_H
typedef struct {
size_t length;
size_t datasize;
unsigned char *data;
} BitStream;
extern BitStream *BitStream_new(void);
#ifdef WITH_TESTS
extern BitStream *BitStream_newWithBits(size_t size, unsigned char *bits);
#endif
extern int BitStream_append(BitStream *bstream, BitStream *arg);
extern int BitStream_appendNum(BitStream *bstream, size_t bits, unsigned int num);
extern int BitStream_appendBytes(BitStream *bstream, size_t size, unsigned char *data);
#define BitStream_size(__bstream__) (__bstream__->length)
#define BitStream_reset(__bstream__) (__bstream__->length = 0)
extern unsigned char *BitStream_toByte(BitStream *bstream);
extern void BitStream_free(BitStream *bstream);
#endif /* BITSTREAM_H */

115
cmake/FindIconv.cmake Normal file
View File

@ -0,0 +1,115 @@
include(CheckFunctionExists)
set(_ICONV_SEARCHES)
# Search ICONV_DIR first if it is set.
if(NOT ICONV_DIR AND ENV{ICONV_DIR})
set(ICONV_DIR $ENV{ICONV_DIR})
endif()
if(ICONV_DIR)
set(_ICONV_DIR_SEARCH PATHS ${ICONV_DIR} NO_DEFAULT_PATH)
list(APPEND _ICONV_SEARCHES _ICONV_DIR_SEARCH)
endif()
# Normal search.
set(_ICONV_SEARCH_NORMAL
PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Iconv;InstallPath]"
"$ENV{PROGRAMFILES}/iconv"
ENV CPATH
ENV C_INCLUDE_PATH
ENV CPLUS_INCLUDE_PATH
ENV LIBRARY_PATH)
list(APPEND _ICONV_SEARCHES _ICONV_SEARCH_NORMAL)
set(ICONV_NAMES iconv iconv2 libiconv iconv64)
set(ICONV_NAMES_DEBUG iconvd iconv64d)
# Try each search configuration.
foreach(search ${_ICONV_SEARCHES})
find_path(ICONV_INCLUDE_DIR NAMES iconv.h ${${search}} PATH_SUFFIXES include)
endforeach()
# Allow ICONV_LIBRARY to be set manually, as the location of the iconv library
if(NOT ICONV_LIBRARY)
foreach(search ${_ICONV_SEARCHES})
find_library(ICONV_LIBRARY_RELEASE NAMES ${ICONV_NAMES} ${${search}} PATH_SUFFIXES lib)
find_library(ICONV_LIBRARY_DEBUG NAMES ${ICONV_NAMES_DEBUG} ${${search}} PATH_SUFFIXES lib)
endforeach()
include(SelectLibraryConfigurations)
select_library_configurations(ICONV)
endif()
unset(ICONV_NAMES)
unset(ICONV_NAMES_DEBUG)
if(ICONV_INCLUDE_DIR AND EXISTS "${ICONV_INCLUDE_DIR}/iconv.h")
file(STRINGS "${ICONV_INCLUDE_DIR}/iconv.h" ICONV_H REGEX "^#define _LIBICONV_VERSION 0x([0-9]+)")
string(REGEX MATCH "q#define _LIBICONV_VERSION 0x([0-9][0-9])([0-9][0-9])?([0-9][0-9])?.*" temp_match "${ICONV_H}")
unset(temp_match)
if(CMAKE_MATCH_0)
set(ICONV_VERSION_MAJOR "${CMAKE_MATCH_1}")
set(ICONV_VERSION_MINOR "${CMAKE_MATCH_2}")
set(ICONV_VERSION_PATCH "${CMAKE_MATCH_3}")
string(REGEX REPLACE "0*([1-9][0-9]*).*" "\\1" ICONV_VERSION_MAJOR "${ICONV_VERSION_MAJOR}")
string(REGEX REPLACE "0*([1-9][0-9]*).*" "\\1" ICONV_VERSION_MINOR "${ICONV_VERSION_MINOR}")
string(REGEX REPLACE "0*([1-9][0-9]*).*" "\\1" ICONV_VERSION_PATCH "${ICONV_VERSION_PATCH}")
set(ICONV_VERSION_STRING "${ICONV_VERSION_MAJOR}.${ICONV_VERSION_MINOR}")
if(ICONV_VERSION_PATCH)
set(ICONV_VERSION_STRING "${ICONV_VERSION_STRING}.${ICONV_VERSION_PATCH}")
endif()
endif()
endif()
check_function_exists(iconv_open ICONV_IN_GLIBC)
set(ICONV_FOUND_ANY FALSE)
if(ICONV_IN_GLIBC OR ICONV_LIBRARY)
set(ICONV_FOUND_ANY TRUE)
endif()
# handle the QUIETLY and REQUIRED arguments and set ICONV_FOUND to TRUE if
# all listed variables are TRUE
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ICONV
REQUIRED_VARS ICONV_FOUND_ANY ICONV_INCLUDE_DIR
VERSION_VAR ICONV_VERSION_STRING)
mark_as_advanced(ICONV_LIBRARY ICONV_INCLUDE_DIR)
if(NOT ICONV_FOUND)
return()
endif()
set(ICONV_INCLUDE_DIRS ${ICONV_INCLUDE_DIR})
if(NOT ICONV_LIBRARIES)
set(ICONV_LIBRARIES ${ICONV_LIBRARY})
endif()
if(ICONV_LIBRARY AND NOT TARGET ICONV::ICONV)
add_library(ICONV::ICONV UNKNOWN IMPORTED)
set_target_properties(ICONV::ICONV PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${ICONV_INCLUDE_DIRS}"
IMPORTED_LOCATION "${ICONV_LIBRARY}")
if(ICONV_LIBRARY_RELEASE)
set_property(TARGET ICONV::ICONV APPEND PROPERTY
IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(ICONV::ICONV PROPERTIES
IMPORTED_LOCATION_RELEASE "${ICONV_LIBRARY_RELEASE}")
endif()
if(ICONV_LIBRARY_DEBUG)
set_property(TARGET ICONV::ICONV APPEND PROPERTY
IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(ICONV::ICONV PROPERTIES
IMPORTED_LOCATION_DEBUG "${ICONV_LIBRARY_DEBUG}")
endif()
elseif(NOT TARGET ICONV::ICONV)
add_library(ICONV::ICONV INTERFACE IMPORTED)
set_target_properties(ICONV::ICONV PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${ICONV_INCLUDE_DIRS}")
endif()

102
config.h.in Normal file
View File

@ -0,0 +1,102 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define if you have the iconv() function and it works. */
#undef HAVE_ICONV
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if using pthread is enabled. */
#undef HAVE_LIBPTHREAD
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if using libpng is enabled. */
#undef HAVE_PNG
/* Define to 1 if using SDL is enabled. */
#undef HAVE_SDL
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#undef LT_OBJDIR
/* Major version number */
#undef MAJOR_VERSION
/* Micro version number */
#undef MICRO_VERSION
/* Minor version number */
#undef MINOR_VERSION
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to 'static' if no test programs will be compiled. */
#define STATIC_IN_RELEASE static
#undef WITH_TESTS

16741
configure vendored Executable file

File diff suppressed because it is too large Load Diff

167
configure.ac Normal file
View File

@ -0,0 +1,167 @@
m4_define([__MAJOR_VERSION], [4])dnl
m4_define([__MINOR_VERSION], [1])dnl
m4_define([__MICRO_VERSION], [1])dnl
m4_define([__VERSION], [__MAJOR_VERSION.__MINOR_VERSION.__MICRO_VERSION])dnl
AC_INIT(QRencode, __VERSION)
MAJOR_VERSION=__MAJOR_VERSION
MINOR_VERSION=__MINOR_VERSION
MICRO_VERSION=__MICRO_VERSION
AC_SUBST(MAJOR_VERSION)
AC_SUBST(MINOR_VERSION)
AC_SUBST(MICRO_VERSION)
AC_DEFINE_UNQUOTED([MAJOR_VERSION], [$MAJOR_VERSION], [Major version number])
AC_DEFINE_UNQUOTED([MINOR_VERSION], [$MINOR_VERSION], [Minor version number])
AC_DEFINE_UNQUOTED([MICRO_VERSION], [$MICRO_VERSION], [Micro version number])
AC_CONFIG_SRCDIR([qrencode.c])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_AUX_DIR(use)
AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_HOST
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE
AC_DISABLE_STATIC
AC_C_CONST
AC_C_INLINE
AC_HEADER_STDC
AC_CHECK_HEADERS(sys/time.h)
LT_INIT
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_INSTALL
AC_PROG_LIBTOOL
PKG_PROG_PKG_CONFIG
case "${target}" in
*-*-mingw*)
mingw=yes
esac
AM_CONDITIONAL(MINGW, [test "x$mingw" = "xyes" ])
AC_CONFIG_FILES([Makefile libqrencode.pc tests/Makefile qrencode.1])
AC_CHECK_FUNCS([strdup])
dnl --enable-thread-safety
AC_ARG_ENABLE([thread-safety], [AS_HELP_STRING([--enable-thread-safety], [make the library thread-safe. [default=yes]])],
[], [enable_thread_safety=yes])
if test x$enable_thread_safety = xyes; then
AC_CHECK_LIB([pthread], [pthread_mutex_init], [AC_SUBST([LIBPTHREAD], [-lpthread])])
fi
AM_CONDITIONAL([HAVE_LIBPTHREAD], [test "x$ac_cv_lib_pthread_pthread_mutex_init" = "xyes" ])
# FIXME: isn't it able to integrate the followings to AC_CHECK_LIB?
if test x$ac_cv_lib_pthread_pthread_mutex_init = xyes ; then
AC_DEFINE([HAVE_LIBPTHREAD], [1], [Define to 1 if using pthread is enabled.])
CFLAGS="$CFLAGS -pthread"
fi
AC_ARG_WITH(png,
[AC_HELP_STRING([--without-png],
[disable PNG support])],
[with_png=$withval], [with_png=yes])
dnl --with-tools
AC_ARG_WITH([tools], [AS_HELP_STRING([--with-tools], [build utility tools [default=yes]])],
[build_tools=$withval], [build_tools=yes])
AM_CONDITIONAL(BUILD_TOOLS, [test "x$build_tools" = "xyes" ])
if test x$build_tools = xyes && test x$with_png = xyes ; then
PKG_CHECK_MODULES(png, "libpng", [AC_DEFINE([HAVE_PNG], [1], [Define to 1 if using libpng is enabled.])], [AC_DEFINE([HAVE_PNG], [0])])
if test "x$png_CFLAGS" = "x" && test x$with_png = xyes ; then
echo "
!!!!!!!!!!
LIBPNG is required to build the utility tools. Temporarily disabled.
!!!!!!!!!!
"
fi
fi
AM_CONDITIONAL(HAVE_PNG, [test "x$png_CFLAGS" != "x" ])
dnl --with-tests
AC_ARG_WITH([tests], [AS_HELP_STRING([--with-tests], [build tests [default=no]])],
[build_tests=$withval], [build_tests=no])
AM_CONDITIONAL(BUILD_TESTS, [test "x$build_tests" = "xyes" ])
AH_VERBATIM([tests],
[/* Define to 'static' if no test programs will be compiled. */
#define STATIC_IN_RELEASE static
#undef WITH_TESTS
])
if test x$build_tests = xyes ; then
echo "#define STATIC_IN_RELEASE" >>confdefs.h
echo "#define WITH_TESTS 1" >>confdefs.h
else
echo "#define STATIC_IN_RELEASE static" >>confdefs.h
echo "/* #undef WITH_TESTS */" >>confdefs.h
fi
if test x$build_tests = xyes ; then
SDL_REQUIRED_VERSION=2.0.0
PKG_CHECK_MODULES(SDL, [sdl2 >= $SDL_REQUIRED_VERSION], [AC_DEFINE([HAVE_SDL], [1], [Define to 1 if using SDL is enabled.])], [AC_DEFINE([HAVE_SDL], [0])])
AM_ICONV_LINK
fi
AM_CONDITIONAL(HAVE_SDL, [test "x$SDL_CFLAGS" != "x" ])
dnl --enable-gprof
AC_ARG_ENABLE([gprof], [AS_HELP_STRING([--enable-gprof], [generate extra code to write profile information suitable for gprof [default=no]])],
[], [enable_gprof=no])
if test x$enable_gprof = xyes; then
CFLAGS="$CFLAGS -g -pg"
fi
dnl --enable-gcov
AC_ARG_ENABLE([gcov], [AS_HELP_STRING([--enable-gcov], [generate extra code to write coverage information suitable for gcov [default=no]])],
[], [enable_gcov=no])
if test x$enable_gcov = xyes; then
CFLAGS="$CFLAGS --coverage"
fi
dnl --enable-mudflap
AC_ARG_ENABLE([mudflap], [AS_HELP_STRING([--enable-mudflap], [generate extra code to check memory leaks [default=no]])],
[], [enable_mudflap=no])
if test x$enable_mudflap = xyes; then
if test x$enable_thread_safety = xyes; then
CFLAGS="$CFLAGS -fmudflapth"
LDFLAGS="$LDFLAGS -lmudflapth"
else
CFLAGS="$CFLAGS -fmudflap"
LDFLAGS="$LDFLAGS -lmudflap"
fi
fi
dnl --enable-asan
AC_ARG_ENABLE([asan], [AS_HELP_STRING([--enable-asan], [use AddressSanitizer [default=no]])],
[], [enable_asan=no])
if test x$enable_asan = xyes; then
CFLAGS="$CFLAGS -fsanitize=address -fno-omit-frame-pointer"
LDFLAGS="$LDFLAGS -fsanitize=address"
fi
dnl set CFLAGS
CFLAGS="-Wall $CFLAGS"
AC_OUTPUT
echo ""
echo "Options used to compile and link:"
echo " CC = $CC"
echo " CFLAGS = $CFLAGS"
echo " CPPFLAGS = $CPPFLAGS"
echo " CXX = $CXX"
echo " CXXFLAGS = $CXXFLAGS"
echo " LDFLAGS = $LDFLAGS"
echo ""

11
libqrencode.pc.in Normal file
View File

@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libqrencode
Description: A QR Code encoding library
Version: @VERSION@
Libs: -L${libdir} -lqrencode
Libs.private: @LIBPTHREAD@
Cflags: -I${includedir}

357
mask.c Normal file
View File

@ -0,0 +1,357 @@
/*
* qrencode - QR Code encoder
*
* Masking.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include "qrencode.h"
#include "qrspec.h"
#include "mask.h"
STATIC_IN_RELEASE int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level)
{
unsigned int format;
unsigned char v;
int i;
int blacks = 0;
format = QRspec_getFormatInfo(mask, level);
for(i = 0; i < 8; i++) {
if(format & 1) {
blacks += 2;
v = 0x85;
} else {
v = 0x84;
}
frame[width * 8 + width - 1 - i] = v;
if(i < 6) {
frame[width * i + 8] = v;
} else {
frame[width * (i + 1) + 8] = v;
}
format= format >> 1;
}
for(i = 0; i < 7; i++) {
if(format & 1) {
blacks += 2;
v = 0x85;
} else {
v = 0x84;
}
frame[width * (width - 7 + i) + 8] = v;
if(i == 0) {
frame[width * 8 + 7] = v;
} else {
frame[width * 8 + 6 - i] = v;
}
format= format >> 1;
}
return blacks;
}
/**
* Demerit coefficients.
* See Section 8.8.2, pp.45, JIS X0510:2004.
*/
#define N1 (3)
#define N2 (3)
#define N3 (40)
#define N4 (10)
#define MASKMAKER(__exp__) \
int x, y;\
int b = 0;\
\
for(y = 0; y < width; y++) {\
for(x = 0; x < width; x++) {\
if(*s & 0x80) {\
*d = *s;\
} else {\
*d = *s ^ ((__exp__) == 0);\
}\
b += (int)(*d & 1);\
s++; d++;\
}\
}\
return b;
static int Mask_mask0(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((x+y)&1)
}
static int Mask_mask1(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(y&1)
}
static int Mask_mask2(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(x%3)
}
static int Mask_mask3(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((x+y)%3)
}
static int Mask_mask4(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(((y/2)+(x/3))&1)
}
static int Mask_mask5(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(((x*y)&1)+(x*y)%3)
}
static int Mask_mask6(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((((x*y)&1)+(x*y)%3)&1)
}
static int Mask_mask7(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((((x*y)%3)+((x+y)&1))&1)
}
#define maskNum (8)
typedef int MaskMaker(int, const unsigned char *, unsigned char *);
static MaskMaker *maskMakers[maskNum] = {
Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3,
Mask_mask4, Mask_mask5, Mask_mask6, Mask_mask7
};
#ifdef WITH_TESTS
unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask)
{
unsigned char *masked;
masked = (unsigned char *)malloc((size_t)(width * width));
if(masked == NULL) return NULL;
maskMakers[mask](width, frame, masked);
return masked;
}
#endif
unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level)
{
unsigned char *masked;
if(mask < 0 || mask >= maskNum) {
errno = EINVAL;
return NULL;
}
masked = (unsigned char *)malloc((size_t)(width * width));
if(masked == NULL) return NULL;
maskMakers[mask](width, frame, masked);
Mask_writeFormatInformation(width, masked, mask, level);
return masked;
}
//static int n1;
//static int n2;
//static int n3;
//static int n4;
STATIC_IN_RELEASE int Mask_calcN1N3(int length, int *runLength)
{
int i;
int demerit = 0;
int fact;
for(i = 0; i < length; i++) {
if(runLength[i] >= 5) {
demerit += N1 + (runLength[i] - 5);
//n1 += N1 + (runLength[i] - 5);
}
if((i & 1)) {
if(i >= 3 && i < length-2 && (runLength[i] % 3) == 0) {
fact = runLength[i] / 3;
if(runLength[i-2] == fact &&
runLength[i-1] == fact &&
runLength[i+1] == fact &&
runLength[i+2] == fact) {
if(i == 3 || runLength[i-3] >= 4 * fact) {
demerit += N3;
//n3 += N3;
} else if(i+4 >= length || runLength[i+3] >= 4 * fact) {
demerit += N3;
//n3 += N3;
}
}
}
}
}
return demerit;
}
STATIC_IN_RELEASE int Mask_calcN2(int width, unsigned char *frame)
{
int x, y;
unsigned char *p;
unsigned char b22, w22;
int demerit = 0;
p = frame + width + 1;
for(y = 1; y < width; y++) {
for(x = 1; x < width; x++) {
b22 = p[0] & p[-1] & p[-width] & p [-width-1];
w22 = p[0] | p[-1] | p[-width] | p [-width-1];
if((b22 | (w22 ^ 1))&1) {
demerit += N2;
}
p++;
}
p++;
}
return demerit;
}
STATIC_IN_RELEASE int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength)
{
int head;
int i;
unsigned char prev;
if(frame[0] & 1) {
runLength[0] = -1;
head = 1;
} else {
head = 0;
}
runLength[head] = 1;
prev = frame[0];
for(i = 1; i < width; i++) {
if((frame[i] ^ prev) & 1) {
head++;
runLength[head] = 1;
prev = frame[i];
} else {
runLength[head]++;
}
}
return head + 1;
}
STATIC_IN_RELEASE int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength)
{
int head;
int i;
unsigned char prev;
if(frame[0] & 1) {
runLength[0] = -1;
head = 1;
} else {
head = 0;
}
runLength[head] = 1;
prev = frame[0];
for(i = 1; i < width; i++) {
if((frame[i * width] ^ prev) & 1) {
head++;
runLength[head] = 1;
prev = frame[i * width];
} else {
runLength[head]++;
}
}
return head + 1;
}
STATIC_IN_RELEASE int Mask_evaluateSymbol(int width, unsigned char *frame)
{
int x, y;
int demerit = 0;
int runLength[QRSPEC_WIDTH_MAX + 1];
int length;
demerit += Mask_calcN2(width, frame);
for(y = 0; y < width; y++) {
length = Mask_calcRunLengthH(width, frame + y * width, runLength);
demerit += Mask_calcN1N3(length, runLength);
}
for(x = 0; x < width; x++) {
length = Mask_calcRunLengthV(width, frame + x, runLength);
demerit += Mask_calcN1N3(length, runLength);
}
return demerit;
}
unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level)
{
int i;
unsigned char *mask, *bestMask;
int minDemerit = INT_MAX;
int blacks;
int bratio;
int demerit;
int w2 = width * width;
mask = (unsigned char *)malloc((size_t)w2);
if(mask == NULL) return NULL;
bestMask = (unsigned char *)malloc((size_t)w2);
if(bestMask == NULL) {
free(mask);
return NULL;
}
for(i = 0; i < maskNum; i++) {
// n1 = n2 = n3 = n4 = 0;
demerit = 0;
blacks = maskMakers[i](width, frame, mask);
blacks += Mask_writeFormatInformation(width, mask, i, level);
bratio = (200 * blacks + w2) / w2 / 2; /* (int)(100*blacks/w2+0.5) */
demerit = (abs(bratio - 50) / 5) * N4;
// n4 = demerit;
demerit += Mask_evaluateSymbol(width, mask);
// printf("(%d,%d,%d,%d)=%d\n", n1, n2, n3 ,n4, demerit);
if(demerit < minDemerit) {
minDemerit = demerit;
memcpy(bestMask, mask, (size_t)w2);
}
}
free(mask);
return bestMask;
}

38
mask.h Normal file
View File

@ -0,0 +1,38 @@
/*
* qrencode - QR Code encoder
*
* Masking.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef MASK_H
#define MASK_H
extern unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level);
extern unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level);
#ifdef WITH_TESTS
extern int Mask_calcN2(int width, unsigned char *frame);
extern int Mask_calcN1N3(int length, int *runLength);
extern int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength);
extern int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength);
extern int Mask_evaluateSymbol(int width, unsigned char *frame);
extern int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level);
extern unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask);
#endif
#endif /* MASK_H */

177
mmask.c Normal file
View File

@ -0,0 +1,177 @@
/*
* qrencode - QR Code encoder
*
* Masking for Micro QR Code.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include "qrencode.h"
#include "mqrspec.h"
#include "mmask.h"
STATIC_IN_RELEASE void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level)
{
unsigned int format;
unsigned char v;
int i;
format = MQRspec_getFormatInfo(mask, version, level);
for(i = 0; i < 8; i++) {
v = 0x84 | (format & 1);
frame[width * (i + 1) + 8] = v;
format = format >> 1;
}
for(i = 0; i < 7; i++) {
v = 0x84 | (format & 1);
frame[width * 8 + 7 - i] = v;
format = format >> 1;
}
}
#define MASKMAKER(__exp__) \
int x, y;\
\
for(y = 0; y < width; y++) {\
for(x = 0; x < width; x++) {\
if(*s & 0x80) {\
*d = *s;\
} else {\
*d = *s ^ ((__exp__) == 0);\
}\
s++; d++;\
}\
}
static void Mask_mask0(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(y&1)
}
static void Mask_mask1(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER(((y/2)+(x/3))&1)
}
static void Mask_mask2(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((((x*y)&1)+(x*y)%3)&1)
}
static void Mask_mask3(int width, const unsigned char *s, unsigned char *d)
{
MASKMAKER((((x+y)&1)+((x*y)%3))&1)
}
#define maskNum (4)
typedef void MaskMaker(int, const unsigned char *, unsigned char *);
static MaskMaker *maskMakers[maskNum] = {
Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3
};
#ifdef WITH_TESTS
unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask)
{
unsigned char *masked;
masked = (unsigned char *)malloc((size_t)(width * width));
if(masked == NULL) return NULL;
maskMakers[mask](width, frame, masked);
return masked;
}
#endif
unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level)
{
unsigned char *masked;
int width;
if(mask < 0 || mask >= maskNum) {
errno = EINVAL;
return NULL;
}
width = MQRspec_getWidth(version);
masked = (unsigned char *)malloc((size_t)(width * width));
if(masked == NULL) return NULL;
maskMakers[mask](width, frame, masked);
MMask_writeFormatInformation(version, width, masked, mask, level);
return masked;
}
STATIC_IN_RELEASE int MMask_evaluateSymbol(int width, unsigned char *frame)
{
int x, y;
unsigned char *p;
int sum1 = 0, sum2 = 0;
p = frame + width * (width - 1);
for(x = 1; x < width; x++) {
sum1 += (p[x] & 1);
}
p = frame + width * 2 - 1;
for(y = 1; y < width; y++) {
sum2 += (*p & 1);
p += width;
}
return (sum1 <= sum2)?(sum1 * 16 + sum2):(sum2 * 16 + sum1);
}
unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level)
{
int i;
unsigned char *mask, *bestMask;
int maxScore = 0;
int score;
int width;
width = MQRspec_getWidth(version);
mask = (unsigned char *)malloc((size_t)(width * width));
if(mask == NULL) return NULL;
bestMask = NULL;
for(i = 0; i < maskNum; i++) {
score = 0;
maskMakers[i](width, frame, mask);
MMask_writeFormatInformation(version, width, mask, i, level);
score = MMask_evaluateSymbol(width, mask);
if(score > maxScore) {
maxScore = score;
free(bestMask);
bestMask = mask;
mask = (unsigned char *)malloc((size_t)(width * width));
if(mask == NULL) break;
}
}
free(mask);
return bestMask;
}

34
mmask.h Normal file
View File

@ -0,0 +1,34 @@
/*
* qrencode - QR Code encoder
*
* Masking for Micro QR Code.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef MMASK_H
#define MMASK_H
extern unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level);
extern unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level);
#ifdef WITH_TESTS
extern int MMask_evaluateSymbol(int width, unsigned char *frame);
extern void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level);
extern unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask);
#endif
#endif /* MMASK_H */

232
mqrspec.c Normal file
View File

@ -0,0 +1,232 @@
/*
* qrencode - QR Code encoder
*
* Micro QR Code specification in convenient format.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* The following data / specifications are taken from
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
* or
* "Automatic identification and data capture techniques --
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "mqrspec.h"
/******************************************************************************
* Version and capacity
*****************************************************************************/
typedef struct {
int width; ///< Edge length of the symbol
int ec[4]; ///< Number of ECC code (bytes)
} MQRspec_Capacity;
/**
* Table of the capacity of symbols
* See Table 1 (pp.106) and Table 8 (pp.113) of Appendix 1, JIS X0510:2004.
*/
static const MQRspec_Capacity mqrspecCapacity[MQRSPEC_VERSION_MAX + 1] = {
{ 0, {0, 0, 0, 0}},
{ 11, {2, 0, 0, 0}},
{ 13, {5, 6, 0, 0}},
{ 15, {6, 8, 0, 0}},
{ 17, {8, 10, 14, 0}}
};
int MQRspec_getDataLengthBit(int version, QRecLevel level)
{
int w;
int ecc;
w = mqrspecCapacity[version].width - 1;
ecc = mqrspecCapacity[version].ec[level];
if(ecc == 0) return 0;
return w * w - 64 - ecc * 8;
}
int MQRspec_getDataLength(int version, QRecLevel level)
{
return (MQRspec_getDataLengthBit(version, level) + 4) / 8;
}
int MQRspec_getECCLength(int version, QRecLevel level)
{
return mqrspecCapacity[version].ec[level];
}
int MQRspec_getWidth(int version)
{
return mqrspecCapacity[version].width;
}
/******************************************************************************
* Length indicator
*****************************************************************************/
/**
* See Table 3 (pp.107) of Appendix 1, JIS X0510:2004.
*/
static const int lengthTableBits[4][4] = {
{ 3, 4, 5, 6},
{ 0, 3, 4, 5},
{ 0, 0, 4, 5},
{ 0, 0, 3, 4}
};
int MQRspec_lengthIndicator(QRencodeMode mode, int version)
{
return lengthTableBits[mode][version - 1];
}
int MQRspec_maximumWords(QRencodeMode mode, int version)
{
int bits;
int words;
bits = lengthTableBits[mode][version - 1];
words = (1 << bits) - 1;
if(mode == QR_MODE_KANJI) {
words *= 2; // the number of bytes is required
}
return words;
}
/******************************************************************************
* Format information
*****************************************************************************/
/* See calcFormatInfo in tests/test_mqrspec.c */
static const unsigned int formatInfo[4][8] = {
{0x4445, 0x55ae, 0x6793, 0x7678, 0x06de, 0x1735, 0x2508, 0x34e3},
{0x4172, 0x5099, 0x62a4, 0x734f, 0x03e9, 0x1202, 0x203f, 0x31d4},
{0x4e2b, 0x5fc0, 0x6dfd, 0x7c16, 0x0cb0, 0x1d5b, 0x2f66, 0x3e8d},
{0x4b1c, 0x5af7, 0x68ca, 0x7921, 0x0987, 0x186c, 0x2a51, 0x3bba}
};
/* See Table 10 of Appendix 1. (pp.115) */
static const int typeTable[MQRSPEC_VERSION_MAX + 1][3] = {
{-1, -1, -1},
{ 0, -1, -1},
{ 1, 2, -1},
{ 3, 4, -1},
{ 5, 6, 7}
};
unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level)
{
int type;
if(mask < 0 || mask > 3) return 0;
if(version <= 0 || version > MQRSPEC_VERSION_MAX) return 0;
if(level == QR_ECLEVEL_H) return 0;
type = typeTable[version][level];
if(type < 0) return 0;
return formatInfo[mask][type];
}
/******************************************************************************
* Frame
*****************************************************************************/
/**
* Put a finder pattern.
* @param frame
* @param width
* @param ox,oy upper-left coordinate of the pattern
*/
static void putFinderPattern(unsigned char *frame, int width, int ox, int oy)
{
static const unsigned char finder[] = {
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
};
int x, y;
const unsigned char *s;
frame += oy * width + ox;
s = finder;
for(y = 0; y < 7; y++) {
for(x = 0; x < 7; x++) {
frame[x] = s[x];
}
frame += width;
s += 7;
}
}
static unsigned char *MQRspec_createFrame(int version)
{
unsigned char *frame, *p, *q;
int width;
int x, y;
width = mqrspecCapacity[version].width;
frame = (unsigned char *)malloc((size_t)(width * width));
if(frame == NULL) return NULL;
memset(frame, 0, (size_t)(width * width));
/* Finder pattern */
putFinderPattern(frame, width, 0, 0);
/* Separator */
p = frame;
for(y = 0; y < 7; y++) {
p[7] = 0xc0;
p += width;
}
memset(frame + width * 7, 0xc0, 8);
/* Mask format information area */
memset(frame + width * 8 + 1, 0x84, 8);
p = frame + width + 8;
for(y = 0; y < 7; y++) {
*p = 0x84;
p += width;
}
/* Timing pattern */
p = frame + 8;
q = frame + width * 8;
for(x = 1; x < width-7; x++) {
*p = 0x90 | (x & 1);
*q = 0x90 | (x & 1);
p++;
q += width;
}
return frame;
}
unsigned char *MQRspec_newFrame(int version)
{
if(version < 1 || version > MQRSPEC_VERSION_MAX) return NULL;
return MQRspec_createFrame(version);
}

150
mqrspec.h Normal file
View File

@ -0,0 +1,150 @@
/*
* qrencode - QR Code encoder
*
* Micro QR Code specification in convenient format.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef MQRSPEC_H
#define MQRSPEC_H
#include "qrencode.h"
/******************************************************************************
* Version and capacity
*****************************************************************************/
/**
* Maximum width of a symbol
*/
#define MQRSPEC_WIDTH_MAX 17
/**
* Return maximum data code length (bits) for the version.
* @param version version of the symbol
* @param level error correction level
* @return maximum size (bits)
*/
extern int MQRspec_getDataLengthBit(int version, QRecLevel level);
/**
* Return maximum data code length (bytes) for the version.
* @param version version of the symbol
* @param level error correction level
* @return maximum size (bytes)
*/
extern int MQRspec_getDataLength(int version, QRecLevel level);
/**
* Return maximum error correction code length (bytes) for the version.
* @param version version of the symbol
* @param level error correction level
* @return ECC size (bytes)
*/
extern int MQRspec_getECCLength(int version, QRecLevel level);
/**
* Return a version number that satisfies the input code length.
* @param size input code length (byte)
* @param level error correction level
* @return version number
*/
extern int MQRspec_getMinimumVersion(int size, QRecLevel level);
/**
* Return the width of the symbol for the version.
* @param version version of the symbol
* @return width
*/
extern int MQRspec_getWidth(int version);
/**
* Return the numer of remainder bits.
* @param version version of the symbol
* @return number of remainder bits
*/
extern int MQRspec_getRemainder(int version);
/******************************************************************************
* Length indicator
*****************************************************************************/
/**
* Return the size of length indicator for the mode and version.
* @param mode encode mode
* @param version vesion of the symbol
* @return the size of the appropriate length indicator (bits).
*/
extern int MQRspec_lengthIndicator(QRencodeMode mode, int version);
/**
* Return the maximum length for the mode and version.
* @param mode encode mode
* @param version vesion of the symbol
* @return the maximum length (bytes)
*/
extern int MQRspec_maximumWords(QRencodeMode mode, int version);
/******************************************************************************
* Version information pattern
*****************************************************************************/
/**
* Return BCH encoded version information pattern that is used for the symbol
* of version 7 or greater. Use lower 18 bits.
* @param version vesion of the symbol
* @return BCH encoded version information pattern
*/
extern unsigned int MQRspec_getVersionPattern(int version);
/******************************************************************************
* Format information
*****************************************************************************/
/**
* Return BCH encoded format information pattern.
* @param mask mask number
* @param version version of the symbol
* @param level error correction level
* @return BCH encoded format information pattern
*/
extern unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level);
/******************************************************************************
* Frame
*****************************************************************************/
/**
* Return a copy of initialized frame.
* @param version version of the symbol
* @return Array of unsigned char. You can free it by free().
*/
extern unsigned char *MQRspec_newFrame(int version);
/******************************************************************************
* Mode indicator
*****************************************************************************/
/**
* Mode indicator. See Table 2 in Appendix 1 of JIS X0510:2004, pp.107.
*/
#define MQRSPEC_MODEID_NUM 0
#define MQRSPEC_MODEID_AN 1
#define MQRSPEC_MODEID_8 2
#define MQRSPEC_MODEID_KANJI 3
#endif /* MQRSPEC_H */

1453
qrenc.c Normal file

File diff suppressed because it is too large Load Diff

136
qrencode.1.in Normal file
View File

@ -0,0 +1,136 @@
.TH QRENCODE 1 "Aug. 28, 2020" "qrencode @VERSION@"
.SH NAME
qrencode \- Encode input data in a QR Code and save as a PNG or EPS image.
.SH SYNOPSIS
.B "qrencode"
[-o FILENAME]
[OPTION]...
[STRING]
.SH DESCRIPTION
Libqrencode is a library for encoding data in a QR Code symbol, a kind of 2D
symbology that can be scanned by handy terminals such as a mobile phone with
CCD. The capacity of QR Code is up to 7000 digits or 4000 characters, and has
high robustness.
Qrencode is a utility software using libqrencode to encode string data in
a QR Code and save as a PNG or EPS image.
.SH OPTIONS
.TP
.B \-h, \-\-help
display help message.
.TP
.B \-o FILENAME, \-\-output=FILENAME
write image to FILENAME. If '\-' is specified, the result will be output to standard output. If \-S is given, structured symbols are written to FILENAME-01.png, FILENAME-02.png, ... (suffix is removed from FILENAME, if specified)
.TP
.B \-r FILENAME, \-\-read\-from=FILENAME
read input data from FILENAME.
.TP
.B \-s NUMBER, \-\-size=NUMBER
specify the size of dot (pixel). (default=3)
.TP
.B \-l {LMQH}, \-\-level={LMQH}
specify error correction level from L (lowest) to H (highest). (default=L)
.TP
.B \-v NUMBER, \-\-symversion=NUMBER
specify the minimum version of the symbol. See SYMBOL VERSIONS for more information. (default=auto)
.TP
.B \-m NUMBER, \-\-margin=NUMBER
specify the width of margin. (default=4)
.TP
.B \-d NUMBER, \-\-dpi=NUMBER
specify the DPI of the generated PNG. (default=72)
.TP
.PD 0
.B \-t {PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8}
.TP
.PD
.B \-\-type={PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8}
specify the type of the generated image. (default=PNG)
.TP
.B \-S, \-\-structured
make structured symbols. Version number must be specified with '-v'.
.TP
.B \-k, \-\-kanji
assume that the input text contains kanji (shift-jis).
.TP
.B \-c, \-\-casesensitive
encode lower-case alphabet characters in 8-bit mode. (default)
.TP
.B \-i, \-\-ignorecase
ignore case distinctions and use only upper-case characters.
.TP
.B \-8, \-\-8bit
encode entire data in 8-bit mode. \-k, \-c and \-i will be ignored.
.TP
.B \-M, \-\-micro
encode in a Micro QR Code. See MICRO QR CODE for more information.
.TP
.B \-\-rle
enable run-length encoding for SVG.
.TP
.B \-\-svg-path
use single path to draw modules for SVG.
.TP
.B \-\-inline
only useful for SVG output, generates an SVG without the XML tag.
.TP
.PD 0
.B \-\-foreground=RRGGBB[AA]
.TP
.PD
.B \-\-background=RRGGBB[AA]
specify foreground/background color in hexadecimal notation.
6-digit (RGB) or 8-digit (RGBA) form are supported.
Color output support available only in PNG, EPS and SVG.
.TP
.B \-\-strict\-version
disable automatic version number adjustment. If the input data is
too large for the specified version, the program exits with the
code of 1.
.TP
.B \-V, \-\-version
display the version number and copyrights of the qrencode.
.TP
.B \-\-verbose
display verbose information to stderr.
.TP
.B [STRING]
input data. If it is not specified, data will be taken from standard input.
.SH SYMBOL VERSIONS
The symbol versions of QR Code range from Version 1 to Version 40.
Each version has a different module configuration or number of modules,
ranging from Version 1 (21 x 21 modules) up to Version 40 (177 x 177 modules).
Each higher version number comprises 4 additional modules per side by default.
See http://www.qrcode.com/en/about/version.html for a detailed version list.
.SH MICRO QR CODE
With Micro QR Code, You can embed data in a smaller area than with QR Code,
but the data capacity is strongly limited. The symbol versions range from
Version 1 to 4.
.SH EXAMPLES
.TP
.B qrencode \-l L \-v 1 \-o output.png 'Hello, world!'
encode into a symbol version 1, level L.
.TP
.B qrencode \-iSv 1 \-\-output=output.png
read standard input and encode it into a structured-appended symbols in
case-insensitive mode.
.TP
.B qrencode \-S \-v 40 \-l L \-r bigfile.txt \-o output.png
read input data from bigfile.txt and encode into a symbol version 40, level L.
.SH AUTHOR
Written by Kentaro Fukuchi.
.SH RESOURCES
.TP
Main Web Site: https://fukuchi.org/works/qrencode/
.TP
Source code repository: https://github.com/fukuchi/libqrencode/
.SH COPYRIGHT
Copyright (C) 2006-2018 Kentaro Fukuchi.

938
qrencode.c Normal file
View File

@ -0,0 +1,938 @@
/*
* qrencode - QR Code encoder
*
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "qrencode.h"
#include "qrspec.h"
#include "mqrspec.h"
#include "bitstream.h"
#include "qrinput.h"
#include "rsecc.h"
#include "split.h"
#include "mask.h"
#include "mmask.h"
/******************************************************************************
* Raw code
*****************************************************************************/
typedef struct {
int dataLength;
int eccLength;
unsigned char *data;
unsigned char *ecc;
} RSblock;
typedef struct {
int version;
int dataLength;
int eccLength;
unsigned char *datacode;
unsigned char *ecccode;
int b1;
int blocks;
RSblock *rsblock;
int count;
} QRRawCode;
static void RSblock_initBlock(RSblock *block, int dl, unsigned char *data, int el, unsigned char *ecc)
{
block->dataLength = dl;
block->data = data;
block->eccLength = el;
block->ecc = ecc;
RSECC_encode((size_t)dl, (size_t)el, data, ecc);
}
static int RSblock_init(RSblock *blocks, int spec[5], unsigned char *data, unsigned char *ecc)
{
int i;
RSblock *block;
unsigned char *dp, *ep;
int el, dl;
dl = QRspec_rsDataCodes1(spec);
el = QRspec_rsEccCodes1(spec);
block = blocks;
dp = data;
ep = ecc;
for(i = 0; i < QRspec_rsBlockNum1(spec); i++) {
RSblock_initBlock(block, dl, dp, el, ep);
dp += dl;
ep += el;
block++;
}
if(QRspec_rsBlockNum2(spec) == 0) return 0;
dl = QRspec_rsDataCodes2(spec);
el = QRspec_rsEccCodes2(spec);
for(i = 0; i < QRspec_rsBlockNum2(spec); i++) {
RSblock_initBlock(block, dl, dp, el, ep);
dp += dl;
ep += el;
block++;
}
return 0;
}
STATIC_IN_RELEASE void QRraw_free(QRRawCode *raw);
STATIC_IN_RELEASE QRRawCode *QRraw_new(QRinput *input)
{
QRRawCode *raw;
int spec[5], ret;
raw = (QRRawCode *)malloc(sizeof(QRRawCode));
if(raw == NULL) return NULL;
raw->datacode = QRinput_getByteStream(input);
if(raw->datacode == NULL) {
free(raw);
return NULL;
}
QRspec_getEccSpec(input->version, input->level, spec);
raw->version = input->version;
raw->b1 = QRspec_rsBlockNum1(spec);
raw->dataLength = QRspec_rsDataLength(spec);
raw->eccLength = QRspec_rsEccLength(spec);
raw->ecccode = (unsigned char *)malloc((size_t)raw->eccLength);
if(raw->ecccode == NULL) {
free(raw->datacode);
free(raw);
return NULL;
}
raw->blocks = QRspec_rsBlockNum(spec);
raw->rsblock = (RSblock *)calloc((size_t)(raw->blocks), sizeof(RSblock));
if(raw->rsblock == NULL) {
QRraw_free(raw);
return NULL;
}
ret = RSblock_init(raw->rsblock, spec, raw->datacode, raw->ecccode);
if(ret < 0) {
QRraw_free(raw);
return NULL;
}
raw->count = 0;
return raw;
}
/**
* Return a code (byte).
* This function can be called iteratively.
* @param raw raw code.
* @return code
*/
STATIC_IN_RELEASE unsigned char QRraw_getCode(QRRawCode *raw)
{
int col, row;
unsigned char ret;
if(raw->count < raw->dataLength) {
row = raw->count % raw->blocks;
col = raw->count / raw->blocks;
if(col >= raw->rsblock[0].dataLength) {
row += raw->b1;
}
ret = raw->rsblock[row].data[col];
} else if(raw->count < raw->dataLength + raw->eccLength) {
row = (raw->count - raw->dataLength) % raw->blocks;
col = (raw->count - raw->dataLength) / raw->blocks;
ret = raw->rsblock[row].ecc[col];
} else {
return 0;
}
raw->count++;
return ret;
}
STATIC_IN_RELEASE void QRraw_free(QRRawCode *raw)
{
if(raw != NULL) {
free(raw->datacode);
free(raw->ecccode);
free(raw->rsblock);
free(raw);
}
}
/******************************************************************************
* Raw code for Micro QR Code
*****************************************************************************/
typedef struct {
int version;
int dataLength;
int eccLength;
unsigned char *datacode;
unsigned char *ecccode;
RSblock *rsblock;
int oddbits;
int count;
} MQRRawCode;
STATIC_IN_RELEASE void MQRraw_free(MQRRawCode *raw);
STATIC_IN_RELEASE MQRRawCode *MQRraw_new(QRinput *input)
{
MQRRawCode *raw;
raw = (MQRRawCode *)malloc(sizeof(MQRRawCode));
if(raw == NULL) return NULL;
raw->version = input->version;
raw->dataLength = MQRspec_getDataLength(input->version, input->level);
raw->eccLength = MQRspec_getECCLength(input->version, input->level);
raw->oddbits = raw->dataLength * 8 - MQRspec_getDataLengthBit(input->version, input->level);
raw->datacode = QRinput_getByteStream(input);
if(raw->datacode == NULL) {
free(raw);
return NULL;
}
raw->ecccode = (unsigned char *)malloc((size_t)raw->eccLength);
if(raw->ecccode == NULL) {
free(raw->datacode);
free(raw);
return NULL;
}
raw->rsblock = (RSblock *)calloc(1, sizeof(RSblock));
if(raw->rsblock == NULL) {
MQRraw_free(raw);
return NULL;
}
RSblock_initBlock(raw->rsblock, raw->dataLength, raw->datacode, raw->eccLength, raw->ecccode);
raw->count = 0;
return raw;
}
/**
* Return a code (byte).
* This function can be called iteratively.
* @param raw raw code.
* @return code
*/
STATIC_IN_RELEASE unsigned char MQRraw_getCode(MQRRawCode *raw)
{
unsigned char ret;
if(raw->count < raw->dataLength) {
ret = raw->datacode[raw->count];
} else if(raw->count < raw->dataLength + raw->eccLength) {
ret = raw->ecccode[raw->count - raw->dataLength];
} else {
return 0;
}
raw->count++;
return ret;
}
STATIC_IN_RELEASE void MQRraw_free(MQRRawCode *raw)
{
if(raw != NULL) {
free(raw->datacode);
free(raw->ecccode);
free(raw->rsblock);
free(raw);
}
}
/******************************************************************************
* Frame filling
*****************************************************************************/
typedef struct {
int width;
unsigned char *frame;
int x, y;
int dir;
int bit;
int mqr;
} FrameFiller;
static void FrameFiller_set(FrameFiller *filler, int width, unsigned char *frame, int mqr)
{
filler->width = width;
filler->frame = frame;
filler->x = width - 1;
filler->y = width - 1;
filler->dir = -1;
filler->bit = -1;
filler->mqr = mqr;
}
static unsigned char *FrameFiller_next(FrameFiller *filler)
{
unsigned char *p;
int x, y, w;
if(filler->bit == -1) {
filler->bit = 0;
return filler->frame + filler->y * filler->width + filler->x;
}
x = filler->x;
y = filler->y;
p = filler->frame;
w = filler->width;
if(filler->bit == 0) {
x--;
filler->bit++;
} else {
x++;
y += filler->dir;
filler->bit--;
}
if(filler->dir < 0) {
if(y < 0) {
y = 0;
x -= 2;
filler->dir = 1;
if(!filler->mqr && x == 6) {
x--;
y = 9;
}
}
} else if(y == w) {
y = w - 1;
x -= 2;
filler->dir = -1;
if(!filler->mqr && x == 6) {
x--;
y -= 8;
}
}
if(x < 0 || y < 0) return NULL;
filler->x = x;
filler->y = y;
if(p[y * w + x] & 0x80) {
// This tail recursion could be optimized.
return FrameFiller_next(filler);
}
return &p[y * w + x];
}
#ifdef WITH_TESTS
unsigned char *FrameFiller_test(int version)
{
int width;
unsigned char *frame, *p;
int i, length;
FrameFiller filler;
width = QRspec_getWidth(version);
frame = QRspec_newFrame(version);
if(frame == NULL) return NULL;
FrameFiller_set(&filler, width, frame, 0);
length = QRspec_getDataLength(version, QR_ECLEVEL_L) * 8
+ QRspec_getECCLength(version, QR_ECLEVEL_L) * 8
+ QRspec_getRemainder(version);
for(i = 0; i < length; i++) {
p = FrameFiller_next(&filler);
if(p == NULL) {
free(frame);
return NULL;
}
*p = (unsigned char)(i & 0x7f) | 0x80;
}
return frame;
}
unsigned char *FrameFiller_testMQR(int version)
{
int width;
unsigned char *frame, *p;
int i, length;
FrameFiller filler;
width = MQRspec_getWidth(version);
frame = MQRspec_newFrame(version);
if(frame == NULL) return NULL;
FrameFiller_set(&filler, width, frame, 1);
length = MQRspec_getDataLengthBit(version, QR_ECLEVEL_L)
+ MQRspec_getECCLength(version, QR_ECLEVEL_L) * 8;
for(i = 0; i < length; i++) {
p = FrameFiller_next(&filler);
if(p == NULL) {
fprintf(stderr, "Frame filler run over the frame!\n");
return frame;
}
*p = (unsigned char)(i & 0x7f) | 0x80;
}
return frame;
}
#endif
/******************************************************************************
* QR-code encoding
*****************************************************************************/
STATIC_IN_RELEASE QRcode *QRcode_new(int version, int width, unsigned char *data)
{
QRcode *qrcode;
qrcode = (QRcode *)malloc(sizeof(QRcode));
if(qrcode == NULL) return NULL;
qrcode->version = version;
qrcode->width = width;
qrcode->data = data;
return qrcode;
}
void QRcode_free(QRcode *qrcode)
{
if(qrcode != NULL) {
free(qrcode->data);
free(qrcode);
}
}
STATIC_IN_RELEASE QRcode *QRcode_encodeMask(QRinput *input, int mask)
{
int width, version;
QRRawCode *raw;
unsigned char *frame, *masked, *p, code, bit;
int i, j;
QRcode *qrcode = NULL;
FrameFiller filler;
if(input->mqr) {
errno = EINVAL;
return NULL;
}
if(input->version < 0 || input->version > QRSPEC_VERSION_MAX) {
errno = EINVAL;
return NULL;
}
if(!(input->level >= QR_ECLEVEL_L && input->level <= QR_ECLEVEL_H)) {
errno = EINVAL;
return NULL;
}
raw = QRraw_new(input);
if(raw == NULL) return NULL;
version = raw->version;
width = QRspec_getWidth(version);
frame = QRspec_newFrame(version);
if(frame == NULL) {
QRraw_free(raw);
return NULL;
}
FrameFiller_set(&filler, width, frame, 0);
/* interleaved data and ecc codes */
for(i = 0; i < raw->dataLength; i++) {
code = QRraw_getCode(raw);
bit = 0x80;
for(j = 0; j < 8; j++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = ((bit & code) != 0);
bit = bit >> 1;
}
}
for(i = 0; i < raw->eccLength; i++) {
code = QRraw_getCode(raw);
bit = 0x80;
for(j = 0; j < 8; j++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = 0x02 | ((bit & code) != 0);
bit = bit >> 1;
}
}
QRraw_free(raw);
raw = NULL;
/* remainder bits */
j = QRspec_getRemainder(version);
for(i = 0; i < j; i++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = 0x02;
}
/* masking */
if(mask == -2) { // just for debug purpose
masked = (unsigned char *)malloc((size_t)(width * width));
memcpy(masked, frame, (size_t)(width * width));
} else if(mask < 0) {
masked = Mask_mask(width, frame, input->level);
} else {
masked = Mask_makeMask(width, frame, mask, input->level);
}
if(masked == NULL) {
goto EXIT;
}
qrcode = QRcode_new(version, width, masked);
if(qrcode == NULL) {
free(masked);
}
EXIT:
QRraw_free(raw);
free(frame);
return qrcode;
}
STATIC_IN_RELEASE QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask)
{
int width, version;
MQRRawCode *raw;
unsigned char *frame, *masked, *p, code, bit;
int i, j, length;
QRcode *qrcode = NULL;
FrameFiller filler;
if(!input->mqr) {
errno = EINVAL;
return NULL;
}
if(input->version <= 0 || input->version > MQRSPEC_VERSION_MAX) {
errno = EINVAL;
return NULL;
}
if(!(input->level >= QR_ECLEVEL_L && input->level <= QR_ECLEVEL_Q)) {
errno = EINVAL;
return NULL;
}
raw = MQRraw_new(input);
if(raw == NULL) return NULL;
version = raw->version;
width = MQRspec_getWidth(version);
frame = MQRspec_newFrame(version);
if(frame == NULL) {
MQRraw_free(raw);
return NULL;
}
FrameFiller_set(&filler, width, frame, 1);
/* interleaved data and ecc codes */
for(i = 0; i < raw->dataLength; i++) {
code = MQRraw_getCode(raw);
bit = 0x80;
if(raw->oddbits && i == raw->dataLength - 1) {
length = raw->oddbits;
} else {
length = 8;
}
for(j = 0; j < length; j++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = ((bit & code) != 0);
bit = bit >> 1;
}
}
for(i = 0; i < raw->eccLength; i++) {
code = MQRraw_getCode(raw);
bit = 0x80;
length = 8;
for(j = 0; j < length; j++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = 0x02 | ((bit & code) != 0);
bit = bit >> 1;
}
}
MQRraw_free(raw);
raw = NULL;
/* masking */
if(mask == -2) { // just for debug purpose
masked = (unsigned char *)malloc((size_t)(width * width));
memcpy(masked, frame, (size_t)(width * width));
} else if(mask < 0) {
masked = MMask_mask(version, frame, input->level);
} else {
masked = MMask_makeMask(version, frame, mask, input->level);
}
if(masked == NULL) {
goto EXIT;
}
qrcode = QRcode_new(version, width, masked);
if(qrcode == NULL) {
free(masked);
}
EXIT:
MQRraw_free(raw);
free(frame);
return qrcode;
}
QRcode *QRcode_encodeInput(QRinput *input)
{
if(input->mqr) {
return QRcode_encodeMaskMQR(input, -1);
} else {
return QRcode_encodeMask(input, -1);
}
}
static QRcode *QRcode_encodeStringReal(const char *string, int version, QRecLevel level, int mqr, QRencodeMode hint, int casesensitive)
{
QRinput *input;
QRcode *code;
int ret;
if(string == NULL) {
errno = EINVAL;
return NULL;
}
if(hint != QR_MODE_8 && hint != QR_MODE_KANJI) {
errno = EINVAL;
return NULL;
}
if(mqr) {
input = QRinput_newMQR(version, level);
} else {
input = QRinput_new2(version, level);
}
if(input == NULL) return NULL;
ret = Split_splitStringToQRinput(string, input, hint, casesensitive);
if(ret < 0) {
QRinput_free(input);
return NULL;
}
code = QRcode_encodeInput(input);
QRinput_free(input);
return code;
}
QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
{
return QRcode_encodeStringReal(string, version, level, 0, hint, casesensitive);
}
QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
{
int i;
if(version == 0) {
version = 1;
}
for(i = version; i <= MQRSPEC_VERSION_MAX ; i++) {
QRcode *code = QRcode_encodeStringReal(string, i, level, 1, hint, casesensitive);
if(code != NULL) return code;
}
return NULL;
}
static QRcode *QRcode_encodeDataReal(const unsigned char *data, int length, int version, QRecLevel level, int mqr)
{
QRinput *input;
QRcode *code;
int ret;
if(data == NULL || length == 0) {
errno = EINVAL;
return NULL;
}
if(mqr) {
input = QRinput_newMQR(version, level);
} else {
input = QRinput_new2(version, level);
}
if(input == NULL) return NULL;
ret = QRinput_append(input, QR_MODE_8, length, data);
if(ret < 0) {
QRinput_free(input);
return NULL;
}
code = QRcode_encodeInput(input);
QRinput_free(input);
return code;
}
QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level)
{
return QRcode_encodeDataReal(data, size, version, level, 0);
}
QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level)
{
if(string == NULL) {
errno = EINVAL;
return NULL;
}
return QRcode_encodeDataReal((unsigned char *)string, (int)strlen(string), version, level, 0);
}
QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level)
{
int i;
if(version == 0) {
version = 1;
}
for(i = version; i <= MQRSPEC_VERSION_MAX; i++) {
QRcode *code = QRcode_encodeDataReal(data, size, i, level, 1);
if(code != NULL) return code;
}
return NULL;
}
QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level)
{
int i;
if(string == NULL) {
errno = EINVAL;
return NULL;
}
if(version == 0) {
version = 1;
}
for(i = version; i <= MQRSPEC_VERSION_MAX; i++) {
QRcode *code = QRcode_encodeDataReal((unsigned char *)string, (int)strlen(string), i, level, 1);
if(code != NULL) return code;
}
return NULL;
}
/******************************************************************************
* Structured QR-code encoding
*****************************************************************************/
static QRcode_List *QRcode_List_newEntry(void)
{
QRcode_List *entry;
entry = (QRcode_List *)malloc(sizeof(QRcode_List));
if(entry == NULL) return NULL;
entry->next = NULL;
entry->code = NULL;
return entry;
}
static void QRcode_List_freeEntry(QRcode_List *entry)
{
if(entry != NULL) {
QRcode_free(entry->code);
free(entry);
}
}
void QRcode_List_free(QRcode_List *qrlist)
{
QRcode_List *list = qrlist, *next;
while(list != NULL) {
next = list->next;
QRcode_List_freeEntry(list);
list = next;
}
}
int QRcode_List_size(QRcode_List *qrlist)
{
QRcode_List *list = qrlist;
int size = 0;
while(list != NULL) {
size++;
list = list->next;
}
return size;
}
#if 0
static unsigned char QRcode_parity(const char *str, int size)
{
unsigned char parity = 0;
int i;
for(i = 0; i < size; i++) {
parity ^= str[i];
}
return parity;
}
#endif
QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s)
{
QRcode_List *head = NULL;
QRcode_List *tail = NULL;
QRcode_List *entry;
QRinput_InputList *list = s->head;
while(list != NULL) {
if(head == NULL) {
entry = QRcode_List_newEntry();
if(entry == NULL) goto ABORT;
head = entry;
tail = head;
} else {
entry = QRcode_List_newEntry();
if(entry == NULL) goto ABORT;
tail->next = entry;
tail = tail->next;
}
tail->code = QRcode_encodeInput(list->input);
if(tail->code == NULL) {
goto ABORT;
}
list = list->next;
}
return head;
ABORT:
QRcode_List_free(head);
return NULL;
}
static QRcode_List *QRcode_encodeInputToStructured(QRinput *input)
{
QRinput_Struct *s;
QRcode_List *codes;
s = QRinput_splitQRinputToStruct(input);
if(s == NULL) return NULL;
codes = QRcode_encodeInputStructured(s);
QRinput_Struct_free(s);
return codes;
}
static QRcode_List *QRcode_encodeDataStructuredReal(
int size, const unsigned char *data,
int version, QRecLevel level,
int eightbit, QRencodeMode hint, int casesensitive)
{
QRinput *input;
QRcode_List *codes;
int ret;
if(version <= 0) {
errno = EINVAL;
return NULL;
}
if(!eightbit && (hint != QR_MODE_8 && hint != QR_MODE_KANJI)) {
errno = EINVAL;
return NULL;
}
input = QRinput_new2(version, level);
if(input == NULL) return NULL;
if(eightbit) {
ret = QRinput_append(input, QR_MODE_8, size, data);
} else {
ret = Split_splitStringToQRinput((char *)data, input, hint, casesensitive);
}
if(ret < 0) {
QRinput_free(input);
return NULL;
}
codes = QRcode_encodeInputToStructured(input);
QRinput_free(input);
return codes;
}
QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level) {
return QRcode_encodeDataStructuredReal(size, data, version, level, 1, QR_MODE_NUL, 0);
}
QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level) {
if(string == NULL) {
errno = EINVAL;
return NULL;
}
return QRcode_encodeDataStructured((int)strlen(string), (unsigned char *)string, version, level);
}
QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
{
if(string == NULL) {
errno = EINVAL;
return NULL;
}
return QRcode_encodeDataStructuredReal((int)strlen(string), (unsigned char *)string, version, level, 0, hint, casesensitive);
}
/******************************************************************************
* System utilities
*****************************************************************************/
void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version)
{
if(major_version != NULL) {
*major_version = MAJOR_VERSION;
}
if(minor_version != NULL) {
*minor_version = MINOR_VERSION;
}
if(micro_version != NULL) {
*micro_version = MICRO_VERSION;
}
}
char *QRcode_APIVersionString(void)
{
return VERSION;
}
void QRcode_clearCache(void)
{
return;
}

568
qrencode.h Normal file
View File

@ -0,0 +1,568 @@
/**
* qrencode - QR Code encoder
*
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** \mainpage
* Libqrencode is a library for encoding data in a QR Code symbol, a kind of 2D
* symbology.
*
* \section encoding Encoding
*
* There are two methods to encode data: <b>encoding a string/data</b> or
* <b>encoding a structured data</b>.
*
* \subsection encoding-string Encoding a string/data
* You can encode a string by calling QRcode_encodeString().
* The given string is parsed automatically and encoded. If you want to encode
* data that can be represented as a C string style (NUL terminated), you can
* simply use this way.
*
* If the input data contains Kanji (Shift-JIS) characters and you want to
* encode them as Kanji in QR Code, you should give QR_MODE_KANJI as a hint.
* Otherwise, all of non-alphanumeric characters are encoded as 8-bit data.
* If you want to encode a whole string in 8-bit mode, you can use
* QRcode_encodeString8bit() instead.
*
* Please note that a C string can not contain NUL characters. If your data
* contains NUL, you must use QRcode_encodeData().
*
* \subsection encoding-input Encoding a structured data
* You can construct a structured input data manually. If the structure of the
* input data is known, you can use this method.
* At first, create a ::QRinput object by QRinput_new(). Then add input data
* to the QRinput object by QRinput_append(). Finally call QRcode_encodeInput()
* to encode the QRinput data.
* You can reuse the QRinput object again to encode it in other symbols with
* different parameters.
*
* \section result Result
* The encoded symbol is generated as a ::QRcode object. It will contain its
* version number, the width of the symbol, and an array represents the symbol.
* See ::QRcode for the details. You can free the object by QRcode_free().
*
* Please note that the version of the result may be larger than specified.
* In such cases, the input data would be too large to be encoded in a
* symbol of the specified version.
*
* \section structured Structured append
* Libqrencode can generate "Structured-appended" symbols that enables to split
* a large data set into mulitple QR codes. A QR code reader concatenates
* multiple QR code symbols into a string.
* Just like QRcode_encodeString(), you can use QRcode_encodeStringStructured()
* to generate structured-appended symbols. This functions returns an instance
* of ::QRcode_List. The returned list is a singly-linked list of QRcode: you
* can retrieve each QR code in this way:
*
* \code
* QRcode_List *qrcodes;
* QRcode_List *entry;
* QRcode *qrcode;
*
* qrcodes = QRcode_encodeStringStructured(...);
* entry = qrcodes;
* while(entry != NULL) {
* qrcode = entry->code;
* // do something
* entry = entry->next;
* }
* QRcode_List_free(entry);
* \endcode
*
* Instead of using auto-parsing functions, you can construct your own
* structured input. At first, instantiate an object of ::QRinput_Struct
* by calling QRinput_Struct_new(). This object can hold multiple ::QRinput,
* and one QR code is generated for a ::QRinput.
* QRinput_Struct_appendInput() appends a ::QRinput to a ::QRinput_Struct
* object. In order to generate structured-appended symbols, it is required to
* embed headers to each symbol. You can use
* QRinput_Struct_insertStructuredAppendHeaders() to insert appropriate
* headers to each symbol. You should call this function just once before
* encoding symbols.
*/
#ifndef QRENCODE_H
#define QRENCODE_H
#if defined(__cplusplus)
extern "C" {
#endif
/**
* Encoding mode.
*/
typedef enum {
QR_MODE_NUL = -1, ///< Terminator (NUL character). Internal use only
QR_MODE_NUM = 0, ///< Numeric mode
QR_MODE_AN, ///< Alphabet-numeric mode
QR_MODE_8, ///< 8-bit data mode
QR_MODE_KANJI, ///< Kanji (shift-jis) mode
QR_MODE_STRUCTURE, ///< Internal use only
QR_MODE_ECI, ///< ECI mode
QR_MODE_FNC1FIRST, ///< FNC1, first position
QR_MODE_FNC1SECOND, ///< FNC1, second position
} QRencodeMode;
/**
* Level of error correction.
*/
typedef enum {
QR_ECLEVEL_L = 0, ///< lowest
QR_ECLEVEL_M,
QR_ECLEVEL_Q,
QR_ECLEVEL_H ///< highest
} QRecLevel;
/**
* Maximum version (size) of QR-code symbol.
*/
#define QRSPEC_VERSION_MAX 40
/**
* Maximum version (size) of QR-code symbol.
*/
#define MQRSPEC_VERSION_MAX 4
/******************************************************************************
* Input data (qrinput.c)
*****************************************************************************/
/**
* Singly linked list to contain input strings. An instance of this class
* contains its version and error correction level too. It is required to
* set them by QRinput_setVersion() and QRinput_setErrorCorrectionLevel(),
* or use QRinput_new2() to instantiate an object.
*/
typedef struct _QRinput QRinput;
/**
* Instantiate an input data object. The version is set to 0 (auto-select)
* and the error correction level is set to QR_ECLEVEL_L.
* @return an input object (initialized). On error, NULL is returned and errno
* is set to indicate the error.
* @throw ENOMEM unable to allocate memory.
*/
extern QRinput *QRinput_new(void);
/**
* Instantiate an input data object.
* @param version version number.
* @param level Error correction level.
* @return an input object (initialized). On error, NULL is returned and errno
* is set to indicate the error.
* @throw ENOMEM unable to allocate memory for input objects.
* @throw EINVAL invalid arguments.
*/
extern QRinput *QRinput_new2(int version, QRecLevel level);
/**
* Instantiate an input data object. Object's Micro QR Code flag is set.
* Unlike with full-sized QR Code, version number must be specified (>0).
* @param version version number (1--4).
* @param level Error correction level.
* @return an input object (initialized). On error, NULL is returned and errno
* is set to indicate the error.
* @throw ENOMEM unable to allocate memory for input objects.
* @throw EINVAL invalid arguments.
*/
extern QRinput *QRinput_newMQR(int version, QRecLevel level);
/**
* Append data to an input object.
* The data is copied and appended to the input object.
* @param input input object.
* @param mode encoding mode.
* @param size size of data (byte).
* @param data a pointer to the memory area of the input data.
* @retval 0 success.
* @retval -1 an error occurred and errno is set to indeicate the error.
* See Execptions for the details.
* @throw ENOMEM unable to allocate memory.
* @throw EINVAL input data is invalid.
*
*/
extern int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data);
/**
* Append ECI header.
* @param input input object.
* @param ecinum ECI indicator number (0 - 999999)
* @retval 0 success.
* @retval -1 an error occurred and errno is set to indeicate the error.
* See Execptions for the details.
* @throw ENOMEM unable to allocate memory.
* @throw EINVAL input data is invalid.
*
*/
extern int QRinput_appendECIheader(QRinput *input, unsigned int ecinum);
/**
* Get current version.
* @param input input object.
* @return current version.
*/
extern int QRinput_getVersion(QRinput *input);
/**
* Set version of the QR code that is to be encoded.
* This function cannot be applied to Micro QR Code.
* @param input input object.
* @param version version number (0 = auto)
* @retval 0 success.
* @retval -1 invalid argument.
*/
extern int QRinput_setVersion(QRinput *input, int version);
/**
* Get current error correction level.
* @param input input object.
* @return Current error correcntion level.
*/
extern QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input);
/**
* Set error correction level of the QR code that is to be encoded.
* This function cannot be applied to Micro QR Code.
* @param input input object.
* @param level Error correction level.
* @retval 0 success.
* @retval -1 invalid argument.
*/
extern int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level);
/**
* Set version and error correction level of the QR code at once.
* This function is recommened for Micro QR Code.
* @param input input object.
* @param version version number (0 = auto)
* @param level Error correction level.
* @retval 0 success.
* @retval -1 invalid argument.
*/
extern int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level);
/**
* Free the input object.
* All of data chunks in the input object are freed too.
* @param input input object.
*/
extern void QRinput_free(QRinput *input);
/**
* Validate the input data.
* @param mode encoding mode.
* @param size size of data (byte).
* @param data a pointer to the memory area of the input data.
* @retval 0 success.
* @retval -1 invalid arguments.
*/
extern int QRinput_check(QRencodeMode mode, int size, const unsigned char *data);
/**
* Set of QRinput for structured symbols.
*/
typedef struct _QRinput_Struct QRinput_Struct;
/**
* Instantiate a set of input data object.
* @return an instance of QRinput_Struct. On error, NULL is returned and errno
* is set to indicate the error.
* @throw ENOMEM unable to allocate memory.
*/
extern QRinput_Struct *QRinput_Struct_new(void);
/**
* Set parity of structured symbols.
* @param s structured input object.
* @param parity parity of s.
*/
extern void QRinput_Struct_setParity(QRinput_Struct *s, unsigned char parity);
/**
* Append a QRinput object to the set. QRinput created by QRinput_newMQR()
* will be rejected.
* @warning never append the same QRinput object twice or more.
* @param s structured input object.
* @param input an input object.
* @retval >0 number of input objects in the structure.
* @retval -1 an error occurred. See Exceptions for the details.
* @throw ENOMEM unable to allocate memory.
* @throw EINVAL invalid arguments.
*/
extern int QRinput_Struct_appendInput(QRinput_Struct *s, QRinput *input);
/**
* Free all of QRinput in the set.
* @param s a structured input object.
*/
extern void QRinput_Struct_free(QRinput_Struct *s);
/**
* Split a QRinput to QRinput_Struct. It calculates a parity, set it, then
* insert structured-append headers. QRinput created by QRinput_newMQR() will
* be rejected.
* @param input input object. Version number and error correction level must be
* set.
* @return a set of input data. On error, NULL is returned, and errno is set
* to indicate the error. See Exceptions for the details.
* @throw ERANGE input data is too large.
* @throw EINVAL invalid input data.
* @throw ENOMEM unable to allocate memory.
*/
extern QRinput_Struct *QRinput_splitQRinputToStruct(QRinput *input);
/**
* Insert structured-append headers to the input structure. It calculates
* a parity and set it if the parity is not set yet.
* @param s input structure
* @retval 0 success.
* @retval -1 an error occurred and errno is set to indeicate the error.
* See Execptions for the details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory.
*/
extern int QRinput_Struct_insertStructuredAppendHeaders(QRinput_Struct *s);
/**
* Set FNC1-1st position flag.
*/
extern int QRinput_setFNC1First(QRinput *input);
/**
* Set FNC1-2nd position flag and application identifier.
*/
extern int QRinput_setFNC1Second(QRinput *input, unsigned char appid);
/******************************************************************************
* QRcode output (qrencode.c)
*****************************************************************************/
/**
* QRcode class.
* Symbol data is represented as an array contains width*width uchars.
* Each uchar represents a module (dot). If the less significant bit of
* the uchar is 1, the corresponding module is black. The other bits are
* meaningless for usual applications, but here its specification is described.
*
* @verbatim
MSB 76543210 LSB
|||||||`- 1=black/0=white
||||||`-- 1=ecc/0=data code area
|||||`--- format information
||||`---- version information
|||`----- timing pattern
||`------ alignment pattern
|`------- finder pattern and separator
`-------- non-data modules (format, timing, etc.)
@endverbatim
*/
typedef struct {
int version; ///< version of the symbol
int width; ///< width of the symbol
unsigned char *data; ///< symbol data
} QRcode;
/**
* Singly-linked list of QRcode. Used to represent a structured symbols.
* A list is terminated with NULL.
*/
typedef struct _QRcode_List {
QRcode *code;
struct _QRcode_List *next;
} QRcode_List;
/**
* Create a symbol from the input data.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param input input data.
* @return an instance of QRcode class. The version of the result QRcode may
* be larger than the designated version. On error, NULL is returned,
* and errno is set to indicate the error. See Exceptions for the
* details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
*/
extern QRcode *QRcode_encodeInput(QRinput *input);
/**
* Create a symbol from the string. The library automatically parses the input
* string and encodes in a QR Code symbol.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param string input string. It must be NUL terminated.
* @param version version of the symbol. If 0, the library chooses the minimum
* version for the given input data.
* @param level error correction level.
* @param hint tell the library how Japanese Kanji characters should be
* encoded. If QR_MODE_KANJI is given, the library assumes that the
* given string contains Shift-JIS characters and encodes them in
* Kanji-mode. If QR_MODE_8 is given, all of non-alphanumerical
* characters will be encoded as is. If you want to embed UTF-8
* string, choose this. Other mode will cause EINVAL error.
* @param casesensitive case-sensitive(1) or not(0).
* @return an instance of QRcode class. The version of the result QRcode may
* be larger than the designated version. On error, NULL is returned,
* and errno is set to indicate the error. See Exceptions for the
* details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
* @throw ERANGE input data is too large.
*/
extern QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
/**
* Same to QRcode_encodeString(), but encode whole data in 8-bit mode.
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level);
/**
* Micro QR Code version of QRcode_encodeString().
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
/**
* Micro QR Code version of QRcode_encodeString8bit().
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level);
/**
* Encode byte stream (may include '\0') in 8-bit mode.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param size size of the input data.
* @param data input data.
* @param version version of the symbol. If 0, the library chooses the minimum
* version for the given input data.
* @param level error correction level.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
* @throw ERANGE input data is too large.
*/
extern QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level);
/**
* Micro QR Code version of QRcode_encodeData().
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level);
/**
* Free the instance of QRcode class.
* @param qrcode an instance of QRcode class.
*/
extern void QRcode_free(QRcode *qrcode);
/**
* Create structured symbols from the input data.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param s input data, structured.
* @return a singly-linked list of QRcode.
*/
extern QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s);
/**
* Create structured symbols from the string. The library automatically parses
* the input string and encodes in a QR Code symbol.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param string input string. It must be NUL terminated.
* @param version version of the symbol.
* @param level error correction level.
* @param hint tell the library how Japanese Kanji characters should be
* encoded. If QR_MODE_KANJI is given, the library assumes that the
* given string contains Shift-JIS characters and encodes them in
* Kanji-mode. If QR_MODE_8 is given, all of non-alphanumerical
* characters will be encoded as is. If you want to embed UTF-8
* string, choose this. Other mode will cause EINVAL error.
* @param casesensitive case-sensitive(1) or not(0).
* @return a singly-linked list of QRcode. On error, NULL is returned, and
* errno is set to indicate the error. See Exceptions for the details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
*/
extern QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
/**
* Same to QRcode_encodeStringStructured(), but encode whole data in 8-bit mode.
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level);
/**
* Create structured symbols from byte stream (may include '\0'). Wholde data
* are encoded in 8-bit mode.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param size size of the input data.
* @param data input dat.
* @param version version of the symbol.
* @param level error correction level.
* @return a singly-linked list of QRcode. On error, NULL is returned, and
* errno is set to indicate the error. See Exceptions for the details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
*/
extern QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level);
/**
* Return the number of symbols included in a QRcode_List.
* @param qrlist a head entry of a QRcode_List.
* @return number of symbols in the list.
*/
extern int QRcode_List_size(QRcode_List *qrlist);
/**
* Free the QRcode_List.
* @param qrlist a head entry of a QRcode_List.
*/
extern void QRcode_List_free(QRcode_List *qrlist);
/******************************************************************************
* System utilities
*****************************************************************************/
/**
* Return a string that identifies the library version.
* @param major_version major version number
* @param minor_version minor version number
* @param micro_version micro version number
*/
extern void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version);
/**
* Return a string that identifies the library version.
* @return a string identifies the library version. The string is held by the
* library. Do NOT free it.
*/
extern char *QRcode_APIVersionString(void);
/**
* @deprecated
*/
#ifndef _MSC_VER
extern void QRcode_clearCache(void) __attribute__ ((deprecated));
#else
extern void QRcode_clearCache(void);
#endif
#if defined(__cplusplus)
}
#endif
#endif /* QRENCODE_H */

88
qrencode_inner.h Normal file
View File

@ -0,0 +1,88 @@
/**
* qrencode - QR Code encoder
*
* Header for test use
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef QRENCODE_INNER_H
#define QRENCODE_INNER_H
/**
* This header file includes definitions for test use.
*/
/******************************************************************************
* Raw code
*****************************************************************************/
typedef struct {
int dataLength;
int eccLength;
unsigned char *data;
unsigned char *ecc;
} RSblock;
typedef struct {
int version;
int dataLength;
int eccLength;
unsigned char *datacode;
unsigned char *ecccode;
int b1;
int blocks;
RSblock *rsblock;
int count;
} QRRawCode;
extern QRRawCode *QRraw_new(QRinput *input);
extern unsigned char QRraw_getCode(QRRawCode *raw);
extern void QRraw_free(QRRawCode *raw);
/******************************************************************************
* Raw code for Micro QR Code
*****************************************************************************/
typedef struct {
int version;
int dataLength;
int eccLength;
unsigned char *datacode;
unsigned char *ecccode;
RSblock *rsblock;
int oddbits;
int count;
} MQRRawCode;
extern MQRRawCode *MQRraw_new(QRinput *input);
extern unsigned char MQRraw_getCode(MQRRawCode *raw);
extern void MQRraw_free(MQRRawCode *raw);
/******************************************************************************
* Frame filling
*****************************************************************************/
extern unsigned char *FrameFiller_test(int version);
extern unsigned char *FrameFiller_testMQR(int version);
/******************************************************************************
* QR-code encoding
*****************************************************************************/
extern QRcode *QRcode_encodeMask(QRinput *input, int mask);
extern QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask);
extern QRcode *QRcode_new(int version, int width, unsigned char *data);
#endif /* QRENCODE_INNER_H */

1639
qrinput.c Normal file

File diff suppressed because it is too large Load Diff

124
qrinput.h Normal file
View File

@ -0,0 +1,124 @@
/*
* qrencode - QR Code encoder
*
* Input data chunk class
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef QRINPUT_H
#define QRINPUT_H
#include "qrencode.h"
#include "bitstream.h"
int QRinput_isSplittableMode(QRencodeMode mode);
/******************************************************************************
* Entry of input data
*****************************************************************************/
typedef struct _QRinput_List QRinput_List;
struct _QRinput_List {
QRencodeMode mode;
int size; ///< Size of data chunk (byte).
unsigned char *data; ///< Data chunk.
BitStream *bstream;
QRinput_List *next;
};
/******************************************************************************
* Input Data
*****************************************************************************/
struct _QRinput {
int version;
QRecLevel level;
QRinput_List *head;
QRinput_List *tail;
int mqr;
int fnc1;
unsigned char appid;
};
/******************************************************************************
* Structured append input data
*****************************************************************************/
typedef struct _QRinput_InputList QRinput_InputList;
struct _QRinput_InputList {
QRinput *input;
QRinput_InputList *next;
};
struct _QRinput_Struct {
int size; ///< number of structured symbols
int parity;
QRinput_InputList *head;
QRinput_InputList *tail;
};
/**
* Pack all bit streams padding bits into a byte array.
* @param input input data.
* @return padded merged byte stream
*/
extern unsigned char *QRinput_getByteStream(QRinput *input);
extern int QRinput_estimateBitsModeNum(int size);
extern int QRinput_estimateBitsModeAn(int size);
extern int QRinput_estimateBitsMode8(int size);
extern int QRinput_estimateBitsModeKanji(int size);
extern QRinput *QRinput_dup(QRinput *input);
extern const signed char QRinput_anTable[128];
/**
* Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19).
* @param __c__ character
* @return value
*/
#define QRinput_lookAnTable(__c__) \
((__c__ & 0x80)?-1:QRinput_anTable[(int)__c__])
/**
* Length of a standard mode indicator in bits.
*/
#define MODE_INDICATOR_SIZE 4
/**
* Length of a segment of structured-append header.
*/
#define STRUCTURE_HEADER_SIZE 20
/**
* Maximum number of symbols in a set of structured-appended symbols.
*/
#define MAX_STRUCTURED_SYMBOLS 16
#ifdef WITH_TESTS
extern int QRinput_mergeBitStream(QRinput *input, BitStream *bstream);
extern int QRinput_getBitStream(QRinput *input, BitStream *bstream);
extern int QRinput_estimateBitStreamSize(QRinput *input, int version);
extern int QRinput_splitEntry(QRinput_List *entry, int bytes);
extern int QRinput_estimateVersion(QRinput *input);
extern int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits);
extern int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int index, unsigned char parity);
#endif
#endif /* QRINPUT_H */

514
qrspec.c Normal file
View File

@ -0,0 +1,514 @@
/*
* qrencode - QR Code encoder
*
* QR Code specification in convenient format.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* The following data / specifications are taken from
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
* or
* "Automatic identification and data capture techniques --
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "qrspec.h"
#include "qrinput.h"
/******************************************************************************
* Version and capacity
*****************************************************************************/
typedef struct {
int width; //< Edge length of the symbol
int words; //< Data capacity (bytes)
int remainder; //< Remainder bit (bits)
int ec[4]; //< Number of ECC code (bytes)
} QRspec_Capacity;
/**
* Table of the capacity of symbols
* See Table 1 (pp.13) and Table 12-16 (pp.30-36), JIS X0510:2004.
*/
static const QRspec_Capacity qrspecCapacity[QRSPEC_VERSION_MAX + 1] = {
{ 0, 0, 0, { 0, 0, 0, 0}},
{ 21, 26, 0, { 7, 10, 13, 17}}, // 1
{ 25, 44, 7, { 10, 16, 22, 28}},
{ 29, 70, 7, { 15, 26, 36, 44}},
{ 33, 100, 7, { 20, 36, 52, 64}},
{ 37, 134, 7, { 26, 48, 72, 88}}, // 5
{ 41, 172, 7, { 36, 64, 96, 112}},
{ 45, 196, 0, { 40, 72, 108, 130}},
{ 49, 242, 0, { 48, 88, 132, 156}},
{ 53, 292, 0, { 60, 110, 160, 192}},
{ 57, 346, 0, { 72, 130, 192, 224}}, //10
{ 61, 404, 0, { 80, 150, 224, 264}},
{ 65, 466, 0, { 96, 176, 260, 308}},
{ 69, 532, 0, { 104, 198, 288, 352}},
{ 73, 581, 3, { 120, 216, 320, 384}},
{ 77, 655, 3, { 132, 240, 360, 432}}, //15
{ 81, 733, 3, { 144, 280, 408, 480}},
{ 85, 815, 3, { 168, 308, 448, 532}},
{ 89, 901, 3, { 180, 338, 504, 588}},
{ 93, 991, 3, { 196, 364, 546, 650}},
{ 97, 1085, 3, { 224, 416, 600, 700}}, //20
{101, 1156, 4, { 224, 442, 644, 750}},
{105, 1258, 4, { 252, 476, 690, 816}},
{109, 1364, 4, { 270, 504, 750, 900}},
{113, 1474, 4, { 300, 560, 810, 960}},
{117, 1588, 4, { 312, 588, 870, 1050}}, //25
{121, 1706, 4, { 336, 644, 952, 1110}},
{125, 1828, 4, { 360, 700, 1020, 1200}},
{129, 1921, 3, { 390, 728, 1050, 1260}},
{133, 2051, 3, { 420, 784, 1140, 1350}},
{137, 2185, 3, { 450, 812, 1200, 1440}}, //30
{141, 2323, 3, { 480, 868, 1290, 1530}},
{145, 2465, 3, { 510, 924, 1350, 1620}},
{149, 2611, 3, { 540, 980, 1440, 1710}},
{153, 2761, 3, { 570, 1036, 1530, 1800}},
{157, 2876, 0, { 570, 1064, 1590, 1890}}, //35
{161, 3034, 0, { 600, 1120, 1680, 1980}},
{165, 3196, 0, { 630, 1204, 1770, 2100}},
{169, 3362, 0, { 660, 1260, 1860, 2220}},
{173, 3532, 0, { 720, 1316, 1950, 2310}},
{177, 3706, 0, { 750, 1372, 2040, 2430}} //40
};
int QRspec_getDataLength(int version, QRecLevel level)
{
return qrspecCapacity[version].words - qrspecCapacity[version].ec[level];
}
int QRspec_getECCLength(int version, QRecLevel level)
{
return qrspecCapacity[version].ec[level];
}
int QRspec_getMinimumVersion(int size, QRecLevel level)
{
int i;
int words;
for(i = 1; i <= QRSPEC_VERSION_MAX; i++) {
words = qrspecCapacity[i].words - qrspecCapacity[i].ec[level];
if(words >= size) return i;
}
return QRSPEC_VERSION_MAX;
}
int QRspec_getWidth(int version)
{
return qrspecCapacity[version].width;
}
int QRspec_getRemainder(int version)
{
return qrspecCapacity[version].remainder;
}
/******************************************************************************
* Length indicator
*****************************************************************************/
static const int lengthTableBits[4][3] = {
{10, 12, 14},
{ 9, 11, 13},
{ 8, 16, 16},
{ 8, 10, 12}
};
int QRspec_lengthIndicator(QRencodeMode mode, int version)
{
int l;
if(!QRinput_isSplittableMode(mode)) return 0;
if(version <= 9) {
l = 0;
} else if(version <= 26) {
l = 1;
} else {
l = 2;
}
return lengthTableBits[mode][l];
}
int QRspec_maximumWords(QRencodeMode mode, int version)
{
int l;
int bits;
int words;
if(!QRinput_isSplittableMode(mode)) return 0;
if(version <= 9) {
l = 0;
} else if(version <= 26) {
l = 1;
} else {
l = 2;
}
bits = lengthTableBits[mode][l];
words = (1 << bits) - 1;
if(mode == QR_MODE_KANJI) {
words *= 2; // the number of bytes is required
}
return words;
}
/******************************************************************************
* Error correction code
*****************************************************************************/
/**
* Table of the error correction code (Reed-Solomon block)
* See Table 12-16 (pp.30-36), JIS X0510:2004.
*/
static const int eccTable[QRSPEC_VERSION_MAX+1][4][2] = {
{{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}},
{{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}}, // 1
{{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}},
{{ 1, 0}, { 1, 0}, { 2, 0}, { 2, 0}},
{{ 1, 0}, { 2, 0}, { 2, 0}, { 4, 0}},
{{ 1, 0}, { 2, 0}, { 2, 2}, { 2, 2}}, // 5
{{ 2, 0}, { 4, 0}, { 4, 0}, { 4, 0}},
{{ 2, 0}, { 4, 0}, { 2, 4}, { 4, 1}},
{{ 2, 0}, { 2, 2}, { 4, 2}, { 4, 2}},
{{ 2, 0}, { 3, 2}, { 4, 4}, { 4, 4}},
{{ 2, 2}, { 4, 1}, { 6, 2}, { 6, 2}}, //10
{{ 4, 0}, { 1, 4}, { 4, 4}, { 3, 8}},
{{ 2, 2}, { 6, 2}, { 4, 6}, { 7, 4}},
{{ 4, 0}, { 8, 1}, { 8, 4}, {12, 4}},
{{ 3, 1}, { 4, 5}, {11, 5}, {11, 5}},
{{ 5, 1}, { 5, 5}, { 5, 7}, {11, 7}}, //15
{{ 5, 1}, { 7, 3}, {15, 2}, { 3, 13}},
{{ 1, 5}, {10, 1}, { 1, 15}, { 2, 17}},
{{ 5, 1}, { 9, 4}, {17, 1}, { 2, 19}},
{{ 3, 4}, { 3, 11}, {17, 4}, { 9, 16}},
{{ 3, 5}, { 3, 13}, {15, 5}, {15, 10}}, //20
{{ 4, 4}, {17, 0}, {17, 6}, {19, 6}},
{{ 2, 7}, {17, 0}, { 7, 16}, {34, 0}},
{{ 4, 5}, { 4, 14}, {11, 14}, {16, 14}},
{{ 6, 4}, { 6, 14}, {11, 16}, {30, 2}},
{{ 8, 4}, { 8, 13}, { 7, 22}, {22, 13}}, //25
{{10, 2}, {19, 4}, {28, 6}, {33, 4}},
{{ 8, 4}, {22, 3}, { 8, 26}, {12, 28}},
{{ 3, 10}, { 3, 23}, { 4, 31}, {11, 31}},
{{ 7, 7}, {21, 7}, { 1, 37}, {19, 26}},
{{ 5, 10}, {19, 10}, {15, 25}, {23, 25}}, //30
{{13, 3}, { 2, 29}, {42, 1}, {23, 28}},
{{17, 0}, {10, 23}, {10, 35}, {19, 35}},
{{17, 1}, {14, 21}, {29, 19}, {11, 46}},
{{13, 6}, {14, 23}, {44, 7}, {59, 1}},
{{12, 7}, {12, 26}, {39, 14}, {22, 41}}, //35
{{ 6, 14}, { 6, 34}, {46, 10}, { 2, 64}},
{{17, 4}, {29, 14}, {49, 10}, {24, 46}},
{{ 4, 18}, {13, 32}, {48, 14}, {42, 32}},
{{20, 4}, {40, 7}, {43, 22}, {10, 67}},
{{19, 6}, {18, 31}, {34, 34}, {20, 61}},//40
};
void QRspec_getEccSpec(int version, QRecLevel level, int spec[5])
{
int b1, b2;
int data, ecc;
b1 = eccTable[version][level][0];
b2 = eccTable[version][level][1];
data = QRspec_getDataLength(version, level);
ecc = QRspec_getECCLength(version, level);
if(b2 == 0) {
spec[0] = b1;
spec[1] = data / b1;
spec[2] = ecc / b1;
spec[3] = spec[4] = 0;
} else {
spec[0] = b1;
spec[1] = data / (b1 + b2);
spec[2] = ecc / (b1 + b2);
spec[3] = b2;
spec[4] = spec[1] + 1;
}
}
/******************************************************************************
* Alignment pattern
*****************************************************************************/
/**
* Positions of alignment patterns.
* This array includes only the second and the third position of the alignment
* patterns. Rest of them can be calculated from the distance between them.
*
* See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
*/
static const int alignmentPattern[QRSPEC_VERSION_MAX+1][2] = {
{ 0, 0},
{ 0, 0}, {18, 0}, {22, 0}, {26, 0}, {30, 0}, // 1- 5
{34, 0}, {22, 38}, {24, 42}, {26, 46}, {28, 50}, // 6-10
{30, 54}, {32, 58}, {34, 62}, {26, 46}, {26, 48}, //11-15
{26, 50}, {30, 54}, {30, 56}, {30, 58}, {34, 62}, //16-20
{28, 50}, {26, 50}, {30, 54}, {28, 54}, {32, 58}, //21-25
{30, 58}, {34, 62}, {26, 50}, {30, 54}, {26, 52}, //26-30
{30, 56}, {34, 60}, {30, 58}, {34, 62}, {30, 54}, //31-35
{24, 50}, {28, 54}, {32, 58}, {26, 54}, {30, 58}, //35-40
};
/**
* Put an alignment marker.
* @param frame
* @param width
* @param ox,oy center coordinate of the pattern
*/
static void QRspec_putAlignmentMarker(unsigned char *frame, int width, int ox, int oy)
{
static const unsigned char finder[] = {
0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
0xa1, 0xa0, 0xa0, 0xa0, 0xa1,
0xa1, 0xa0, 0xa1, 0xa0, 0xa1,
0xa1, 0xa0, 0xa0, 0xa0, 0xa1,
0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
};
int x, y;
const unsigned char *s;
frame += (oy - 2) * width + ox - 2;
s = finder;
for(y = 0; y < 5; y++) {
for(x = 0; x < 5; x++) {
frame[x] = s[x];
}
frame += width;
s += 5;
}
}
static void QRspec_putAlignmentPattern(int version, unsigned char *frame, int width)
{
int d, w, x, y, cx, cy;
if(version < 2) return;
d = alignmentPattern[version][1] - alignmentPattern[version][0];
if(d < 0) {
w = 2;
} else {
w = (width - alignmentPattern[version][0]) / d + 2;
}
if(w * w - 3 == 1) {
x = alignmentPattern[version][0];
y = alignmentPattern[version][0];
QRspec_putAlignmentMarker(frame, width, x, y);
return;
}
cx = alignmentPattern[version][0];
for(x = 1; x < w - 1; x++) {
QRspec_putAlignmentMarker(frame, width, 6, cx);
QRspec_putAlignmentMarker(frame, width, cx, 6);
cx += d;
}
cy = alignmentPattern[version][0];
for(y = 0; y < w-1; y++) {
cx = alignmentPattern[version][0];
for(x = 0; x < w-1; x++) {
QRspec_putAlignmentMarker(frame, width, cx, cy);
cx += d;
}
cy += d;
}
}
/******************************************************************************
* Version information pattern
*****************************************************************************/
/**
* Version information pattern (BCH coded).
* See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
*/
static const unsigned int versionPattern[QRSPEC_VERSION_MAX - 6] = {
0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
0x27541, 0x28c69
};
unsigned int QRspec_getVersionPattern(int version)
{
if(version < 7 || version > QRSPEC_VERSION_MAX) return 0;
return versionPattern[version - 7];
}
/******************************************************************************
* Format information
*****************************************************************************/
/* See calcFormatInfo in tests/test_qrspec.c */
static const unsigned int formatInfo[4][8] = {
{0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976},
{0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0},
{0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed},
{0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b}
};
unsigned int QRspec_getFormatInfo(int mask, QRecLevel level)
{
if(mask < 0 || mask > 7) return 0;
return formatInfo[level][mask];
}
/******************************************************************************
* Frame
*****************************************************************************/
/**
* Put a finder pattern.
* @param frame
* @param width
* @param ox,oy upper-left coordinate of the pattern
*/
static void putFinderPattern(unsigned char *frame, int width, int ox, int oy)
{
static const unsigned char finder[] = {
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
};
int x, y;
const unsigned char *s;
frame += oy * width + ox;
s = finder;
for(y = 0; y < 7; y++) {
for(x = 0; x < 7; x++) {
frame[x] = s[x];
}
frame += width;
s += 7;
}
}
static unsigned char *QRspec_createFrame(int version)
{
unsigned char *frame, *p, *q;
int width;
int x, y;
unsigned int verinfo, v;
width = qrspecCapacity[version].width;
frame = (unsigned char *)malloc((size_t)(width * width));
if(frame == NULL) return NULL;
memset(frame, 0, (size_t)(width * width));
/* Finder pattern */
putFinderPattern(frame, width, 0, 0);
putFinderPattern(frame, width, width - 7, 0);
putFinderPattern(frame, width, 0, width - 7);
/* Separator */
p = frame;
q = frame + width * (width - 7);
for(y = 0; y < 7; y++) {
p[7] = 0xc0;
p[width - 8] = 0xc0;
q[7] = 0xc0;
p += width;
q += width;
}
memset(frame + width * 7, 0xc0, 8);
memset(frame + width * 8 - 8, 0xc0, 8);
memset(frame + width * (width - 8), 0xc0, 8);
/* Mask format information area */
memset(frame + width * 8, 0x84, 9);
memset(frame + width * 9 - 8, 0x84, 8);
p = frame + 8;
for(y = 0; y < 8; y++) {
*p = 0x84;
p += width;
}
p = frame + width * (width - 7) + 8;
for(y = 0; y < 7; y++) {
*p = 0x84;
p += width;
}
/* Timing pattern */
p = frame + width * 6 + 8;
q = frame + width * 8 + 6;
for(x = 1; x < width-15; x++) {
*p = 0x90 | (x & 1);
*q = 0x90 | (x & 1);
p++;
q += width;
}
/* Alignment pattern */
QRspec_putAlignmentPattern(version, frame, width);
/* Version information */
if(version >= 7) {
verinfo = QRspec_getVersionPattern(version);
p = frame + width * (width - 11);
v = verinfo;
for(x = 0; x < 6; x++) {
for(y = 0; y < 3; y++) {
p[width * y + x] = 0x88 | (v & 1);
v = v >> 1;
}
}
p = frame + width - 11;
v = verinfo;
for(y = 0; y < 6; y++) {
for(x = 0; x < 3; x++) {
p[x] = 0x88 | (v & 1);
v = v >> 1;
}
p += width;
}
}
/* and a little bit... */
frame[width * (width - 8) + 8] = 0x81;
return frame;
}
unsigned char *QRspec_newFrame(int version)
{
if(version < 1 || version > QRSPEC_VERSION_MAX) return NULL;
return QRspec_createFrame(version);
}

174
qrspec.h Normal file
View File

@ -0,0 +1,174 @@
/*
* qrencode - QR Code encoder
*
* QR Code specification in convenient format.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef QRSPEC_H
#define QRSPEC_H
#include "qrencode.h"
/******************************************************************************
* Version and capacity
*****************************************************************************/
/**
* Maximum width of a symbol
*/
#define QRSPEC_WIDTH_MAX 177
/**
* Return maximum data code length (bytes) for the version.
* @param version version of the symbol
* @param level error correction level
* @return maximum size (bytes)
*/
extern int QRspec_getDataLength(int version, QRecLevel level);
/**
* Return maximum error correction code length (bytes) for the version.
* @param version version of the symbol
* @param level error correction level
* @return ECC size (bytes)
*/
extern int QRspec_getECCLength(int version, QRecLevel level);
/**
* Return a version number that satisfies the input code length.
* @param size input code length (byte)
* @param level error correction level
* @return version number
*/
extern int QRspec_getMinimumVersion(int size, QRecLevel level);
/**
* Return the width of the symbol for the version.
* @param version vesion of the symbol
* @return width of the symbol
*/
extern int QRspec_getWidth(int version);
/**
* Return the numer of remainder bits.
* @param version vesion of the symbol
* @return number of remainder bits
*/
extern int QRspec_getRemainder(int version);
/******************************************************************************
* Length indicator
*****************************************************************************/
/**
* Return the size of length indicator for the mode and version.
* @param mode encode mode
* @param version vesion of the symbol
* @return the size of the appropriate length indicator (bits).
*/
extern int QRspec_lengthIndicator(QRencodeMode mode, int version);
/**
* Return the maximum length for the mode and version.
* @param mode encode mode
* @param version vesion of the symbol
* @return the maximum length (bytes)
*/
extern int QRspec_maximumWords(QRencodeMode mode, int version);
/******************************************************************************
* Error correction code
*****************************************************************************/
/**
* Return an array of ECC specification.
* @param version version of the symbol
* @param level error correction level
* @param spec an array of ECC specification contains as following:
* {# of type1 blocks, # of data code, # of ecc code,
* # of type2 blocks, # of data code}
*/
void QRspec_getEccSpec(int version, QRecLevel level, int spec[5]);
#define QRspec_rsBlockNum(__spec__) (__spec__[0] + __spec__[3])
#define QRspec_rsBlockNum1(__spec__) (__spec__[0])
#define QRspec_rsDataCodes1(__spec__) (__spec__[1])
#define QRspec_rsEccCodes1(__spec__) (__spec__[2])
#define QRspec_rsBlockNum2(__spec__) (__spec__[3])
#define QRspec_rsDataCodes2(__spec__) (__spec__[4])
#define QRspec_rsEccCodes2(__spec__) (__spec__[2])
#define QRspec_rsDataLength(__spec__) \
((QRspec_rsBlockNum1(__spec__) * QRspec_rsDataCodes1(__spec__)) + \
(QRspec_rsBlockNum2(__spec__) * QRspec_rsDataCodes2(__spec__)))
#define QRspec_rsEccLength(__spec__) \
(QRspec_rsBlockNum(__spec__) * QRspec_rsEccCodes1(__spec__))
/******************************************************************************
* Version information pattern
*****************************************************************************/
/**
* Return BCH encoded version information pattern that is used for the symbol
* of version 7 or greater. Use lower 18 bits.
* @param version version of the symbol
* @return BCH encoded version information pattern
*/
extern unsigned int QRspec_getVersionPattern(int version);
/******************************************************************************
* Format information
*****************************************************************************/
/**
* Return BCH encoded format information pattern.
* @param mask mask number
* @param level error correction level
* @return BCH encoded format information pattern
*/
extern unsigned int QRspec_getFormatInfo(int mask, QRecLevel level);
/******************************************************************************
* Frame
*****************************************************************************/
/**
* Return a copy of initialized frame.
* @param version version of the symbol
* @return Array of unsigned char. You can free it by free().
*/
extern unsigned char *QRspec_newFrame(int version);
/******************************************************************************
* Mode indicator
*****************************************************************************/
/**
* Mode indicator. See Table 2 of JIS X0510:2004, pp.16.
*/
#define QRSPEC_MODEID_ECI 7
#define QRSPEC_MODEID_NUM 1
#define QRSPEC_MODEID_AN 2
#define QRSPEC_MODEID_8 4
#define QRSPEC_MODEID_KANJI 8
#define QRSPEC_MODEID_FNC1FIRST 5
#define QRSPEC_MODEID_FNC1SECOND 9
#define QRSPEC_MODEID_STRUCTURE 3
#define QRSPEC_MODEID_TERMINATOR 0
#endif /* QRSPEC_H */

149
rsecc.c Normal file
View File

@ -0,0 +1,149 @@
/*
* qrencode - QR Code encoder
*
* Reed solomon error correction code encoder specialized for QR code.
* This code is rewritten by Kentaro Fukuchi, referring to the FEC library
* developed by Phil Karn (KA9Q).
*
* Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
* Copyright (C) 2014-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#if HAVE_LIBPTHREAD
#include <pthread.h>
#endif
#include "rsecc.h"
#if HAVE_LIBPTHREAD
static pthread_mutex_t RSECC_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
static int initialized = 0;
#define SYMBOL_SIZE (8)
#define symbols ((1U << SYMBOL_SIZE) - 1)
static const unsigned int proot = 0x11d; /* stands for x^8+x^4+x^3+x^2+1 (see pp.37 of JIS X0510:2004) */
/* min/max codeword length of ECC, calculated from the specification. */
#define min_length (2)
#define max_length (30)
#define max_generatorSize (max_length)
static unsigned char alpha[symbols + 1];
static unsigned char aindex[symbols + 1];
static unsigned char generator[max_length - min_length + 1][max_generatorSize + 1];
static unsigned char generatorInitialized[max_length - min_length + 1];
static void RSECC_initLookupTable(void)
{
unsigned int i, b;
alpha[symbols] = 0;
aindex[0] = symbols;
b = 1;
for(i = 0; i < symbols; i++) {
alpha[i] = b;
aindex[b] = i;
b <<= 1;
if(b & (symbols + 1)) {
b ^= proot;
}
b &= symbols;
}
}
static void RSECC_init(void)
{
RSECC_initLookupTable();
memset(generatorInitialized, 0, (max_length - min_length + 1));
initialized = 1;
}
static void generator_init(size_t length)
{
size_t i, j;
int g[max_generatorSize + 1];
g[0] = 1;
for(i = 0; i < length; i++) {
g[i + 1] = 1;
/* Because g[0] never be zero, skipped some conditional checks. */
for(j = i; j > 0; j--) {
g[j] = g[j - 1] ^ alpha[(aindex[g[j]] + i) % symbols];
}
g[0] = alpha[(aindex[g[0]] + i) % symbols];
}
for(i = 0; i <= length; i++) {
generator[length - min_length][i] = aindex[g[i]];
}
generatorInitialized[length - min_length] = 1;
}
int RSECC_encode(size_t data_length, size_t ecc_length, const unsigned char *data, unsigned char *ecc)
{
size_t i, j;
unsigned char feedback;
unsigned char *gen;
#if HAVE_LIBPTHREAD
pthread_mutex_lock(&RSECC_mutex);
#endif
if(!initialized) {
RSECC_init();
}
#if HAVE_LIBPTHREAD
pthread_mutex_unlock(&RSECC_mutex);
#endif
if(ecc_length > max_length) return -1;
memset(ecc, 0, ecc_length);
#if HAVE_LIBPTHREAD
pthread_mutex_lock(&RSECC_mutex);
#endif
if(!generatorInitialized[ecc_length - min_length]) generator_init(ecc_length);
#if HAVE_LIBPTHREAD
pthread_mutex_unlock(&RSECC_mutex);
#endif
gen = generator[ecc_length - min_length];
for(i = 0; i < data_length; i++) {
feedback = aindex[data[i] ^ ecc[0]];
if(feedback != symbols) {
for(j = 1; j < ecc_length; j++) {
ecc[j] ^= alpha[(unsigned int)(feedback + gen[ecc_length - j]) % symbols];
}
}
memmove(&ecc[0], &ecc[1], ecc_length - 1);
if(feedback != symbols) {
ecc[ecc_length - 1] = alpha[(unsigned int)(feedback + gen[0]) % symbols];
} else {
ecc[ecc_length - 1] = 0;
}
}
return 0;
}

31
rsecc.h Normal file
View File

@ -0,0 +1,31 @@
/*
* qrencode - QR Code encoder
*
* Reed solomon error correction code encoder specialized for QR code.
* This code is rewritten by Kentaro Fukuchi, referring to the FEC library
* developed by Phil Karn (KA9Q).
*
* Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
* Copyright (C) 2014-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef RSECC_H
#define RSECC_H
extern int RSECC_encode(size_t data_length, size_t ecc_length, const unsigned char *data, unsigned char *ecc);
#endif /* RSECC_H */

323
split.c Normal file
View File

@ -0,0 +1,323 @@
/*
* qrencode - QR Code encoder
*
* Input data splitter.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* The following data / specifications are taken from
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
* or
* "Automatic identification and data capture techniques --
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "qrencode.h"
#include "qrinput.h"
#include "qrspec.h"
#include "split.h"
#define isdigit(__c__) ((unsigned char)((signed char)(__c__) - '0') < 10)
#define isalnum(__c__) (QRinput_lookAnTable(__c__) >= 0)
#if !HAVE_STRDUP
#undef strdup
char *strdup(const char *s)
{
size_t len = strlen(s) + 1;
void *newstring = malloc(len);
if(newstring == NULL) return NULL;
return (char *)memcpy(newstring, s, len);
}
#endif
static QRencodeMode Split_identifyMode(const char *string, QRencodeMode hint)
{
unsigned char c, d;
unsigned int word;
c = (unsigned char)string[0];
if(c == '\0') return QR_MODE_NUL;
if(isdigit(c)) {
return QR_MODE_NUM;
} else if(isalnum(c)) {
return QR_MODE_AN;
} else if(hint == QR_MODE_KANJI) {
d = (unsigned char)string[1];
if(d != '\0') {
word = ((unsigned int)c << 8) | d;
if((word >= 0x8140 && word <= 0x9ffc) || (word >= 0xe040 && word <= 0xebbf)) {
return QR_MODE_KANJI;
}
}
}
return QR_MODE_8;
}
static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint);
static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint);
static int Split_eatNum(const char *string, QRinput *input,QRencodeMode hint)
{
const char *p;
int ret;
int run;
int dif;
int ln;
QRencodeMode mode;
ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
p = string;
while(isdigit(*p)) {
p++;
}
run = (int)(p - string);
mode = Split_identifyMode(p, hint);
if(mode == QR_MODE_8) {
dif = QRinput_estimateBitsModeNum(run) + 4 + ln
+ QRinput_estimateBitsMode8(1) /* + 4 + l8 */
- QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */;
if(dif > 0) {
return Split_eat8(string, input, hint);
}
}
if(mode == QR_MODE_AN) {
dif = QRinput_estimateBitsModeNum(run) + 4 + ln
+ QRinput_estimateBitsModeAn(1) /* + 4 + la */
- QRinput_estimateBitsModeAn(run + 1) /* - 4 - la */;
if(dif > 0) {
return Split_eatAn(string, input, hint);
}
}
ret = QRinput_append(input, QR_MODE_NUM, run, (unsigned char *)string);
if(ret < 0) return -1;
return run;
}
static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint)
{
const char *p, *q;
int ret;
int run;
int dif;
int la, ln;
la = QRspec_lengthIndicator(QR_MODE_AN, input->version);
ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
p = string;
while(isalnum(*p)) {
if(isdigit(*p)) {
q = p;
while(isdigit(*q)) {
q++;
}
dif = QRinput_estimateBitsModeAn((int)(p - string)) /* + 4 + la */
+ QRinput_estimateBitsModeNum((int)(q - p)) + 4 + ln
+ (isalnum(*q)?(4 + ln):0)
- QRinput_estimateBitsModeAn((int)(q - string)) /* - 4 - la */;
if(dif < 0) {
break;
}
p = q;
} else {
p++;
}
}
run = (int)(p - string);
if(*p && !isalnum(*p)) {
dif = QRinput_estimateBitsModeAn(run) + 4 + la
+ QRinput_estimateBitsMode8(1) /* + 4 + l8 */
- QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */;
if(dif > 0) {
return Split_eat8(string, input, hint);
}
}
ret = QRinput_append(input, QR_MODE_AN, run, (unsigned char *)string);
if(ret < 0) return -1;
return run;
}
static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint)
{
const char *p;
int ret;
int run;
p = string;
while(Split_identifyMode(p, hint) == QR_MODE_KANJI) {
p += 2;
}
run = (int)(p - string);
ret = QRinput_append(input, QR_MODE_KANJI, run, (unsigned char *)string);
if(ret < 0) return -1;
return run;
}
static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint)
{
const char *p, *q;
QRencodeMode mode;
int ret;
int run;
int dif;
int la, ln, l8;
int swcost;
la = QRspec_lengthIndicator(QR_MODE_AN, input->version);
ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
l8 = QRspec_lengthIndicator(QR_MODE_8, input->version);
p = string + 1;
while(*p != '\0') {
mode = Split_identifyMode(p, hint);
if(mode == QR_MODE_KANJI) {
break;
}
if(mode == QR_MODE_NUM) {
q = p;
while(isdigit(*q)) {
q++;
}
if(Split_identifyMode(q, hint) == QR_MODE_8) {
swcost = 4 + l8;
} else {
swcost = 0;
}
dif = QRinput_estimateBitsMode8((int)(p - string)) /* + 4 + l8 */
+ QRinput_estimateBitsModeNum((int)(q - p)) + 4 + ln
+ swcost
- QRinput_estimateBitsMode8((int)(q - string)) /* - 4 - l8 */;
if(dif < 0) {
break;
}
p = q;
} else if(mode == QR_MODE_AN) {
q = p;
while(isalnum(*q)) {
q++;
}
if(Split_identifyMode(q, hint) == QR_MODE_8) {
swcost = 4 + l8;
} else {
swcost = 0;
}
dif = QRinput_estimateBitsMode8((int)(p - string)) /* + 4 + l8 */
+ QRinput_estimateBitsModeAn((int)(q - p)) + 4 + la
+ swcost
- QRinput_estimateBitsMode8((int)(q - string)) /* - 4 - l8 */;
if(dif < 0) {
break;
}
p = q;
} else {
p++;
}
}
run = (int)(p - string);
ret = QRinput_append(input, QR_MODE_8, run, (unsigned char *)string);
if(ret < 0) return -1;
return run;
}
static int Split_splitString(const char *string, QRinput *input,
QRencodeMode hint)
{
int length;
QRencodeMode mode;
while(*string != '\0') {
mode = Split_identifyMode(string, hint);
if(mode == QR_MODE_NUM) {
length = Split_eatNum(string, input, hint);
} else if(mode == QR_MODE_AN) {
length = Split_eatAn(string, input, hint);
} else if(mode == QR_MODE_KANJI && hint == QR_MODE_KANJI) {
length = Split_eatKanji(string, input, hint);
} else {
length = Split_eat8(string, input, hint);
}
if(length == 0) break;
if(length < 0) return -1;
string += length;
}
return 0;
}
static char *dupAndToUpper(const char *str, QRencodeMode hint)
{
char *newstr, *p;
QRencodeMode mode;
newstr = strdup(str);
if(newstr == NULL) return NULL;
p = newstr;
while(*p != '\0') {
mode = Split_identifyMode(p, hint);
if(mode == QR_MODE_KANJI) {
p += 2;
} else {
if (*p >= 'a' && *p <= 'z') {
*p = (char)((int)*p - 32);
}
p++;
}
}
return newstr;
}
int Split_splitStringToQRinput(const char *string, QRinput *input,
QRencodeMode hint, int casesensitive)
{
char *newstr;
int ret;
if(string == NULL || *string == '\0') {
errno = EINVAL;
return -1;
}
if(!casesensitive) {
newstr = dupAndToUpper(string, hint);
if(newstr == NULL) return -1;
ret = Split_splitString(newstr, input, hint);
free(newstr);
} else {
ret = Split_splitString(string, input, hint);
}
return ret;
}

47
split.h Normal file
View File

@ -0,0 +1,47 @@
/*
* qrencode - QR Code encoder
*
* Input data splitter.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* The following data / specifications are taken from
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
* or
* "Automatic identification and data capture techniques --
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef SPLIT_H
#define SPLIT_H
#include "qrencode.h"
/**
* Split the input string (null terminated) into QRinput.
* @param string input string
* @param hint give QR_MODE_KANJI if the input string contains Kanji character encoded in Shift-JIS. If not, give QR_MODE_8.
* @param casesensitive 0 for case-insensitive encoding (all alphabet characters are replaced to UPPER-CASE CHARACTERS.
* @retval 0 success.
* @retval -1 an error occurred. errno is set to indicate the error. See
* Exceptions for the details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
*/
extern int Split_splitStringToQRinput(const char *string, QRinput *input,
QRencodeMode hint, int casesensitive);
#endif /* SPLIT_H */

81
tests/CMakeLists.txt Normal file
View File

@ -0,0 +1,81 @@
add_library(common
common.c common.h)
target_link_libraries(common qrencode)
add_library(rscode
rscode.c rscode.h)
target_link_libraries(rscode common)
macro(MAKE_TEST test_name)
set(ADDITIONAL_LIBS "${ARGN}")
add_executable(${test_name} ${test_name}.c)
target_link_libraries(${test_name} common ${ADDITIONAL_LIBS})
add_test(${test_name} ${test_name})
endmacro(MAKE_TEST)
if(TARGET PNG::PNG)
add_executable(create_frame_pattern create_frame_pattern.c)
target_link_libraries(create_frame_pattern common PNG::PNG)
add_executable(create_mqr_frame_pattern create_mqr_frame_pattern.c)
target_link_libraries(create_mqr_frame_pattern common PNG::PNG)
endif()
if(HAVE_SDL)
add_executable(view_qrcode view_qrcode.c)
target_link_libraries(view_qrcode common)
endif(HAVE_SDL)
if(TARGET Threads::Threads)
if(HAVE_SYS_TIME_H)
add_definitions(-DHAVE_SYS_TIME_H)
endif()
if(HAVE_TIME_H)
add_definitions(-DHAVE_TIME_H)
endif()
add_executable(prof_qrencode prof_qrencode.c)
target_link_libraries(prof_qrencode common Threads::Threads)
if(HAVE_PTHREAD_H)
add_executable(pthread_qrencode pthread_qrencode.c)
target_link_libraries(pthread_qrencode common Threads::Threads)
endif()
endif()
MAKE_TEST(test_bitstream)
MAKE_TEST(test_estimatebit)
MAKE_TEST(test_split)
if(TARGET ICONV::ICONV)
add_library(decoder STATIC
decoder.c decoder.h
datachunk.c datachunk.h
rsecc_decoder.c rsecc_decoder.h)
target_link_libraries(decoder ICONV::ICONV)
MAKE_TEST(test_qrinput decoder)
MAKE_TEST(test_qrspec decoder)
target_compile_definitions(test_qrspec PRIVATE -DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}/")
MAKE_TEST(test_mqrspec decoder)
MAKE_TEST(test_qrencode decoder)
MAKE_TEST(test_split_urls decoder)
MAKE_TEST(test_monkey decoder)
include(CheckCSourceCompiles)
check_c_source_compiles(
"int main(){
const int w = 1;
char buf[w];
return 0;
}"
FIXED_SIZE_BUFFER_INITIALIZATION)
if(FIXED_SIZE_BUFFER_INITIALIZATION)
MAKE_TEST(test_mask decoder)
MAKE_TEST(test_mmask decoder)
MAKE_TEST(test_rs rscode decoder)
endif()
endif()

86
tests/Makefile.am Normal file
View File

@ -0,0 +1,86 @@
AM_CFLAGS =
AM_LDFLAGS =
if HAVE_SDL
sdlPROGRAMS = view_qrcode
AM_CFLAGS += $(SDL_CFLAGS)
AM_LDFLAGS += $(SDL_LIBS)
endif
if HAVE_PNG
pngPROGRAMS = create_frame_pattern create_mqr_frame_pattern
endif
check_PROGRAMS = test_qrinput test_bitstream test_estimatebit test_qrspec \
test_rs test_qrencode test_mqrspec test_split test_mask \
test_mmask test_split_urls test_monkey
noinst_PROGRAMS = $(pngPROGRAMS) $(sdlPROGRAMS) $(check_PROGRAMS) prof_qrencode
noinst_LIBRARIES = libdecoder.a
DECODER_LIBS = libdecoder.a $(LIBICONV)
noinst_HEADERS = common.h rscode.h
if HAVE_LIBPTHREAD
noinst_PROGRAMS += pthread_qrencode
endif
TESTS = $(check_PROGRAMS)
EXTRA_DIST = test_all.sh test_basic.sh test_configure.sh frame URI_testset.inc CMakeLists.txt
libdecoder_a_SOURCES = decoder.c decoder.h datachunk.c datachunk.h rsecc_decoder.c rsecc_decoder.h
test_qrinput_SOURCES = test_qrinput.c common.c
test_qrinput_LDADD = $(DECODER_LIBS) ../libqrencode.la
test_bitstream_SOURCES = test_bitstream.c common.c
test_bitstream_LDADD = ../libqrencode.la
test_estimatebit_SOURCES = test_estimatebit.c common.c
test_estimatebit_LDADD = ../libqrencode.la
test_qrspec_SOURCES = test_qrspec.c common.c
test_qrspec_CPPFLAGS = -DSRCDIR=\"$(srcdir)/\"
test_qrspec_LDADD = $(DECODER_LIBS) ../libqrencode.la
test_mqrspec_SOURCES = test_mqrspec.c common.c
test_mqrspec_LDADD = $(DECODER_LIBS) ../libqrencode.la
test_rs_SOURCES = test_rs.c rscode.c common.c
test_rs_LDADD = $(DECODER_LIBS) ../libqrencode.la
test_qrencode_SOURCES = test_qrencode.c common.c
test_qrencode_LDADD = $(DECODER_LIBS) ../libqrencode.la
test_split_SOURCES = test_split.c common.c
test_split_LDADD = ../libqrencode.la
test_split_urls_SOURCES = test_split_urls.c common.c
test_split_urls_LDADD = $(DECODER_LIBS) ../libqrencode.la
test_monkey_SOURCES = test_monkey.c common.c
test_monkey_LDADD = $(DECODER_LIBS) ../libqrencode.la
test_mask_SOURCES = test_mask.c common.c
test_mask_LDADD = $(DECODER_LIBS) ../libqrencode.la
test_mmask_SOURCES = test_mmask.c common.c
test_mmask_LDADD = $(DECODER_LIBS) ../libqrencode.la
prof_qrencode_SOURCES = prof_qrencode.c common.c
prof_qrencode_LDADD = ../libqrencode.la
pthread_qrencode_SOURCES = pthread_qrencode.c common.c
pthread_qrencode_LDADD = ../libqrencode.la
if HAVE_PNG
create_frame_pattern_SOURCES = create_frame_pattern.c common.c
create_frame_pattern_CFLAGS = $(png_CFLAGS) $(AM_CFLAGS)
create_frame_pattern_LDADD = ../libqrencode.la $(png_LIBS)
create_mqr_frame_pattern_SOURCES = create_mqr_frame_pattern.c common.c
create_mqr_frame_pattern_CFLAGS = $(png_CFLAGS) $(AM_CFLAGS)
create_mqr_frame_pattern_LDADD = ../libqrencode.la $(png_LIBS)
endif
if HAVE_SDL
view_qrcode_SOURCES = view_qrcode.c common.c
view_qrcode_LDADD = ../libqrencode.la
endif

1477
tests/Makefile.in Normal file

File diff suppressed because it is too large Load Diff

1273
tests/URI_testset.inc Normal file

File diff suppressed because it is too large Load Diff

290
tests/common.c Normal file
View File

@ -0,0 +1,290 @@
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
static int tests = 0;
static int failed = 0;
int assertionFailed = 0;
int assertionNum = 0;
static const char *testName = NULL;
static const char *testFunc = NULL;
const char levelChar[4] = {'L', 'M', 'Q', 'H'};
const char *modeStr[5] = {"nm", "an", "8", "kj", "st"};
int ncmpBin(char *correct, BitStream *bstream, size_t len)
{
int bit;
size_t i;
char *p;
if(len != BitStream_size(bstream)) {
printf("Length is not match: %zu, %zu expected.\n", BitStream_size(bstream), len);
return -1;
}
p = correct;
i = 0;
while(*p != '\0') {
while(*p == ' ') {
p++;
}
bit = (*p == '1')?1:0;
if(bstream->data[i] != bit) return -1;
i++;
p++;
if(i == len) break;
}
return 0;
}
int cmpBin(char *correct, BitStream *bstream)
{
size_t len = 0;
char *p;
for(p = correct; *p != '\0'; p++) {
if(*p != ' ') len++;
}
return ncmpBin(correct, bstream, len);
}
void testInit(int tests)
{
printf("1..%d\n", tests);
}
void testStartReal(const char *func, const char *name)
{
tests++;
testName = name;
testFunc = func;
assertionFailed = 0;
assertionNum = 0;
//printf("_____%d: %s: %s...\n", tests, func, name);
}
void testEnd(int result)
{
if(result) {
printf("not ok %d %s: %s\n", tests, testFunc, testName);
failed++;
} else {
printf("ok %d %s: %s\n", tests, testFunc, testName);
}
}
void testFinish(void)
{
if(assertionFailed) {
printf("not ok %d %s: %s (%d assertions failed.)\n", tests, testFunc, testName, assertionFailed);
failed++;
} else {
printf("ok %d %s: %s (%d assertions passed.)\n", tests, testFunc, testName, assertionNum);
}
}
void testReport(int expectedTests)
{
printf("Total %d tests, %d fails.\n", tests, failed);
if(failed) exit(-1);
if(expectedTests != tests) {
printf("WARNING: the number of the executed tests (%d) is not equal to the expecetd (%d).\n", tests, expectedTests);
}
}
int testNum(void)
{
return tests;
}
void printBinary(unsigned char *data, int length)
{
int i;
for(i=0; i<length; i++) {
printf(data[i]?"1":"0");
}
printf("\n");
}
void printBstream(BitStream *bstream)
{
printBinary(bstream->data, BitStream_size(bstream));
}
void printQRinput(QRinput *input)
{
QRinput_List *list;
int i;
list = input->head;
while(list != NULL) {
for(i=0; i<list->size; i++) {
printf("0x%02x,", list->data[i]);
}
list = list->next;
}
printf("\n");
}
void printQRinputInfo(QRinput *input)
{
QRinput_List *list;
BitStream *b;
int i, ret;
printf("QRinput info:\n");
printf(" version: %d\n", input->version);
printf(" level : %c\n", levelChar[input->level]);
list = input->head;
i = 0;
while(list != NULL) {
i++;
list = list->next;
}
printf(" chunks: %d\n", i);
b = BitStream_new();
ret = QRinput_mergeBitStream(input, b);
if(ret == 0) {
printf(" bitstream-size: %zu\n", BitStream_size(b));
BitStream_free(b);
}
list = input->head;
i = 0;
while(list != NULL) {
printf("\t#%d: mode = %s, size = %d\n", i, modeStr[list->mode], list->size);
i++;
list = list->next;
}
}
void printQRinputStruct(QRinput_Struct *s)
{
QRinput_InputList *list;
int i = 1;
printf("Struct size: %d\n", s->size);
printf("Struct parity: %08x\n", s->parity);
for(list = s->head; list != NULL; list = list->next) {
printf("Symbol %d - ", i);
printQRinputInfo(list->input);
i++;
}
}
void printFrame(int width, unsigned char *frame)
{
int x, y;
for(y=0; y<width; y++) {
for(x=0; x<width; x++) {
printf("%02x ", *frame++);
}
printf("\n");
}
}
void printQRcode(QRcode *code)
{
printFrame(code->width, code->data);
}
void printQRRawCodeFromQRinput(QRinput *input)
{
QRRawCode *raw;
int i;
puts("QRRawCode dump image:");
raw = QRraw_new(input);
if(raw == NULL) {
puts("Failed to generate QRRawCode from this input.\n");
return;
}
for(i=0; i<raw->dataLength; i++) {
printf(" %02x", raw->datacode[i]);
}
for(i=0; i<raw->eccLength; i++) {
printf(" %02x", raw->ecccode[i]);
}
printf("\n");
QRraw_free(raw);
}
#if HAVE_SDL
/* Experimental debug function */
/* You can call show_QRcode(QRcode *code) to display the QR Code from anywhere
* in test code using SDL. */
#include <SDL.h>
static void draw_QRcode(QRcode *qrcode, int ox, int oy, int margin, int size, SDL_Surface *surface)
{
int x, y, width;
unsigned char *p;
SDL_Rect rect;
Uint32 color[2];
color[0] = SDL_MapRGBA(surface->format, 255, 255, 255, 255);
color[1] = SDL_MapRGBA(surface->format, 0, 0, 0, 255);
SDL_FillRect(surface, NULL, color[0]);
ox += margin * size;
oy += margin * size;
width = qrcode->width;
p = qrcode->data;
for(y=0; y<width; y++) {
for(x=0; x<width; x++) {
rect.x = ox + x * size;
rect.y = oy + y * size;
rect.w = size;
rect.h = size;
SDL_FillRect(surface, &rect, color[*p&1]);
p++;
}
}
}
void show_QRcode(QRcode *qrcode)
{
SDL_Event event;
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Surface *surface;
SDL_Texture *texture;
if(!SDL_WasInit(SDL_INIT_VIDEO)) {
SDL_Init(SDL_INIT_VIDEO);
atexit(SDL_Quit);
}
int width = (qrcode->width + 4 * 2) * 4; //maring = 4, size = 4
SDL_CreateWindowAndRenderer(width, width, SDL_WINDOW_SHOWN, &window, &renderer);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
surface = SDL_CreateRGBSurface(0, width, width, 32, 0, 0, 0, 0);
draw_QRcode(qrcode, 0, 0, 4, 4, surface);
texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
fprintf(stderr, "Press any key on the QR Code window to proceed.\n");
int loop = 1;
while(loop) {
SDL_WaitEvent(&event);
if(event.type == SDL_KEYDOWN) {
loop = 0;
}
}
SDL_FreeSurface(surface);
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
}
#else
void show_QRcode(QRcode *qrcode) {
}
#endif

56
tests/common.h Normal file
View File

@ -0,0 +1,56 @@
/*
* common part of test units.
*/
#ifndef COMMON_H__
#define COMMON_H__
#include <stdlib.h>
#if HAVE_CONFIG_H
#include "../config.h"
#endif
#include "../qrencode.h"
#include "../qrinput.h"
#include "../bitstream.h"
#include "../qrencode_inner.h"
extern int assertionFailed;
extern int assertionNum;
extern const char levelChar[4];
extern const char *modeStr[5];
void testInit(int tests);
#define testStart(__arg__) (testStartReal(__func__, __arg__))
#define testEndExp(__arg__) (testEnd(!(__arg__)))
void testStartReal(const char *func, const char *name);
void testEnd(int result);
void testFinish(void);
void testReport(int tests);
#define assert_exp(__exp__, ...) \
{assertionNum++;if(!(__exp__)) {assertionFailed++; printf(__VA_ARGS__);}}
#define assert_zero(__exp__, ...) assert_exp((__exp__) == 0, __VA_ARGS__)
#define assert_nonzero(__exp__, ...) assert_exp((__exp__) != 0, __VA_ARGS__)
#define assert_null(__ptr__, ...) assert_exp((__ptr__) == NULL, __VA_ARGS__)
#define assert_nonnull(__ptr__, ...) assert_exp((__ptr__) != NULL, __VA_ARGS__)
#define assert_equal(__e1__, __e2__, ...) assert_exp((__e1__) == (__e2__), __VA_ARGS__)
#define assert_notequal(__e1__, __e2__, ...) assert_exp((__e1__) != (__e2__), __VA_ARGS__)
#define assert_nothing(__exp__, ...) {printf(__VA_ARGS__); __exp__;}
int ncmpBin(char *correct, BitStream *bstream, size_t len);
int cmpBin(char *correct, BitStream *bstream);
void printFrame(int width, unsigned char *frame);
void printQRcode(QRcode *code);
void printQRRawCodeFromQRinput(QRinput *input);
void printQRinput(QRinput *input);
void printQRinputInfo(QRinput *input);
void printQRinputStruct(QRinput_Struct *s);
void printBinary(unsigned char *data, int length);
void printBstream(BitStream *bstream);
void show_QRcode(QRcode *qrcode);
#endif /* COMMON_H__ */

View File

@ -0,0 +1,170 @@
/*
* This tool creates a frame pattern data for debug purpose used by
* test_qrspec. test_qrspec and create_frame_pattern uses the same function
* of libqrencode. This means the test is meaningless if test_qrspec is run
* with a pattern data created by create_frame_pattern of the same version.
* In order to test it correctly, create a pattern data by the tool of the
* previous version, or use the frame data attached to the package.
*/
#include <stdio.h>
#include <string.h>
#include <png.h>
#include "common.h"
#include "../qrspec.h"
void append_pattern(int version, FILE *fp)
{
int width;
unsigned char *frame;
frame = QRspec_newFrame(version);
width = QRspec_getWidth(version);
fwrite(frame, 1, width * width, fp);
free(frame);
}
static int writePNG(unsigned char *frame, int width, const char *outfile)
{
static FILE *fp;
png_structp png_ptr;
png_infop info_ptr;
unsigned char *row, *p, *q;
int x, y, xx, yy, bit;
int realwidth;
const int margin = 0;
const int size = 1;
realwidth = (width + margin * 2) * size;
row = (unsigned char *)malloc((realwidth + 7) / 8);
if(row == NULL) {
fprintf(stderr, "Failed to allocate memory.\n");
exit(EXIT_FAILURE);
}
if(outfile[0] == '-' && outfile[1] == '\0') {
fp = stdout;
} else {
fp = fopen(outfile, "wb");
if(fp == NULL) {
fprintf(stderr, "Failed to create file: %s\n", outfile);
perror(NULL);
exit(EXIT_FAILURE);
}
}
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if(png_ptr == NULL) {
fclose(fp);
fprintf(stderr, "Failed to initialize PNG writer.\n");
exit(EXIT_FAILURE);
}
info_ptr = png_create_info_struct(png_ptr);
if(info_ptr == NULL) {
fclose(fp);
fprintf(stderr, "Failed to initialize PNG write.\n");
exit(EXIT_FAILURE);
}
if(setjmp(png_jmpbuf(png_ptr))) {
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
fprintf(stderr, "Failed to write PNG image.\n");
exit(EXIT_FAILURE);
}
png_init_io(png_ptr, fp);
png_set_IHDR(png_ptr, info_ptr,
realwidth, realwidth,
1,
PNG_COLOR_TYPE_GRAY,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
png_write_info(png_ptr, info_ptr);
/* top margin */
memset(row, 0xff, (realwidth + 7) / 8);
for(y=0; y<margin * size; y++) {
png_write_row(png_ptr, row);
}
/* data */
p = frame;
for(y=0; y<width; y++) {
bit = 7;
memset(row, 0xff, (realwidth + 7) / 8);
q = row;
q += margin * size / 8;
bit = 7 - (margin * size % 8);
for(x=0; x<width; x++) {
for(xx=0; xx<size; xx++) {
*q ^= (*p & 1) << bit;
bit--;
if(bit < 0) {
q++;
bit = 7;
}
}
p++;
}
for(yy=0; yy<size; yy++) {
png_write_row(png_ptr, row);
}
}
/* bottom margin */
memset(row, 0xff, (realwidth + 7) / 8);
for(y=0; y<margin * size; y++) {
png_write_row(png_ptr, row);
}
png_write_end(png_ptr, info_ptr);
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
free(row);
return 0;
}
void write_pattern_image(int version, const char *filename)
{
int width;
unsigned char *frame;
static char str[256];
frame = QRspec_newFrame(version);
width = QRspec_getWidth(version);
snprintf(str, 256, "%s-%d.png", filename, version);
writePNG(frame, width, str);
free(frame);
}
void write_pattern(const char *filename)
{
FILE *fp;
int i;
fp = fopen(filename, "wb");
if(fp == NULL) {
perror("Failed to open a file to write:");
abort();
}
for(i=1; i<=QRSPEC_VERSION_MAX; i++) {
append_pattern(i, fp);
write_pattern_image(i, filename);
}
fclose(fp);
}
int main(int argc, char **argv)
{
if(argc < 2) {
printf("Create empty frame patterns.\nUsage: %s FILENAME\n", argv[0]);
exit(0);
}
write_pattern(argv[1]);
return 0;
}

View File

@ -0,0 +1,170 @@
/*
* This tool creates a frame pattern data for debug purpose used by
* test_qrspec. test_qrspec and create_frame_pattern uses the same function
* of libqrencode. This means the test is meaningless if test_qrspec is run
* with a pattern data created by create_frame_pattern of the same version.
* In order to test it correctly, create a pattern data by the tool of the
* previous version, or use the frame data attached to the package.
*/
#include <stdio.h>
#include <string.h>
#include <png.h>
#include "common.h"
#include "../mqrspec.h"
void append_pattern(int version, FILE *fp)
{
int width;
unsigned char *frame;
frame = MQRspec_newFrame(version);
width = MQRspec_getWidth(version);
fwrite(frame, 1, width * width, fp);
free(frame);
}
static int writePNG(unsigned char *frame, int width, const char *outfile)
{
static FILE *fp;
png_structp png_ptr;
png_infop info_ptr;
unsigned char *row, *p, *q;
int x, y, xx, yy, bit;
int realwidth;
const int margin = 0;
const int size = 1;
realwidth = (width + margin * 2) * size;
row = (unsigned char *)malloc((realwidth + 7) / 8);
if(row == NULL) {
fprintf(stderr, "Failed to allocate memory.\n");
exit(EXIT_FAILURE);
}
if(outfile[0] == '-' && outfile[1] == '\0') {
fp = stdout;
} else {
fp = fopen(outfile, "wb");
if(fp == NULL) {
fprintf(stderr, "Failed to create file: %s\n", outfile);
perror(NULL);
exit(EXIT_FAILURE);
}
}
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if(png_ptr == NULL) {
fclose(fp);
fprintf(stderr, "Failed to initialize PNG writer.\n");
exit(EXIT_FAILURE);
}
info_ptr = png_create_info_struct(png_ptr);
if(info_ptr == NULL) {
fclose(fp);
fprintf(stderr, "Failed to initialize PNG write.\n");
exit(EXIT_FAILURE);
}
if(setjmp(png_jmpbuf(png_ptr))) {
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
fprintf(stderr, "Failed to write PNG image.\n");
exit(EXIT_FAILURE);
}
png_init_io(png_ptr, fp);
png_set_IHDR(png_ptr, info_ptr,
realwidth, realwidth,
1,
PNG_COLOR_TYPE_GRAY,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
png_write_info(png_ptr, info_ptr);
/* top margin */
memset(row, 0xff, (realwidth + 7) / 8);
for(y=0; y<margin * size; y++) {
png_write_row(png_ptr, row);
}
/* data */
p = frame;
for(y=0; y<width; y++) {
bit = 7;
memset(row, 0xff, (realwidth + 7) / 8);
q = row;
q += margin * size / 8;
bit = 7 - (margin * size % 8);
for(x=0; x<width; x++) {
for(xx=0; xx<size; xx++) {
*q ^= (*p & 1) << bit;
bit--;
if(bit < 0) {
q++;
bit = 7;
}
}
p++;
}
for(yy=0; yy<size; yy++) {
png_write_row(png_ptr, row);
}
}
/* bottom margin */
memset(row, 0xff, (realwidth + 7) / 8);
for(y=0; y<margin * size; y++) {
png_write_row(png_ptr, row);
}
png_write_end(png_ptr, info_ptr);
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
free(row);
return 0;
}
void write_pattern_image(int version, const char *filename)
{
int width;
unsigned char *frame;
static char str[256];
frame = MQRspec_newFrame(version);
width = MQRspec_getWidth(version);
snprintf(str, 256, "%s-M%d.png", filename, version);
writePNG(frame, width, str);
free(frame);
}
void write_pattern(const char *filename)
{
FILE *fp;
int i;
fp = fopen(filename, "wb");
if(fp == NULL) {
perror("Failed to open a file to write:");
abort();
}
for(i=1; i<=MQRSPEC_VERSION_MAX; i++) {
append_pattern(i, fp);
write_pattern_image(i, filename);
}
fclose(fp);
}
int main(int argc, char **argv)
{
if(argc < 2) {
printf("Create empty frame patterns.\nUsage: %s FILENAME\n", argv[0]);
exit(0);
}
write_pattern(argv[1]);
return 0;
}

174
tests/datachunk.c Normal file
View File

@ -0,0 +1,174 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iconv.h>
#include "datachunk.h"
DataChunk *DataChunk_new(QRencodeMode mode)
{
DataChunk *chunk;
chunk = (DataChunk *)calloc(1, sizeof(DataChunk));
if(chunk == NULL) return NULL;
chunk->mode = mode;
return chunk;
}
void DataChunk_free(DataChunk *chunk)
{
if(chunk) {
if(chunk->data) free(chunk->data);
free(chunk);
}
}
void DataChunk_freeList(DataChunk *list)
{
DataChunk *next;
while(list != NULL) {
next = list->next;
DataChunk_free(list);
list = next;
}
}
static void dumpNum(DataChunk *chunk)
{
printf("%s\n", chunk->data);
}
static void dumpAn(DataChunk *chunk)
{
printf("%s\n", chunk->data);
}
static void dump8(DataChunk *chunk)
{
int i, j;
unsigned char c;
int count = 0;
unsigned char buf[16];
for(i=0; i<chunk->size; i++) {
buf[count] = chunk->data[i];
c = chunk->data[i];
if(c >= ' ' && c <= '~') {
putchar(c);
} else {
putchar('.');
}
count++;
if(count >= 16) {
putchar(' ');
for(j=0; j<16; j++) {
printf(" %02x", buf[j]);
}
count = 0;
putchar('\n');
}
}
if(count > 0) {
for(i=0; i<16 - count; i++) {
putchar(' ');
}
putchar(' ');
for(j=0; j<count; j++) {
printf(" %02x", buf[j]);
}
count = 0;
putchar('\n');
}
}
static void dumpKanji(DataChunk *chunk)
{
iconv_t conv;
char *inbuf, *outbuf, *outp;
size_t inbytes, outbytes, ret;
conv = iconv_open("UTF-8", "SHIFT_JIS");
inbytes = chunk->size;
inbuf = (char *)chunk->data;
outbytes = inbytes * 4 + 1;
outbuf = (char *)malloc(inbytes * 4 + 1);
outp = outbuf;
ret = iconv(conv, &inbuf, &inbytes, &outp, &outbytes);
if(ret == (size_t) -1) { perror(NULL); }
*outp = '\0';
printf("%s\n", outbuf);
iconv_close(conv);
free(outbuf);
}
static void dumpChunk(DataChunk *chunk)
{
switch(chunk->mode) {
case QR_MODE_NUM:
printf("Numeric: %d bytes\n", chunk->size);
dumpNum(chunk);
break;
case QR_MODE_AN:
printf("AlphaNumeric: %d bytes\n", chunk->size);
dumpAn(chunk);
break;
case QR_MODE_8:
printf("8-bit data: %d bytes\n", chunk->size);
dump8(chunk);
break;
case QR_MODE_KANJI:
printf("Kanji: %d bytes\n", chunk->size);
dumpKanji(chunk);
break;
default:
printf("Invalid or reserved: %d bytes\n", chunk->size);
dump8(chunk);
break;
}
}
void DataChunk_dumpChunkList(DataChunk *list)
{
while(list != NULL) {
dumpChunk(list);
list = list->next;
}
}
int DataChunk_totalSize(DataChunk *list)
{
int size = 0;
while(list != NULL) {
size += list->size;
list = list->next;
}
return size;
}
unsigned char *DataChunk_concatChunkList(DataChunk *list, int *retsize)
{
int size, idx;
unsigned char *data;
size = DataChunk_totalSize(list);
if(size <= 0) return NULL;
data = (unsigned char *)malloc(size + 1);
idx = 0;
while(list != NULL) {
memcpy(&data[idx], list->data, list->size);
idx += list->size;
list = list->next;
}
data[size] = '\0';
*retsize = size;
return data;
}

21
tests/datachunk.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef DATACHUNK_H
#define DATACHUNK_H
#include "../qrencode.h"
typedef struct _DataChunk {
QRencodeMode mode;
int size;
int bits;
unsigned char *data;
struct _DataChunk *next;
} DataChunk;
DataChunk *DataChunk_new(QRencodeMode mode);
void DataChunk_free(DataChunk *chunk);
void DataChunk_freeList(DataChunk *list);
void DataChunk_dumpChunkList(DataChunk *list);
int DataChunk_totalSize(DataChunk *list);
unsigned char *DataChunk_concatChunkList(DataChunk *list, int *retsize);
#endif /* DATACHUNK_H */

953
tests/decoder.c Normal file
View File

@ -0,0 +1,953 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iconv.h>
#if HAVE_CONFIG_H
#include "../config.h"
#endif
#include "../qrspec.h"
#include "../bitstream.h"
#include "../mask.h"
#include "../mqrspec.h"
#include "../mmask.h"
#include "common.h"
#include "decoder.h"
static unsigned int bitToInt(unsigned char *bits, int length)
{
int i;
unsigned int val = 0;
for(i=0; i<length; i++) {
val = val << 1;
val |= (bits[i] & 1);
}
return val;
}
static int decodeLength(int *bits_length, unsigned char **bits, QRencodeMode mode, int version, int mqr)
{
int i;
int length = 0;
int lbits;
if(mqr) {
lbits = MQRspec_lengthIndicator(mode, version);
} else {
lbits = QRspec_lengthIndicator(mode, version);
}
if(*bits_length < lbits) {
printf("Bit length is too short: %d\n", *bits_length);
return 0;
}
length = 0;
for(i=0; i<lbits; i++) {
length = length << 1;
length += (*bits)[i];
}
*bits_length -= lbits;
*bits += lbits;
return length;
}
static DataChunk *decodeNum(int *bits_length, unsigned char **bits, int version, int mqr)
{
int i;
int size, sizeInBit, words, remain;
unsigned char *p;
char *buf, *q;
unsigned int val;
DataChunk *chunk;
size = decodeLength(bits_length, bits, QR_MODE_NUM, version, mqr);
if(size < 0) return NULL;
words = size / 3;
remain = size - words * 3;
sizeInBit = words * 10;
if(remain == 2) {
sizeInBit += 7;
} else if(remain == 1) {
sizeInBit += 4;
}
if(*bits_length < sizeInBit) {
printf("Bit length is too short: %d, expected %d.\n", *bits_length, sizeInBit);
return NULL;
}
buf = (char *)malloc((size_t)size + 1);
p = *bits;
q = buf;
for(i=0; i<words; i++) {
val = bitToInt(p, 10);
sprintf(q, "%03d", val);
p += 10;
q += 3;
}
if(remain == 2) {
val = bitToInt(p, 7);
sprintf(q, "%02d", val);
} else if(remain == 1) {
val = bitToInt(p, 4);
sprintf(q, "%1d", val);
}
buf[size] = '\0';
chunk = DataChunk_new(QR_MODE_NUM);
chunk->size = size;
chunk->data = (unsigned char *)buf;
*bits_length -= sizeInBit;
*bits += sizeInBit;
return chunk;
}
static const char decodeAnTable[45] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', ' ', '$', '%', '*',
'+', '-', '.', '/', ':'
};
static DataChunk *decodeAn(int *bits_length, unsigned char **bits, int version, int mqr)
{
int i;
int size, sizeInBit, words, remain;
unsigned char *p;
char *buf, *q;
unsigned int val;
int ch, cl;
DataChunk *chunk;
size = decodeLength(bits_length, bits, QR_MODE_AN, version, mqr);
if(size < 0) return NULL;
words = size / 2;
remain = size - words * 2;
sizeInBit = words * 11 + remain * 6;
if(*bits_length < sizeInBit) {
printf("Bit length is too short: %d, expected %d.\n", *bits_length, sizeInBit);
return NULL;
}
buf = (char *)malloc((size_t)size + 1);
p = *bits;
q = buf;
for(i=0; i<words; i++) {
val = bitToInt(p, 11);
ch = (int)(val / 45);
cl = (int)(val % 45);
sprintf(q, "%c%c", decodeAnTable[ch], decodeAnTable[cl]);
p += 11;
q += 2;
}
if(remain == 1) {
val = bitToInt(p, 6);
sprintf(q, "%c", decodeAnTable[val]);
}
chunk = DataChunk_new(QR_MODE_AN);
chunk->size = size;
chunk->data = (unsigned char *)buf;
*bits_length -= sizeInBit;
*bits += sizeInBit;
return chunk;
}
static DataChunk *decode8(int *bits_length, unsigned char **bits, int version, int mqr)
{
int i;
int size, sizeInBit;
unsigned char *p;
unsigned char *buf, *q;
DataChunk *chunk;
size = decodeLength(bits_length, bits, QR_MODE_8, version, mqr);
if(size < 0) return NULL;
sizeInBit = size * 8;
if(*bits_length < sizeInBit) {
printf("Bit length is too short: %d, expected %d.\n", *bits_length, sizeInBit);
return NULL;
}
buf = (unsigned char *)malloc((size_t)size);
p = *bits;
q = buf;
for(i=0; i<size; i++) {
*q = (unsigned char)bitToInt(p, 8);
p += 8;
q += 1;
}
chunk = DataChunk_new(QR_MODE_8);
chunk->size = size;
chunk->data = buf;
*bits_length -= sizeInBit;
*bits += sizeInBit;
return chunk;
}
static DataChunk *decodeKanji(int *bits_length, unsigned char **bits, int version, int mqr)
{
int i;
int size, sizeInBit;
unsigned char *p;
char *buf, *q;
unsigned int val;
unsigned int ch, cl;
DataChunk *chunk;
size = decodeLength(bits_length, bits, QR_MODE_KANJI, version, mqr);
if(size < 0) return NULL;
sizeInBit = size * 13;
if(*bits_length < sizeInBit) {
printf("Bit length is too short: %d, expected %d.\n", *bits_length, sizeInBit);
return NULL;
}
buf = (char *)malloc((size_t)size * 2 + 1);
p = *bits;
q = buf;
for(i=0; i<size; i++) {
val = bitToInt(p, 13);
ch = val / 0xc0;
cl = val - ch * 0xc0;
val = ch * 256 + cl;
if(val >= 0x1f00) {
val += 0xc140;
} else {
val += 0x8140;
}
sprintf(q, "%c%c", (val>>8) & 0xff, val & 0xff);
p += 13;
q += 2;
}
chunk = DataChunk_new(QR_MODE_KANJI);
chunk->size = size * 2;
chunk->data = (unsigned char *)buf;
*bits_length -= sizeInBit;
*bits += sizeInBit;
return chunk;
}
static DataChunk *decodeChunk(int *bits_length, unsigned char **bits, int version)
{
unsigned int val;
if(*bits_length < 4) {
return NULL;
}
val = bitToInt(*bits, 4);
*bits_length -= 4;
*bits += 4;
switch(val) {
case 0:
return NULL;
case 1:
return decodeNum(bits_length, bits, version, 0);
case 2:
return decodeAn(bits_length, bits, version, 0);
case 4:
return decode8(bits_length, bits, version, 0);
case 8:
return decodeKanji(bits_length, bits, version, 0);
default:
break;
}
printf("Invalid mode in a chunk: %d\n", val);
return NULL;
}
static DataChunk *decodeChunkMQR(int *bits_length, unsigned char **bits, int version)
{
int modebits, termbits;
unsigned int val;
modebits = version - 1;
termbits = version * 2 + 1;
if(*bits_length >= termbits) {
val = bitToInt(*bits, termbits);
if(val == 0) {
*bits += termbits;
*bits_length -= termbits;
return NULL;
}
} else {
if(*bits_length < modebits) {
val = bitToInt(*bits, *bits_length);
} else {
val = bitToInt(*bits, modebits);
}
if(val == 0) {
return NULL;
} else {
printf("Terminating bits include 1-bit.\n");
return NULL;
}
}
val = bitToInt(*bits, modebits);
if(version == 4 && val > 3) {
printf("Invalid mode number %d.\n", val);
}
*bits_length -= modebits;
*bits += modebits;
switch(val) {
case 0:
return decodeNum(bits_length, bits, version, 1);
case 1:
return decodeAn(bits_length, bits, version, 1);
case 2:
return decode8(bits_length, bits, version, 1);
case 3:
return decodeKanji(bits_length, bits, version, 1);
default:
break;
}
printf("Invalid mode in a chunk: %d\n", val);
return NULL;
}
static int appendChunk(QRdata *qrdata, int *bits_length, unsigned char **bits)
{
DataChunk *chunk;
if(qrdata->mqr) {
chunk = decodeChunkMQR(bits_length, bits, qrdata->version);
} else {
chunk = decodeChunk(bits_length, bits, qrdata->version);
}
if(chunk == NULL) {
return 1;
}
if(qrdata->last == NULL) {
qrdata->chunks = chunk;
} else {
qrdata->last->next = chunk;
}
qrdata->last = chunk;
return 0;
}
QRdata *QRdata_new(void)
{
QRdata *qrdata;
qrdata = (QRdata *)calloc(sizeof(QRdata), 1);
if(qrdata == NULL) return NULL;
qrdata->eccResult = 0;
return qrdata;
}
QRdata *QRdata_newMQR(void)
{
QRdata *qrdata;
qrdata = QRdata_new();
if(qrdata == NULL) return NULL;
qrdata->mqr = 1;
return qrdata;
}
void QRdata_free(QRdata *qrdata)
{
DataChunk_freeList(qrdata->chunks);
if(qrdata->data != NULL) {
free(qrdata->data);
}
free(qrdata);
}
static int QRdata_decodeBits(QRdata *qrdata, int length, unsigned char *bits)
{
int ret = 0;
while(ret == 0) {
ret = appendChunk(qrdata, &length, &bits);
}
return length;
}
int QRdata_decodeBitStream(QRdata *qrdata, BitStream *bstream)
{
return QRdata_decodeBits(qrdata, bstream->length, bstream->data);
}
void QRdata_dump(QRdata *data)
{
DataChunk_dumpChunkList(data->chunks);
}
int QRcode_decodeVersion(QRcode *code)
{
unsigned int v1, v2;
int x, y, width;
unsigned char *p;
width = code->width;
if(width < 45) {
return (width - 21)/ 4 + 1;
}
v1 = 0;
p = code->data + width * (width - 9) + 5;
for(x=0; x<6; x++) {
for(y=0; y<3; y++) {
v1 = v1 << 1;
v1 |= *(p - y * width - x) & 1;
}
}
v2 = 0;
p = code->data + width * 5 + width - 9;
for(y=0; y<6; y++) {
for(x=0; x<3; x++) {
v2 = v2 << 1;
v2 |= *(p - y * width - x) & 1;
}
}
if(v1 != v2) {
printf("Two verion patterns are different.\n");
return -1;
}
return (int)(v1 >> 12);
}
int QRcode_decodeFormat(QRcode *code, QRecLevel *level, int *mask)
{
unsigned int v1, v2;
int i, width;
unsigned char *p;
width = code->width;
v1 = 0;
p = code->data + width * 8;
for(i=0; i<8; i++) {
v1 = v1 << 1;
if(i < 6) {
v1 |= *(p + i) & 1;
} else {
v1 |= *(p + i + 1) & 1;
}
}
p = code->data + width * 7 + 8;
for(i=0; i<7; i++) {
v1 = v1 << 1;
if(i < 1) {
v1 |= *(p - width * i) & 1;
} else {
v1 |= *(p - width * (i + 1)) & 1;
}
}
v2 = 0;
p = code->data + width * (width - 1) + 8;
for(i=0; i<7; i++) {
v2 = v2 << 1;
v2 |= *(p - width * i) & 1;
}
p = code->data + width * 8 + width - 8;
for(i=0; i<8; i++) {
v2 = v2 << 1;
v2 |= *(p + i) & 1;
}
if(v1 != v2) {
printf("Two format infos are different.\n");
return -1;
}
v1 = (v1 ^ 0x5412) >> 10;
*mask = v1 & 7;
switch((v1 >> 3) & 3) {
case 1:
*level = QR_ECLEVEL_L;
break;
case 0:
*level = QR_ECLEVEL_M;
break;
case 3:
*level = QR_ECLEVEL_Q;
break;
case 2:
*level = QR_ECLEVEL_H;
break;
default:
break;
}
return 0;
}
static unsigned char *unmask(QRcode *code, QRecLevel level, int mask)
{
unsigned char *unmasked;
unmasked = Mask_makeMask(code->width, code->data, mask, level);
return unmasked;
}
unsigned char *QRcode_unmask(QRcode *code)
{
int ret, version, mask;
QRecLevel level;
version = QRcode_decodeVersion(code);
if(version < 1) return NULL;
ret = QRcode_decodeFormat(code, &level, &mask);
if(ret < 0) return NULL;
return unmask(code, level, mask);
}
typedef struct {
int width;
unsigned char *frame;
int x, y;
int dir;
int bit;
int mqr;
} FrameFiller;
static FrameFiller *FrameFiller_new(int width, unsigned char *frame, int mqr)
{
FrameFiller *filler;
filler = (FrameFiller *)malloc(sizeof(FrameFiller));
if(filler == NULL) return NULL;
filler->width = width;
filler->frame = frame;
filler->x = width - 1;
filler->y = width - 1;
filler->dir = -1;
filler->bit = -1;
filler->mqr = mqr;
return filler;
}
static unsigned char *FrameFiller_next(FrameFiller *filler)
{
unsigned char *p;
int x, y, w;
if(filler->bit == -1) {
filler->bit = 0;
return filler->frame + filler->y * filler->width + filler->x;
}
x = filler->x;
y = filler->y;
p = filler->frame;
w = filler->width;
if(filler->bit == 0) {
x--;
filler->bit++;
} else {
x++;
y += filler->dir;
filler->bit--;
}
if(filler->dir < 0) {
if(y < 0) {
y = 0;
x -= 2;
filler->dir = 1;
if(!filler->mqr && x == 6) {
x--;
y = 9;
}
}
} else {
if(y == w) {
y = w - 1;
x -= 2;
filler->dir = -1;
if(!filler->mqr && x == 6) {
x--;
y -= 8;
}
}
}
if(x < 0 || y < 0) return NULL;
filler->x = x;
filler->y = y;
if(p[y * w + x] & 0x80) {
// This tail recursion could be optimized.
return FrameFiller_next(filler);
}
return &p[y * w + x];
}
static BitStream *extractBits(int width, unsigned char *frame, int spec[5])
{
BitStream *bstream;
unsigned char *bits, *p, *q;
FrameFiller *filler;
int i, j;
int col, row, d1, b1, blocks, idx, words;
blocks = QRspec_rsBlockNum(spec);
words = QRspec_rsDataLength(spec);
d1 = QRspec_rsDataCodes1(spec);
b1 = QRspec_rsBlockNum1(spec);
bits = (unsigned char *)malloc((size_t)words * 8);
/*
* 00 01 02 03 04 05 06 07 08 09
* 10 11 12 13 14 15 16 17 18 19
* 20 21 22 23 24 25 26 27 28 29 30
* 31 32 33 34 35 36 37 38 39 40 41
* 42 43 44 45 46 47 48 49 50 51 52
*/
row = col = 0;
filler = FrameFiller_new(width, frame, 0);
for(i=0; i<words; i++) {
col = i / blocks;
row = i % blocks + ((col >= d1)?b1:0);
idx = d1 * row + col + ((row > b1)?(row-b1):0);
q = bits + idx * 8;
for(j=0; j<8; j++) {
p = FrameFiller_next(filler);
q[j] = *p & 1;
}
}
free(filler);
bstream = BitStream_newWithBits((size_t)words * 8, bits);
free(bits);
return bstream;
}
BitStream *QRcode_extractBits(QRcode *code, int *dataLength, int *eccLength)
{
BitStream *bstream;
unsigned char *unmasked;
int spec[5];
int ret, version, mask;
QRecLevel level;
version = QRcode_decodeVersion(code);
if(version < 1) return NULL;
ret = QRcode_decodeFormat(code, &level, &mask);
if(ret < 0) return NULL;
QRspec_getEccSpec(version, level, spec);
unmasked = unmask(code, level, mask);
if(unmasked == NULL) return NULL;
bstream = extractBits(code->width, unmasked, spec);
free(unmasked);
*dataLength = QRspec_rsDataLength(spec) * 8;
*eccLength = QRspec_rsEccLength(spec) * 8;
return bstream;
}
static int checkRemainderWords(int length, unsigned char *bits, int remainder)
{
int rbits, words;
unsigned char *p, v;
int i;
words = remainder / 8;
rbits = remainder - words * 8;
bits += (length - remainder);
for(i=0; i<rbits; i++) {
if((bits[i]&1) != 0) {
printf("Terminating code includes 1-bit.\n");
printBinary(bits, remainder);
return -1;
}
}
p = bits + rbits;
for(i=0; i<words; i++) {
v = (unsigned char)bitToInt(p, 8);
if(v != ((i&1)?0x11:0xec)) {
printf("Remainder codewords wrong.\n");
printBinary(bits, remainder);
return -1;
}
p += 8;
}
return 0;
}
QRdata *QRcode_decodeBits(QRcode *code)
{
BitStream *bstream;
unsigned char *unmasked;
int spec[5];
int ret, version, mask;
int length;
QRecLevel level;
QRdata *qrdata;
version = QRcode_decodeVersion(code);
if(version < 1) return NULL;
ret = QRcode_decodeFormat(code, &level, &mask);
if(ret < 0) return NULL;
QRspec_getEccSpec(version, level, spec);
length = QRspec_rsDataLength(spec) * 8;
unmasked = unmask(code, level, mask);
if(unmasked == NULL) return NULL;
bstream = extractBits(code->width, unmasked, spec);
free(unmasked);
qrdata = QRdata_new();
qrdata->version = version;
qrdata->level = level;
ret = QRdata_decodeBitStream(qrdata, bstream);
if(ret > 0) {
checkRemainderWords(length, bstream->data, ret);
}
BitStream_free(bstream);
return qrdata;
}
void QRdata_concatChunks(QRdata *qrdata)
{
qrdata->data = DataChunk_concatChunkList(qrdata->chunks, &qrdata->size);
}
QRdata *QRcode_decode(QRcode *code)
{
QRdata *qrdata;
qrdata = QRcode_decodeBits(code);
QRdata_concatChunks(qrdata);
return qrdata;
}
/*
* Micro QR Code decoder
*/
struct FormatInfo MQRformat[] = {
{1, QR_ECLEVEL_L},
{2, QR_ECLEVEL_L},
{2, QR_ECLEVEL_M},
{3, QR_ECLEVEL_L},
{3, QR_ECLEVEL_M},
{4, QR_ECLEVEL_L},
{4, QR_ECLEVEL_M},
{4, QR_ECLEVEL_Q}
};
int QRcode_decodeFormatMQR(QRcode *code, int *version, QRecLevel *level, int *mask)
{
unsigned int v, t;
int i, width;
unsigned char *p;
width = code->width;
v = 0;
p = code->data + width * 8 + 1;
for(i=0; i<8; i++) {
v = v << 1;
v |= p[i] & 1;
}
p = code->data + width * 7 + 8;
for(i=0; i<7; i++) {
v = v << 1;
v |= *(p - width * i) & 1;
}
v ^= 0x4445;
*mask = (v >> 10) & 3;
t = (v >> 12) & 7;
*version = MQRformat[t].version;
*level = MQRformat[t].level;
if(*version * 2 + 9 != width) {
printf("Decoded version number does not match to the size.\n");
return -1;
}
return 0;
}
static unsigned char *unmaskMQR(QRcode *code, QRecLevel level, int mask)
{
unsigned char *unmasked;
unmasked = MMask_makeMask(code->version, code->data, mask, level);
return unmasked;
}
unsigned char *QRcode_unmaskMQR(QRcode *code)
{
int ret, version, mask;
QRecLevel level;
ret = QRcode_decodeFormatMQR(code, &version, &level, &mask);
if(ret < 0) return NULL;
return unmaskMQR(code, level, mask);
}
static BitStream *extractBitsMQR(int width, unsigned char *frame, int version, QRecLevel level)
{
BitStream *bstream;
unsigned char *bits;
FrameFiller *filler;
int i;
int size;
size = MQRspec_getDataLengthBit(version, level) + MQRspec_getECCLength(version, level) * 8;
bits = (unsigned char *)malloc((size_t)size);
filler = FrameFiller_new(width, frame, 1);
for(i=0; i<size; i++) {
bits[i] = *(FrameFiller_next(filler)) & 1;
}
free(filler);
bstream = BitStream_newWithBits((size_t)size, bits);
free(bits);
return bstream;
}
BitStream *QRcode_extractBitsMQR(QRcode *code, int *dataLength, int *eccLength, int *version, QRecLevel *level)
{
BitStream *bstream;
unsigned char *unmasked;
int ret, mask;
ret = QRcode_decodeFormatMQR(code, version, level, &mask);
if(ret < 0) return NULL;
unmasked = unmaskMQR(code, *level, mask);
if(unmasked == NULL) return NULL;
*dataLength = MQRspec_getDataLengthBit(*version, *level);
*eccLength = MQRspec_getECCLength(*version, *level) * 8;
bstream = extractBitsMQR(code->width, unmasked, *version, *level);
free(unmasked);
return bstream;
}
static int checkRemainderWordsMQR(int length, unsigned char *bits, int remainder, int version)
{
int rbits, words, paddings;
unsigned char *p, v;
int i, decoded;
decoded = length - remainder;
bits += decoded;
words = (decoded + 7) / 8;
rbits = words * 8 - decoded;
for(i=0; i<rbits; i++) {
if((bits[i]&1) != 0) {
printf("Terminating code includes 1-bit.\n");
printBinary(bits, remainder);
return -1;
}
}
paddings = (length - words * 8) / 8;
p = bits + rbits;
for(i=0; i<paddings; i++) {
v = (unsigned char)bitToInt(p, 8);
if(v != ((i&1)?0x11:0xec)) {
printf("Remainder codewords wrong.\n");
printBinary(bits, remainder);
return -1;
}
p += 8;
}
rbits = length - (paddings + words)* 8;
if(rbits > 0) {
if((version == 1 || version == 3) && rbits == 4) {
v = (unsigned char)bitToInt(p, 4);
if(v != 0) {
printf("Last padding bits include 1-bit.\n");
return -1;
}
} else {
printf("The length of the last padding bits is %d, not %d.\n", rbits, (version == 1 || version == 3)?4:0);
return -1;
}
}
return 0;
}
QRdata *QRcode_decodeBitsMQR(QRcode *code)
{
BitStream *bstream;
int ret, version, dataLength, eccLength;
QRecLevel level;
QRdata *qrdata;
bstream = QRcode_extractBitsMQR(code, &dataLength, &eccLength, &version, &level);
if(bstream == NULL) {
return NULL;
}
qrdata = QRdata_newMQR();
qrdata->version = version;
qrdata->level = level;
ret = QRdata_decodeBits(qrdata, dataLength, bstream->data);
if(ret > 0) {
ret = checkRemainderWordsMQR(dataLength, bstream->data, ret, version);
if(ret < 0) {
QRdata_free(qrdata);
qrdata = NULL;
}
}
BitStream_free(bstream);
return qrdata;
}
QRdata *QRcode_decodeMQR(QRcode *code)
{
QRdata *qrdata;
qrdata = QRcode_decodeBitsMQR(code);
if(qrdata != NULL) {
QRdata_concatChunks(qrdata);
}
return qrdata;
}

43
tests/decoder.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef DECODER_H
#define DECODER_H
#include "../qrencode.h"
#include "datachunk.h"
typedef struct {
unsigned char *data;
int size;
int mqr;
int version;
QRecLevel level;
DataChunk *chunks, *last;
int eccResult;
} QRdata;
struct FormatInfo {
int version;
QRecLevel level;
};
extern struct FormatInfo MQRformat[];
QRdata *QRdata_new(void);
QRdata *QRdata_newMQR(void);
int QRdata_decodeBitStream(QRdata *qrdata, BitStream *bstream);
void QRdata_dump(QRdata *data);
void QRdata_free(QRdata *data);
int QRcode_decodeVersion(QRcode *code);
int QRcode_decodeFormat(QRcode *code, QRecLevel *level, int *mask);
unsigned char *QRcode_unmask(QRcode *code);
BitStream *QRcode_extractBits(QRcode *code, int *dataLength, int *eccLength);
QRdata *QRcode_decodeBits(QRcode *code);
QRdata *QRcode_decode(QRcode *code);
int QRcode_decodeFormatMQR(QRcode *code, int *vesion, QRecLevel *level, int *mask);
unsigned char *QRcode_unmaskMQR(QRcode *code);
BitStream *QRcode_extractBitsMQR(QRcode *code, int *dataLength, int *eccLength, int *version, QRecLevel *level);
QRdata *QRcode_decodeBitsMQR(QRcode *code);
QRdata *QRcode_decodeMQR(QRcode *code);
#endif /* DECODER_H */

BIN
tests/frame Normal file

Binary file not shown.

102
tests/prof_qrencode.c Normal file
View File

@ -0,0 +1,102 @@
#include <stdio.h>
#include <stdlib.h>
#if HAVE_CONFIG_H
#include "../config.h"
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <errno.h>
#include "../qrencode.h"
#ifdef _MSC_VER
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
static LARGE_INTEGER startTime;
static LARGE_INTEGER frequency = { .QuadPart = 0 };
#else
static struct timeval tv;
#endif
static void timerStart(const char *str)
{
printf("%s: START\n", str);
#ifdef _MSC_VER
(void) QueryPerformanceCounter(&startTime);
#else
gettimeofday(&tv, NULL);
#endif
}
static void timerStop(void)
{
#ifdef _MSC_VER
LARGE_INTEGER endTime, elapsed;
(void) QueryPerformanceCounter(&endTime);
if (frequency.QuadPart == 0) {
(void) QueryPerformanceFrequency(&frequency);
}
elapsed.QuadPart = endTime.QuadPart - startTime.QuadPart;
elapsed.QuadPart *= 1000;
elapsed.QuadPart /= frequency.QuadPart;
printf("STOP: %lld msec\n", elapsed.QuadPart);
#else
struct timeval tc;
gettimeofday(&tc, NULL);
printf("STOP: %ld msec\n", (tc.tv_sec - tv.tv_sec) * 1000
+ (tc.tv_usec - tv.tv_usec) / 1000);
#endif
}
static void prof_ver1to10(void)
{
QRcode *code;
int i;
int version;
static const char *data = "This is test.";
timerStart("Version 1 - 10 (500 symbols for each)");
for(i=0; i<500; i++) {
for(version = 0; version < 11; version++) {
code = QRcode_encodeString(data, version, QR_ECLEVEL_L, QR_MODE_8, 0);
if(code == NULL) {
perror("Failed to encode:");
} else {
QRcode_free(code);
}
}
}
timerStop();
}
static void prof_ver31to40(void)
{
QRcode *code;
int i;
int version;
static const char *data = "This is test.";
timerStart("Version 31 - 40 (50 symbols for each)");
for(i=0; i<50; i++) {
for(version = 31; version < 41; version++) {
code = QRcode_encodeString(data, version, QR_ECLEVEL_L, QR_MODE_8, 0);
if(code == NULL) {
perror("Failed to encode:");
} else {
QRcode_free(code);
}
}
}
timerStop();
}
int main()
{
prof_ver1to10();
prof_ver31to40();
return 0;
}

135
tests/pthread_qrencode.c Normal file
View File

@ -0,0 +1,135 @@
#include <stdio.h>
#include <stdlib.h>
#if HAVE_CONFIG_H
#include "../config.h"
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <pthread.h>
#include <errno.h>
#include "../qrencode.h"
#define THREADS (10)
static pthread_t threads[THREADS];
#ifdef _MSC_VER
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
static LARGE_INTEGER startTime;
static LARGE_INTEGER frequency = { .QuadPart = 0 };
#else
static struct timeval tv;
#endif
static void timerStart(const char *str)
{
printf("%s: START\n", str);
#ifdef _MSC_VER
(void) QueryPerformanceCounter(&startTime);
#else
gettimeofday(&tv, NULL);
#endif
}
static void timerStop(void)
{
#ifdef _MSC_VER
LARGE_INTEGER endTime, elapsed;
(void) QueryPerformanceCounter(&endTime);
if (frequency.QuadPart == 0) {
(void) QueryPerformanceFrequency(&frequency);
}
elapsed.QuadPart = endTime.QuadPart - startTime.QuadPart;
elapsed.QuadPart *= 1000;
elapsed.QuadPart /= frequency.QuadPart;
printf("STOP: %lld msec\n", elapsed.QuadPart);
#else
struct timeval tc;
gettimeofday(&tc, NULL);
printf("STOP: %ld msec\n", (tc.tv_sec - tv.tv_sec) * 1000
+ (tc.tv_usec - tv.tv_usec) / 1000);
#endif
}
static void *encode_ver1to10(void *arg)
{
QRcode *code;
int i;
int version;
static const char *data = "This is test.";
for(i=0; i<500; i++) {
for(version = 0; version < 11; version++) {
code = QRcode_encodeString(data, version, QR_ECLEVEL_L, QR_MODE_8, 0);
if(code == NULL) {
perror("Failed to encode:");
} else {
QRcode_free(code);
}
}
}
return NULL;
}
static void prof_ver1to10(void)
{
int i;
timerStart("Version 1 - 10 (500 symbols for each)");
for(i=0; i<THREADS; i++) {
pthread_create(&threads[i], NULL, encode_ver1to10, NULL);
}
for(i=0; i<THREADS; i++) {
pthread_join(threads[i], NULL);
}
timerStop();
}
static void *encode_ver31to40(void *arg)
{
QRcode *code;
int i;
int version;
static const char *data = "This is test.";
for(i=0; i<50; i++) {
for(version = 31; version < 41; version++) {
code = QRcode_encodeString(data, version, QR_ECLEVEL_L, QR_MODE_8, 0);
if(code == NULL) {
perror("Failed to encode:");
} else {
QRcode_free(code);
}
}
}
return NULL;
}
static void prof_ver31to40(void)
{
int i;
timerStart("Version 31 - 40 (50 symbols for each)");
for(i=0; i<THREADS; i++) {
pthread_create(&threads[i], NULL, encode_ver31to40, NULL);
}
for(i=0; i<THREADS; i++) {
pthread_join(threads[i], NULL);
}
timerStop();
}
int main()
{
prof_ver1to10();
prof_ver31to40();
return 0;
}

274
tests/rscode.c Normal file
View File

@ -0,0 +1,274 @@
/*
* qrencode - QR Code encoder
*
* Reed solomon encoder. This code is taken from Phil Karn's libfec then
* editted and packed into a pair of .c and .h files.
*
* Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
* (libfec is released under the GNU Lesser General Public License.)
*
* Copyright (C) 2006-2011 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include "rscode.h"
/* Stuff specific to the 8-bit symbol version of the general purpose RS codecs
*
*/
typedef unsigned char data_t;
/**
* Reed-Solomon codec control block
*/
struct _RS {
int mm; /* Bits per symbol */
int nn; /* Symbols per block (= (1<<mm)-1) */
data_t *alpha_to; /* log lookup table */
data_t *index_of; /* Antilog lookup table */
data_t *genpoly; /* Generator polynomial */
int nroots; /* Number of generator roots = number of parity symbols */
int fcr; /* First consecutive root, index form */
int prim; /* Primitive element, index form */
int iprim; /* prim-th root of 1, index form */
int pad; /* Padding bytes in shortened block */
int gfpoly;
};
static inline int modnn(RS *rs, int x){
while (x >= rs->nn) {
x -= rs->nn;
x = (x >> rs->mm) + (x & rs->nn);
}
return x;
}
#define MODNN(x) modnn(rs,x)
#define MM (rs->mm)
#define NN (rs->nn)
#define ALPHA_TO (rs->alpha_to)
#define INDEX_OF (rs->index_of)
#define GENPOLY (rs->genpoly)
#define NROOTS (rs->nroots)
#define FCR (rs->fcr)
#define PRIM (rs->prim)
#define IPRIM (rs->iprim)
#define PAD (rs->pad)
#define A0 (NN)
/* Initialize a Reed-Solomon codec
* symsize = symbol size, bits
* gfpoly = Field generator polynomial coefficients
* fcr = first root of RS code generator polynomial, index form
* prim = primitive element to generate polynomial roots
* nroots = RS code generator polynomial degree (number of roots)
* pad = padding bytes at front of shortened block
*/
static RS *init_rs_char(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad)
{
RS *rs;
/* Common code for intializing a Reed-Solomon control block (char or int symbols)
* Copyright 2004 Phil Karn, KA9Q
* May be used under the terms of the GNU Lesser General Public License (LGPL)
*/
//#undef NULL
//#define NULL ((void *)0)
int i, j, sr,root,iprim;
rs = NULL;
/* Check parameter ranges */
if(symsize < 0 || symsize > (int)(8*sizeof(data_t))){
goto done;
}
if(fcr < 0 || fcr >= (1<<symsize))
goto done;
if(prim <= 0 || prim >= (1<<symsize))
goto done;
if(nroots < 0 || nroots >= (1<<symsize))
goto done; /* Can't have more roots than symbol values! */
if(pad < 0 || pad >= ((1<<symsize) -1 - nroots))
goto done; /* Too much padding */
rs = (RS *)calloc(1,sizeof(RS));
if(rs == NULL)
goto done;
rs->mm = symsize;
rs->nn = (1<<symsize)-1;
rs->pad = pad;
rs->alpha_to = (data_t *)malloc(sizeof(data_t)*(rs->nn+1));
if(rs->alpha_to == NULL){
free(rs);
rs = NULL;
goto done;
}
rs->index_of = (data_t *)malloc(sizeof(data_t)*(rs->nn+1));
if(rs->index_of == NULL){
free(rs->alpha_to);
free(rs);
rs = NULL;
goto done;
}
/* Generate Galois field lookup tables */
rs->index_of[0] = A0; /* log(zero) = -inf */
rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */
sr = 1;
for(i=0;i<rs->nn;i++){
rs->index_of[sr] = i;
rs->alpha_to[i] = sr;
sr <<= 1;
if(sr & (1<<symsize))
sr ^= gfpoly;
sr &= rs->nn;
}
if(sr != 1){
/* field generator polynomial is not primitive! */
free(rs->alpha_to);
free(rs->index_of);
free(rs);
rs = NULL;
goto done;
}
/* Form RS code generator polynomial from its roots */
rs->genpoly = (data_t *)malloc(sizeof(data_t)*(nroots+1));
if(rs->genpoly == NULL){
free(rs->alpha_to);
free(rs->index_of);
free(rs);
rs = NULL;
goto done;
}
rs->fcr = fcr;
rs->prim = prim;
rs->nroots = nroots;
rs->gfpoly = gfpoly;
/* Find prim-th root of 1, used in decoding */
for(iprim=1;(iprim % prim) != 0;iprim += rs->nn)
;
rs->iprim = iprim / prim;
rs->genpoly[0] = 1;
for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) {
rs->genpoly[i+1] = 1;
/* Multiply rs->genpoly[] by @**(root + x) */
for (j = i; j > 0; j--){
if (rs->genpoly[j] != 0)
rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)];
else
rs->genpoly[j] = rs->genpoly[j-1];
}
/* rs->genpoly[0] can never be zero */
rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)];
}
/* convert rs->genpoly[] to index form for quicker encoding */
for (i = 0; i <= nroots; i++)
rs->genpoly[i] = rs->index_of[rs->genpoly[i]];
done:;
return rs;
}
RS *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad)
{
return init_rs_char(symsize, gfpoly, fcr, prim, nroots, pad);
}
void free_rs_char(RS *rs)
{
free(rs->alpha_to);
free(rs->index_of);
free(rs->genpoly);
free(rs);
}
/* The guts of the Reed-Solomon encoder, meant to be #included
* into a function body with the following typedefs, macros and variables supplied
* according to the code parameters:
* data_t - a typedef for the data symbol
* data_t data[] - array of NN-NROOTS-PAD and type data_t to be encoded
* data_t parity[] - an array of NROOTS and type data_t to be written with parity symbols
* NROOTS - the number of roots in the RS code generator polynomial,
* which is the same as the number of parity symbols in a block.
Integer variable or literal.
*
* NN - the total number of symbols in a RS block. Integer variable or literal.
* PAD - the number of pad symbols in a block. Integer variable or literal.
* ALPHA_TO - The address of an array of NN elements to convert Galois field
* elements in index (log) form to polynomial form. Read only.
* INDEX_OF - The address of an array of NN elements to convert Galois field
* elements in polynomial form to index (log) form. Read only.
* MODNN - a function to reduce its argument modulo NN. May be inline or a macro.
* GENPOLY - an array of NROOTS+1 elements containing the generator polynomial in index form
* The memset() and memmove() functions are used. The appropriate header
* file declaring these functions (usually <string.h>) must be included by the calling
* program.
* Copyright 2004, Phil Karn, KA9Q
* May be used under the terms of the GNU Lesser General Public License (LGPL)
*/
#undef A0
#define A0 (NN) /* Special reserved value encoding zero in index form */
void encode_rs_char(RS *rs, const data_t *data, data_t *parity)
{
int i, j;
data_t feedback;
memset(parity,0,NROOTS*sizeof(data_t));
for(i=0;i<NN-NROOTS-PAD;i++){
feedback = INDEX_OF[data[i] ^ parity[0]];
if(feedback != A0){ /* feedback term is non-zero */
#ifdef UNNORMALIZED
/* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
* always be for the polynomials constructed by init_rs()
*/
feedback = MODNN(NN - GENPOLY[NROOTS] + feedback);
#endif
for(j=1;j<NROOTS;j++)
parity[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS-j])];
}
/* Shift */
memmove(&parity[0],&parity[1],sizeof(data_t)*(NROOTS-1));
if(feedback != A0)
parity[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])];
else
parity[NROOTS-1] = 0;
}
}

40
tests/rscode.h Normal file
View File

@ -0,0 +1,40 @@
/*
* qrencode - QR Code encoder
*
* Reed solomon encoder. This code is taken from Phil Karn's libfec then
* editted and packed into a pair of .c and .h files.
*
* Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
* (libfec is released under the GNU Lesser General Public License.)
*
* Copyright (C) 2006-2011 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef RSCODE_H
#define RSCODE_H
/*
* General purpose RS codec, 8-bit symbols.
*/
typedef struct _RS RS;
extern RS *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad);
extern void encode_rs_char(RS *rs, const unsigned char *data, unsigned char *parity);
extern void free_rs_char(RS *rs);
#endif /* RSCODE_H */

64
tests/rsecc_decoder.c Normal file
View File

@ -0,0 +1,64 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../qrspec.h"
#include "rsecc_decoder.h"
#define SYMBOL_SIZE (8)
#define symbols ((1 << SYMBOL_SIZE) - 1)
static const int proot = 0x11d; /* stands for x^8+x^4+x^3+x^2+1 (see pp.37 of JIS X0510:2004) */
/* min/max codeword length of ECC, calculated from the specification. */
#define min_length (2)
#define max_length (30)
#define max_generatorSize (max_length)
static unsigned char alpha[symbols + 1];
static unsigned char aindex[symbols + 1];
void RSECC_decoder_init() {
int i, b;
alpha[symbols] = 0;
aindex[0] = symbols;
b = 1;
for(i = 0; i < symbols; i++) {
alpha[i] = b;
aindex[b] = i;
b <<= 1;
if(b & (symbols + 1)) {
b ^= proot;
}
b &= symbols;
}
}
int RSECC_decoder_checkSyndrome(int dl, unsigned char *data, int el, unsigned char *ecc)
{
int i, j;
int s;
for(i=0; i<el; i++) {
s = data[0];
for(j=1; j<dl; j++) {
if(s == 0) {
s = data[j];
} else {
s = data[j] ^ alpha[(aindex[s] + i) % symbols];
}
}
for(j=0; j<el; j++) {
if(s == 0) {
s = ecc[j];
} else {
s = ecc[j] ^ alpha[(aindex[s] + i) % symbols];
}
}
if(s != 0) {
return -1;
}
}
return 0;
}

7
tests/rsecc_decoder.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef RSECC_DECODER_H
#define RSECC_DECODER_H
void RSECC_decoder_init();
int RSECC_decoder_checkSyndrome(int dl, unsigned char *data, int el, unsigned char *ecc);
#endif /* RSECC_DECODER_H */

3
tests/test_all.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh -e
. ./test_basic.sh
./test_configure.sh

12
tests/test_basic.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/sh -e
./test_bitstream
./test_estimatebit
./test_qrencode
./test_qrinput
./test_qrspec
./test_rs
./test_split
./test_mask
./test_mqrspec
./test_mmask
./test_monkey

257
tests/test_bitstream.c Normal file
View File

@ -0,0 +1,257 @@
#include <stdio.h>
#include <string.h>
#include "common.h"
#include "../bitstream.h"
static void test_null(void)
{
BitStream *bstream;
testStart("Empty stream");
bstream = BitStream_new();
assert_zero(BitStream_size(bstream), "Size of empty BitStream is not 0.\n");
assert_null(BitStream_toByte(bstream), "BitStream_toByte returned non-NULL.\n");
assert_nothing(BitStream_free(NULL), "Checking BitStream_free(NULL).\n");
testFinish();
BitStream_free(bstream);
}
static void test_num(void)
{
BitStream *bstream;
unsigned int data = 0x13579bdf;
char correct[] = "0010011010101111001101111011111";
testStart("New from num");
bstream = BitStream_new();
BitStream_appendNum(bstream, 31, data);
testEnd(cmpBin(correct, bstream));
BitStream_free(bstream);
}
static void test_bytes(void)
{
BitStream *bstream;
unsigned char data[1] = {0x3a};
char correct[] = "00111010";
testStart("New from bytes");
bstream = BitStream_new();
BitStream_appendBytes(bstream, 1, data);
testEnd(cmpBin(correct, bstream));
BitStream_free(bstream);
}
static void test_appendNum(void)
{
BitStream *bstream;
char correct[] = "10001010 11111111 11111111 00010010001101000101011001111000";
testStart("Append Num");
bstream = BitStream_new();
BitStream_appendNum(bstream, 8, 0x0000008a);
assert_zero(ncmpBin(correct, bstream, 8), "Internal data is incorrect.\n");
BitStream_appendNum(bstream, 16, 0x0000ffff);
assert_zero(ncmpBin(correct, bstream, 24), "Internal data is incorrect.\n");
BitStream_appendNum(bstream, 32, 0x12345678);
assert_zero(cmpBin(correct, bstream), "Internal data is incorrect.\n");
testFinish();
BitStream_free(bstream);
}
static void test_appendBytes(void)
{
BitStream *bstream;
unsigned char data[8];
char correct[] = "10001010111111111111111100010010001101000101011001111000";
testStart("Append Bytes");
bstream = BitStream_new();
data[0] = 0x8a;
BitStream_appendBytes(bstream, 1, data);
assert_zero(ncmpBin(correct, bstream, 8), "Internal data is incorrect.");
data[0] = 0xff;
data[1] = 0xff;
BitStream_appendBytes(bstream, 2, data);
assert_zero(ncmpBin(correct, bstream, 24), "Internal data is incorrect.\n");
data[0] = 0x12;
data[1] = 0x34;
data[2] = 0x56;
data[3] = 0x78;
BitStream_appendBytes(bstream, 4, data);
assert_zero(cmpBin(correct, bstream), "Internal data is incorrect.\n");
testFinish();
BitStream_free(bstream);
}
static void test_toByte(void)
{
BitStream *bstream;
unsigned char correct[] = {
0x8a, 0xff, 0xff, 0x12, 0x34, 0x56, 0x78
};
unsigned char *result;
testStart("Convert to a byte array");
bstream = BitStream_new();
BitStream_appendBytes(bstream, 1, &correct[0]);
BitStream_appendBytes(bstream, 2, &correct[1]);
BitStream_appendBytes(bstream, 4, &correct[3]);
result = BitStream_toByte(bstream);
testEnd(memcmp(correct, result, 7));
BitStream_free(bstream);
free(result);
}
static void test_toByte_4bitpadding(void)
{
BitStream *bstream;
unsigned char *result;
testStart("Convert to a byte array");
bstream = BitStream_new();
BitStream_appendNum(bstream, 4, 0xb);
result = BitStream_toByte(bstream);
assert_equal(result[0], 0xb0, "incorrect paddings\n");
BitStream_free(bstream);
free(result);
bstream = BitStream_new();
BitStream_appendNum(bstream, 12, 0x335);
result = BitStream_toByte(bstream);
assert_equal(result[0], 0x33, "incorrect paddings\n");
assert_equal(result[1], 0x50, "incorrect paddings\n");
BitStream_free(bstream);
free(result);
testFinish();
}
static void test_size(void)
{
BitStream *bstream;
testStart("size check");
bstream = BitStream_new();
assert_equal(BitStream_size(bstream), 0, "Initialized BitStream is not 0 length");
BitStream_appendNum(bstream, 1, 0);
assert_equal(BitStream_size(bstream), 1, "Size incorrect. (first append)");
BitStream_appendNum(bstream, 2, 0);
assert_equal(BitStream_size(bstream), 3, "Size incorrect. (second append)");
testFinish();
BitStream_free(bstream);
}
static void test_append(void)
{
BitStream *bs1, *bs2;
char c1[] = "00";
char c2[] = "0011";
char c3[] = "01111111111111111";
char c4[] = "001101111111111111111";
char c5[] = "0011011111111111111111111111111111";
int ret;
testStart("Append two BitStreams");
bs1 = BitStream_new();
bs2 = BitStream_new();
ret = BitStream_appendNum(bs1, 1, 0);
ret = BitStream_appendNum(bs2, 1, 0);
ret = BitStream_append(bs1, bs2);
assert_zero(ret, "Failed to append.");
assert_zero(cmpBin(c1, bs1), "Internal data is incorrect.");
ret = BitStream_appendNum(bs1, 2, 3);
assert_zero(ret, "Failed to append.");
assert_zero(cmpBin(c2, bs1), "Internal data is incorrect.");
ret = BitStream_appendNum(bs2, 16, 65535);
assert_zero(ret, "Failed to append.");
assert_zero(cmpBin(c3, bs2), "Internal data is incorrect.");
ret = BitStream_append(bs1, bs2);
assert_zero(ret, "Failed to append.");
assert_zero(cmpBin(c4, bs1), "Internal data is incorrect.");
ret = BitStream_appendNum(bs1, 13, 16383);
assert_zero(ret, "Failed to append.");
assert_zero(cmpBin(c5, bs1), "Internal data is incorrect.");
testFinish();
BitStream_free(bs1);
BitStream_free(bs2);
}
static void test_newWithBits(void)
{
BitStream *bstream;
unsigned char data[4] = {0, 1, 0, 1};
testStart("New with bits");
bstream = BitStream_newWithBits(4, data);
assert_equal(bstream->length, 4, "Internal bit length is incorrect.\n");
assert_equal(bstream->datasize, 4, "Internal buffer size is incorrect.\n");
assert_zero(cmpBin("0101", bstream), "Internal data is incorrect.\n");
testFinish();
BitStream_free(bstream);
}
static void test_newWithBits_size0(void)
{
BitStream *bstream;
testStart("New with bits (size = 0)");
bstream = BitStream_newWithBits(0, NULL);
assert_equal(bstream->length, 0, "Internal bit length is incorrect.\n");
assert_nonzero(bstream->datasize, "Internal buffer size is incorrect.\n");
assert_nonnull(bstream->data, "Internal buffer not allocated.\n");
testFinish();
BitStream_free(bstream);
}
int main()
{
int tests = 11;
testInit(tests);
test_null();
test_num();
test_bytes();
test_appendNum();
test_appendBytes();
test_toByte();
test_toByte_4bitpadding();
test_size();
test_append();
test_newWithBits();
test_newWithBits_size0();
testReport(tests);
return 0;
}

61
tests/test_configure.sh Executable file
View File

@ -0,0 +1,61 @@
#!/bin/sh
BASEDIR=..
CONFIG_H_IN="$BASEDIR/config.h.in"
CONFIG_H="$BASEDIR/config.h"
LIBQRENCODE_PC_IN="$BASEDIR/libqrencode.pc.in"
LIBQRENCODE_PC="$BASEDIR/libqrencode.pc"
echo "Testing configure scripts..."
(cd $BASEDIR; ./autogen.sh)
# test config.h.in
grep "#undef HAVE_LIBPTHREAD" $CONFIG_H_IN > /dev/null
if test ! $? -eq 0; then
echo "HAVE_LIBPTHREAD undefined in config.h.in."
exit 1
fi
# test libqrencode.pc.in
grep "Libs.private: @LIBPTHREAD@" $LIBQRENCODE_PC_IN > /dev/null
if test ! $? -eq 0; then
echo "Pthread is not handled in libqrencode.pc.in."
exit 1
fi
# test pthread checks in configure
(cd $BASEDIR; ./configure --with-tests --enable-thread-safety > /dev/null)
grep "#define HAVE_LIBPTHREAD 1" $CONFIG_H > /dev/null
if test ! $? -eq 0; then
echo "HAVE_LIBPTHREAD undefined in config.h."
exit 1
fi
grep "Libs.private: -lpthread" $LIBQRENCODE_PC > /dev/null
if test ! $? -eq 0; then
echo "Pthread is not handled in libqrencode.pc."
exit 1
fi
(cd $BASEDIR; ./configure --with-tests --disable-thread-safety > /dev/null)
grep "#define HAVE_LIBPTHREAD 1" $CONFIG_H > /dev/null
if test ! $? -eq 1; then
echo "HAVE_LIBPTHREAD incorrectly defined in config.h."
exit 1
fi
grep "Libs.private: -lpthread" $LIBQRENCODE_PC > /dev/null
if test ! $? -eq 1; then
echo "Pthread is incorrectly handled in libqrencode.pc."
exit 1
fi
echo "All tests of configure script passed. Now reconfiguring..."
(cd $BASEDIR; ./configure --with-tests > /dev/null)
echo "Done."
exit 0

183
tests/test_estimatebit.c Normal file
View File

@ -0,0 +1,183 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "../qrinput.h"
static QRinput *gstream;
static void test_numbit(void)
{
QRinput *stream;
char num[9]="01234567";
int bits;
testStart("Estimation of Numeric stream (8 digits)");
stream = QRinput_new();
QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)num);
bits = QRinput_estimateBitStreamSize(stream, 0);
testEndExp(bits == 41);
QRinput_append(gstream, QR_MODE_NUM, 8, (unsigned char *)num);
QRinput_free(stream);
}
static void test_numbit2(void)
{
QRinput *stream;
char num[17]="0123456789012345";
int bits;
testStart("Estimation of Numeric stream (16 digits)");
stream = QRinput_new();
QRinput_append(stream, QR_MODE_NUM, 16, (unsigned char *)num);
bits = QRinput_estimateBitStreamSize(stream, 0);
testEndExp(bits == 68);
QRinput_append(gstream, QR_MODE_NUM, 16, (unsigned char *)num);
QRinput_free(stream);
}
static void test_numbit3(void)
{
QRinput *stream;
char *num;
int bits;
testStart("Estimation of Numeric stream (400 digits)");
stream = QRinput_new();
num = (char *)malloc(401);
memset(num, '1', 400);
num[400] = '\0';
QRinput_append(stream, QR_MODE_NUM, 400, (unsigned char *)num);
bits = QRinput_estimateBitStreamSize(stream, 0);
/* 4 + 10 + 133*10 + 4 = 1348 */
testEndExp(bits == 1348);
QRinput_append(gstream, QR_MODE_NUM, 400, (unsigned char *)num);
QRinput_free(stream);
free(num);
}
static void test_an(void)
{
QRinput *stream;
char str[6]="AC-42";
int bits;
testStart("Estimation of Alphabet-Numeric stream (5 chars)");
stream = QRinput_new();
QRinput_append(stream, QR_MODE_AN, 5, (unsigned char *)str);
bits = QRinput_estimateBitStreamSize(stream, 0);
testEndExp(bits == 41);
QRinput_append(gstream, QR_MODE_AN, 5, (unsigned char *)str);
QRinput_free(stream);
}
static void test_8(void)
{
QRinput *stream;
char str[9]="12345678";
int bits;
testStart("Estimation of 8 bit data stream (8 bytes)");
stream = QRinput_new();
QRinput_append(stream, QR_MODE_8, 8, (unsigned char *)str);
bits = QRinput_estimateBitStreamSize(stream, 0);
testEndExp(bits == 76);
QRinput_append(gstream, QR_MODE_8, 8, (unsigned char *)str);
QRinput_free(stream);
}
static void test_structure(void)
{
QRinput *stream;
int bits;
testStart("Estimation of a structure-append header");
stream = QRinput_new();
QRinput_insertStructuredAppendHeader(stream, 10, 1, 0);
bits = QRinput_estimateBitStreamSize(stream, 1);
testEndExp(bits == 20);
QRinput_insertStructuredAppendHeader(gstream, 10, 1, 0);
QRinput_free(stream);
}
static void test_kanji(void)
{
int res;
QRinput *stream;
unsigned char str[4]= {0x93, 0x5f,0xe4, 0xaa};
int bits;
testStart("Estimation of Kanji stream (2 chars)");
stream = QRinput_new();
res = QRinput_append(stream, QR_MODE_KANJI, 4, (unsigned char *)str);
if(res < 0) {
printf("Failed to add.\n");
testEnd(1);
} else {
bits = QRinput_estimateBitStreamSize(stream, 0);
testEndExp(bits == 38);
QRinput_append(gstream, QR_MODE_KANJI, 4, (unsigned char *)str);
}
QRinput_free(stream);
}
static void test_mix(void)
{
int bits;
testStart("Estimation of Mixed stream");
bits = QRinput_estimateBitStreamSize(gstream, 0);
testEndExp(bits == (41 + 68 + 1348 + 41 + 76 + 38 + 20));
QRinput_free(gstream);
}
/* Taken from JISX 0510:2018, p.23 */
static void test_numbit1_mqr(void)
{
QRinput *stream;
char *str = "0123456789012345";
int bits;
testStart("Estimation of Numeric stream for Micro QR Code (16 digits)");
stream = QRinput_newMQR(3, QR_ECLEVEL_M);
QRinput_append(stream, QR_MODE_NUM, 16, (const unsigned char *)str);
bits = QRinput_estimateBitStreamSize(stream, QRinput_getVersion(stream));
assert_equal(bits, 61, "Estimated bit length is wrong: %d, expected: %d.\n", bits, 61);
QRinput_free(stream);
stream = QRinput_newMQR(4, QR_ECLEVEL_M);
QRinput_append(stream, QR_MODE_NUM, 16, (const unsigned char *)str);
bits = QRinput_estimateBitStreamSize(stream, QRinput_getVersion(stream));
assert_equal(bits, 63, "Estimated bit length is wrong: %d, expected: %d.\n", bits, 63);
QRinput_free(stream);
testFinish();
}
int main()
{
gstream = QRinput_new();
int tests = 9;
testInit(tests);
test_numbit();
test_numbit2();
test_numbit3();
test_an();
test_8();
test_kanji();
test_structure();
test_mix();
test_numbit1_mqr();
testReport(tests);
return 0;
}

411
tests/test_mask.c Normal file
View File

@ -0,0 +1,411 @@
#include <stdio.h>
#include <string.h>
#include "common.h"
#include "../mask.h"
#include "../qrspec.h"
#include "decoder.h"
static char dot[2] = {'_', '#'};
static char *maskPatterns[8] = {
/* (i + j) mod 2 = 0 */
"#_#_#_"
"_#_#_#"
"#_#_#_"
"_#_#_#"
"#_#_#_"
"_#_#_#",
/* i mod 2 = 0 */
"######"
"______"
"######"
"______"
"######"
"______",
/* j mod 3 = 0 */
"#__#__"
"#__#__"
"#__#__"
"#__#__"
"#__#__"
"#__#__",
/* (i + j) mod 3 = 0 */
"#__#__"
"__#__#"
"_#__#_"
"#__#__"
"__#__#"
"_#__#_",
/* ((i div 2) + (j div 3)) mod 2 = 0 */
"###___"
"###___"
"___###"
"___###"
"###___"
"###___",
/* (ij) mod 2 + (ij) mod 3 = 0 */
"######"
"#_____"
"#__#__"
"#_#_#_"
"#__#__"
"#_____",
/* ((ij) mod 2 + (ij) mod 3) mod 2 = 0 */
"######"
"###___"
"##_##_"
"#_#_#_"
"#_##_#"
"#___##",
/* ((ij) mod 3 + (i+j) mod 2) mod 2 = 0 */
"#_#_#_"
"___###"
"#___##"
"_#_#_#"
"###___"
"_###__"
};
static void print_mask(int mask)
{
const unsigned int w = 6;
unsigned char frame[w * w], *masked, *p;
int x, y;
memset(frame, 0, w * w);
masked = Mask_makeMaskedFrame(w, frame, mask);
p = masked;
for(y=0; y<w; y++) {
for(x=0; x<w; x++) {
putchar(dot[*p&1]);
p++;
}
printf("\n");
}
printf("\n");
free(masked);
}
static void print_masks(void)
{
int i;
puts("\nPrinting mask patterns.");
for(i=0; i<8; i++) {
print_mask(i);
}
}
static int test_mask(int mask)
{
const int w = 6;
unsigned char frame[w * w], *masked, *p;
char *q;
int x, y;
int err = 0;
memset(frame, 0, w * w);
masked = Mask_makeMaskedFrame(w, frame, mask);
p = masked;
q = maskPatterns[mask];
for(y=0; y<w; y++) {
for(x=0; x<w; x++) {
if(dot[*p&1] != *q) {
err++;
}
p++;
q++;
}
}
free(masked);
return err;
}
static void test_masks(void)
{
int i;
testStart("Mask pattern checks");
for(i=0; i<8; i++) {
assert_zero(test_mask(i), "Mask pattern %d incorrect.\n", i);
}
testFinish();
}
#define N1 (3)
#define N2 (3)
#define N3 (40)
#define N4 (10)
static void test_eval(void)
{
unsigned char *frame;
unsigned int w = 6;
int demerit;
frame = (unsigned char *)malloc(w * w);
testStart("Test mask evaluation (all white)");
memset(frame, 0, w * w);
demerit = Mask_evaluateSymbol(w, frame);
testEndExp(demerit == ((N1 + 1)*w*2 + N2 * (w - 1) * (w - 1)));
testStart("Test mask evaluation (all black)");
memset(frame, 1, w * w);
demerit = Mask_evaluateSymbol(w, frame);
testEndExp(demerit == ((N1 + 1)*w*2 + N2 * (w - 1) * (w - 1)));
free(frame);
}
/* .#.#.#.#.#
* #.#.#.#.#.
* ..##..##..
* ##..##..##
* ...###...#
* ###...###.
* ....####..
* ####....##
* .....#####
* #####.....
*/
static void test_eval2(void)
{
unsigned char *frame;
unsigned int w = 10;
int demerit;
unsigned int x;
frame = (unsigned char *)malloc(w * w);
testStart("Test mask evaluation (run length penalty check)");
for(x=0; x<w; x++) {
frame[ x] = x & 1;
frame[w + x] = (x & 1) ^ 1;
frame[w*2 + x] = (x / 2) & 1;
frame[w*3 + x] = ((x / 2) & 1) ^ 1;
frame[w*4 + x] = (x / 3) & 1;
frame[w*5 + x] = ((x / 3) & 1) ^ 1;
frame[w*6 + x] = (x / 4) & 1;
frame[w*7 + x] = ((x / 4) & 1) ^ 1;
frame[w*8 + x] = (x / 5) & 1;
frame[w*9 + x] = ((x / 5) & 1) ^ 1;
}
demerit = Mask_evaluateSymbol(w, frame);
testEndExp(demerit == N1 * 4 + N2 * 4);
free(frame);
}
static void test_calcN2(void)
{
unsigned char frame[64];
int width;
int demerit;
int x, y;
testStart("Test mask evaluation (2x2 block check)");
width = 4;
for(y = 0; y < width; y++) {
for(x = 0; x < width; x++) {
frame[y * width + x] = ((x & 2) ^ (y & 2)) >> 1;
}
}
demerit = Mask_calcN2(width, frame);
assert_equal(demerit, N2 * 4, "Calculation of N2 demerit is wrong: %d, expected %d", demerit, N2 * 4);
width = 4;
for(y = 0; y < width; y++) {
for(x = 0; x < width; x++) {
frame[y * width + x] = (((x + 1) & 2) ^ (y & 2)) >> 1;
}
}
demerit = Mask_calcN2(width, frame);
assert_equal(demerit, N2 * 2, "Calculation of N2 demerit is wrong: %d, expected %d", demerit, N2 * 2);
width = 6;
for(y = 0; y < width; y++) {
for(x = 0; x < width; x++) {
frame[y * width + x] = (x / 3) ^ (y / 3);
}
}
demerit = Mask_calcN2(width, frame);
assert_equal(demerit, N2 * 16, "Calculation of N2 demerit is wrong: %d, expected %d", demerit, N2 * 16);
testFinish();
}
static void test_eval3(void)
{
unsigned char *frame;
int w = 15;
int demerit;
int x, y;
static unsigned char pattern[7][15] = {
{0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0}, // N3x1
{1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1}, // N3x1
{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1}, // N3x1
{1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0}, // 0
{1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1}, // N3x2
{1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0}, // N3 + (N1+1)
{1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1} // (N1+1)
};
frame = (unsigned char *)malloc(w * w);
testStart("Test mask evaluation (1:1:3:1:1 check)");
for(y=0; y<5; y++) {
for(x=0; x<w; x++) {
frame[w*y*2 + x] = pattern[y][x];
frame[w*(y*2+1) + x] = pattern[y][x]^1;
}
}
for(x=0; x<w; x++) {
frame[w*10 + x] = x & 1;
}
for(y=5; y<7; y++) {
for(x=0; x<w; x++) {
frame[w*(y*2+1) + x] = pattern[y][x];
frame[w*(y*2+2) + x] = pattern[y][x]^1;
}
}
/*
for(y=0; y<w; y++) {
for(x=0; x<w; x++) {
printf("%s", frame[w*y+x]?"##":"..");
}
printf("\n");
}
*/
demerit = Mask_evaluateSymbol(w, frame);
testEndExp(demerit == N3 * 10 + (N1 + 1) * 4);
free(frame);
}
static void test_format(void)
{
unsigned char *frame, *masked;
int version, mask, width, dmask;
QRecLevel level, dlevel;
QRcode *code;
int ret;
testStart("Checking format info.");
for(version=1; version<=QRSPEC_VERSION_MAX; version++) {
frame = QRspec_newFrame(version);
width = QRspec_getWidth(version);
for(level=QR_ECLEVEL_L; level<=QR_ECLEVEL_H; level++) {
for(mask=0; mask<8; mask++) {
masked = Mask_makeMask(width, frame, mask, level);
code = QRcode_new(version, width, masked);
ret = QRcode_decodeFormat(code, &dlevel, &dmask);
assert_zero(ret, "Something wrong in format info.\n");
assert_equal(dlevel, level, "Decoded level is wrong: %d, expected %d", dlevel, level);
assert_equal(dmask, mask, "Decoded mask is wrong: %d, expected %d", dlevel, level);
QRcode_free(code);
}
}
free(frame);
}
testFinish();
}
static void test_calcRunLength(void)
{
int width = 5;
unsigned char frame[width * width];
int runLength[width + 1];
int i, j;
int length;
static unsigned char pattern[6][5] = {
{0, 1, 0, 1, 0},
{1, 0, 1, 0, 1},
{0, 0, 0, 0, 0},
{1, 1, 1, 1, 1},
{0, 0, 1, 1, 1},
{1, 1, 0, 0, 0}
};
static int expected[6][7] = {
{ 1, 1, 1, 1, 1, 0, 5},
{-1, 1, 1, 1, 1, 1, 6},
{ 5, 0, 0, 0, 0, 0, 1},
{-1, 5, 0, 0, 0, 0, 2},
{ 2, 3, 0, 0, 0, 0, 2},
{-1, 2, 3, 0, 0, 0, 3}
};
testStart("Test runlength calc function");
for(i=0; i<6; i++) {
length = Mask_calcRunLengthH(width, pattern[i], runLength);
assert_equal(expected[i][6], length, "Length incorrect: %d, expected %d.\n", length, expected[i][6]);
assert_zero(memcmp(runLength, expected[i], sizeof(int) * expected[i][6]), "Run length does not match: pattern %d, horizontal access.\n", i);
for(j=0; j<width; j++) {
frame[j * width] = pattern[i][j];
}
length = Mask_calcRunLengthV(width, frame, runLength);
assert_equal(expected[i][6], length, "Length incorrect: %d, expected %d.\n", length, expected[i][6]);
assert_zero(memcmp(runLength, expected[i], sizeof(int) * expected[i][6]), "Run length does not match: pattern %d, vertical access.\n", i);
}
testFinish();
}
static void test_calcN1N3(void)
{
int runLength[26];
int length;
int demerit;
int i;
static unsigned char pattern[][16] = {
{1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, N3},
{0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, N3},
{1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0},
{1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, N3},
{1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, N3},
{1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, N3 * 2},
};
static unsigned char pattern2[][19] = {
{1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, N3 + N1 + 1},
{0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, N3 + N1 + 1},
{1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, N1 + 1},
{1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, N3 + N1 + 1},
{1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, N3 + N1 + 1}
};
testStart("Test N3 penalty calculation");
for(i=0; i<6; i++) {
length = Mask_calcRunLengthH(15, pattern[i], runLength);
demerit = Mask_calcN1N3(length, runLength);
assert_equal(pattern[i][15], demerit, "N3 penalty is wrong: %d, expected %d\n", demerit, pattern[i][15]);
}
for(i=0; i<5; i++) {
length = Mask_calcRunLengthH(18, pattern2[i], runLength);
demerit = Mask_calcN1N3(length, runLength);
assert_equal(pattern2[i][18], demerit, "N3 penalty is wrong: %d, expected %d\n", demerit, pattern2[i][18]);
}
testFinish();
}
int main(int argc, char **argv)
{
int tests = 9;
testInit(tests);
test_masks();
test_eval();
test_eval2();
test_eval3();
test_format();
test_calcN2();
test_calcRunLength();
test_calcN1N3();
testReport(tests);
if(argc > 1) {
print_masks();
}
return 0;
}

155
tests/test_mmask.c Normal file
View File

@ -0,0 +1,155 @@
#include <stdio.h>
#include <string.h>
#include "common.h"
#include "../mmask.h"
#include "../mqrspec.h"
static char dot[2] = {'_', '#'};
static char *maskPatterns[4] = {
/* i mod 2 = 0 */
"######"
"______"
"######"
"______"
"######"
"______",
/* ((i div 2) + (j div 3)) mod 2 = 0 */
"###___"
"###___"
"___###"
"___###"
"###___"
"###___",
/* ((ij) mod 2 + (ij) mod 3) mod 2 = 0 */
"######"
"###___"
"##_##_"
"#_#_#_"
"#_##_#"
"#___##",
/* ((ij) mod 3 + (i+j) mod 2) mod 2 = 0 */
"#_#_#_"
"___###"
"#___##"
"_#_#_#"
"###___"
"_###__"
};
static void print_mask(int mask)
{
const int w = 6;
unsigned char frame[w * w], *masked, *p;
int x, y;
memset(frame, 0, w * w);
masked = MMask_makeMaskedFrame(w, frame, mask);
p = masked;
for(y=0; y<w; y++) {
for(x=0; x<w; x++) {
putchar(dot[*p&1]);
p++;
}
printf("\n");
}
printf("\n");
free(masked);
}
static void print_masks(void)
{
int i;
puts("\nPrinting mask patterns.");
for(i=0; i<4; i++) {
print_mask(i);
}
}
static int test_mask(int mask)
{
const int w = 6;
unsigned char frame[w * w], *masked, *p;
char *q;
int x, y;
int err = 0;
memset(frame, 0, w * w);
masked = MMask_makeMaskedFrame(w, frame, mask);
p = masked;
q = maskPatterns[mask];
for(y=0; y<w; y++) {
for(x=0; x<w; x++) {
if(dot[*p&1] != *q) {
err++;
}
p++;
q++;
}
}
free(masked);
return err;
}
static void test_masks(void)
{
int i;
testStart("Mask pattern checks");
for(i=0; i<4; i++) {
assert_zero(test_mask(i), "Mask pattern %d incorrect.\n", i);
}
testFinish();
}
static void test_maskEvaluation(void)
{
static const int w = 11;
unsigned char pattern[w * w];
int i, score;
memset(pattern, 0, w * w);
testStart("Test mask evaluation");
score = MMask_evaluateSymbol(w, pattern);
assert_equal(score, 0, "Mask score caluculation is incorrect. (score=%d (%d expected)\n", score, 0);
for(i=0; i<w; i++) {
pattern[(w-1) * w + i] = 1;
}
score = MMask_evaluateSymbol(w, pattern);
assert_equal(score, 16 + w - 1, "Mask score caluculation is incorrect. (score=%d) (%d expected)\n", score, 16 + w - 1);
for(i=0; i<w; i++) {
pattern[(w-1) * w + i] = 0;
pattern[i * w + w - 1] = 1;
}
score = MMask_evaluateSymbol(w, pattern);
assert_equal(score, 16 + w - 1, "Mask score caluculation is incorrect. (score=%d) (%d expected)\n", score, 16 + w - 1);
for(i=0; i<w; i++) {
pattern[(w-1) * w + i] = 1;
pattern[i * w + w - 1] = 1;
}
score = MMask_evaluateSymbol(w, pattern);
assert_equal(score, 16 * (w - 1) + w - 1, "Mask score caluculation is incorrect. (score=%d) (%d expected)\n", score, 16 * (w - 1) + w - 1);
testFinish();
}
int main(int argc, char **argv)
{
int tests = 2;
testInit(tests);
test_masks();
test_maskEvaluation();
testReport(tests);
if(argc > 1) {
print_masks();
}
return 0;
}

582
tests/test_monkey.c Normal file
View File

@ -0,0 +1,582 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "common.h"
#include "../qrinput.h"
#include "../split.h"
#include "../qrspec.h"
#include "decoder.h"
#define MAX_LENGTH 7091
static unsigned char data[MAX_LENGTH];
static unsigned char check[MAX_LENGTH];
static const char *AN = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
#define drand(__scale__) ((__scale__) * (double)rand() / ((double)RAND_MAX + 1.0))
static int fill8bitString(void)
{
int len, i;
len = 1 + (int)drand((MAX_LENGTH - 2));
for(i=0; i<len; i++) {
data[i] = (unsigned char)drand(255) + 1;
}
data[len] = '\0';
return len;
}
static int fill8bitData(void)
{
int len, i;
len = 1 + (int)drand((MAX_LENGTH - 2));
for(i=0; i<len; i++) {
data[i] = (unsigned char)drand(256);
}
data[len] = '\0';
return len;
}
static int fillANData(void)
{
int len, i;
len = 1 + (int)drand((MAX_LENGTH - 2));
for(i=0; i<len; i++) {
data[i] = AN[(int)drand(45)];
}
data[len] = '\0';
return len;
}
static void test_encode_an(int num)
{
int ret;
int len;
len = fillANData();
QRcode *qrcode;
QRdata *qrdata;
FILE *fp;
char buf[256];
qrcode = QRcode_encodeString((char *)data, 0, num % 4, QR_MODE_8, num % 2);
if(qrcode == NULL) {
if(errno == ERANGE) return;
perror("test_encode_an aborted at QRcode_encodeString():");
printf("Length: %d\n", len);
printf("Level: %d\n", num % 4);
return;
}
qrdata = QRcode_decode(qrcode);
if(qrdata == NULL) {
printf("#%d: Failed to decode this code.\n", num);
QRcode_free(qrcode);
return;
}
if(qrdata->size != len) {
printf("#%d: length mismatched (orig: %d, decoded: %d)\n", num, len, qrdata->size);
}
ret = memcmp(qrdata->data, data, len);
if(ret != 0) {
unsigned char *frame, *p;
unsigned int x;
int y,c;
int dataLength, eccLength;
QRinput *input;
QRcode *origcode;
BitStream *bstream;
int spec[5];
printf("#%d: data mismatched.\n", num);
printf("Version: %d\n", qrcode->version);
QRspec_getEccSpec(qrcode->version, num%4, spec);
printf("DataLength: %d\n", QRspec_rsDataLength(spec));
printf("BlockNum1: %d\n", QRspec_rsBlockNum1(spec));
printf("BlockNum: %d\n", QRspec_rsBlockNum(spec));
printf("DataCodes1: %d\n", QRspec_rsDataCodes1(spec));
snprintf(buf, 256, "monkey-orig-%d.dat", num);
fp = fopen(buf, "w");
fputs((char *)data, fp);
fclose(fp);
snprintf(buf, 256, "monkey-result-%d.dat", num);
fp = fopen(buf, "w");
fputs((char *)qrdata->data, fp);
fclose(fp);
snprintf(buf, 256, "monkey-result-unmasked-%d.dat", num);
fp = fopen(buf, "w");
frame = QRcode_unmask(qrcode);
p = frame;
for(y=0; y<qrcode->width; y++) {
for(x=0; x<qrcode->width; x++) {
fputc((*p&1)?'1':'0', fp);
p++;
}
fputc('\n', fp);
}
fclose(fp);
free(frame);
snprintf(buf, 256, "monkey-orig-unmasked-%d.dat", num);
fp = fopen(buf, "w");
input = QRinput_new2(0, num % 4);
Split_splitStringToQRinput((char *)data, input, QR_MODE_8, num % 2);
origcode = QRcode_encodeMask(input, -2);
p = origcode->data;
for(y=0; y<origcode->width; y++) {
for(x=0; x<origcode->width; x++) {
fputc((*p&1)?'1':'0', fp);
p++;
}
fputc('\n', fp);
}
fclose(fp);
QRcode_free(origcode);
snprintf(buf, 256, "monkey-orig-bits-%d.dat", num);
fp = fopen(buf, "w");
bstream = BitStream_new();
QRinput_mergeBitStream(input, bstream);
c = 0;
for(x=0; x<bstream->length; x++) {
fputc((bstream->data[x]&1)?'1':'0', fp);
if((x & 7) == 7) {
fputc(' ', fp);
c++;
}
if((x & 63) == 63) {
fprintf(fp, "%d\n", c);
}
}
fclose(fp);
QRinput_free(input);
BitStream_free(bstream);
snprintf(buf, 256, "monkey-result-bits-%d.dat", num);
fp = fopen(buf, "w");
bstream = QRcode_extractBits(qrcode, &dataLength, &eccLength);
y = bstream->length;
p = bstream->data;
c = 0;
for(x=0; x<y; x++) {
fputc((p[x]&1)?'1':'0', fp);
if((x & 7) == 7) {
fputc(' ', fp);
c++;
}
if((x & 63) == 63) {
fprintf(fp, "%d\n", c);
}
}
fclose(fp);
BitStream_free(bstream);
}
QRdata_free(qrdata);
QRcode_free(qrcode);
}
static void monkey_encode_an(int loop)
{
int i;
testStart("Monkey test: QRcode_encodeString() - AlphaNumeric string.");
srand(0);
for(i=0; i<loop; i++) {
test_encode_an(i);
}
testEnd(0);
}
static void test_split_an(int num)
{
QRinput *input;
QRinput_List *list;
int len, i, ret;
len = fillANData();
input = QRinput_new2(0, QR_ECLEVEL_L);
if(input == NULL) {
perror("test_split_an aborted at QRinput_new2():");
return;
}
ret = Split_splitStringToQRinput((char *)data, input, QR_MODE_8, 1);
if(ret < 0) {
perror("test_split_an aborted at Split_splitStringToQRinput():");
QRinput_free(input);
return;
}
list = input->head;
i = 0;
while(list != NULL) {
memcpy(check + i, list->data, list->size);
i += list->size;
list = list->next;
}
if(i != len) {
printf("#%d: length is not correct. (%d should be %d)\n", num, i, len);
}
check[i] = '\0';
ret = memcmp(data, check, len);
if(ret != 0) {
printf("#%d: data mismatched.\n", num);
list = input->head;
i = 0;
while(list != NULL) {
ret = memcmp(data + i, list->data, list->size);
printf("wrong chunk:\n");
printf(" position: %d\n", i);
printf(" mode : %d\n", list->mode);
printf(" size : %d\n", list->size);
printf(" data : %.*s\n", list->size, list->data);
i += list->size;
list = list->next;
}
exit(1);
}
QRinput_free(input);
}
static void monkey_split_an(int loop)
{
int i;
testStart("Monkey test: Split_splitStringToQRinput() - AlphaNumeric string.");
srand(0);
for(i=0; i<loop; i++) {
test_split_an(i);
}
testEnd(0);
}
static void test_encode_8(int num)
{
QRcode *qrcode;
QRdata *qrdata;
int len, ret;
len = fill8bitData();
qrcode = QRcode_encodeData(len, data, 0, num % 4);
if(qrcode == NULL) {
if(errno == ERANGE) return;
perror("test_encdoe_8 aborted at QRcode_encodeData():");
return;
}
qrdata = QRcode_decode(qrcode);
if(qrdata == NULL) {
printf("#%d: Failed to decode this code.\n", num);
QRcode_free(qrcode);
return;
}
if(qrdata->size != len) {
printf("#%d: length mismatched (orig: %d, decoded: %d)\n", num, len, qrdata->size);
}
ret = memcmp(qrdata->data, data, len);
if(ret != 0) {
printf("#%d: data mismatched.\n", num);
}
QRdata_free(qrdata);
QRcode_free(qrcode);
}
static void monkey_encode_8(int loop)
{
int i;
testStart("Monkey test: QRcode_encodeData() - 8bit char string.");
srand(0);
for(i=0; i<loop; i++) {
test_encode_8(i);
}
testEnd(0);
}
static void test_split_8(int num)
{
QRinput *input;
QRinput_List *list;
int len, i, ret;
len = fill8bitString();
input = QRinput_new2(0, QR_ECLEVEL_L);
if(input == NULL) {
perror("test_split_8 aborted at QRinput_new2():");
return;
}
ret = Split_splitStringToQRinput((char *)data, input, QR_MODE_8, 1);
if(ret < 0) {
perror("test_split_8 aborted at Split_splitStringToQRinput():");
QRinput_free(input);
return;
}
list = input->head;
i = 0;
while(list != NULL) {
memcpy(check + i, list->data, list->size);
i += list->size;
list = list->next;
}
if(i != len) {
printf("#%d: length is not correct. (%d should be %d)\n", num, i, len);
}
check[i] = '\0';
ret = memcmp(data, check, len);
if(ret != 0) {
printf("#%d: data mismatched.\n", num);
list = input->head;
i = 0;
while(list != NULL) {
ret = memcmp(data + i, list->data, list->size);
printf("wrong chunk:\n");
printf(" position: %d\n", i);
printf(" mode : %d\n", list->mode);
printf(" size : %d\n", list->size);
printf(" data : %.*s\n", list->size, list->data);
i += list->size;
list = list->next;
}
exit(1);
}
QRinput_free(input);
}
static void monkey_split_8(int loop)
{
int i;
testStart("Monkey test: Split_splitStringToQRinput() - 8bit char string.");
srand(0);
for(i=0; i<loop; i++) {
test_split_8(i);
}
testEnd(0);
}
static void test_encode_kanji(int num)
{
QRcode *qrcode;
QRdata *qrdata;
int len, ret;
len = fill8bitString();
qrcode = QRcode_encodeString((char *)data, 0, num % 4, QR_MODE_8, 1);
if(qrcode == NULL) {
if(errno == ERANGE) return;
perror("test_encdoe_kanji aborted at QRcode_encodeString():");
return;
}
qrdata = QRcode_decode(qrcode);
if(qrdata == NULL) {
printf("#%d: Failed to decode this code.\n", num);
QRcode_free(qrcode);
return;
}
if(qrdata->size != len) {
printf("#%d: length mismatched (orig: %d, decoded: %d)\n", num, len, qrdata->size);
}
ret = memcmp(qrdata->data, data, len);
if(ret != 0) {
printf("#%d: data mismatched.\n", num);
}
QRdata_free(qrdata);
QRcode_free(qrcode);
}
static void monkey_encode_kanji(int loop)
{
int i;
testStart("Monkey test: QRcode_encodeString() - kanji string.");
srand(0);
for(i=0; i<loop; i++) {
test_encode_kanji(i);
}
testEnd(0);
}
static void test_split_kanji(int num)
{
QRinput *input;
QRinput_List *list;
int len, i, ret;
len = fill8bitString();
input = QRinput_new2(0, QR_ECLEVEL_L);
if(input == NULL) {
perror("test_split_kanji aborted at QRinput_new2():");
return;
}
ret = Split_splitStringToQRinput((char *)data, input, QR_MODE_KANJI, 1);
if(ret < 0) {
perror("test_split_kanji aborted at Split_splitStringToQRinput():");
QRinput_free(input);
return;
}
list = input->head;
i = 0;
while(list != NULL) {
memcpy(check + i, list->data, list->size);
i += list->size;
list = list->next;
}
if(i != len) {
printf("#%d: length is not correct. (%d should be %d)\n", num, i, len);
}
check[i] = '\0';
ret = memcmp(data, check, len);
if(ret != 0) {
printf("#%d: data mismatched.\n", num);
list = input->head;
i = 0;
while(list != NULL) {
ret = memcmp(data + i, list->data, list->size);
printf("wrong chunk:\n");
printf(" position: %d\n", i);
printf(" mode : %d\n", list->mode);
printf(" size : %d\n", list->size);
printf(" data : %.*s\n", list->size, list->data);
i += list->size;
list = list->next;
}
exit(1);
}
QRinput_free(input);
}
static void monkey_split_kanji(int loop)
{
int i;
testStart("Monkey test: Split_splitStringToQRinput() - kanji string.");
srand(0);
for(i=0; i<loop; i++) {
test_split_kanji(i);
}
testEnd(0);
}
static void test_split_structure(int num)
{
QRinput *input;
QRinput_Struct *s;
QRcode_List *codes, *list;
QRinput_InputList *il;
int version;
QRecLevel level;
int c, i, ret;
version = (int)drand(40) + 1;
level = (QRecLevel)drand(4);
fill8bitString();
input = QRinput_new2(version, level);
if(input == NULL) {
perror("test_split_structure aborted at QRinput_new2():");
return;
}
ret = Split_splitStringToQRinput((char *)data, input, QR_MODE_KANJI, 1);
if(ret < 0) {
perror("test_split_structure aborted at Split_splitStringToQRinput():");
QRinput_free(input);
return;
}
s = QRinput_splitQRinputToStruct(input);
if(s == NULL) {
if(errno != 0 && errno != ERANGE) {
perror("test_split_structure aborted at QRinput_splitQRinputToStruct():");
}
QRinput_free(input);
return;
}
il = s->head;
i = 0;
while(il != NULL) {
if(il->input->version != version) {
printf("Test: version %d, level %c\n", version, levelChar[level]);
printf("wrong version number.\n");
printQRinputInfo(il->input);
exit(1);
}
i++;
il = il->next;
}
codes = QRcode_encodeInputStructured(s);
if(codes == NULL) {
perror("test_split_structure aborted at QRcode_encodeInputStructured():");
QRinput_free(input);
QRinput_Struct_free(s);
return;
}
list = codes;
il = s->head;
c = 0;
while(list != NULL) {
if(list->code->version != version) {
printf("#%d: data mismatched.\n", num);
printf("Test: version %d, level %c\n", version, levelChar[level]);
printf("code #%d\n", c);
printf("Version mismatch: %d should be %d\n", list->code->version, version);
printf("max bits: %d\n", QRspec_getDataLength(version, level) * 8 - 20);
printQRinputInfo(il->input);
printQRinput(input);
exit(1);
}
list = list->next;
il = il->next;
c++;
}
QRinput_free(input);
QRinput_Struct_free(s);
QRcode_List_free(codes);
return;
}
static void monkey_split_structure(int loop)
{
int i;
testStart("Monkey test: QRinput_splitQRinputToStruct.");
srand(0);
for(i=0; i<loop; i++) {
test_split_structure(i);
}
testEnd(0);
}
int main(int argc, char **argv)
{
int loop = 1000;
if(argc == 2) {
loop = atoi(argv[1]);
}
int tests = 7;
testInit(tests);
monkey_split_an(loop);
monkey_encode_an(loop);
monkey_split_8(loop);
monkey_encode_8(loop);
monkey_split_kanji(loop);
monkey_encode_kanji(loop);
monkey_split_structure(loop);
testReport(tests);
return 0;
}

181
tests/test_mqrspec.c Normal file
View File

@ -0,0 +1,181 @@
#include <stdio.h>
#include <string.h>
#include "common.h"
#include "../mqrspec.h"
static unsigned char v4frame[] = {
0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc0,0x91,0x90,0x91,0x90,0x91,0x90,0x91,0x90,0x91,
0xc1,0xc0,0xc0,0xc0,0xc0,0xc0,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xc1,0xc0,0xc1,0xc1,0xc1,0xc0,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xc1,0xc0,0xc1,0xc1,0xc1,0xc0,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xc1,0xc0,0xc1,0xc1,0xc1,0xc0,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xc1,0xc0,0xc0,0xc0,0xc0,0xc0,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x91,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
static void test_newFrame(void)
{
int width, i, y;
unsigned char *frame;
testStart("Test empty frames");
for(i=1; i<MQRSPEC_VERSION_MAX; i++) {
frame = MQRspec_newFrame(i);
width = MQRspec_getWidth(i);
for(y=0; y<width; y++) {
assert_zero(memcmp(&frame[y * width], &v4frame[y * MQRSPEC_WIDTH_MAX], width), "Mismatch found in version %d, line %d.\n", i, y);
}
free(frame);
}
testFinish();
}
static void test_newframe_invalid(void)
{
unsigned char *frame;
testStart("Checking MQRspec_newFrame with invalid version.");
frame = MQRspec_newFrame(0);
assert_null(frame, "MQRspec_newFrame(0) returns non-NULL.");
frame = MQRspec_newFrame(MQRSPEC_VERSION_MAX+1);
assert_null(frame, "MQRspec_newFrame(0) returns non-NULL.");
testFinish();
}
/* See Table 10 (pp.115) of Appendix 1, JIS X0510:2004 */
static unsigned int calcFormatInfo(int type, int mask)
{
unsigned int data, ecc, b, code;
int i, c;
data = (type << 12) | (mask << 10);
ecc = data;
b = 1 << 14;
for(i=0; b != 0; i++) {
if(ecc & b) break;
b = b >> 1;
}
c = 4 - i;
code = 0x537 << c ; //10100110111
b = 1 << (10 + c);
for(i=0; i<=c; i++) {
if(b & ecc) {
ecc ^= code;
}
code = code >> 1;
b = b >> 1;
}
return (data | ecc) ^ 0x4445;
}
/* See Table 10 of Appendix 1. (pp.115) */
static const int typeTable[4][3] = {
{ 0, -1, -1},
{ 1, 2, -1},
{ 3, 4, -1},
{ 5, 6, 7}
};
static void test_format(void)
{
unsigned int format;
int version, l, mask;
int type;
int err = 0;
testStart("Format info test");
for(version=1; version<=MQRSPEC_VERSION_MAX; version++) {
for(l=QR_ECLEVEL_L; l<=QR_ECLEVEL_Q; l++) {
for(mask=0; mask<4; mask++) {
format = MQRspec_getFormatInfo(mask, version, (QRecLevel)l);
type = typeTable[version - 1][l];
if(type == -1) {
if(format != 0) {
printf("Error in version %d, level %d, mask %d\n",
version, l, mask);
err++;
}
} else {
if(format != calcFormatInfo(type, mask)) {
printf("Error in version %d, level %d, mask %d\n",
version, l, mask);
err++;
}
}
}
}
}
testEnd(err);
}
static void print_format(void)
{
unsigned int format;
int i, j;
puts("\nPrinting hex strings of format information.");
for(i=0; i<4; i++) {
for(j=0; j<8; j++) {
format = calcFormatInfo(j, i);
printf("0x%04x, ", format);
}
printf("\n");
}
}
/**
* See Table 7 of Appendix 1.
*/
static int datalen[4][3] = {
{ 20, 0, 0},
{ 40, 32, 0},
{ 84, 68, 0},
{128, 112, 80},
};
static void test_dataLength(void)
{
int v, l;
int bits;
int err = 0;
testStart("Test dataLength");
for(v=0; v<4; v++) {
for(l=0; l<3; l++) {
bits = MQRspec_getDataLengthBit(v+1, (QRecLevel)l);
if(bits != datalen[v][l]) {
printf("Error in version %d, level %d.\n", v, l);
err++;
}
}
}
testEnd(err);
}
int main(int argc, char **argv)
{
int tests = 4;
testInit(tests);
test_newFrame();
test_newframe_invalid();
test_format();
test_dataLength();
testReport(tests);
if(argc > 1) {
print_format();
}
return 0;
}

1061
tests/test_qrencode.c Normal file

File diff suppressed because it is too large Load Diff

1129
tests/test_qrinput.c Normal file

File diff suppressed because it is too large Load Diff

319
tests/test_qrspec.c Normal file
View File

@ -0,0 +1,319 @@
#include <stdio.h>
#include <string.h>
#include "common.h"
#include "../qrspec.h"
#include "../qrencode_inner.h"
#include "decoder.h"
#ifndef SRCDIR
# define SRCDIR
#endif
static void print_eccTable(void)
{
int i, j;
int ecc;
int data;
int spec[5];
puts("\nPrinting ECC table.\n");
for(i=1; i<=QRSPEC_VERSION_MAX; i++) {
printf("Version %2d\n", i);
for(j=0; j<4; j++) {
QRspec_getEccSpec(i, (QRecLevel)j, spec);
data = QRspec_rsBlockNum1(spec) * QRspec_rsDataCodes1(spec)
+ QRspec_rsBlockNum2(spec) * QRspec_rsDataCodes2(spec);
ecc = QRspec_rsBlockNum1(spec) * QRspec_rsEccCodes1(spec)
+ QRspec_rsBlockNum2(spec) * QRspec_rsEccCodes2(spec);
printf("%3d\t", data);
printf("%3d\t", ecc);
printf("%2d\t", QRspec_rsBlockNum1(spec));
printf("(%3d, %3d, %3d)\n",
QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec),
QRspec_rsDataCodes1(spec),
QRspec_rsEccCodes1(spec));
if(QRspec_rsBlockNum2(spec) > 0) {
printf("\t%2d\t", QRspec_rsBlockNum2(spec));
printf("(%3d, %3d, %3d)\n",
QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec),
QRspec_rsDataCodes2(spec),
QRspec_rsEccCodes2(spec));
}
}
}
}
static void test_eccTable(void)
{
int i, j;
int ecc;
int data;
int err = 0;
int spec[5];
testStart("Checking ECC table.");
for(i=1; i<=QRSPEC_VERSION_MAX; i++) {
for(j=0; j<4; j++) {
QRspec_getEccSpec(i, (QRecLevel)j, spec);
data = QRspec_rsBlockNum1(spec) * QRspec_rsDataCodes1(spec)
+ QRspec_rsBlockNum2(spec) * QRspec_rsDataCodes2(spec);
ecc = QRspec_rsBlockNum1(spec) * QRspec_rsEccCodes1(spec)
+ QRspec_rsBlockNum2(spec) * QRspec_rsEccCodes2(spec);
if(data + ecc != QRspec_getDataLength(i, (QRecLevel)j) + QRspec_getECCLength(i, (QRecLevel)j)) {
printf("Error in version %d, level %d: invalid size\n", i, j);
printf("%d %d %d %d %d %d\n", spec[0], spec[1], spec[2], spec[3], spec[4], spec[2]);
err++;
}
if(ecc != QRspec_getECCLength(i, (QRecLevel)j)) {
printf("Error in version %d, level %d: invalid data\n", i, j);
printf("%d %d %d %d %d %d\n", spec[0], spec[1], spec[2], spec[3], spec[4], spec[2]);
err++;
}
}
}
testEnd(err);
}
static void test_eccTable2(void)
{
int i;
int spec[5];
const int correct[7][6] = {
{ 8, 1, 0, 2, 60, 38},
{ 8, 1, 1, 2, 61, 39},
{24, 2, 0, 11, 54, 24},
{24, 2, 1, 16, 55, 25},
{32, 0, 0, 17, 145, 115},
{40, 3, 0, 20, 45, 15},
{40, 3, 1, 61, 46, 16},
};
testStart("Checking ECC table(2)");
for(i=0; i<7; i++) {
QRspec_getEccSpec(correct[i][0], (QRecLevel)correct[i][1], spec);
if(correct[i][2] == 0) {
assert_equal(QRspec_rsBlockNum1(spec), correct[i][3],
"Error in version %d, level %d. rsBlockNum1 was %d, expected %d.\n",
correct[i][0], correct[i][1],
QRspec_rsBlockNum1(spec), correct[i][3]);
assert_equal(QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec), correct[i][4],
"Error in version %d, level %d. rsDataCodes1 + rsEccCodes1 was %d, expected %d.\n",
correct[i][0], correct[i][1],
QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec), correct[i][4]);
assert_equal(QRspec_rsDataCodes1(spec), correct[i][5],
"Error in version %d, level %d. rsDataCodes1 was %d, expected %d.\n",
correct[i][0], correct[i][1],
QRspec_rsDataCodes1(spec), correct[i][5]);
} else {
assert_equal(QRspec_rsBlockNum2(spec), correct[i][3],
"Error in version %d, level %d. rsBlockNum2 was %d, expected %d.\n",
correct[i][0], correct[i][1],
QRspec_rsBlockNum2(spec), correct[i][3]);
assert_equal(QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec), correct[i][4],
"Error in version %d, level %d. rsDataCodes2 + rsEccCodes2 was %d, expected %d.\n",
correct[i][0], correct[i][1],
QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec), correct[i][4]);
assert_equal(QRspec_rsDataCodes2(spec), correct[i][5],
"Error in version %d, level %d. rsDataCodes2 was %d, expected %d.\n",
correct[i][0], correct[i][1],
QRspec_rsDataCodes2(spec), correct[i][5]);
}
}
testFinish();
}
static void test_newframe(void)
{
unsigned char buf[QRSPEC_WIDTH_MAX * QRSPEC_WIDTH_MAX];
int i, width;
size_t len;
FILE *fp;
unsigned char *frame;
QRcode *qrcode;
int version;
testStart("Checking newly created frame.");
fp = fopen(SRCDIR "frame", "rb");
if(fp == NULL) {
perror("Failed to open \"" SRCDIR "frame\":");
abort();
}
for(i=1; i<=QRSPEC_VERSION_MAX; i++) {
frame = QRspec_newFrame(i);
width = QRspec_getWidth(i);
len = fread(buf, 1, width * width, fp);
if((int)len != width * width) {
perror("Failed to read the pattern file:");
abort();
}
assert_zero(memcmp(frame, buf, len), "frame pattern mismatch (version %d)\n", i);
qrcode = QRcode_new(i, width, frame);
version = QRcode_decodeVersion(qrcode);
assert_equal(version, i, "Decoded version number is wrong: %d, expected %d.\n", version, i);
QRcode_free(qrcode);
}
testFinish();
fclose(fp);
}
static void test_newframe_invalid(void)
{
unsigned char *frame;
testStart("Checking QRspec_newFrame with invalid version.");
frame = QRspec_newFrame(0);
assert_null(frame, "QRspec_newFrame(0) returns non-NULL.");
frame = QRspec_newFrame(QRSPEC_VERSION_MAX+1);
assert_null(frame, "QRspec_newFrame(0) returns non-NULL.");
testFinish();
}
#if 0
/* This test is used to check positions of alignment pattern. See Appendix E
* (p.71) of JIS X0510:2004 and compare to the output. Before comment out
* this test, change the value of the pattern marker's center dot from 0xa1
* to 0xb1 (QRspec_putAlignmentMarker() : finder).
*/
static void test_alignment(void)
{
unsigned char *frame;
int i, x, y, width, c;
testStart("Checking alignment pattern.");
for(i=2; i<=QRSPEC_VERSION_MAX; i++) {
printf("%2d", i);
frame = QRspec_newFrame(i);
width = QRspec_getWidth(i);
c = 0;
for(x=0; x<width * width; x++) {
if(frame[x] == 0xb1) {
c++;
}
}
printf("|%2d| 6", c);
y = width - 7;
for(x=0; x < width; x++) {
if(frame[y * width + x] == 0xb1) {
printf(", %3d", x);
}
}
printf("\n");
free(frame);
}
testFinish();
}
#endif
static void test_verpat(void)
{
int version;
unsigned int pattern;
int err = 0;
unsigned int data;
unsigned int code;
int i, c;
unsigned int mask;
testStart("Checking version pattern.");
for(version=7; version <= QRSPEC_VERSION_MAX; version++) {
pattern = QRspec_getVersionPattern(version);
if((pattern >> 12) != (unsigned int)version) {
printf("Error in version %d.\n", version);
err++;
continue;
}
mask = 0x40;
for(i=0; mask != 0; i++) {
if(version & mask) break;
mask = mask >> 1;
}
c = 6 - i;
data = version << 12;
code = 0x1f25 << c;
mask = 0x40000 >> (6 - c);
for(i=0; i<=c; i++) {
if(mask & data) {
data ^= code;
}
code = code >> 1;
mask = mask >> 1;
}
data = (version << 12) | (data & 0xfff);
if(data != pattern) {
printf("Error in version %d\n", version);
err++;
}
}
testEnd(err);
}
/* See Table 22 (p.45) and Appendix C (p. 65) of JIS X0510:2004 */
static unsigned int levelIndicator[4] = {1, 0, 3, 2};
static unsigned int calcFormatInfo(int mask, QRecLevel level)
{
unsigned int data, ecc, b, code;
int i, c;
data = (levelIndicator[level] << 13) | (mask << 10);
ecc = data;
b = 1 << 14;
for(i=0; b != 0; i++) {
if(ecc & b) break;
b = b >> 1;
}
c = 4 - i;
code = 0x537 << c ; //10100110111
b = 1 << (10 + c);
for(i=0; i<=c; i++) {
if(b & ecc) {
ecc ^= code;
}
code = code >> 1;
b = b >> 1;
}
return (data | ecc) ^ 0x5412;
}
static void test_format(void)
{
unsigned int format;
int i, j;
int err = 0;
testStart("Format info test");
for(i=0; i<4; i++) {
for(j=0; j<8; j++) {
format = calcFormatInfo(j, (QRecLevel)i);
// printf("0x%04x, ", format);
if(format != QRspec_getFormatInfo(j, (QRecLevel)i)) {
printf("Level %d, mask %x\n", i, j);
err++;
}
}
// printf("\n");
}
testEnd(err);
}
int main(int argc, char **argv)
{
int tests = 6;
testInit(tests);
test_eccTable();
test_eccTable2();
test_newframe();
test_newframe_invalid();
//test_alignment();
test_verpat();
test_format();
testReport(tests);
if(argc > 1) {
print_eccTable();
}
return 0;
}

126
tests/test_rs.c Normal file
View File

@ -0,0 +1,126 @@
#include <stdio.h>
#include <string.h>
#include "common.h"
#include "../qrencode_inner.h"
#include "../qrspec.h"
#include "../mqrspec.h"
#include "../qrinput.h"
#include "../rsecc.h"
#include "decoder.h"
#include "rsecc_decoder.h"
#include "rscode.h"
/* See pp. 73 of JIS X0510:2004 */
void test_rscodeexample(void)
{
QRinput *stream;
QRRawCode *code;
static const char str[9] = "01234567";
static unsigned char correct[26] = {
0x10, 0x20, 0x0c, 0x56, 0x61, 0x80, 0xec, 0x11, 0xec, 0x11, 0xec, 0x11,
0xec, 0x11, 0xec, 0x11, 0xa5, 0x24, 0xd4, 0xc1, 0xed, 0x36, 0xc7, 0x87,
0x2c, 0x55};
testStart("RS ecc test");
stream = QRinput_new();
QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)str);
QRinput_setErrorCorrectionLevel(stream, QR_ECLEVEL_M);
code = QRraw_new(stream);
testEnd(memcmp(correct + 16, code->rsblock[0].ecc, 10));
QRinput_free(stream);
QRraw_free(code);
}
static void compareRS(unsigned char data[])
{
int i, j;
RS *rs;
int spec[5];
int dl, el;
unsigned char ecc_expected[256], ecc_rscodec[256];
for(i = 1; i <= QRSPEC_VERSION_MAX; i++) {
for(j = QR_ECLEVEL_L; j <= QR_ECLEVEL_H; j++) {
QRspec_getEccSpec(i, (QRecLevel)j, spec);
dl = QRspec_rsDataCodes1(spec);
el = QRspec_rsEccCodes1(spec);
rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el);
RSECC_encode(dl, el, data, ecc_rscodec);
encode_rs_char(rs, data, ecc_expected);
assert_zero(memcmp(ecc_expected, ecc_rscodec, el), "Invalid ECC found: length %d.\n", el);
assert_zero(RSECC_decoder_checkSyndrome(dl, data, el, ecc_rscodec), "ECC error found.");
free_rs_char(rs);
dl = QRspec_rsDataCodes2(spec);
el = QRspec_rsEccCodes2(spec);
if(dl != 0) {
rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el);
RSECC_encode(dl, el, data, ecc_rscodec);
encode_rs_char(rs, data, ecc_expected);
assert_zero(memcmp(ecc_expected, ecc_rscodec, el), "Invalid ECC found: length %d.\n", el);
assert_zero(RSECC_decoder_checkSyndrome(dl, data, el, ecc_rscodec), "ECC error found.");
free_rs_char(rs);
}
}
}
}
static void compareRSMQR(unsigned char data[])
{
int i, j;
RS *rs;
int dl, el;
unsigned char ecc_expected[256], ecc_rscodec[256];
for(i = 1; i <= MQRSPEC_VERSION_MAX; i++) {
for(j = QR_ECLEVEL_L; j <= QR_ECLEVEL_Q; j++) {
dl = MQRspec_getDataLength(i, (QRecLevel)j);
el = MQRspec_getECCLength(i, (QRecLevel)j);
if(dl != 0) {
rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el);
RSECC_encode(dl, el, data, ecc_rscodec);
encode_rs_char(rs, data, ecc_expected);
assert_zero(memcmp(ecc_expected, ecc_rscodec, el), "Invalid ECC found: length %d.\n", el);
assert_zero(RSECC_decoder_checkSyndrome(dl, data, el, ecc_rscodec), "ECC error found.");
free_rs_char(rs);
}
}
}
}
void test_allQRSizeAndECCLevel(void)
{
int i;
unsigned char data[256];
testStart("Comparing with KA9Q's code: all QR Code sizes and ECC levels");
memset(data, 0, 256);
compareRS(data);
compareRSMQR(data);
memset(data, 0xaa, 256);
compareRS(data);
compareRSMQR(data);
memset(data, 0xff, 256);
compareRS(data);
compareRSMQR(data);
for(i=0; i<256; i++) {
data[i] = i;
}
compareRS(data);
compareRSMQR(data);
testFinish();
}
int main()
{
RSECC_decoder_init();
int tests = 2;
testInit(tests);
test_rscodeexample();
test_allQRSizeAndECCLevel();
testReport(tests);
return 0;
}

553
tests/test_split.c Normal file
View File

@ -0,0 +1,553 @@
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "common.h"
#include "../qrspec.h"
#include "../qrinput.h"
#include "../mask.h"
#include "../split.h"
#include "../bitstream.h"
static int inputTest(QRinput_List *list, const char *fmt, ...)
{
va_list ap;
int size;
QRencodeMode mode;
int i, err = 0;
va_start(ap, fmt);
i = 1;
while(*fmt) {
if(list == NULL) {
err = 1;
break;
}
size = va_arg(ap, int);
if(list->size != size) {
err = 1;
break;
}
switch(*fmt++) {
case 'n':
mode = QR_MODE_NUM;
break;
case 'a':
mode = QR_MODE_AN;
break;
case 'k':
mode = QR_MODE_KANJI;
break;
case '8':
mode = QR_MODE_8;
break;
default:
return -1;
break;
}
if(list->mode != mode) {
err = 1;
break;
}
list = list->next;
i++;
}
va_end(ap);
if(list != NULL) {
err = 1;
}
if(err) {
return -i;
}
return 0;
}
static int inputSize(QRinput *input)
{
BitStream *bstream;
int size;
bstream = BitStream_new();
QRinput_mergeBitStream(input, bstream);
size = BitStream_size(bstream);
BitStream_free(bstream);
return size;
}
static void test_split1(void)
{
QRinput *input;
BitStream *bstream;
testStart("Split test: null string");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("", input, QR_MODE_8, 0);
bstream = BitStream_new();
QRinput_mergeBitStream(input, bstream);
testEndExp(BitStream_size(bstream) == 0);
QRinput_free(input);
BitStream_free(bstream);
}
static void test_split2(void)
{
QRinput *input;
QRinput_List *list;
int err = 0;
testStart("Split test: single typed strings (num)");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("0123", input, QR_MODE_8, 0);
list = input->head;
if(inputTest(list, "n", 4)) {
err++;
}
testEnd(err);
QRinput_free(input);
err = 0;
testStart("Split test: single typed strings (num2)");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("12345678901234567890", input, QR_MODE_KANJI, 0);
list = input->head;
if(inputTest(list, "n", 20)) {
err++;
}
testEnd(err);
QRinput_free(input);
}
static void test_split3(void)
{
QRinput *input;
QRinput_List *list;
int err = 0;
testStart("Split test: single typed strings (an)");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("ab:-E", input, QR_MODE_8, 0);
list = input->head;
if(inputTest(list, "a", 5)) {
printQRinputInfo(input);
err++;
}
testEnd(err);
QRinput_free(input);
err = 0;
testStart("Split test: num + an");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("0123abcde", input, QR_MODE_KANJI, 0);
list = input->head;
if(inputTest(list, "a", 9)) {
err++;
}
testEnd(err);
QRinput_free(input);
err = 0;
testStart("Split test: an + num + an");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("Ab345fg", input, QR_MODE_KANJI, 0);
list = input->head;
if(inputTest(list, "a", 7)) {
err++;
}
testEnd(err);
QRinput_free(input);
}
static void test_split4(void)
{
QRinput *input;
QRinput *i1, *i2;
int s1, s2, size;
#define CHUNKA "ABCDEFGHIJK"
#define CHUNKB "123456"
#define CHUNKC "1234567"
testStart("Split test: an and num entries");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput(CHUNKA/**/CHUNKB, input, QR_MODE_8, 0);
i1 = QRinput_new();
QRinput_append(i1, QR_MODE_AN, 17, (unsigned char *)CHUNKA/**/CHUNKB);
i2 = QRinput_new();
QRinput_append(i2, QR_MODE_AN, 11, (unsigned char *)CHUNKA);
QRinput_append(i2, QR_MODE_NUM, 6, (unsigned char *)CHUNKB);
size = inputSize(input);
s1 = inputSize(i1);
s2 = inputSize(i2);
testEndExp(size == ((s1 < s2)?s1:s2));
QRinput_free(input);
QRinput_free(i1);
QRinput_free(i2);
testStart("Split test: num and an entries");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput(CHUNKB/**/CHUNKA, input, QR_MODE_8, 0);
i1 = QRinput_new();
QRinput_append(i1, QR_MODE_AN, 17, (unsigned char *)CHUNKB/**/CHUNKA);
i2 = QRinput_new();
QRinput_append(i2, QR_MODE_NUM, 6, (unsigned char *)CHUNKB);
QRinput_append(i2, QR_MODE_AN, 11, (unsigned char *)CHUNKA);
size = inputSize(input);
s1 = inputSize(i1);
s2 = inputSize(i2);
testEndExp(size == ((s1 < s2)?s1:s2));
QRinput_free(input);
QRinput_free(i1);
QRinput_free(i2);
testStart("Split test: num and an entries (should be splitted)");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput(CHUNKC/**/CHUNKA, input, QR_MODE_8, 0);
i1 = QRinput_new();
QRinput_append(i1, QR_MODE_AN, 18, (unsigned char *)CHUNKC/**/CHUNKA);
i2 = QRinput_new();
QRinput_append(i2, QR_MODE_NUM, 7, (unsigned char *)CHUNKC);
QRinput_append(i2, QR_MODE_AN, 11, (unsigned char *)CHUNKA);
size = inputSize(input);
s1 = inputSize(i1);
s2 = inputSize(i2);
testEndExp(size == ((s1 < s2)?s1:s2));
QRinput_free(input);
QRinput_free(i1);
QRinput_free(i2);
}
static void test_split5(void)
{
QRinput *input;
QRinput_List *list;
int err = 0;
testStart("Split test: bit, an, bit, num");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("\x82\xd9""abcdeabcdea\x82\xb0""123456", input, QR_MODE_8, 0);
list = input->head;
if(inputTest(list, "8a8n", 2, 11, 2, 6)) {
err++;
}
testEnd(err);
QRinput_free(input);
}
static void test_split6(void)
{
QRinput *input;
QRinput_List *list;
int err = 0;
testStart("Split test: kanji, an, kanji, num");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("\x82\xd9""abcdeabcdea\x82\xb0""123456", input, QR_MODE_KANJI, 0);
list = input->head;
if(inputTest(list, "kakn", 2, 11, 2, 6)) {
printQRinputInfo(input);
err++;
}
testEnd(err);
QRinput_free(input);
}
static void test_split7(void)
{
QRinput *input;
QRinput_List *list;
int err = 0;
testStart("Split test: an and num as bits");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("\x82\xd9""abcde\x82\xb0""12345", input, QR_MODE_8, 0);
list = input->head;
if(inputTest(list, "8n", 9, 5)) {
err++;
}
testEnd(err);
QRinput_free(input);
}
static void test_split8(void)
{
QRinput *input;
QRinput_List *list;
int err = 0;
testStart("Split test: terminated with a half of kanji code");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("\x82\xd9""abcdefgh\x82", input, QR_MODE_KANJI, 0);
list = input->head;
if(inputTest(list, "ka8", 2, 8, 1)) {
err++;
}
testEnd(err);
QRinput_free(input);
}
static void test_split3c(void)
{
QRinput *input;
QRinput_List *list;
int err = 0;
testStart("Split test: single typed strings (an, case-sensitive)");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("ab:-E", input, QR_MODE_8, 1);
list = input->head;
if(inputTest(list, "8", 5)) {
err++;
}
testEnd(err);
QRinput_free(input);
err = 0;
testStart("Split test: num + an");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("0123abcde", input, QR_MODE_KANJI, 1);
list = input->head;
if(inputTest(list, "n8", 4, 5)) {
err++;
}
testEnd(err);
QRinput_free(input);
err = 0;
testStart("Split test: an + num + an");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("Ab345fg", input, QR_MODE_KANJI, 1);
list = input->head;
if(inputTest(list, "8", 7)) {
printQRinputInfo(input);
err++;
}
testEnd(err);
QRinput_free(input);
}
static void test_toupper(void)
{
QRinput *input;
QRinput_List *list;
int err = 0;
testStart("Split test: check dupAndToUpper (lower->upper)");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("abcde", input, QR_MODE_8, 0);
list = input->head;
if(inputTest(list, "a", 5)) {
err++;
}
if(strncmp((char *)list->data, "ABCDE", list->size)) {
err++;
}
testEnd(err);
QRinput_free(input);
err = 0;
testStart("Split test: check dupAndToUpper (kanji)");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("\x83n\x83q\x83t\x83w\x83z", input, QR_MODE_KANJI, 0);
list = input->head;
if(inputTest(list, "k", 10)) {
printQRinputInfo(input);
err++;
}
if(strncmp((char *)list->data, "\x83n\x83q\x83t\x83w\x83z", list->size)) {
err++;
}
testEnd(err);
QRinput_free(input);
err = 0;
testStart("Split test: check dupAndToUpper (8bit)");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("\x83n\x83q\x83t\x83w\x83z", input, QR_MODE_8, 0);
list = input->head;
if(inputTest(list, "8", 10)) {
printQRinputInfo(input);
err++;
}
if(strncmp((char *)list->data, "\x83N\x83Q\x83T\x83W\x83Z", list->size)) {
err++;
}
testEnd(err);
QRinput_free(input);
}
static void test_splitNum8(void)
{
QRinput *input;
QRinput_List *list;
int err = 0;
testStart("Split test: num and 8bit to 8bit");
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput("1abcdefg", input, QR_MODE_8, 1);
list = input->head;
if(inputTest(list, "8", 8)) {
err++;
printQRinputInfo(input);
}
testEnd(err);
QRinput_free(input);
}
static void test_splitAnNAn(void)
{
QRinput *input1, *input2, *input3;
int s1, s2, s3;
char *strall = "326A80A9C5004C0875571F8B71C311F2F86";
char *str1 = "326A80A9C5004C";
char *str2 = "0875571";
char *str3 = "F8B71C311F2F86";
testStart("Split test: An-N-An switching cost test");
input1 = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput(strall, input1, QR_MODE_8, 0);
input2 = QRinput_new();
QRinput_append(input2, QR_MODE_AN, 35, (unsigned char *)strall);
input3 = QRinput_new();
QRinput_append(input3, QR_MODE_AN, 14, (unsigned char *)str1);
QRinput_append(input3, QR_MODE_NUM, 7, (unsigned char *)str2);
QRinput_append(input3, QR_MODE_AN, 14, (unsigned char *)str3);
s1 = inputSize(input1);
s2 = inputSize(input2);
s3 = inputSize(input3);
assert_equal(s1, s2, "Incorrect split");
assert_exp(s2 < s3, "Incorrect estimation");
testFinish();
QRinput_free(input1);
QRinput_free(input2);
QRinput_free(input3);
}
static void test_splitAn8An(void)
{
QRinput *input1, *input2, *input3;
int s1, s2, s3;
char *strall = "ABCDabcdefABCD";
char *str1 = "ABCD";
char *str2 = "abcdef";
char *str3 = "ABCD";
testStart("Split test: An-8-An switching cost test");
input1 = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput(strall, input1, QR_MODE_8, 1);
input2 = QRinput_new();
QRinput_append(input2, QR_MODE_8, 14, (unsigned char *)strall);
input3 = QRinput_new();
QRinput_append(input3, QR_MODE_AN, 4, (unsigned char *)str1);
QRinput_append(input3, QR_MODE_8, 6, (unsigned char *)str2);
QRinput_append(input3, QR_MODE_AN, 4, (unsigned char *)str3);
s1 = inputSize(input1);
s2 = inputSize(input2);
s3 = inputSize(input3);
assert_equal(s1, s2, "Incorrect split");
assert_exp(s2 < s3, "Incorrect estimation");
testFinish();
QRinput_free(input1);
QRinput_free(input2);
QRinput_free(input3);
}
static void test_split8An8(void)
{
QRinput *input1, *input2, *input3;
int s1, s2, s3;
char *strall = "abcABCDEFGHabc";
char *str1 = "abc";
char *str2 = "ABCDEFGH";
char *str3 = "abc";
testStart("Split test: 8-An-8 switching cost test");
input1 = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput(strall, input1, QR_MODE_8, 1);
input2 = QRinput_new();
QRinput_append(input2, QR_MODE_8, 14, (unsigned char *)strall);
input3 = QRinput_new();
QRinput_append(input3, QR_MODE_8, 3, (unsigned char *)str1);
QRinput_append(input3, QR_MODE_AN, 8, (unsigned char *)str2);
QRinput_append(input3, QR_MODE_8, 3, (unsigned char *)str3);
s1 = inputSize(input1);
s2 = inputSize(input2);
s3 = inputSize(input3);
assert_equal(s1, s2, "Incorrect split");
assert_exp(s2 < s3, "Incorrect estimation");
testFinish();
QRinput_free(input1);
QRinput_free(input2);
QRinput_free(input3);
}
static void test_split8N8(void)
{
QRinput *input1, *input2, *input3;
int s1, s2, s3;
char *strall = "abc1234abc";
char *str1 = "abc";
char *str2 = "1234";
char *str3 = "abc";
testStart("Split test: 8-N-8 switching cost test");
input1 = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput(strall, input1, QR_MODE_8, 1);
input2 = QRinput_new();
QRinput_append(input2, QR_MODE_8, 10, (unsigned char *)strall);
input3 = QRinput_new();
QRinput_append(input3, QR_MODE_8, 3, (unsigned char *)str1);
QRinput_append(input3, QR_MODE_NUM, 4, (unsigned char *)str2);
QRinput_append(input3, QR_MODE_8, 3, (unsigned char *)str3);
s1 = inputSize(input1);
s2 = inputSize(input2);
s3 = inputSize(input3);
assert_equal(s1, s2, "Incorrect split");
assert_exp(s2 < s3, "Incorrect estimation");
testFinish();
QRinput_free(input1);
QRinput_free(input2);
QRinput_free(input3);
}
int main()
{
int tests = 24;
testInit(tests);
test_split1();
test_split2();
test_split3();
test_split4();
test_split5();
test_split6();
test_split7();
test_split8();
test_split3c();
test_toupper();
test_splitNum8();
test_splitAnNAn();
test_splitAn8An();
test_split8An8();
test_split8N8();
testReport(tests);
return 0;
}

92
tests/test_split_urls.c Normal file
View File

@ -0,0 +1,92 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "common.h"
#include "../qrinput.h"
#include "../qrencode_inner.h"
#include "../split.h"
#include "decoder.h"
#include "URI_testset.inc"
#if 0
static void encodeURLandPrint(char *url) {
QRinput *input;
BitStream *bstream;
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput(url, input, QR_MODE_8, 1);
bstream = BitStream_new();
QRinput_mergeBitStream(input, bstream);
printf("{%zu,\"%s\"},\n", BitStream_size(bstream), url);
QRinput_free(input);
BitStream_free(bstream);
}
static void print_currentBitLength() {
struct TestSet *ts = testset;
puts("struct TestSet {\n\tint expected_length;\n\tchar *url;\n};");
puts("\nstruct TestSet testset[] = {");
while(ts->url != NULL) {
encodeURLandPrint(ts->url);
ts++;
}
puts("{0,NULL}\n};");
}
#endif
static int encodeURLandCompare(char *url, size_t expected_length) {
QRinput *input;
BitStream *bstream;
int ret = 0;
input = QRinput_new2(0, QR_ECLEVEL_L);
Split_splitStringToQRinput(url, input, QR_MODE_8, 1);
bstream = BitStream_new();
QRinput_mergeBitStream(input, bstream);
size_t length = BitStream_size(bstream);
if(length > expected_length) {
printf("The length of the encode stream is longer than expected: %zu over %zu\n", length, expected_length);
printQRinput(input);
ret = 1;
} else if(length < expected_length) {
printf("The length of the encode stream is shorter than expected: %zu under %zu\n", length, expected_length);
printQRinput(input);
ret = 1;
}
QRinput_free(input);
BitStream_free(bstream);
return ret;
}
static void test_bitstream_length() {
struct TestSet *ts = testset;
int err = 0;
testStart("Split_URL test: compare bitstream length");
while(ts->url != NULL) {
err += encodeURLandCompare(ts->url, ts->expected_length);
ts++;
}
testEnd(err);
}
int main()
{
int tests = 1;
testInit(tests);
test_bitstream_length();
testReport(tests);
return 0;
}

641
tests/view_qrcode.c Normal file
View File

@ -0,0 +1,641 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <SDL.h>
#include <getopt.h>
#include <errno.h>
#include "../config.h"
#include "../qrspec.h"
#include "../qrinput.h"
#include "../split.h"
#include "../qrencode_inner.h"
static SDL_Window *window;
static SDL_Renderer *renderer;
static SDL_Texture *texture = NULL;
static SDL_Surface *surface = NULL;
static int casesensitive = 1;
static int eightbit = 0;
static int version = 0;
static int size = 4;
static int margin = -1;
static int structured = 0;
static int micro = 0;
static int colorize = 0;
static QRecLevel level = QR_ECLEVEL_L;
static QRencodeMode hint = QR_MODE_8;
static char **textv;
static int textc;
static const struct option options[] = {
{"help" , no_argument , NULL, 'h'},
{"level" , required_argument, NULL, 'l'},
{"size" , required_argument, NULL, 's'},
{"symversion" , required_argument, NULL, 'v'},
{"margin" , required_argument, NULL, 'm'},
{"structured" , no_argument , NULL, 'S'},
{"kanji" , no_argument , NULL, 'k'},
{"casesensitive", no_argument , NULL, 'c'},
{"ignorecase" , no_argument , NULL, 'i'},
{"8bit" , no_argument , NULL, '8'},
{"micro" , no_argument , NULL, 'M'},
{"version" , no_argument , NULL, 'V'},
{NULL, 0, NULL, 0}
};
static char *optstring = "hl:s:v:m:Skci8MV";
static char levelChar[4] = {'L', 'M', 'Q', 'H'};
static void usage(int help, int longopt)
{
fprintf(stderr,
"view_qrcode version %s\n"
"Copyright (C) 2008, 2009, 2010 Kentaro Fukuchi\n", VERSION);
if(help) {
if(longopt) {
fprintf(stderr,
"Usage: view_qrcode [OPTION]... [STRING]\n"
"Encode input data in a QR Code and display.\n\n"
" -h, --help display the help message. -h displays only the help of short\n"
" options.\n\n"
" -s NUMBER, --size=NUMBER\n"
" specify module size in dots (pixels). (default=3)\n\n"
" -l {LMQH}, --level={LMQH}\n"
" specify error correction level from L (lowest) to H (highest).\n"
" (default=L)\n\n"
" -v NUMBER, --symversion=NUMBER\n"
" specify the version of the symbol. See SYMBOL VERSIONS for more\n"
" information. (default=auto)\n\n"
" -m NUMBER, --margin=NUMBER\n"
" specify the width of the margins. (default=4 (2 for Micro QR)))\n\n"
" -S, --structured\n"
" make structured symbols. Version must be specified.\n\n"
" -k, --kanji assume that the input text contains kanji (shift-jis).\n\n"
" -c, --casesensitive\n"
" encode lower-case alphabet characters in 8-bit mode. (default)\n\n"
" -i, --ignorecase\n"
" ignore case distinctions and use only upper-case characters.\n\n"
" -8, --8bit encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n\n"
" -M, --micro encode in a Micro QR Code. (experimental)\n\n"
" -V, --version\n"
" display the version number and copyrights of the qrencode.\n\n"
" [STRING] input data. If it is not specified, data will be taken from\n"
" standard input.\n\n"
"*SYMBOL VERSIONS\n"
" The symbol versions of QR Code range from Version 1 to Version\n"
" 40. Each version has a different module configuration or number\n"
" of modules, ranging from Version 1 (21 x 21 modules) up to\n"
" Version 40 (177 x 177 modules). Each higher version number\n"
" comprises 4 additional modules per side by default. See\n"
" http://www.qrcode.com/en/about/version.html for a detailed\n"
" version list.\n"
);
} else {
fprintf(stderr,
"Usage: view_qrcode [OPTION]... [STRING]\n"
"Encode input data in a QR Code and display.\n\n"
" -h display this message.\n"
" --help display the usage of long options.\n"
" -s NUMBER specify module size in dots (pixels). (default=3)\n"
" -l {LMQH} specify error correction level from L (lowest) to H (highest).\n"
" (default=L)\n"
" -v NUMBER specify the version of the symbol. (default=auto)\n"
" -m NUMBER specify the width of the margins. (default=4 (2 for Micro))\n"
" -S make structured symbols. Version must be specified.\n"
" -k assume that the input text contains kanji (shift-jis).\n"
" -c encode lower-case alphabet characters in 8-bit mode. (default)\n"
" -i ignore case distinctions and use only upper-case characters.\n"
" -8 encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n"
" -M encode in a Micro QR Code.\n"
" -V display the version number and copyrights of the qrencode.\n"
" [STRING] input data. If it is not specified, data will be taken from\n"
" standard input.\n"
);
}
}
}
#define MAX_DATA_SIZE (7090 * 16) /* from the specification */
static unsigned char *readStdin(int *length)
{
unsigned char *buffer;
int ret;
buffer = (unsigned char *)malloc(MAX_DATA_SIZE + 1);
if(buffer == NULL) {
fprintf(stderr, "Memory allocation failed.\n");
exit(EXIT_FAILURE);
}
ret = fread(buffer, 1, MAX_DATA_SIZE, stdin);
if(ret == 0) {
fprintf(stderr, "No input data.\n");
exit(EXIT_FAILURE);
}
if(feof(stdin) == 0) {
fprintf(stderr, "Input data is too large.\n");
exit(EXIT_FAILURE);
}
buffer[ret] = '\0';
*length = ret;
return buffer;
}
static void draw_QRcode(QRcode *qrcode, int ox, int oy)
{
int x, y, width;
unsigned char *p;
SDL_Rect rect;
Uint32 color[8];
int col;
color[0] = SDL_MapRGBA(surface->format, 255, 255, 255, 255);
color[1] = SDL_MapRGBA(surface->format, 0, 0, 0, 255);
color[2] = SDL_MapRGBA(surface->format, 192, 192, 255, 255);
color[3] = SDL_MapRGBA(surface->format, 0, 0, 64, 255);
color[4] = SDL_MapRGBA(surface->format, 255, 255, 192, 255);
color[5] = SDL_MapRGBA(surface->format, 64, 64, 0, 255);
color[6] = SDL_MapRGBA(surface->format, 255, 192, 192, 255);
color[7] = SDL_MapRGBA(surface->format, 64, 0, 0, 255);
ox += margin * size;
oy += margin * size;
width = qrcode->width;
p = qrcode->data;
for(y=0; y<width; y++) {
for(x=0; x<width; x++) {
rect.x = ox + x * size;
rect.y = oy + y * size;
rect.w = size;
rect.h = size;
if(!colorize) {
col = 0;
} else {
if(*p & 0x80) {
col = 6;
} else if(*p & 0x02) {
col = 4;
} else {
col = 2;
}
}
col += (*p & 1);
SDL_FillRect(surface, &rect, color[col]);
p++;
}
}
}
static void draw_singleQRcode(QRinput *stream, int mask)
{
QRcode *qrcode;
int width;
QRinput_setVersionAndErrorCorrectionLevel(stream, version, level);
if(micro) {
qrcode = QRcode_encodeMaskMQR(stream, mask);
} else {
qrcode = QRcode_encodeMask(stream, mask);
}
if(qrcode == NULL) {
width = (11 + margin * 2) * size;
fprintf(stderr, "Input data does not fit to this setting.\n");
} else {
version = qrcode->version;
width = (qrcode->width + margin * 2) * size;
}
SDL_SetWindowSize(window, width, width);
if(surface != NULL) {
SDL_FreeSurface(surface);
}
surface = SDL_CreateRGBSurface(0, width, width, 32, 0, 0, 0, 0);
SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, 255, 255, 255, 255));
if(qrcode) {
draw_QRcode(qrcode, 0, 0);
}
if(texture != NULL) {
SDL_DestroyTexture(texture);
}
texture = SDL_CreateTextureFromSurface(renderer, surface);
QRcode_free(qrcode);
}
static void draw_structuredQRcode(QRinput_Struct *s)
{
int i, w, h, n, x, y;
int swidth;
QRcode_List *qrcodes, *p;
qrcodes = QRcode_encodeInputStructured(s);
if(qrcodes == NULL) return;
swidth = (qrcodes->code->width + margin * 2) * size;
n = QRcode_List_size(qrcodes);
w = (n < 4)?n:4;
h = (n - 1) / 4 + 1;
SDL_SetWindowSize(window, swidth * w, swidth * h);
if(surface != NULL) {
SDL_FreeSurface(surface);
}
surface = SDL_CreateRGBSurface(0, swidth * w, swidth * h, 32, 0, 0, 0, 0);
SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, 255, 255, 255, 255));
p = qrcodes;
for(i=0; i<n; i++) {
x = (i % 4) * swidth;
y = (i / 4) * swidth;
draw_QRcode(p->code, x, y);
p = p->next;
}
if(texture != NULL) {
SDL_DestroyTexture(texture);
}
texture = SDL_CreateTextureFromSurface(renderer, surface);
QRcode_List_free(qrcodes);
}
static void draw_structuredQRcodeFromText(int argc, char **argv)
{
QRinput_Struct *s;
QRinput *input;
int i, ret;
s = QRinput_Struct_new();
if(s == NULL) {
fprintf(stderr, "Failed to allocate memory.\n");
exit(EXIT_FAILURE);
}
for(i=0; i<argc; i++) {
input = QRinput_new2(version, level);
if(input == NULL) {
fprintf(stderr, "Failed to allocate memory.\n");
exit(EXIT_FAILURE);
}
if(eightbit) {
ret = QRinput_append(input, QR_MODE_8, strlen(argv[i]), (unsigned char *)argv[i]);
} else {
ret = Split_splitStringToQRinput(argv[i], input, hint, casesensitive);
}
if(ret < 0) {
perror("Encoding the input string");
exit(EXIT_FAILURE);
}
ret = QRinput_Struct_appendInput(s, input);
if(ret < 0) {
perror("Encoding the input string");
exit(EXIT_FAILURE);
}
}
ret = QRinput_Struct_insertStructuredAppendHeaders(s);
if(ret < 0) {
fprintf(stderr, "Too many inputs.\n");
}
draw_structuredQRcode(s);
QRinput_Struct_free(s);
}
static void draw_structuredQRcodeFromQRinput(QRinput *stream)
{
QRinput_Struct *s;
QRinput_setVersion(stream, version);
QRinput_setErrorCorrectionLevel(stream, level);
s = QRinput_splitQRinputToStruct(stream);
if(s != NULL) {
draw_structuredQRcode(s);
QRinput_Struct_free(s);
} else {
fprintf(stderr, "Input data is too large for this setting.\n");
}
}
static void view(int mode, QRinput *input)
{
int flag = 1;
int mask = -1;
SDL_Event event;
int loop;
int codeChanged = 1;
while(flag) {
if(codeChanged) {
if(mode) {
draw_structuredQRcodeFromText(textc, textv);
} else {
if(structured) {
draw_structuredQRcodeFromQRinput(input);
} else {
draw_singleQRcode(input, mask);
}
}
if(mode || structured) {
printf("Version %d, Level %c.\n", version, levelChar[level]);
} else {
printf("Version %d, Level %c, Mask %d.\n", version, levelChar[level], mask);
}
}
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
loop = 1;
codeChanged = 0;
while(loop) {
SDL_WaitEvent(&event);
if(event.type == SDL_KEYDOWN) {
codeChanged = 1;
switch(event.key.keysym.sym) {
case SDLK_RIGHT:
version++;
if(version > QRSPEC_VERSION_MAX)
version = QRSPEC_VERSION_MAX;
loop = 0;
break;
case SDLK_LEFT:
version--;
if(version < 1)
version = 1;
loop = 0;
break;
case SDLK_UP:
size++;
loop = 0;
break;
case SDLK_DOWN:
size--;
if(size < 1) size = 1;
loop = 0;
break;
case SDLK_0:
case SDLK_1:
case SDLK_2:
case SDLK_3:
case SDLK_4:
case SDLK_5:
case SDLK_6:
case SDLK_7:
if(!mode && !structured) {
mask = (event.key.keysym.sym - SDLK_0);
loop = 0;
}
break;
case SDLK_8:
if(!mode && !structured) {
mask = -1;
loop = 0;
}
break;
case SDLK_9:
if(!mode && !structured) {
mask = -2;
loop = 0;
}
break;
case SDLK_l:
level = QR_ECLEVEL_L;
loop = 0;
break;
case SDLK_m:
level = QR_ECLEVEL_M;
loop = 0;
break;
case SDLK_h:
level = QR_ECLEVEL_H;
loop = 0;
break;
case SDLK_q:
level = QR_ECLEVEL_Q;
loop = 0;
break;
case SDLK_c:
colorize ^= 1;
loop = 0;
break;
case SDLK_ESCAPE:
loop = 0;
flag = 0;
break;
default:
break;
}
if(event.type == SDL_QUIT) {
loop = 0;
flag = 0;
}
}
if (event.type == SDL_WINDOWEVENT) {
switch (event.window.event) {
case SDL_WINDOWEVENT_SHOWN:
case SDL_WINDOWEVENT_EXPOSED:
case SDL_WINDOWEVENT_SIZE_CHANGED:
case SDL_WINDOWEVENT_RESIZED:
loop = 0;
break;
default:
break;
}
}
}
}
}
static void view_simple(const unsigned char *str, int length)
{
QRinput *input;
int ret;
if(micro) {
input = QRinput_newMQR(version, level);
} else {
input = QRinput_new2(version, level);
}
if(input == NULL) {
fprintf(stderr, "Memory allocation error.\n");
exit(EXIT_FAILURE);
}
if(eightbit) {
ret = QRinput_append(input, QR_MODE_8, length, str);
} else {
ret = Split_splitStringToQRinput((char *)str, input, hint, casesensitive);
}
if(ret < 0) {
perror("Encoding the input string");
exit(EXIT_FAILURE);
}
view(0, input);
QRinput_free(input);
}
static void view_multiText(char **argv, int argc)
{
textc = argc;
textv = argv;
view(1, NULL);
}
int main(int argc, char **argv)
{
int opt, lindex = -1;
unsigned char *intext = NULL;
int length = 0;
int ret;
while((opt = getopt_long(argc, argv, optstring, options, &lindex)) != -1) {
switch(opt) {
case 'h':
if(lindex == 0) {
usage(1, 1);
} else {
usage(1, 0);
}
exit(EXIT_SUCCESS);
break;
case 's':
size = atoi(optarg);
if(size <= 0) {
fprintf(stderr, "Invalid size: %d\n", size);
exit(EXIT_FAILURE);
}
break;
case 'v':
version = atoi(optarg);
if(version < 0) {
fprintf(stderr, "Invalid version: %d\n", version);
exit(EXIT_FAILURE);
}
break;
case 'l':
switch(*optarg) {
case 'l':
case 'L':
level = QR_ECLEVEL_L;
break;
case 'm':
case 'M':
level = QR_ECLEVEL_M;
break;
case 'q':
case 'Q':
level = QR_ECLEVEL_Q;
break;
case 'h':
case 'H':
level = QR_ECLEVEL_H;
break;
default:
fprintf(stderr, "Invalid level: %s\n", optarg);
exit(EXIT_FAILURE);
break;
}
break;
case 'm':
margin = atoi(optarg);
if(margin < 0) {
fprintf(stderr, "Invalid margin: %d\n", margin);
exit(EXIT_FAILURE);
}
break;
case 'S':
structured = 1;
case 'k':
hint = QR_MODE_KANJI;
break;
case 'c':
casesensitive = 1;
break;
case 'i':
casesensitive = 0;
break;
case '8':
eightbit = 1;
break;
case 'M':
micro = 1;
break;
case 'V':
usage(0, 0);
exit(EXIT_SUCCESS);
break;
default:
fprintf(stderr, "Try `view_qrcode --help' for more information.\n");
exit(EXIT_FAILURE);
break;
}
}
if(argc == 1) {
usage(1, 0);
exit(EXIT_SUCCESS);
}
if(optind < argc) {
intext = (unsigned char *)argv[optind];
length = strlen((char *)intext);
}
if(intext == NULL) {
intext = readStdin(&length);
}
if(micro && version > MQRSPEC_VERSION_MAX) {
fprintf(stderr, "Version should be less or equal to %d.\n", MQRSPEC_VERSION_MAX);
exit(EXIT_FAILURE);
} else if(!micro && version > QRSPEC_VERSION_MAX) {
fprintf(stderr, "Version should be less or equal to %d.\n", QRSPEC_VERSION_MAX);
exit(EXIT_FAILURE);
}
if(margin < 0) {
if(micro) {
margin = 2;
} else {
margin = 4;
}
}
if(micro) {
if(version == 0) {
fprintf(stderr, "Version must be specified to encode a Micro QR Code symbol.\n");
exit(EXIT_FAILURE);
}
if(structured) {
fprintf(stderr, "Micro QR Code does not support structured symbols.\n");
exit(EXIT_FAILURE);
}
}
if(structured && version == 0) {
fprintf(stderr, "Version must be specified to encode structured symbols.\n");
exit(EXIT_FAILURE);
}
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "Failed initializing SDL: %s\n", SDL_GetError());
return -1;
}
ret = SDL_CreateWindowAndRenderer(100, 100, SDL_WINDOW_SHOWN, &window, &renderer);
if(ret < 0) {
fprintf(stderr, "Failed to create a window: %s\n", SDL_GetError());
return -1;
}
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
if(structured && (argc - optind > 1)) {
view_multiText(argv + optind, argc - optind);
} else {
view_simple(intext, length);
}
SDL_Quit();
return 0;
}

347
use/compile Executable file
View File

@ -0,0 +1,347 @@
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2012-10-14.11; # UTC
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# 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 2, or (at your option)
# 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 <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
nl='
'
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" "" $nl"
file_conv=
# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv/,$2, in
*,$file_conv,*)
;;
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
func_file_conv "$1"
if test -z "$lib_path"; then
lib_path=$file
else
lib_path="$lib_path;$file"
fi
linker_opts="$linker_opts -LIBPATH:$file"
}
# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
lib=$1
found=no
save_IFS=$IFS
IFS=';'
for dir in $lib_path $LIB
do
IFS=$save_IFS
if $shared && test -f "$dir/$lib.dll.lib"; then
found=yes
lib=$dir/$lib.dll.lib
break
fi
if test -f "$dir/$lib.lib"; then
found=yes
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
if test "$found" != yes; then
lib=$lib.lib
fi
}
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
# Assume a capable shell
lib_path=
shared=:
linker_opts=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
eat=1
case $2 in
*.o | *.[oO][bB][jJ])
func_file_conv "$2"
set x "$@" -Fo"$file"
shift
;;
*)
func_file_conv "$2"
set x "$@" -Fe"$file"
shift
;;
esac
;;
-I)
eat=1
func_file_conv "$2" mingw
set x "$@" -I"$file"
shift
;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
-l)
eat=1
func_cl_dashl "$2"
set x "$@" "$lib"
shift
;;
-l*)
func_cl_dashl "${1#-l}"
set x "$@" "$lib"
shift
;;
-L)
eat=1
func_cl_dashL "$2"
;;
-L*)
func_cl_dashL "${1#-L}"
;;
-static)
shared=false
;;
-Wl,*)
arg=${1#-Wl,}
save_ifs="$IFS"; IFS=','
for flag in $arg; do
IFS="$save_ifs"
linker_opts="$linker_opts $flag"
done
IFS="$save_ifs"
;;
-Xlinker)
eat=1
linker_opts="$linker_opts $2"
;;
-*)
set x "$@" "$1"
shift
;;
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
func_file_conv "$1"
set x "$@" -Tp"$file"
shift
;;
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
func_file_conv "$1" mingw
set x "$@" "$file"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -n "$linker_opts"; then
linker_opts="-link$linker_opts"
fi
exec "$@" $linker_opts
exit 1
}
eat=
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
ofile=
cfile=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
# So we strip '-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no '-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# '.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

1558
use/config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

684
use/config.rpath Executable file
View File

@ -0,0 +1,684 @@
#! /bin/sh
# Output a system dependent set of variables, describing how to set the
# run time search path of shared libraries in an executable.
#
# Copyright 1996-2016 Free Software Foundation, Inc.
# Taken from GNU libtool, 2001
# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# The first argument passed to this file is the canonical host specification,
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
# should be set by the caller.
#
# The set of defined variables is at the end of this script.
# Known limitations:
# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer
# than 256 bytes, otherwise the compiler driver will dump core. The only
# known workaround is to choose shorter directory names for the build
# directory and/or the installation directory.
# All known linkers require a '.a' archive for static linking (except MSVC,
# which needs '.lib').
libext=a
shrext=.so
host="$1"
host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
# Code taken from libtool.m4's _LT_CC_BASENAME.
for cc_temp in $CC""; do
case $cc_temp in
compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
\-*) ;;
*) break;;
esac
done
cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'`
# Code taken from libtool.m4's _LT_COMPILER_PIC.
wl=
if test "$GCC" = yes; then
wl='-Wl,'
else
case "$host_os" in
aix*)
wl='-Wl,'
;;
mingw* | cygwin* | pw32* | os2* | cegcc*)
;;
hpux9* | hpux10* | hpux11*)
wl='-Wl,'
;;
irix5* | irix6* | nonstopux*)
wl='-Wl,'
;;
linux* | k*bsd*-gnu | kopensolaris*-gnu)
case $cc_basename in
ecc*)
wl='-Wl,'
;;
icc* | ifort*)
wl='-Wl,'
;;
lf95*)
wl='-Wl,'
;;
nagfor*)
wl='-Wl,-Wl,,'
;;
pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
wl='-Wl,'
;;
ccc*)
wl='-Wl,'
;;
xl* | bgxl* | bgf* | mpixl*)
wl='-Wl,'
;;
como)
wl='-lopt='
;;
*)
case `$CC -V 2>&1 | sed 5q` in
*Sun\ F* | *Sun*Fortran*)
wl=
;;
*Sun\ C*)
wl='-Wl,'
;;
esac
;;
esac
;;
newsos6)
;;
*nto* | *qnx*)
;;
osf3* | osf4* | osf5*)
wl='-Wl,'
;;
rdos*)
;;
solaris*)
case $cc_basename in
f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
wl='-Qoption ld '
;;
*)
wl='-Wl,'
;;
esac
;;
sunos4*)
wl='-Qoption ld '
;;
sysv4 | sysv4.2uw2* | sysv4.3*)
wl='-Wl,'
;;
sysv4*MP*)
;;
sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
wl='-Wl,'
;;
unicos*)
wl='-Wl,'
;;
uts4*)
;;
esac
fi
# Code taken from libtool.m4's _LT_LINKER_SHLIBS.
hardcode_libdir_flag_spec=
hardcode_libdir_separator=
hardcode_direct=no
hardcode_minus_L=no
case "$host_os" in
cygwin* | mingw* | pw32* | cegcc*)
# FIXME: the MSVC++ port hasn't been tested in a loooong time
# When not using gcc, we currently assume that we are using
# Microsoft Visual C++.
if test "$GCC" != yes; then
with_gnu_ld=no
fi
;;
interix*)
# we just hope/assume this is gcc and not c89 (= MSVC++)
with_gnu_ld=yes
;;
openbsd*)
with_gnu_ld=no
;;
esac
ld_shlibs=yes
if test "$with_gnu_ld" = yes; then
# Set some defaults for GNU ld with shared library support. These
# are reset later if shared libraries are not supported. Putting them
# here allows them to be overridden if necessary.
# Unlike libtool, we use -rpath here, not --rpath, since the documented
# option of GNU ld is called -rpath, not --rpath.
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
case "$host_os" in
aix[3-9]*)
# On AIX/PPC, the GNU linker is very broken
if test "$host_cpu" != ia64; then
ld_shlibs=no
fi
;;
amigaos*)
case "$host_cpu" in
powerpc)
;;
m68k)
hardcode_libdir_flag_spec='-L$libdir'
hardcode_minus_L=yes
;;
esac
;;
beos*)
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
:
else
ld_shlibs=no
fi
;;
cygwin* | mingw* | pw32* | cegcc*)
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
hardcode_libdir_flag_spec='-L$libdir'
if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
:
else
ld_shlibs=no
fi
;;
haiku*)
;;
interix[3-9]*)
hardcode_direct=no
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
;;
gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
:
else
ld_shlibs=no
fi
;;
netbsd*)
;;
solaris*)
if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
ld_shlibs=no
elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
:
else
ld_shlibs=no
fi
;;
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
case `$LD -v 2>&1` in
*\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
ld_shlibs=no
;;
*)
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
else
ld_shlibs=no
fi
;;
esac
;;
sunos4*)
hardcode_direct=yes
;;
*)
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
:
else
ld_shlibs=no
fi
;;
esac
if test "$ld_shlibs" = no; then
hardcode_libdir_flag_spec=
fi
else
case "$host_os" in
aix3*)
# Note: this linker hardcodes the directories in LIBPATH if there
# are no directories specified by -L.
hardcode_minus_L=yes
if test "$GCC" = yes; then
# Neither direct hardcoding nor static linking is supported with a
# broken collect2.
hardcode_direct=unsupported
fi
;;
aix[4-9]*)
if test "$host_cpu" = ia64; then
# On IA64, the linker does run time linking by default, so we don't
# have to do anything special.
aix_use_runtimelinking=no
else
aix_use_runtimelinking=no
# Test if we are trying to use run time linking or normal
# AIX style linking. If -brtl is somewhere in LDFLAGS, we
# need to do runtime linking.
case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
for ld_flag in $LDFLAGS; do
if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
aix_use_runtimelinking=yes
break
fi
done
;;
esac
fi
hardcode_direct=yes
hardcode_libdir_separator=':'
if test "$GCC" = yes; then
case $host_os in aix4.[012]|aix4.[012].*)
collect2name=`${CC} -print-prog-name=collect2`
if test -f "$collect2name" && \
strings "$collect2name" | grep resolve_lib_name >/dev/null
then
# We have reworked collect2
:
else
# We have old collect2
hardcode_direct=unsupported
hardcode_minus_L=yes
hardcode_libdir_flag_spec='-L$libdir'
hardcode_libdir_separator=
fi
;;
esac
fi
# Begin _LT_AC_SYS_LIBPATH_AIX.
echo 'int main () { return 0; }' > conftest.c
${CC} ${LDFLAGS} conftest.c -o conftest
aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
}'`
if test -z "$aix_libpath"; then
aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
}'`
fi
if test -z "$aix_libpath"; then
aix_libpath="/usr/lib:/lib"
fi
rm -f conftest.c conftest
# End _LT_AC_SYS_LIBPATH_AIX.
if test "$aix_use_runtimelinking" = yes; then
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
else
if test "$host_cpu" = ia64; then
hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
else
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
fi
fi
;;
amigaos*)
case "$host_cpu" in
powerpc)
;;
m68k)
hardcode_libdir_flag_spec='-L$libdir'
hardcode_minus_L=yes
;;
esac
;;
bsdi[45]*)
;;
cygwin* | mingw* | pw32* | cegcc*)
# When not using gcc, we currently assume that we are using
# Microsoft Visual C++.
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
hardcode_libdir_flag_spec=' '
libext=lib
;;
darwin* | rhapsody*)
hardcode_direct=no
if { case $cc_basename in ifort*) true;; *) test "$GCC" = yes;; esac; }; then
:
else
ld_shlibs=no
fi
;;
dgux*)
hardcode_libdir_flag_spec='-L$libdir'
;;
freebsd2.[01]*)
hardcode_direct=yes
hardcode_minus_L=yes
;;
freebsd* | dragonfly*)
hardcode_libdir_flag_spec='-R$libdir'
hardcode_direct=yes
;;
hpux9*)
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
hardcode_libdir_separator=:
hardcode_direct=yes
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
hardcode_minus_L=yes
;;
hpux10*)
if test "$with_gnu_ld" = no; then
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
hardcode_libdir_separator=:
hardcode_direct=yes
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
hardcode_minus_L=yes
fi
;;
hpux11*)
if test "$with_gnu_ld" = no; then
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
hardcode_libdir_separator=:
case $host_cpu in
hppa*64*|ia64*)
hardcode_direct=no
;;
*)
hardcode_direct=yes
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
hardcode_minus_L=yes
;;
esac
fi
;;
irix5* | irix6* | nonstopux*)
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
hardcode_libdir_separator=:
;;
netbsd*)
hardcode_libdir_flag_spec='-R$libdir'
hardcode_direct=yes
;;
newsos6)
hardcode_direct=yes
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
hardcode_libdir_separator=:
;;
*nto* | *qnx*)
;;
openbsd*)
if test -f /usr/libexec/ld.so; then
hardcode_direct=yes
if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
else
case "$host_os" in
openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
hardcode_libdir_flag_spec='-R$libdir'
;;
*)
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
;;
esac
fi
else
ld_shlibs=no
fi
;;
os2*)
hardcode_libdir_flag_spec='-L$libdir'
hardcode_minus_L=yes
;;
osf3*)
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
hardcode_libdir_separator=:
;;
osf4* | osf5*)
if test "$GCC" = yes; then
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
else
# Both cc and cxx compiler support -rpath directly
hardcode_libdir_flag_spec='-rpath $libdir'
fi
hardcode_libdir_separator=:
;;
solaris*)
hardcode_libdir_flag_spec='-R$libdir'
;;
sunos4*)
hardcode_libdir_flag_spec='-L$libdir'
hardcode_direct=yes
hardcode_minus_L=yes
;;
sysv4)
case $host_vendor in
sni)
hardcode_direct=yes # is this really true???
;;
siemens)
hardcode_direct=no
;;
motorola)
hardcode_direct=no #Motorola manual says yes, but my tests say they lie
;;
esac
;;
sysv4.3*)
;;
sysv4*MP*)
if test -d /usr/nec; then
ld_shlibs=yes
fi
;;
sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
;;
sysv5* | sco3.2v5* | sco5v6*)
hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
hardcode_libdir_separator=':'
;;
uts4*)
hardcode_libdir_flag_spec='-L$libdir'
;;
*)
ld_shlibs=no
;;
esac
fi
# Check dynamic linker characteristics
# Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER.
# Unlike libtool.m4, here we don't care about _all_ names of the library, but
# only about the one the linker finds when passed -lNAME. This is the last
# element of library_names_spec in libtool.m4, or possibly two of them if the
# linker has special search rules.
library_names_spec= # the last element of library_names_spec in libtool.m4
libname_spec='lib$name'
case "$host_os" in
aix3*)
library_names_spec='$libname.a'
;;
aix[4-9]*)
library_names_spec='$libname$shrext'
;;
amigaos*)
case "$host_cpu" in
powerpc*)
library_names_spec='$libname$shrext' ;;
m68k)
library_names_spec='$libname.a' ;;
esac
;;
beos*)
library_names_spec='$libname$shrext'
;;
bsdi[45]*)
library_names_spec='$libname$shrext'
;;
cygwin* | mingw* | pw32* | cegcc*)
shrext=.dll
library_names_spec='$libname.dll.a $libname.lib'
;;
darwin* | rhapsody*)
shrext=.dylib
library_names_spec='$libname$shrext'
;;
dgux*)
library_names_spec='$libname$shrext'
;;
freebsd[23].*)
library_names_spec='$libname$shrext$versuffix'
;;
freebsd* | dragonfly*)
library_names_spec='$libname$shrext'
;;
gnu*)
library_names_spec='$libname$shrext'
;;
haiku*)
library_names_spec='$libname$shrext'
;;
hpux9* | hpux10* | hpux11*)
case $host_cpu in
ia64*)
shrext=.so
;;
hppa*64*)
shrext=.sl
;;
*)
shrext=.sl
;;
esac
library_names_spec='$libname$shrext'
;;
interix[3-9]*)
library_names_spec='$libname$shrext'
;;
irix5* | irix6* | nonstopux*)
library_names_spec='$libname$shrext'
case "$host_os" in
irix5* | nonstopux*)
libsuff= shlibsuff=
;;
*)
case $LD in
*-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;;
*-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;;
*-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;;
*) libsuff= shlibsuff= ;;
esac
;;
esac
;;
linux*oldld* | linux*aout* | linux*coff*)
;;
linux* | k*bsd*-gnu | kopensolaris*-gnu)
library_names_spec='$libname$shrext'
;;
knetbsd*-gnu)
library_names_spec='$libname$shrext'
;;
netbsd*)
library_names_spec='$libname$shrext'
;;
newsos6)
library_names_spec='$libname$shrext'
;;
*nto* | *qnx*)
library_names_spec='$libname$shrext'
;;
openbsd*)
library_names_spec='$libname$shrext$versuffix'
;;
os2*)
libname_spec='$name'
shrext=.dll
library_names_spec='$libname.a'
;;
osf3* | osf4* | osf5*)
library_names_spec='$libname$shrext'
;;
rdos*)
;;
solaris*)
library_names_spec='$libname$shrext'
;;
sunos4*)
library_names_spec='$libname$shrext$versuffix'
;;
sysv4 | sysv4.3*)
library_names_spec='$libname$shrext'
;;
sysv4*MP*)
library_names_spec='$libname$shrext'
;;
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
library_names_spec='$libname$shrext'
;;
tpf*)
library_names_spec='$libname$shrext'
;;
uts4*)
library_names_spec='$libname$shrext'
;;
esac
sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
shlibext=`echo "$shrext" | sed -e 's,^\.,,'`
escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
# How to pass a linker flag through the compiler.
wl="$escaped_wl"
# Static library suffix (normally "a").
libext="$libext"
# Shared library suffix (normally "so").
shlibext="$shlibext"
# Format of library name prefix.
libname_spec="$escaped_libname_spec"
# Library names that the linker finds when passed -lNAME.
library_names_spec="$escaped_library_names_spec"
# Flag to hardcode \$libdir into a binary during linking.
# This must work even if \$libdir does not exist.
hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"
# Whether we need a single -rpath flag with a separated argument.
hardcode_libdir_separator="$hardcode_libdir_separator"
# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
# resulting binary.
hardcode_direct="$hardcode_direct"
# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
# resulting binary.
hardcode_minus_L="$hardcode_minus_L"
EOF

1791
use/config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

791
use/depcomp Executable file
View File

@ -0,0 +1,791 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2013-05-30.07; # UTC
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# 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 2, or (at your option)
# 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 <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by 'PROGRAMS ARGS'.
object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
# Get the directory component of the given path, and save it in the
# global variables '$dir'. Note that this directory component will
# be either empty or ending with a '/' character. This is deliberate.
set_dir_from ()
{
case $1 in
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
*) dir=;;
esac
}
# Get the suffix-stripped basename of the given path, and save it the
# global variable '$base'.
set_base_from ()
{
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
}
# If no dependency file was actually created by the compiler invocation,
# we still have to create a dummy depfile, to avoid errors with the
# Makefile "include basename.Plo" scheme.
make_dummy_depfile ()
{
echo "#dummy" > "$depfile"
}
# Factor out some common post-processing of the generated depfile.
# Requires the auxiliary global variable '$tmpdepfile' to be set.
aix_post_process_depfile ()
{
# If the compiler actually managed to produce a dependency file,
# post-process it.
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependency.h'.
# Do two passes, one to just change these to
# $object: dependency.h
# and one to simply output
# dependency.h:
# which is needed to avoid the deleted-header problem.
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
} > "$depfile"
rm -f "$tmpdepfile"
else
make_dummy_depfile
fi
}
# A tabulation character.
tab=' '
# A newline character.
nl='
'
# Character ranges might be problematic outside the C locale.
# These definitions help.
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lower=abcdefghijklmnopqrstuvwxyz
digits=0123456789
alpha=${upper}${lower}
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Avoid interferences from the environment.
gccflag= dashmflag=
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
## (see the conditional assignment to $gccflag above).
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say). Also, it might not be
## supported by the other compilers which use the 'gcc' depmode.
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The second -e expression handles DOS-style file names with drive
# letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
| tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
xlc)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
aix_post_process_depfile
;;
tcc)
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
# FIXME: That version still under development at the moment of writing.
# Make that this statement remains true also for stable, released
# versions.
# It will wrap lines (doesn't matter whether long or short) with a
# trailing '\', as in:
#
# foo.o : \
# foo.c \
# foo.h \
#
# It will put a trailing '\' even on the last line, and will use leading
# spaces rather than leading tabs (at least since its commit 0394caf7
# "Emit spaces for -MD").
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
# We have to change lines of the first kind to '$object: \'.
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
# And for each line of the second kind, we have to emit a 'dep.h:'
# dummy dependency, to avoid the deleted-header problem.
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
## The order of this option in the case statement is important, since the
## shell code in configure will try each of these formats in the order
## listed in this file. A plain '-MD' option would be understood by many
## compilers, so we must ensure this comes after the gcc and icc options.
pgcc)
# Portland's C compiler understands '-MD'.
# Will always output deps to 'file.d' where file is the root name of the
# source file under compilation, even if file resides in a subdirectory.
# The object file name does not affect the name of the '.d' file.
# pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
set_dir_from "$object"
# Use the source, not the object, to determine the base name, since
# that's sadly what pgcc will do too.
set_base_from "$source"
tmpdepfile=$base.d
# For projects that build the same source file twice into different object
# files, the pgcc approach of using the *source* file root name can cause
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
trap "
echo '$0: caught signal, cleaning up...' >&2
rmdir '$lockdir'
exit 1
" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
# mkdir is a portable test-and-set.
if mkdir "$lockdir" 2>/dev/null; then
# This process acquired the lock.
"$@" -MD
stat=$?
# Release the lock.
rmdir "$lockdir"
break
else
# If the lock is being held by a different process, wait
# until the winning process is done or we timeout.
while test -d "$lockdir" && test $i -gt 0; do
sleep 1
i=`expr $i - 1`
done
fi
i=`expr $i - 1`
done
trap - 1 2 13 15
if test $i -le 0; then
echo "$0: failed to acquire lock after $numtries attempts" >&2
echo "$0: check lockdir '$lockdir'" >&2
exit 1
fi
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
# Libtool generates 2 separate objects for the 2 libraries. These
# two compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir$base.o.d # libtool 1.5
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
# Same post-processing that is required for AIX mode.
aix_post_process_depfile
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
msvc7msys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this sed invocation
# correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process the last invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed '1,2d' "$tmpdepfile" \
| tr ' ' "$nl" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E \
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
| sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

527
use/install-sh Executable file
View File

@ -0,0 +1,527 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2011-11-20.07; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
nl='
'
IFS=" "" $nl"
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit=${DOITPROG-}
if test -z "$doit"; then
doit_exec=exec
else
doit_exec=$doit
fi
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_glob='?'
initialize_posix_glob='
test "$posix_glob" != "?" || {
if (set -f) 2>/dev/null; then
posix_glob=
else
posix_glob=:
fi
}
'
posix_mkdir=
# Desired mode of installed file.
mode=0755
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
no_target_directory=
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *' '* | *'
'* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t) dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) no_target_directory=true;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test -n "$no_target_directory"; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
# Prefer dirname, but fall back on a substitute if dirname fails.
dstdir=`
(dirname "$dst") 2>/dev/null ||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$dst" : 'X\(//\)[^/]' \| \
X"$dst" : 'X\(//\)$' \| \
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
echo X"$dst" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'
`
test -d "$dstdir"
dstdir_status=$?
fi
fi
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
eval "$initialize_posix_glob"
oIFS=$IFS
IFS=/
$posix_glob set -f
set fnord $dstdir
shift
$posix_glob set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
eval "$initialize_posix_glob" &&
$posix_glob set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
$posix_glob set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

11156
use/ltmain.sh Normal file

File diff suppressed because it is too large Load Diff

215
use/missing Executable file
View File

@ -0,0 +1,215 @@
#! /bin/sh
# Common wrapper for a few potentially missing GNU programs.
scriptversion=2013-10-28.13; # UTC
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# 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 2, or (at your option)
# 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 <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
case $1 in
--is-lightweight)
# Used by our autoconf macros to check whether the available missing
# script is modern enough.
exit 0
;;
--run)
# Back-compat with the calling convention used by older automake.
shift
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
to PROGRAM being missing or too old.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal autoconf autoheader autom4te automake makeinfo
bison yacc flex lex help2man
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
'g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: unknown '$1' option"
echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
# Run the given program, remember its exit status.
"$@"; st=$?
# If it succeeded, we are done.
test $st -eq 0 && exit 0
# Also exit now if we it failed (or wasn't found), and '--version' was
# passed; such an option is passed most likely to detect whether the
# program is present and works.
case $2 in --version|--help) exit $st;; esac
# Exit code 63 means version mismatch. This often happens when the user
# tries to use an ancient version of a tool on a file that requires a
# minimum version.
if test $st -eq 63; then
msg="probably too old"
elif test $st -eq 127; then
# Program was missing.
msg="missing on your system"
else
# Program was found and executed, but failed. Give up.
exit $st
fi
perl_URL=http://www.perl.org/
flex_URL=http://flex.sourceforge.net/
gnu_software_URL=http://www.gnu.org/software
program_details ()
{
case $1 in
aclocal|automake)
echo "The '$1' program is part of the GNU Automake package:"
echo "<$gnu_software_URL/automake>"
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/autoconf>"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
autoconf|autom4te|autoheader)
echo "The '$1' program is part of the GNU Autoconf package:"
echo "<$gnu_software_URL/autoconf/>"
echo "It also requires GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
esac
}
give_advice ()
{
# Normalize program name to check for.
normalized_program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
printf '%s\n' "'$1' is $msg."
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
case $normalized_program in
autoconf*)
echo "You should only need it if you modified 'configure.ac',"
echo "or m4 files included by it."
program_details 'autoconf'
;;
autoheader*)
echo "You should only need it if you modified 'acconfig.h' or"
echo "$configure_deps."
program_details 'autoheader'
;;
automake*)
echo "You should only need it if you modified 'Makefile.am' or"
echo "$configure_deps."
program_details 'automake'
;;
aclocal*)
echo "You should only need it if you modified 'acinclude.m4' or"
echo "$configure_deps."
program_details 'aclocal'
;;
autom4te*)
echo "You might have modified some maintainer files that require"
echo "the 'autom4te' program to be rebuilt."
program_details 'autom4te'
;;
bison*|yacc*)
echo "You should only need it if you modified a '.y' file."
echo "You may want to install the GNU Bison package:"
echo "<$gnu_software_URL/bison/>"
;;
lex*|flex*)
echo "You should only need it if you modified a '.l' file."
echo "You may want to install the Fast Lexical Analyzer package:"
echo "<$flex_URL>"
;;
help2man*)
echo "You should only need it if you modified a dependency" \
"of a man page."
echo "You may want to install the GNU Help2man package:"
echo "<$gnu_software_URL/help2man/>"
;;
makeinfo*)
echo "You should only need it if you modified a '.texi' file, or"
echo "any other file indirectly affecting the aspect of the manual."
echo "You might want to install the Texinfo package:"
echo "<$gnu_software_URL/texinfo/>"
echo "The spurious makeinfo call might also be the consequence of"
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
echo "want to install GNU make:"
echo "<$gnu_software_URL/make/>"
;;
*)
echo "You might have modified some files without having the proper"
echo "tools for further handling them. Check the 'README' file, it"
echo "often tells you about the needed prerequisites for installing"
echo "this package. You may also peek at any GNU archive site, in"
echo "case some other package contains this missing '$1' program."
;;
esac
}
give_advice "$1" | sed -e '1s/^/WARNING: /' \
-e '2,$s/^/ /' >&2
# Propagate the correct exit status (expected to be 127 for a program
# not found, 63 for a program that failed due to version mismatch).
exit $st
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

148
use/test-driver Executable file
View File

@ -0,0 +1,148 @@
#! /bin/sh
# test-driver - basic testsuite driver script.
scriptversion=2013-07-13.22; # UTC
# Copyright (C) 2011-2014 Free Software Foundation, Inc.
#
# 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 2, or (at your option)
# 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 <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
# Make unconditional expansion of undefined variables an error. This
# helps a lot in preventing typo-related bugs.
set -u
usage_error ()
{
echo "$0: $*" >&2
print_usage >&2
exit 2
}
print_usage ()
{
cat <<END
Usage:
test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
[--expect-failure={yes|no}] [--color-tests={yes|no}]
[--enable-hard-errors={yes|no}] [--]
TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
The '--test-name', '--log-file' and '--trs-file' options are mandatory.
END
}
test_name= # Used for reporting.
log_file= # Where to save the output of the test script.
trs_file= # Where to save the metadata of the test run.
expect_failure=no
color_tests=no
enable_hard_errors=yes
while test $# -gt 0; do
case $1 in
--help) print_usage; exit $?;;
--version) echo "test-driver $scriptversion"; exit $?;;
--test-name) test_name=$2; shift;;
--log-file) log_file=$2; shift;;
--trs-file) trs_file=$2; shift;;
--color-tests) color_tests=$2; shift;;
--expect-failure) expect_failure=$2; shift;;
--enable-hard-errors) enable_hard_errors=$2; shift;;
--) shift; break;;
-*) usage_error "invalid option: '$1'";;
*) break;;
esac
shift
done
missing_opts=
test x"$test_name" = x && missing_opts="$missing_opts --test-name"
test x"$log_file" = x && missing_opts="$missing_opts --log-file"
test x"$trs_file" = x && missing_opts="$missing_opts --trs-file"
if test x"$missing_opts" != x; then
usage_error "the following mandatory options are missing:$missing_opts"
fi
if test $# -eq 0; then
usage_error "missing argument"
fi
if test $color_tests = yes; then
# Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
red='' # Red.
grn='' # Green.
lgn='' # Light green.
blu='' # Blue.
mgn='' # Magenta.
std='' # No color.
else
red= grn= lgn= blu= mgn= std=
fi
do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
trap "st=129; $do_exit" 1
trap "st=130; $do_exit" 2
trap "st=141; $do_exit" 13
trap "st=143; $do_exit" 15
# Test script is run here.
"$@" >$log_file 2>&1
estatus=$?
if test $enable_hard_errors = no && test $estatus -eq 99; then
tweaked_estatus=1
else
tweaked_estatus=$estatus
fi
case $tweaked_estatus:$expect_failure in
0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
0:*) col=$grn res=PASS recheck=no gcopy=no;;
77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
*:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
*:*) col=$red res=FAIL recheck=yes gcopy=yes;;
esac
# Report the test outcome and exit status in the logs, so that one can
# know whether the test passed or failed simply by looking at the '.log'
# file, without the need of also peaking into the corresponding '.trs'
# file (automake bug#11814).
echo "$res $test_name (exit status: $estatus)" >>$log_file
# Report outcome to console.
echo "${col}${res}${std}: $test_name"
# Register the test result, and other relevant metadata.
echo ":test-result: $res" > $trs_file
echo ":global-test-result: $res" >> $trs_file
echo ":recheck: $recheck" >> $trs_file
echo ":copy-in-global-log: $gcopy" >> $trs_file
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End: