mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 08:13:04 +04:00
Compare commits
121 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b1459928f5 | |||
| 7db6c31400 | |||
| 391603e2e8 | |||
| a31ad531f0 | |||
| 8bd792d72b | |||
| 4bc4cdb919 | |||
| cd24a3ec45 | |||
| f296e22580 | |||
| 53f67de6a1 | |||
| 14e70599f2 | |||
| 7cc52490ec | |||
| 11a03c89a4 | |||
| b487ba4d63 | |||
| 4adcfc6215 | |||
| 69f55e9a99 | |||
| 2b689f34f7 | |||
| 1dbd9a5547 | |||
| 48a4493dfa | |||
| 785e77086f | |||
| 403b9b36a4 | |||
| 9d2d0404e5 | |||
| 8771046092 | |||
| b4c468836b | |||
| 341f9f9272 | |||
| ac0e7f6e85 | |||
| 6a964b81d4 | |||
| 00ca5812d5 | |||
| 9a2e0b81e9 | |||
| 42da4bd438 | |||
| 9b71f222ee | |||
| 9289b7be7e | |||
| 43b772846b | |||
| a6de4b522b | |||
| 40853a7917 | |||
| 6414e3fcc8 | |||
| 30e393dfa6 | |||
| 05c98f568f | |||
| 36af349ab4 | |||
| 6d810b13be | |||
| 9638448c81 | |||
| 7f38aa60a2 | |||
| e7c62abbd6 | |||
| 04cbb956bf | |||
| da1f141422 | |||
| 37d76471ac | |||
| 9074e79f7d | |||
| 183be05274 | |||
| 284a9b083e | |||
| f8597ceb8b | |||
| 57344608ea | |||
| 0aaea76621 | |||
| c6b7cfc13c | |||
| a2880a547a | |||
| 9ec6d4a467 | |||
| fea2b6e5dd | |||
| c21cf06c5f | |||
| 4bf7000c5c | |||
| 831857994c | |||
| 2835fe88ac | |||
| f7495e5845 | |||
| 0f0573e722 | |||
| f9782b3a06 | |||
| ef392b0553 | |||
| 86ab189b01 | |||
| 83f25a345d | |||
| ea520d1307 | |||
| 1c41a747f7 | |||
| eb0714da28 | |||
| 8003831f93 | |||
| c10fea8368 | |||
| cf7f189fb2 | |||
| 07b07481ec | |||
| e2219b724e | |||
| 0e3af357d3 | |||
| d758cca902 | |||
| ed977a476a | |||
| 8b6fe3b21f | |||
| 0bd3d6d2aa | |||
| 501033db8b | |||
| 84e4f59704 | |||
| c7840ab126 | |||
| 187f628f5b | |||
| f8d23637e5 | |||
| a3da7951dc | |||
| 3692eb6976 | |||
| 04d484c6ce | |||
| 023f48dcf3 | |||
| 62bedd190e | |||
| 270e130d68 | |||
| 3ae78b1b96 | |||
| f7fec3c1b5 | |||
| 168a6c3751 | |||
| beed941949 | |||
| a927b0e7c2 | |||
| 01daea8227 | |||
| 333371dd8c | |||
| c4bca84bc9 | |||
| 3fa4c8f091 | |||
| fc02f7ff4a | |||
| 9f6cbb507e | |||
| 784e12cc2d | |||
| 19b383b141 | |||
| 79626f0883 | |||
| b60a277e4e | |||
| 0d58749f2e | |||
| 85606acad7 | |||
| 5d3306da85 | |||
| a5b90e3127 | |||
| e5b1454368 | |||
| 65291b6095 | |||
| 6aa396936e | |||
| 8c2246bdc8 | |||
| f6bc96c4fb | |||
| 121b8d2319 | |||
| a5d656f31a | |||
| 9cff09d37e | |||
| cb9681174d | |||
| a971e06177 | |||
| 9a7d86d939 | |||
| 4fa1c641eb | |||
| e5f7a0c65f |
@@ -1,84 +0,0 @@
|
|||||||
* text=auto whitespace=trailing-space,space-before-tab,-indent-with-non-tab,tab-in-indent,tabwidth=4
|
|
||||||
|
|
||||||
.git* text export-ignore
|
|
||||||
|
|
||||||
*.aidl text
|
|
||||||
*.appxmanifest text
|
|
||||||
*.bib text
|
|
||||||
*.c text
|
|
||||||
*.cl text
|
|
||||||
*.conf text
|
|
||||||
*.cpp text
|
|
||||||
*.css_t text
|
|
||||||
*.cu text
|
|
||||||
*.cxx text
|
|
||||||
*.def text
|
|
||||||
*.filelist text
|
|
||||||
*.h text
|
|
||||||
*.hpp text
|
|
||||||
*.htm text
|
|
||||||
*.html text
|
|
||||||
*.hxx text
|
|
||||||
*.i text
|
|
||||||
*.idl text
|
|
||||||
*.java text
|
|
||||||
*.js text
|
|
||||||
*.m text
|
|
||||||
*.mk text
|
|
||||||
*.mm text
|
|
||||||
*.plist text
|
|
||||||
*.properties text
|
|
||||||
*.py text
|
|
||||||
*.qrc text
|
|
||||||
*.qss text
|
|
||||||
*.S text
|
|
||||||
*.sbt text
|
|
||||||
*.scala text
|
|
||||||
*.sty text
|
|
||||||
*.tex text
|
|
||||||
*.txt text
|
|
||||||
*.xaml text
|
|
||||||
|
|
||||||
# reST underlines/overlines can look like conflict markers
|
|
||||||
*.rst text conflict-marker-size=80
|
|
||||||
|
|
||||||
*.cmake text whitespace=tabwidth=2
|
|
||||||
*.cmakein text whitespace=tabwidth=2
|
|
||||||
*.in text whitespace=tabwidth=2
|
|
||||||
CMakeLists.txt text whitespace=tabwidth=2
|
|
||||||
|
|
||||||
*.avi binary
|
|
||||||
*.bmp binary
|
|
||||||
*.exr binary
|
|
||||||
*.ico binary
|
|
||||||
*.jpeg binary
|
|
||||||
*.jpg binary
|
|
||||||
*.png binary
|
|
||||||
|
|
||||||
*.a binary
|
|
||||||
*.so binary
|
|
||||||
*.dll binary
|
|
||||||
*.jar binary
|
|
||||||
|
|
||||||
*.pdf binary
|
|
||||||
*.pbxproj binary
|
|
||||||
*.vec binary
|
|
||||||
*.doc binary
|
|
||||||
*.dia binary
|
|
||||||
|
|
||||||
*.xml -text whitespace=cr-at-eol
|
|
||||||
*.yml -text whitespace=cr-at-eol
|
|
||||||
.project -text whitespace=cr-at-eol merge=union
|
|
||||||
.classpath -text whitespace=cr-at-eol merge=union
|
|
||||||
.cproject -text whitespace=cr-at-eol merge=union
|
|
||||||
org.eclipse.jdt.core.prefs -text whitespace=cr-at-eol merge=union
|
|
||||||
|
|
||||||
*.bat text eol=crlf
|
|
||||||
*.cmd text eol=crlf
|
|
||||||
*.cmd.tmpl text eol=crlf
|
|
||||||
*.dsp text eol=crlf -whitespace
|
|
||||||
*.sln text eol=crlf -whitespace
|
|
||||||
*.vcproj text eol=crlf -whitespace merge=union
|
|
||||||
*.vcxproj text eol=crlf -whitespace merge=union
|
|
||||||
|
|
||||||
*.sh text eol=lf
|
|
||||||
-25
@@ -1,25 +0,0 @@
|
|||||||
*.autosave
|
|
||||||
*.pyc
|
|
||||||
*.user
|
|
||||||
*~
|
|
||||||
.*.swp
|
|
||||||
.DS_Store
|
|
||||||
.sw[a-z]
|
|
||||||
Thumbs.db
|
|
||||||
tags
|
|
||||||
tegra/
|
|
||||||
bin/
|
|
||||||
*.sdf
|
|
||||||
*.opensdf
|
|
||||||
*.obj
|
|
||||||
*.stamp
|
|
||||||
*.depend
|
|
||||||
*.rule
|
|
||||||
*.tmp
|
|
||||||
*/debug
|
|
||||||
*/CMakeFiles
|
|
||||||
CMakeCache.txt
|
|
||||||
*.suo
|
|
||||||
*.log
|
|
||||||
*.tlog
|
|
||||||
build
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
[tgit]
|
|
||||||
icon = doc/opencv.ico
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
* -whitespace
|
|
||||||
Vendored
+18
@@ -0,0 +1,18 @@
|
|||||||
|
if(NOT ZLIB_FOUND)
|
||||||
|
add_subdirectory(zlib)
|
||||||
|
endif()
|
||||||
|
if(WITH_JASPER AND NOT JASPER_FOUND)
|
||||||
|
add_subdirectory(libjasper)
|
||||||
|
endif()
|
||||||
|
if(WITH_JPEG AND NOT JPEG_FOUND)
|
||||||
|
add_subdirectory(libjpeg)
|
||||||
|
endif()
|
||||||
|
if(WITH_PNG AND NOT PNG_FOUND)
|
||||||
|
add_subdirectory(libpng)
|
||||||
|
endif()
|
||||||
|
if(WITH_TIFF AND NOT TIFF_FOUND)
|
||||||
|
add_subdirectory(libtiff)
|
||||||
|
endif()
|
||||||
|
if(WIN32)
|
||||||
|
add_subdirectory(ffmpeg)
|
||||||
|
endif()
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
downloads/
|
|
||||||
*.dll
|
|
||||||
ffmpeg_version.cmake
|
|
||||||
Vendored
+20
@@ -0,0 +1,20 @@
|
|||||||
|
project(opencv_ffmpeg)
|
||||||
|
|
||||||
|
if(MSVC64 OR MINGW64)
|
||||||
|
set(FFMPEG_SUFFIX _64)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(module_bare_name "opencv_ffmpeg${FFMPEG_SUFFIX}.dll")
|
||||||
|
set(module_name "${CMAKE_CURRENT_SOURCE_DIR}/${module_bare_name}")
|
||||||
|
|
||||||
|
get_target_property(bin_dir opencv_traincascade LOCATION)
|
||||||
|
get_filename_component(bin_dir ${bin_dir} PATH)
|
||||||
|
|
||||||
|
message(STATUS "ffmpeg output dir: ${bin_dir}")
|
||||||
|
|
||||||
|
add_custom_target(opencv_ffmpeg ALL
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
|
${module_name} ${bin_dir}/${module_bare_name}
|
||||||
|
COMMENT "Copying ${module_name} to the output directory")
|
||||||
|
|
||||||
|
install(FILES ${module_name} DESTINATION bin COMPONENT main)
|
||||||
Vendored
-25
@@ -1,25 +0,0 @@
|
|||||||
# Binary branch name: ffmpeg/master_20150703
|
|
||||||
# Binaries were created for OpenCV: e379ea6ed60b0caad4d4e3eea096e9d850cb8c86
|
|
||||||
set(FFMPEG_BINARIES_COMMIT "8aeefc4efe3215de89d8c7e114ae6f7a6091b8eb")
|
|
||||||
set(FFMPEG_FILE_HASH_BIN32 "89c783eee1c47bfc733f08334ec2e31c")
|
|
||||||
set(FFMPEG_FILE_HASH_BIN64 "35fe6ccdda6d7a04e9056b0d73b98e76")
|
|
||||||
set(FFMPEG_FILE_HASH_CMAKE "8606f947a780071f8fcce8cbf39ceef5")
|
|
||||||
|
|
||||||
set(FFMPEG_DOWNLOAD_URL ${OPENCV_FFMPEG_URL};$ENV{OPENCV_FFMPEG_URL};https://raw.githubusercontent.com/Itseez/opencv_3rdparty/${FFMPEG_BINARIES_COMMIT}/ffmpeg/)
|
|
||||||
|
|
||||||
ocv_download(PACKAGE opencv_ffmpeg.dll
|
|
||||||
HASH ${FFMPEG_FILE_HASH_BIN32}
|
|
||||||
URL ${FFMPEG_DOWNLOAD_URL}
|
|
||||||
DESTINATION_DIR ${CMAKE_CURRENT_LIST_DIR})
|
|
||||||
|
|
||||||
ocv_download(PACKAGE opencv_ffmpeg_64.dll
|
|
||||||
HASH ${FFMPEG_FILE_HASH_BIN64}
|
|
||||||
URL ${FFMPEG_DOWNLOAD_URL}
|
|
||||||
DESTINATION_DIR ${CMAKE_CURRENT_LIST_DIR})
|
|
||||||
|
|
||||||
ocv_download(PACKAGE ffmpeg_version.cmake
|
|
||||||
HASH ${FFMPEG_FILE_HASH_CMAKE}
|
|
||||||
URL ${FFMPEG_DOWNLOAD_URL}
|
|
||||||
DESTINATION_DIR ${CMAKE_CURRENT_LIST_DIR})
|
|
||||||
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/ffmpeg_version.cmake)
|
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
#include "cap_ffmpeg_impl.hpp"
|
||||||
Vendored
-520
@@ -1,520 +0,0 @@
|
|||||||
Copyright (C) 2001 Fabrice Bellard
|
|
||||||
|
|
||||||
FFmpeg 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.
|
|
||||||
|
|
||||||
FFmpeg 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 FFmpeg; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
==================================================================================
|
|
||||||
|
|
||||||
GNU LESSER GENERAL PUBLIC LICENSE
|
|
||||||
Version 2.1, February 1999
|
|
||||||
|
|
||||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
|
||||||
51 Franklin Street, 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 Street, 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!
|
|
||||||
Vendored
+2
@@ -0,0 +1,2 @@
|
|||||||
|
gcc -Wall -shared -o opencv_ffmpeg.dll -O2 -x c++ -I../include -I../include/ffmpeg_ -I../../modules/highgui/src ffopencv.c -L../lib -lavformat -lavcodec -lavdevice -lswscale -lavutil -lwsock32
|
||||||
|
set path=c:\apps\mingw64\bin;%path% & gcc -Wall -shared -o opencv_ffmpeg_64.dll -O2 -x c++ -I../include -I../include/ffmpeg_ -I../../modules/highgui/src ffopencv.c -L../lib -lavformat64 -lavcodec64 -lavdevice64 -lswscale64 -lavutil64 -lavcore64 -lwsock32
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
+7
-36
@@ -1,38 +1,9 @@
|
|||||||
* On Linux and other Unix flavors OpenCV uses default or user-built ffmpeg/libav libraries.
|
The build script is to be fixed.
|
||||||
If user builds ffmpeg/libav from source and wants OpenCV to stay BSD library, not GPL/LGPL,
|
Right now it assumes that 32-bit MinGW is in the system path and
|
||||||
he/she should use --enabled-shared configure flag and make sure that no GPL components are
|
64-bit mingw is installed to c:\Apps\MinGW64.
|
||||||
enabled (some notable examples are x264 (H264 encoder) and libac3 (Dolby AC3 audio codec)).
|
|
||||||
See https://www.ffmpeg.org/legal.html for details.
|
|
||||||
|
|
||||||
If you want to play very safe and do not want to use FFMPEG at all, regardless of whether it's installed on
|
It is important that gcc is used, not g++!
|
||||||
your system or not, configure and build OpenCV using CMake with WITH_FFMPEG=OFF flag. OpenCV will then use
|
Otherwise the produced DLL will likely be dependent on libgcc_s_dw2-1.dll or similar DLL.
|
||||||
AVFoundation (OSX), GStreamer (Linux) or other available backends supported by opencv_videoio module.
|
While we want to make the DLLs with minimum dependencies: Win32 libraries + msvcrt.dll.
|
||||||
|
|
||||||
There is also our self-contained motion jpeg codec, which you can use without any worries.
|
ffopencv.c is really a C++ source, hence -x c++ is used.
|
||||||
It handles CV_FOURCC('M', 'J', 'P', 'G') streams within an AVI container (".avi").
|
|
||||||
|
|
||||||
* On Windows OpenCV uses pre-built ffmpeg binaries, built with proper flags (without GPL components) and
|
|
||||||
wrapped with simple, stable OpenCV-compatible API.
|
|
||||||
The binaries are opencv_ffmpeg.dll (version for 32-bit Windows) and
|
|
||||||
opencv_ffmpeg_64.dll (version for 64-bit Windows).
|
|
||||||
|
|
||||||
See build_win32.txt for the build instructions, if you want to rebuild opencv_ffmpeg*.dll from scratch.
|
|
||||||
|
|
||||||
The pre-built opencv_ffmpeg*.dll is:
|
|
||||||
* LGPL library, not BSD libraries.
|
|
||||||
* Loaded at runtime by opencv_videoio module.
|
|
||||||
If it succeeds, ffmpeg can be used to decode/encode videos;
|
|
||||||
otherwise, other API is used.
|
|
||||||
|
|
||||||
FFMPEG build contains H264 encoder based on the OpenH264 library, that should be installed separatelly.
|
|
||||||
OpenH264 Video Codec provided by Cisco Systems, Inc.
|
|
||||||
See https://github.com/cisco/openh264/releases for details and OpenH264 license.
|
|
||||||
Downloaded binary file can be placed into global system path (System32 or SysWOW64) or near application binaries.
|
|
||||||
You can also specify location of binary file via OPENH264_LIBRARY_PATH environment variable.
|
|
||||||
|
|
||||||
If LGPL/GPL software can not be supplied with your OpenCV-based product, simply exclude
|
|
||||||
opencv_ffmpeg*.dll from your distribution; OpenCV will stay fully functional except for the ability to
|
|
||||||
decode/encode videos using FFMPEG (though, it may still be able to do that using other API,
|
|
||||||
such as Video for Windows, Windows Media Foundation or our self-contained motion jpeg codec).
|
|
||||||
|
|
||||||
See license.txt for the FFMPEG copyright notice and the licensing terms.
|
|
||||||
|
|||||||
Vendored
+34
@@ -0,0 +1,34 @@
|
|||||||
|
Copyright (c) 2004, Industrial Light & Magic, a division of Lucasfilm
|
||||||
|
Entertainment Company Ltd. Portions contributed and copyright held by
|
||||||
|
others as indicated. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided with
|
||||||
|
the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Industrial Light & Magic nor the names of
|
||||||
|
any other contributors to this software may be used to endorse or
|
||||||
|
promote products derived from this software without specific prior
|
||||||
|
written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
Vendored
+123
@@ -0,0 +1,123 @@
|
|||||||
|
ABOUT THE OPENEXR LIBRARIES
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Half is a class that encapsulates our 16-bit floating-point format.
|
||||||
|
|
||||||
|
IlmThread is a thread abstraction library for use with IlmImf. It
|
||||||
|
currently supports pthreads and Windows threads.
|
||||||
|
|
||||||
|
IlmImf is our "EXR" file format for storing 16-bit FP images.
|
||||||
|
|
||||||
|
Imath is a math library. IlmImf only uses a subset of it,
|
||||||
|
but we're releasing the full library because it's easier for us to
|
||||||
|
maintain, and we think it'll be useful to others.
|
||||||
|
|
||||||
|
Iex is an exception-handling library.
|
||||||
|
|
||||||
|
See the IlmImfExamples directory for some code that demonstrates how
|
||||||
|
to use the IlmImf library to read and write OpenEXR files. The doc
|
||||||
|
directory contains some high-level documentation and history about the
|
||||||
|
OpenEXR format.
|
||||||
|
|
||||||
|
If you have questions about using the OpenEXR libraries, you may want
|
||||||
|
to join our developer mailing list. See http://www.openexr.com for
|
||||||
|
details.
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE
|
||||||
|
-------
|
||||||
|
|
||||||
|
The OpenEXR source code distribution is free software. See the file
|
||||||
|
named COPYING (included in this distribution) for details.
|
||||||
|
|
||||||
|
|
||||||
|
WHAT'S INCLUDED
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Besides the core OpenEXR libraries, the release includes several
|
||||||
|
utilities for reading, writing, viewing, and manipulating OpenEXR
|
||||||
|
images. These include:
|
||||||
|
|
||||||
|
* exrdisplay, an image viewer.
|
||||||
|
* exrheader, a utility for dumping header information.
|
||||||
|
* exrstdattr, a utility for modifying OpenEXR standard attributes.
|
||||||
|
* exrmaketiled, for generating tiled and rip/mipmapped images.
|
||||||
|
* exrenvmap, for creating OpenEXR environment maps.
|
||||||
|
* exrmakepreview, for creating preview images for OpenEXR files.
|
||||||
|
|
||||||
|
exrdisplay requires FLTK 1.1 or greater and OpenGL. exrdisplay
|
||||||
|
supports fragment shaders if you have the Nvidia Cg SDK and a graphics
|
||||||
|
card capable of running fp30 profile fragment shaders. See
|
||||||
|
exrdisplay/README for details.
|
||||||
|
|
||||||
|
We have also released an OpenEXR display driver for Renderman, a file
|
||||||
|
I/O plugin for Shake, and a file I/O plugin for Adobe Photoshop (on
|
||||||
|
both Windows and MacOS). These are packaged separately. Go to
|
||||||
|
http://www.openexr.com to download them. NOTE: the most recent
|
||||||
|
versions of these applications now have native support for OpenEXR, so
|
||||||
|
you should only use our open-source versions of the plugins if you
|
||||||
|
have an older version of the application.
|
||||||
|
|
||||||
|
|
||||||
|
BUILDING OPENEXR
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Building OpenEXR requires the zlib library. If you want to build the
|
||||||
|
'exrdisplay' image viewer, you'll also need FLTK 1.1, but this program
|
||||||
|
is not required to use OpenEXR's libraries in your application.
|
||||||
|
exrdisplay can also accelerate the display of OpenEXR images if you
|
||||||
|
have the NVIDIA Cg SDK.
|
||||||
|
|
||||||
|
Your OS distribution may already include these libraries, or supply
|
||||||
|
packages for them. That is the preferred way to obtain them for use
|
||||||
|
with OpenEXR. If not, you can obtain the source code for zlib and
|
||||||
|
FLTK from:
|
||||||
|
|
||||||
|
http://www.zlib.net
|
||||||
|
http://www.fltk.org
|
||||||
|
|
||||||
|
and you can download the NVIDIA Cg SDK from
|
||||||
|
http://developer.nvidia.com.
|
||||||
|
|
||||||
|
If you're building OpenEXR on a Windows platform, see README.win32 for
|
||||||
|
instructions on how to build OpenEXR. The remainder of this file
|
||||||
|
applies only to GNU/Linux or other UNIX-like systems.
|
||||||
|
|
||||||
|
After installing the required libraries, to build OpenEXR on
|
||||||
|
GNU/Linux or other UNIX-like systems, do this:
|
||||||
|
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
|
||||||
|
unless you obtained OpenEXR directly from CVS, in which case you
|
||||||
|
should first read README.CVS.
|
||||||
|
|
||||||
|
If you have the Nvidia Cg SDK and you want to build support for
|
||||||
|
fragment shaders into exrdisplay, specify the path to the SDK using
|
||||||
|
the "--with-cg-prefix" flag. There are some additional compile-time
|
||||||
|
configuration options available; type `./configure --help` for more
|
||||||
|
information.
|
||||||
|
|
||||||
|
See README.OSX for details on building OpenEXR in MacOS X.
|
||||||
|
|
||||||
|
Do `make check` to run the OpenEXR confidence tests. They should all
|
||||||
|
pass; if you find a test that does not pass on your system, please let
|
||||||
|
us know.
|
||||||
|
|
||||||
|
Other UNIX variants haven't been tested, but should be easy to build.
|
||||||
|
Let us know if you're having problems porting OpenEXR to a particular
|
||||||
|
platform.
|
||||||
|
|
||||||
|
All include files needed to use the OpenEXR libraries are installed in the
|
||||||
|
OpenEXR subdirectory of the install prefix, e.g. /usr/local/include/OpenEXR.
|
||||||
|
|
||||||
|
|
||||||
|
USING OPENEXR IN YOUR APPLICATIONS
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
On systems with support for pkg-config, use `pkg-config --cflags
|
||||||
|
OpenEXR` for the C++ flags required to compile against OpenEXR
|
||||||
|
headers; and `pkg-config --libs OpenEXR` for the linker flags required
|
||||||
|
to link against OpenEXR libraries.
|
||||||
|
|
||||||
+3968
File diff suppressed because it is too large
Load Diff
+99
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_AVFFT_H
|
||||||
|
#define AVCODEC_AVFFT_H
|
||||||
|
|
||||||
|
typedef float FFTSample;
|
||||||
|
|
||||||
|
typedef struct FFTComplex {
|
||||||
|
FFTSample re, im;
|
||||||
|
} FFTComplex;
|
||||||
|
|
||||||
|
typedef struct FFTContext FFTContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up a complex FFT.
|
||||||
|
* @param nbits log2 of the length of the input array
|
||||||
|
* @param inverse if 0 perform the forward transform, if 1 perform the inverse
|
||||||
|
*/
|
||||||
|
FFTContext *av_fft_init(int nbits, int inverse);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do the permutation needed BEFORE calling ff_fft_calc().
|
||||||
|
*/
|
||||||
|
void av_fft_permute(FFTContext *s, FFTComplex *z);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do a complex FFT with the parameters defined in av_fft_init(). The
|
||||||
|
* input data must be permuted before. No 1.0/sqrt(n) normalization is done.
|
||||||
|
*/
|
||||||
|
void av_fft_calc(FFTContext *s, FFTComplex *z);
|
||||||
|
|
||||||
|
void av_fft_end(FFTContext *s);
|
||||||
|
|
||||||
|
FFTContext *av_mdct_init(int nbits, int inverse, double scale);
|
||||||
|
void av_imdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input);
|
||||||
|
void av_imdct_half(FFTContext *s, FFTSample *output, const FFTSample *input);
|
||||||
|
void av_mdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input);
|
||||||
|
void av_mdct_end(FFTContext *s);
|
||||||
|
|
||||||
|
/* Real Discrete Fourier Transform */
|
||||||
|
|
||||||
|
enum RDFTransformType {
|
||||||
|
DFT_R2C,
|
||||||
|
IDFT_C2R,
|
||||||
|
IDFT_R2C,
|
||||||
|
DFT_C2R,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct RDFTContext RDFTContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up a real FFT.
|
||||||
|
* @param nbits log2 of the length of the input array
|
||||||
|
* @param trans the type of transform
|
||||||
|
*/
|
||||||
|
RDFTContext *av_rdft_init(int nbits, enum RDFTransformType trans);
|
||||||
|
void av_rdft_calc(RDFTContext *s, FFTSample *data);
|
||||||
|
void av_rdft_end(RDFTContext *s);
|
||||||
|
|
||||||
|
/* Discrete Cosine Transform */
|
||||||
|
|
||||||
|
typedef struct DCTContext DCTContext;
|
||||||
|
|
||||||
|
enum DCTTransformType {
|
||||||
|
DCT_II = 0,
|
||||||
|
DCT_III,
|
||||||
|
DCT_I,
|
||||||
|
DST_I,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up DCT.
|
||||||
|
* @param nbits size of the input array:
|
||||||
|
* (1 << nbits) for DCT-II, DCT-III and DST-I
|
||||||
|
* (1 << nbits) + 1 for DCT-I
|
||||||
|
*
|
||||||
|
* @note the first element of the input of DST-I is ignored
|
||||||
|
*/
|
||||||
|
DCTContext *av_dct_init(int nbits, enum DCTTransformType type);
|
||||||
|
void av_dct_calc(DCTContext *s, FFTSample *data);
|
||||||
|
void av_dct_end (DCTContext *s);
|
||||||
|
|
||||||
|
#endif /* AVCODEC_AVFFT_H */
|
||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* DXVA2 HW acceleration
|
||||||
|
*
|
||||||
|
* copyright (c) 2009 Laurent Aimar
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_DXVA_H
|
||||||
|
#define AVCODEC_DXVA_H
|
||||||
|
|
||||||
|
#include <msc_stdint.h>
|
||||||
|
|
||||||
|
#include <dxva2api.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This structure is used to provides the necessary configurations and data
|
||||||
|
* to the DXVA2 FFmpeg HWAccel implementation.
|
||||||
|
*
|
||||||
|
* The application must make it available as AVCodecContext.hwaccel_context.
|
||||||
|
*/
|
||||||
|
struct dxva_context {
|
||||||
|
/**
|
||||||
|
* DXVA2 decoder object
|
||||||
|
*/
|
||||||
|
IDirectXVideoDecoder *decoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DXVA2 configuration used to create the decoder
|
||||||
|
*/
|
||||||
|
const DXVA2_ConfigPictureDecode *cfg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of surface in the surface array
|
||||||
|
*/
|
||||||
|
unsigned surface_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array of Direct3D surfaces used to create the decoder
|
||||||
|
*/
|
||||||
|
LPDIRECT3DSURFACE9 *surface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bit field configuring the workarounds needed for using the decoder
|
||||||
|
*/
|
||||||
|
uint64_t workaround;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private to the FFmpeg AVHWAccel implementation
|
||||||
|
*/
|
||||||
|
unsigned report_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* AVCODEC_DXVA_H */
|
||||||
+211
@@ -0,0 +1,211 @@
|
|||||||
|
/*
|
||||||
|
* AVOptions
|
||||||
|
* copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_OPT_H
|
||||||
|
#define AVCODEC_OPT_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* AVOptions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libavutil/rational.h"
|
||||||
|
#include "avcodec.h"
|
||||||
|
|
||||||
|
enum AVOptionType{
|
||||||
|
FF_OPT_TYPE_FLAGS,
|
||||||
|
FF_OPT_TYPE_INT,
|
||||||
|
FF_OPT_TYPE_INT64,
|
||||||
|
FF_OPT_TYPE_DOUBLE,
|
||||||
|
FF_OPT_TYPE_FLOAT,
|
||||||
|
FF_OPT_TYPE_STRING,
|
||||||
|
FF_OPT_TYPE_RATIONAL,
|
||||||
|
FF_OPT_TYPE_BINARY, ///< offset must point to a pointer immediately followed by an int for the length
|
||||||
|
FF_OPT_TYPE_CONST=128,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AVOption
|
||||||
|
*/
|
||||||
|
typedef struct AVOption {
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* short English help text
|
||||||
|
* @todo What about other languages?
|
||||||
|
*/
|
||||||
|
const char *help;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The offset relative to the context structure where the option
|
||||||
|
* value is stored. It should be 0 for named constants.
|
||||||
|
*/
|
||||||
|
int offset;
|
||||||
|
enum AVOptionType type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the default value for scalar options
|
||||||
|
*/
|
||||||
|
double default_val;
|
||||||
|
double min; ///< minimum valid value for the option
|
||||||
|
double max; ///< maximum valid value for the option
|
||||||
|
|
||||||
|
int flags;
|
||||||
|
#define AV_OPT_FLAG_ENCODING_PARAM 1 ///< a generic parameter which can be set by the user for muxing or encoding
|
||||||
|
#define AV_OPT_FLAG_DECODING_PARAM 2 ///< a generic parameter which can be set by the user for demuxing or decoding
|
||||||
|
#define AV_OPT_FLAG_METADATA 4 ///< some data extracted or inserted into the file like title, comment, ...
|
||||||
|
#define AV_OPT_FLAG_AUDIO_PARAM 8
|
||||||
|
#define AV_OPT_FLAG_VIDEO_PARAM 16
|
||||||
|
#define AV_OPT_FLAG_SUBTITLE_PARAM 32
|
||||||
|
//FIXME think about enc-audio, ... style flags
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logical unit to which the option belongs. Non-constant
|
||||||
|
* options and corresponding named constants share the same
|
||||||
|
* unit. May be NULL.
|
||||||
|
*/
|
||||||
|
const char *unit;
|
||||||
|
} AVOption;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AVOption2.
|
||||||
|
* THIS IS NOT PART OF THE API/ABI YET!
|
||||||
|
* This is identical to AVOption except that default_val was replaced by
|
||||||
|
* an union, it should be compatible with AVOption on normal platforms.
|
||||||
|
*/
|
||||||
|
typedef struct AVOption2 {
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* short English help text
|
||||||
|
* @todo What about other languages?
|
||||||
|
*/
|
||||||
|
const char *help;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The offset relative to the context structure where the option
|
||||||
|
* value is stored. It should be 0 for named constants.
|
||||||
|
*/
|
||||||
|
int offset;
|
||||||
|
enum AVOptionType type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the default value for scalar options
|
||||||
|
*/
|
||||||
|
union {
|
||||||
|
double dbl;
|
||||||
|
const char *str;
|
||||||
|
} default_val;
|
||||||
|
|
||||||
|
double min; ///< minimum valid value for the option
|
||||||
|
double max; ///< maximum valid value for the option
|
||||||
|
|
||||||
|
int flags;
|
||||||
|
/*
|
||||||
|
#define AV_OPT_FLAG_ENCODING_PARAM 1 ///< a generic parameter which can be set by the user for muxing or encoding
|
||||||
|
#define AV_OPT_FLAG_DECODING_PARAM 2 ///< a generic parameter which can be set by the user for demuxing or decoding
|
||||||
|
#define AV_OPT_FLAG_METADATA 4 ///< some data extracted or inserted into the file like title, comment, ...
|
||||||
|
#define AV_OPT_FLAG_AUDIO_PARAM 8
|
||||||
|
#define AV_OPT_FLAG_VIDEO_PARAM 16
|
||||||
|
#define AV_OPT_FLAG_SUBTITLE_PARAM 32
|
||||||
|
*/
|
||||||
|
//FIXME think about enc-audio, ... style flags
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logical unit to which the option belongs. Non-constant
|
||||||
|
* options and corresponding named constants share the same
|
||||||
|
* unit. May be NULL.
|
||||||
|
*/
|
||||||
|
const char *unit;
|
||||||
|
} AVOption2;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks for an option in obj. Looks only for the options which
|
||||||
|
* have the flags set as specified in mask and flags (that is,
|
||||||
|
* for which it is the case that opt->flags & mask == flags).
|
||||||
|
*
|
||||||
|
* @param[in] obj a pointer to a struct whose first element is a
|
||||||
|
* pointer to an AVClass
|
||||||
|
* @param[in] name the name of the option to look for
|
||||||
|
* @param[in] unit the unit of the option to look for, or any if NULL
|
||||||
|
* @return a pointer to the option found, or NULL if no option
|
||||||
|
* has been found
|
||||||
|
*/
|
||||||
|
const AVOption *av_find_opt(void *obj, const char *name, const char *unit, int mask, int flags);
|
||||||
|
|
||||||
|
#if LIBAVCODEC_VERSION_MAJOR < 53
|
||||||
|
/**
|
||||||
|
* @see av_set_string2()
|
||||||
|
*/
|
||||||
|
attribute_deprecated const AVOption *av_set_string(void *obj, const char *name, const char *val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a pointer to the AVOption corresponding to the field set or
|
||||||
|
* NULL if no matching AVOption exists, or if the value val is not
|
||||||
|
* valid
|
||||||
|
* @see av_set_string3()
|
||||||
|
*/
|
||||||
|
attribute_deprecated const AVOption *av_set_string2(void *obj, const char *name, const char *val, int alloc);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the field of obj with the given name to value.
|
||||||
|
*
|
||||||
|
* @param[in] obj A struct whose first element is a pointer to an
|
||||||
|
* AVClass.
|
||||||
|
* @param[in] name the name of the field to set
|
||||||
|
* @param[in] val The value to set. If the field is not of a string
|
||||||
|
* type, then the given string is parsed.
|
||||||
|
* SI postfixes and some named scalars are supported.
|
||||||
|
* If the field is of a numeric type, it has to be a numeric or named
|
||||||
|
* scalar. Behavior with more than one scalar and +- infix operators
|
||||||
|
* is undefined.
|
||||||
|
* If the field is of a flags type, it has to be a sequence of numeric
|
||||||
|
* scalars or named flags separated by '+' or '-'. Prefixing a flag
|
||||||
|
* with '+' causes it to be set without affecting the other flags;
|
||||||
|
* similarly, '-' unsets a flag.
|
||||||
|
* @param[out] o_out if non-NULL put here a pointer to the AVOption
|
||||||
|
* found
|
||||||
|
* @param alloc when 1 then the old value will be av_freed() and the
|
||||||
|
* new av_strduped()
|
||||||
|
* when 0 then no av_free() nor av_strdup() will be used
|
||||||
|
* @return 0 if the value has been set, or an AVERROR code in case of
|
||||||
|
* error:
|
||||||
|
* AVERROR(ENOENT) if no matching option exists
|
||||||
|
* AVERROR(ERANGE) if the value is out of range
|
||||||
|
* AVERROR(EINVAL) if the value is not valid
|
||||||
|
*/
|
||||||
|
int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out);
|
||||||
|
|
||||||
|
const AVOption *av_set_double(void *obj, const char *name, double n);
|
||||||
|
const AVOption *av_set_q(void *obj, const char *name, AVRational n);
|
||||||
|
const AVOption *av_set_int(void *obj, const char *name, int64_t n);
|
||||||
|
double av_get_double(void *obj, const char *name, const AVOption **o_out);
|
||||||
|
AVRational av_get_q(void *obj, const char *name, const AVOption **o_out);
|
||||||
|
int64_t av_get_int(void *obj, const char *name, const AVOption **o_out);
|
||||||
|
const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len);
|
||||||
|
const AVOption *av_next_option(void *obj, const AVOption *last);
|
||||||
|
int av_opt_show(void *obj, void *av_log_obj);
|
||||||
|
void av_opt_set_defaults(void *s);
|
||||||
|
void av_opt_set_defaults2(void *s, int mask, int flags);
|
||||||
|
|
||||||
|
#endif /* AVCODEC_OPT_H */
|
||||||
+167
@@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* Video Acceleration API (shared data between FFmpeg and the video player)
|
||||||
|
* HW decode acceleration for MPEG-2, MPEG-4, H.264 and VC-1
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008-2009 Splitted-Desktop Systems
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_VAAPI_H
|
||||||
|
#define AVCODEC_VAAPI_H
|
||||||
|
|
||||||
|
#include <msc_stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup VAAPI_Decoding VA API Decoding
|
||||||
|
* \ingroup Decoder
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This structure is used to share data between the FFmpeg library and
|
||||||
|
* the client video application.
|
||||||
|
* This shall be zero-allocated and available as
|
||||||
|
* AVCodecContext.hwaccel_context. All user members can be set once
|
||||||
|
* during initialization or through each AVCodecContext.get_buffer()
|
||||||
|
* function call. In any case, they must be valid prior to calling
|
||||||
|
* decoding functions.
|
||||||
|
*/
|
||||||
|
struct vaapi_context {
|
||||||
|
/**
|
||||||
|
* Window system dependent data
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by user
|
||||||
|
*/
|
||||||
|
void *display;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration ID
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by user
|
||||||
|
*/
|
||||||
|
uint32_t config_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context ID (video decode pipeline)
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by user
|
||||||
|
*/
|
||||||
|
uint32_t context_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VAPictureParameterBuffer ID
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
uint32_t pic_param_buf_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VAIQMatrixBuffer ID
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
uint32_t iq_matrix_buf_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VABitPlaneBuffer ID (for VC-1 decoding)
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
uint32_t bitplane_buf_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slice parameter/data buffer IDs
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
uint32_t *slice_buf_ids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of effective slice buffer IDs to send to the HW
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
unsigned int n_slice_buf_ids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of pre-allocated slice_buf_ids
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
unsigned int slice_buf_ids_alloc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer to VASliceParameterBuffers
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
void *slice_params;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of a VASliceParameterBuffer element
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
unsigned int slice_param_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of pre-allocated slice_params
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
unsigned int slice_params_alloc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of slices currently filled in
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
unsigned int slice_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer to slice data buffer base
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
const uint8_t *slice_data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current size of slice data
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
uint32_t slice_data_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* @} */
|
||||||
|
|
||||||
|
#endif /* AVCODEC_VAAPI_H */
|
||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* The Video Decode and Presentation API for UNIX (VDPAU) is used for
|
||||||
|
* hardware-accelerated decoding of MPEG-1/2, H.264 and VC-1.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 NVIDIA
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_VDPAU_H
|
||||||
|
#define AVCODEC_VDPAU_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup Decoder VDPAU Decoder and Renderer
|
||||||
|
*
|
||||||
|
* VDPAU hardware acceleration has two modules
|
||||||
|
* - VDPAU decoding
|
||||||
|
* - VDPAU presentation
|
||||||
|
*
|
||||||
|
* The VDPAU decoding module parses all headers using FFmpeg
|
||||||
|
* parsing mechanisms and uses VDPAU for the actual decoding.
|
||||||
|
*
|
||||||
|
* As per the current implementation, the actual decoding
|
||||||
|
* and rendering (API calls) are done as part of the VDPAU
|
||||||
|
* presentation (vo_vdpau.c) module.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
* \defgroup VDPAU_Decoding VDPAU Decoding
|
||||||
|
* \ingroup Decoder
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <vdpau/vdpau.h>
|
||||||
|
#include <vdpau/vdpau_x11.h>
|
||||||
|
|
||||||
|
/** \brief The videoSurface is used for rendering. */
|
||||||
|
#define FF_VDPAU_STATE_USED_FOR_RENDER 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief The videoSurface is needed for reference/prediction.
|
||||||
|
* The codec manipulates this.
|
||||||
|
*/
|
||||||
|
#define FF_VDPAU_STATE_USED_FOR_REFERENCE 2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This structure is used as a callback between the FFmpeg
|
||||||
|
* decoder (vd_) and presentation (vo_) module.
|
||||||
|
* This is used for defining a video frame containing surface,
|
||||||
|
* picture parameter, bitstream information etc which are passed
|
||||||
|
* between the FFmpeg decoder and its clients.
|
||||||
|
*/
|
||||||
|
struct vdpau_render_state {
|
||||||
|
VdpVideoSurface surface; ///< Used as rendered surface, never changed.
|
||||||
|
|
||||||
|
int state; ///< Holds FF_VDPAU_STATE_* values.
|
||||||
|
|
||||||
|
/** picture parameter information for all supported codecs */
|
||||||
|
union VdpPictureInfo {
|
||||||
|
VdpPictureInfoH264 h264;
|
||||||
|
VdpPictureInfoMPEG1Or2 mpeg;
|
||||||
|
VdpPictureInfoVC1 vc1;
|
||||||
|
VdpPictureInfoMPEG4Part2 mpeg4;
|
||||||
|
} info;
|
||||||
|
|
||||||
|
/** Describe size/location of the compressed video data.
|
||||||
|
Set to 0 when freeing bitstream_buffers. */
|
||||||
|
int bitstream_buffers_allocated;
|
||||||
|
int bitstream_buffers_used;
|
||||||
|
/** The user is responsible for freeing this buffer using av_freep(). */
|
||||||
|
VdpBitstreamBuffer *bitstream_buffers;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* @}*/
|
||||||
|
|
||||||
|
#endif /* AVCODEC_VDPAU_H */
|
||||||
+172
@@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2003 Ivan Kalvachev
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_XVMC_H
|
||||||
|
#define AVCODEC_XVMC_H
|
||||||
|
|
||||||
|
#include <X11/extensions/XvMC.h>
|
||||||
|
|
||||||
|
#include "avcodec.h"
|
||||||
|
|
||||||
|
#if LIBAVCODEC_VERSION_MAJOR < 53
|
||||||
|
#define AV_XVMC_STATE_DISPLAY_PENDING 1 /** the surface should be shown, the video driver manipulates this */
|
||||||
|
#define AV_XVMC_STATE_PREDICTION 2 /** the surface is needed for prediction, the codec manipulates this */
|
||||||
|
#define AV_XVMC_STATE_OSD_SOURCE 4 /** the surface is needed for subpicture rendering */
|
||||||
|
#endif
|
||||||
|
#define AV_XVMC_ID 0x1DC711C0 /**< special value to ensure that regular pixel routines haven't corrupted the struct
|
||||||
|
the number is 1337 speak for the letters IDCT MCo (motion compensation) */
|
||||||
|
|
||||||
|
struct xvmc_pix_fmt {
|
||||||
|
/** The field contains the special constant value AV_XVMC_ID.
|
||||||
|
It is used as a test that the application correctly uses the API,
|
||||||
|
and that there is no corruption caused by pixel routines.
|
||||||
|
- application - set during initialization
|
||||||
|
- libavcodec - unchanged
|
||||||
|
*/
|
||||||
|
int xvmc_id;
|
||||||
|
|
||||||
|
/** Pointer to the block array allocated by XvMCCreateBlocks().
|
||||||
|
The array has to be freed by XvMCDestroyBlocks().
|
||||||
|
Each group of 64 values represents one data block of differential
|
||||||
|
pixel information (in MoCo mode) or coefficients for IDCT.
|
||||||
|
- application - set the pointer during initialization
|
||||||
|
- libavcodec - fills coefficients/pixel data into the array
|
||||||
|
*/
|
||||||
|
short* data_blocks;
|
||||||
|
|
||||||
|
/** Pointer to the macroblock description array allocated by
|
||||||
|
XvMCCreateMacroBlocks() and freed by XvMCDestroyMacroBlocks().
|
||||||
|
- application - set the pointer during initialization
|
||||||
|
- libavcodec - fills description data into the array
|
||||||
|
*/
|
||||||
|
XvMCMacroBlock* mv_blocks;
|
||||||
|
|
||||||
|
/** Number of macroblock descriptions that can be stored in the mv_blocks
|
||||||
|
array.
|
||||||
|
- application - set during initialization
|
||||||
|
- libavcodec - unchanged
|
||||||
|
*/
|
||||||
|
int allocated_mv_blocks;
|
||||||
|
|
||||||
|
/** Number of blocks that can be stored at once in the data_blocks array.
|
||||||
|
- application - set during initialization
|
||||||
|
- libavcodec - unchanged
|
||||||
|
*/
|
||||||
|
int allocated_data_blocks;
|
||||||
|
|
||||||
|
/** Indicates that the hardware would interpret data_blocks as IDCT
|
||||||
|
coefficients and perform IDCT on them.
|
||||||
|
- application - set during initialization
|
||||||
|
- libavcodec - unchanged
|
||||||
|
*/
|
||||||
|
int idct;
|
||||||
|
|
||||||
|
/** In MoCo mode it indicates that intra macroblocks are assumed to be in
|
||||||
|
unsigned format; same as the XVMC_INTRA_UNSIGNED flag.
|
||||||
|
- application - set during initialization
|
||||||
|
- libavcodec - unchanged
|
||||||
|
*/
|
||||||
|
int unsigned_intra;
|
||||||
|
|
||||||
|
/** Pointer to the surface allocated by XvMCCreateSurface().
|
||||||
|
It has to be freed by XvMCDestroySurface() on application exit.
|
||||||
|
It identifies the frame and its state on the video hardware.
|
||||||
|
- application - set during initialization
|
||||||
|
- libavcodec - unchanged
|
||||||
|
*/
|
||||||
|
XvMCSurface* p_surface;
|
||||||
|
|
||||||
|
/** Set by the decoder before calling ff_draw_horiz_band(),
|
||||||
|
needed by the XvMCRenderSurface function. */
|
||||||
|
//@{
|
||||||
|
/** Pointer to the surface used as past reference
|
||||||
|
- application - unchanged
|
||||||
|
- libavcodec - set
|
||||||
|
*/
|
||||||
|
XvMCSurface* p_past_surface;
|
||||||
|
|
||||||
|
/** Pointer to the surface used as future reference
|
||||||
|
- application - unchanged
|
||||||
|
- libavcodec - set
|
||||||
|
*/
|
||||||
|
XvMCSurface* p_future_surface;
|
||||||
|
|
||||||
|
/** top/bottom field or frame
|
||||||
|
- application - unchanged
|
||||||
|
- libavcodec - set
|
||||||
|
*/
|
||||||
|
unsigned int picture_structure;
|
||||||
|
|
||||||
|
/** XVMC_SECOND_FIELD - 1st or 2nd field in the sequence
|
||||||
|
- application - unchanged
|
||||||
|
- libavcodec - set
|
||||||
|
*/
|
||||||
|
unsigned int flags;
|
||||||
|
//}@
|
||||||
|
|
||||||
|
/** Number of macroblock descriptions in the mv_blocks array
|
||||||
|
that have already been passed to the hardware.
|
||||||
|
- application - zeroes it on get_buffer().
|
||||||
|
A successful ff_draw_horiz_band() may increment it
|
||||||
|
with filled_mb_block_num or zero both.
|
||||||
|
- libavcodec - unchanged
|
||||||
|
*/
|
||||||
|
int start_mv_blocks_num;
|
||||||
|
|
||||||
|
/** Number of new macroblock descriptions in the mv_blocks array (after
|
||||||
|
start_mv_blocks_num) that are filled by libavcodec and have to be
|
||||||
|
passed to the hardware.
|
||||||
|
- application - zeroes it on get_buffer() or after successful
|
||||||
|
ff_draw_horiz_band().
|
||||||
|
- libavcodec - increment with one of each stored MB
|
||||||
|
*/
|
||||||
|
int filled_mv_blocks_num;
|
||||||
|
|
||||||
|
/** Number of the the next free data block; one data block consists of
|
||||||
|
64 short values in the data_blocks array.
|
||||||
|
All blocks before this one have already been claimed by placing their
|
||||||
|
position into the corresponding block description structure field,
|
||||||
|
that are part of the mv_blocks array.
|
||||||
|
- application - zeroes it on get_buffer().
|
||||||
|
A successful ff_draw_horiz_band() may zero it together
|
||||||
|
with start_mb_blocks_num.
|
||||||
|
- libavcodec - each decoded macroblock increases it by the number
|
||||||
|
of coded blocks it contains.
|
||||||
|
*/
|
||||||
|
int next_free_data_block_num;
|
||||||
|
|
||||||
|
/** extensions may be placed here */
|
||||||
|
#if LIBAVCODEC_VERSION_MAJOR < 53
|
||||||
|
//@{
|
||||||
|
/** State flags used to work around limitations in the MPlayer video system.
|
||||||
|
0 - Surface is not used.
|
||||||
|
1 - Surface is still held in application to be displayed or is
|
||||||
|
still visible.
|
||||||
|
2 - Surface is still held in libavcodec buffer for prediction.
|
||||||
|
*/
|
||||||
|
int state;
|
||||||
|
|
||||||
|
/** pointer to the surface where the subpicture is rendered */
|
||||||
|
void* p_osd_target_surface_render;
|
||||||
|
//}@
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* AVCODEC_XVMC_H */
|
||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVDEVICE_AVDEVICE_H
|
||||||
|
#define AVDEVICE_AVDEVICE_H
|
||||||
|
|
||||||
|
#include "libavutil/avutil.h"
|
||||||
|
|
||||||
|
#define LIBAVDEVICE_VERSION_MAJOR 52
|
||||||
|
#define LIBAVDEVICE_VERSION_MINOR 2
|
||||||
|
#define LIBAVDEVICE_VERSION_MICRO 0
|
||||||
|
|
||||||
|
#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
|
||||||
|
LIBAVDEVICE_VERSION_MINOR, \
|
||||||
|
LIBAVDEVICE_VERSION_MICRO)
|
||||||
|
#define LIBAVDEVICE_VERSION AV_VERSION(LIBAVDEVICE_VERSION_MAJOR, \
|
||||||
|
LIBAVDEVICE_VERSION_MINOR, \
|
||||||
|
LIBAVDEVICE_VERSION_MICRO)
|
||||||
|
#define LIBAVDEVICE_BUILD LIBAVDEVICE_VERSION_INT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the LIBAVDEVICE_VERSION_INT constant.
|
||||||
|
*/
|
||||||
|
unsigned avdevice_version(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the libavdevice build-time configuration.
|
||||||
|
*/
|
||||||
|
const char *avdevice_configuration(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the libavdevice license.
|
||||||
|
*/
|
||||||
|
const char *avdevice_license(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize libavdevice and register all the input and output devices.
|
||||||
|
* @warning This function is not thread safe.
|
||||||
|
*/
|
||||||
|
void avdevice_register_all(void);
|
||||||
|
|
||||||
|
#endif /* AVDEVICE_AVDEVICE_H */
|
||||||
|
|
||||||
+1355
File diff suppressed because it is too large
Load Diff
+525
@@ -0,0 +1,525 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2001 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#ifndef AVFORMAT_AVIO_H
|
||||||
|
#define AVFORMAT_AVIO_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* unbuffered I/O operations
|
||||||
|
*
|
||||||
|
* @warning This file has to be considered an internal but installed
|
||||||
|
* header, so it should not be directly included in your projects.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <msc_stdint.h>
|
||||||
|
|
||||||
|
#include "libavutil/common.h"
|
||||||
|
|
||||||
|
/* unbuffered I/O */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL Context.
|
||||||
|
* New fields can be added to the end with minor version bumps.
|
||||||
|
* Removal, reordering and changes to existing fields require a major
|
||||||
|
* version bump.
|
||||||
|
* sizeof(URLContext) must not be used outside libav*.
|
||||||
|
*/
|
||||||
|
typedef struct URLContext {
|
||||||
|
#if LIBAVFORMAT_VERSION_MAJOR >= 53
|
||||||
|
const AVClass *av_class; ///< information for av_log(). Set by url_open().
|
||||||
|
#endif
|
||||||
|
struct URLProtocol *prot;
|
||||||
|
int flags;
|
||||||
|
int is_streamed; /**< true if streamed (no seek possible), default = false */
|
||||||
|
int max_packet_size; /**< if non zero, the stream is packetized with this max packet size */
|
||||||
|
void *priv_data;
|
||||||
|
char *filename; /**< specified URL */
|
||||||
|
} URLContext;
|
||||||
|
|
||||||
|
typedef struct URLPollEntry {
|
||||||
|
URLContext *handle;
|
||||||
|
int events;
|
||||||
|
int revents;
|
||||||
|
} URLPollEntry;
|
||||||
|
|
||||||
|
#define URL_RDONLY 0
|
||||||
|
#define URL_WRONLY 1
|
||||||
|
#define URL_RDWR 2
|
||||||
|
|
||||||
|
typedef int URLInterruptCB(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an URLContext for accessing to the resource indicated by
|
||||||
|
* url, and opens it using the URLProtocol up.
|
||||||
|
*
|
||||||
|
* @param puc pointer to the location where, in case of success, the
|
||||||
|
* function puts the pointer to the created URLContext
|
||||||
|
* @param flags flags which control how the resource indicated by url
|
||||||
|
* is to be opened
|
||||||
|
* @return 0 in case of success, a negative value corresponding to an
|
||||||
|
* AVERROR code in case of failure
|
||||||
|
*/
|
||||||
|
int url_open_protocol (URLContext **puc, struct URLProtocol *up,
|
||||||
|
const char *url, int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an URLContext for accessing to the resource indicated by
|
||||||
|
* url, and opens it.
|
||||||
|
*
|
||||||
|
* @param puc pointer to the location where, in case of success, the
|
||||||
|
* function puts the pointer to the created URLContext
|
||||||
|
* @param flags flags which control how the resource indicated by url
|
||||||
|
* is to be opened
|
||||||
|
* @return 0 in case of success, a negative value corresponding to an
|
||||||
|
* AVERROR code in case of failure
|
||||||
|
*/
|
||||||
|
int url_open(URLContext **h, const char *url, int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads up to size bytes from the resource accessed by h, and stores
|
||||||
|
* the read bytes in buf.
|
||||||
|
*
|
||||||
|
* @return The number of bytes actually read, or a negative value
|
||||||
|
* corresponding to an AVERROR code in case of error. A value of zero
|
||||||
|
* indicates that it is not possible to read more from the accessed
|
||||||
|
* resource (except if the value of the size argument is also zero).
|
||||||
|
*/
|
||||||
|
int url_read(URLContext *h, unsigned char *buf, int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read as many bytes as possible (up to size), calling the
|
||||||
|
* read function multiple times if necessary.
|
||||||
|
* Will also retry if the read function returns AVERROR(EAGAIN).
|
||||||
|
* This makes special short-read handling in applications
|
||||||
|
* unnecessary, if the return value is < size then it is
|
||||||
|
* certain there was either an error or the end of file was reached.
|
||||||
|
*/
|
||||||
|
int url_read_complete(URLContext *h, unsigned char *buf, int size);
|
||||||
|
int url_write(URLContext *h, unsigned char *buf, int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the position that will be used by the next read/write
|
||||||
|
* operation on the resource accessed by h.
|
||||||
|
*
|
||||||
|
* @param pos specifies the new position to set
|
||||||
|
* @param whence specifies how pos should be interpreted, it must be
|
||||||
|
* one of SEEK_SET (seek from the beginning), SEEK_CUR (seek from the
|
||||||
|
* current position), SEEK_END (seek from the end), or AVSEEK_SIZE
|
||||||
|
* (return the filesize of the requested resource, pos is ignored).
|
||||||
|
* @return a negative value corresponding to an AVERROR code in case
|
||||||
|
* of failure, or the resulting file position, measured in bytes from
|
||||||
|
* the beginning of the file. You can use this feature together with
|
||||||
|
* SEEK_CUR to read the current file position.
|
||||||
|
*/
|
||||||
|
int64_t url_seek(URLContext *h, int64_t pos, int whence);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the resource accessed by the URLContext h, and frees the
|
||||||
|
* memory used by it.
|
||||||
|
*
|
||||||
|
* @return a negative value if an error condition occurred, 0
|
||||||
|
* otherwise
|
||||||
|
*/
|
||||||
|
int url_close(URLContext *h);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a non-zero value if the resource indicated by url
|
||||||
|
* exists, 0 otherwise.
|
||||||
|
*/
|
||||||
|
int url_exist(const char *url);
|
||||||
|
|
||||||
|
int64_t url_filesize(URLContext *h);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the file descriptor associated with this URL. For RTP, this
|
||||||
|
* will return only the RTP file descriptor, not the RTCP file descriptor.
|
||||||
|
* To get both, use rtp_get_file_handles().
|
||||||
|
*
|
||||||
|
* @return the file descriptor associated with this URL, or <0 on error.
|
||||||
|
*/
|
||||||
|
int url_get_file_handle(URLContext *h);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the maximum packet size associated to packetized file
|
||||||
|
* handle. If the file is not packetized (stream like HTTP or file on
|
||||||
|
* disk), then 0 is returned.
|
||||||
|
*
|
||||||
|
* @param h file handle
|
||||||
|
* @return maximum packet size in bytes
|
||||||
|
*/
|
||||||
|
int url_get_max_packet_size(URLContext *h);
|
||||||
|
void url_get_filename(URLContext *h, char *buf, int buf_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The callback is called in blocking functions to test regulary if
|
||||||
|
* asynchronous interruption is needed. AVERROR(EINTR) is returned
|
||||||
|
* in this case by the interrupted function. 'NULL' means no interrupt
|
||||||
|
* callback is given.
|
||||||
|
*/
|
||||||
|
void url_set_interrupt_cb(URLInterruptCB *interrupt_cb);
|
||||||
|
|
||||||
|
/* not implemented */
|
||||||
|
int url_poll(URLPollEntry *poll_table, int n, int timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pause and resume playing - only meaningful if using a network streaming
|
||||||
|
* protocol (e.g. MMS).
|
||||||
|
* @param pause 1 for pause, 0 for resume
|
||||||
|
*/
|
||||||
|
int av_url_read_pause(URLContext *h, int pause);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seek to a given timestamp relative to some component stream.
|
||||||
|
* Only meaningful if using a network streaming protocol (e.g. MMS.).
|
||||||
|
* @param stream_index The stream index that the timestamp is relative to.
|
||||||
|
* If stream_index is (-1) the timestamp should be in AV_TIME_BASE
|
||||||
|
* units from the beginning of the presentation.
|
||||||
|
* If a stream_index >= 0 is used and the protocol does not support
|
||||||
|
* seeking based on component streams, the call will fail with ENOTSUP.
|
||||||
|
* @param timestamp timestamp in AVStream.time_base units
|
||||||
|
* or if there is no stream specified then in AV_TIME_BASE units.
|
||||||
|
* @param flags Optional combination of AVSEEK_FLAG_BACKWARD, AVSEEK_FLAG_BYTE
|
||||||
|
* and AVSEEK_FLAG_ANY. The protocol may silently ignore
|
||||||
|
* AVSEEK_FLAG_BACKWARD and AVSEEK_FLAG_ANY, but AVSEEK_FLAG_BYTE will
|
||||||
|
* fail with ENOTSUP if used and not supported.
|
||||||
|
* @return >= 0 on success
|
||||||
|
* @see AVInputFormat::read_seek
|
||||||
|
*/
|
||||||
|
int64_t av_url_read_seek(URLContext *h, int stream_index,
|
||||||
|
int64_t timestamp, int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Passing this as the "whence" parameter to a seek function causes it to
|
||||||
|
* return the filesize without seeking anywhere. Supporting this is optional.
|
||||||
|
* If it is not supported then the seek function will return <0.
|
||||||
|
*/
|
||||||
|
#define AVSEEK_SIZE 0x10000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Oring this flag as into the "whence" parameter to a seek function causes it to
|
||||||
|
* seek by any means (like reopening and linear reading) or other normally unreasonble
|
||||||
|
* means that can be extreemly slow.
|
||||||
|
* This may be ignored by the seek code.
|
||||||
|
*/
|
||||||
|
#define AVSEEK_FORCE 0x20000
|
||||||
|
|
||||||
|
typedef struct URLProtocol {
|
||||||
|
const char *name;
|
||||||
|
int (*url_open)(URLContext *h, const char *url, int flags);
|
||||||
|
int (*url_read)(URLContext *h, unsigned char *buf, int size);
|
||||||
|
int (*url_write)(URLContext *h, unsigned char *buf, int size);
|
||||||
|
int64_t (*url_seek)(URLContext *h, int64_t pos, int whence);
|
||||||
|
int (*url_close)(URLContext *h);
|
||||||
|
struct URLProtocol *next;
|
||||||
|
int (*url_read_pause)(URLContext *h, int pause);
|
||||||
|
int64_t (*url_read_seek)(URLContext *h, int stream_index,
|
||||||
|
int64_t timestamp, int flags);
|
||||||
|
int (*url_get_file_handle)(URLContext *h);
|
||||||
|
} URLProtocol;
|
||||||
|
|
||||||
|
#if LIBAVFORMAT_VERSION_MAJOR < 53
|
||||||
|
extern URLProtocol *first_protocol;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern URLInterruptCB *url_interrupt_cb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If protocol is NULL, returns the first registered protocol,
|
||||||
|
* if protocol is non-NULL, returns the next registered protocol after protocol,
|
||||||
|
* or NULL if protocol is the last one.
|
||||||
|
*/
|
||||||
|
URLProtocol *av_protocol_next(URLProtocol *p);
|
||||||
|
|
||||||
|
#if LIBAVFORMAT_VERSION_MAJOR < 53
|
||||||
|
/**
|
||||||
|
* @deprecated Use av_register_protocol() instead.
|
||||||
|
*/
|
||||||
|
attribute_deprecated int register_protocol(URLProtocol *protocol);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the URLProtocol protocol.
|
||||||
|
*/
|
||||||
|
int av_register_protocol(URLProtocol *protocol);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bytestream IO Context.
|
||||||
|
* New fields can be added to the end with minor version bumps.
|
||||||
|
* Removal, reordering and changes to existing fields require a major
|
||||||
|
* version bump.
|
||||||
|
* sizeof(ByteIOContext) must not be used outside libav*.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
unsigned char *buffer;
|
||||||
|
int buffer_size;
|
||||||
|
unsigned char *buf_ptr, *buf_end;
|
||||||
|
void *opaque;
|
||||||
|
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size);
|
||||||
|
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size);
|
||||||
|
int64_t (*seek)(void *opaque, int64_t offset, int whence);
|
||||||
|
int64_t pos; /**< position in the file of the current buffer */
|
||||||
|
int must_flush; /**< true if the next seek should flush */
|
||||||
|
int eof_reached; /**< true if eof reached */
|
||||||
|
int write_flag; /**< true if open for writing */
|
||||||
|
int is_streamed;
|
||||||
|
int max_packet_size;
|
||||||
|
unsigned long checksum;
|
||||||
|
unsigned char *checksum_ptr;
|
||||||
|
unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);
|
||||||
|
int error; ///< contains the error code or 0 if no error happened
|
||||||
|
int (*read_pause)(void *opaque, int pause);
|
||||||
|
int64_t (*read_seek)(void *opaque, int stream_index,
|
||||||
|
int64_t timestamp, int flags);
|
||||||
|
} ByteIOContext;
|
||||||
|
|
||||||
|
int init_put_byte(ByteIOContext *s,
|
||||||
|
unsigned char *buffer,
|
||||||
|
int buffer_size,
|
||||||
|
int write_flag,
|
||||||
|
void *opaque,
|
||||||
|
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||||
|
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||||
|
int64_t (*seek)(void *opaque, int64_t offset, int whence));
|
||||||
|
ByteIOContext *av_alloc_put_byte(
|
||||||
|
unsigned char *buffer,
|
||||||
|
int buffer_size,
|
||||||
|
int write_flag,
|
||||||
|
void *opaque,
|
||||||
|
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||||
|
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||||
|
int64_t (*seek)(void *opaque, int64_t offset, int whence));
|
||||||
|
|
||||||
|
void put_byte(ByteIOContext *s, int b);
|
||||||
|
void put_buffer(ByteIOContext *s, const unsigned char *buf, int size);
|
||||||
|
void put_le64(ByteIOContext *s, uint64_t val);
|
||||||
|
void put_be64(ByteIOContext *s, uint64_t val);
|
||||||
|
void put_le32(ByteIOContext *s, unsigned int val);
|
||||||
|
void put_be32(ByteIOContext *s, unsigned int val);
|
||||||
|
void put_le24(ByteIOContext *s, unsigned int val);
|
||||||
|
void put_be24(ByteIOContext *s, unsigned int val);
|
||||||
|
void put_le16(ByteIOContext *s, unsigned int val);
|
||||||
|
void put_be16(ByteIOContext *s, unsigned int val);
|
||||||
|
void put_tag(ByteIOContext *s, const char *tag);
|
||||||
|
|
||||||
|
void put_strz(ByteIOContext *s, const char *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fseek() equivalent for ByteIOContext.
|
||||||
|
* @return new position or AVERROR.
|
||||||
|
*/
|
||||||
|
int64_t url_fseek(ByteIOContext *s, int64_t offset, int whence);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skip given number of bytes forward.
|
||||||
|
* @param offset number of bytes
|
||||||
|
*/
|
||||||
|
void url_fskip(ByteIOContext *s, int64_t offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ftell() equivalent for ByteIOContext.
|
||||||
|
* @return position or AVERROR.
|
||||||
|
*/
|
||||||
|
int64_t url_ftell(ByteIOContext *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the filesize.
|
||||||
|
* @return filesize or AVERROR
|
||||||
|
*/
|
||||||
|
int64_t url_fsize(ByteIOContext *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* feof() equivalent for ByteIOContext.
|
||||||
|
* @return non zero if and only if end of file
|
||||||
|
*/
|
||||||
|
int url_feof(ByteIOContext *s);
|
||||||
|
|
||||||
|
int url_ferror(ByteIOContext *s);
|
||||||
|
|
||||||
|
int av_url_read_fpause(ByteIOContext *h, int pause);
|
||||||
|
int64_t av_url_read_fseek(ByteIOContext *h, int stream_index,
|
||||||
|
int64_t timestamp, int flags);
|
||||||
|
|
||||||
|
#define URL_EOF (-1)
|
||||||
|
/** @note return URL_EOF (-1) if EOF */
|
||||||
|
int url_fgetc(ByteIOContext *s);
|
||||||
|
|
||||||
|
/** @warning currently size is limited */
|
||||||
|
#ifdef __GNUC__
|
||||||
|
int url_fprintf(ByteIOContext *s, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
|
||||||
|
#else
|
||||||
|
int url_fprintf(ByteIOContext *s, const char *fmt, ...);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @note unlike fgets, the EOL character is not returned and a whole
|
||||||
|
line is parsed. return NULL if first char read was EOF */
|
||||||
|
char *url_fgets(ByteIOContext *s, char *buf, int buf_size);
|
||||||
|
|
||||||
|
void put_flush_packet(ByteIOContext *s);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads size bytes from ByteIOContext into buf.
|
||||||
|
* @return number of bytes read or AVERROR
|
||||||
|
*/
|
||||||
|
int get_buffer(ByteIOContext *s, unsigned char *buf, int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads size bytes from ByteIOContext into buf.
|
||||||
|
* This reads at most 1 packet. If that is not enough fewer bytes will be
|
||||||
|
* returned.
|
||||||
|
* @return number of bytes read or AVERROR
|
||||||
|
*/
|
||||||
|
int get_partial_buffer(ByteIOContext *s, unsigned char *buf, int size);
|
||||||
|
|
||||||
|
/** @note return 0 if EOF, so you cannot use it if EOF handling is
|
||||||
|
necessary */
|
||||||
|
int get_byte(ByteIOContext *s);
|
||||||
|
unsigned int get_le24(ByteIOContext *s);
|
||||||
|
unsigned int get_le32(ByteIOContext *s);
|
||||||
|
uint64_t get_le64(ByteIOContext *s);
|
||||||
|
unsigned int get_le16(ByteIOContext *s);
|
||||||
|
|
||||||
|
char *get_strz(ByteIOContext *s, char *buf, int maxlen);
|
||||||
|
unsigned int get_be16(ByteIOContext *s);
|
||||||
|
unsigned int get_be24(ByteIOContext *s);
|
||||||
|
unsigned int get_be32(ByteIOContext *s);
|
||||||
|
uint64_t get_be64(ByteIOContext *s);
|
||||||
|
|
||||||
|
uint64_t ff_get_v(ByteIOContext *bc);
|
||||||
|
|
||||||
|
static inline int url_is_streamed(ByteIOContext *s)
|
||||||
|
{
|
||||||
|
return s->is_streamed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and initializes a ByteIOContext for accessing the
|
||||||
|
* resource referenced by the URLContext h.
|
||||||
|
* @note When the URLContext h has been opened in read+write mode, the
|
||||||
|
* ByteIOContext can be used only for writing.
|
||||||
|
*
|
||||||
|
* @param s Used to return the pointer to the created ByteIOContext.
|
||||||
|
* In case of failure the pointed to value is set to NULL.
|
||||||
|
* @return 0 in case of success, a negative value corresponding to an
|
||||||
|
* AVERROR code in case of failure
|
||||||
|
*/
|
||||||
|
int url_fdopen(ByteIOContext **s, URLContext *h);
|
||||||
|
|
||||||
|
/** @warning must be called before any I/O */
|
||||||
|
int url_setbufsize(ByteIOContext *s, int buf_size);
|
||||||
|
#if LIBAVFORMAT_VERSION_MAJOR < 53
|
||||||
|
/** Reset the buffer for reading or writing.
|
||||||
|
* @note Will drop any data currently in the buffer without transmitting it.
|
||||||
|
* @param flags URL_RDONLY to set up the buffer for reading, or URL_WRONLY
|
||||||
|
* to set up the buffer for writing. */
|
||||||
|
int url_resetbuf(ByteIOContext *s, int flags);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rewinds the ByteIOContext using the specified buffer containing the first buf_size bytes of the file.
|
||||||
|
* Used after probing to avoid seeking.
|
||||||
|
* Joins buf and s->buffer, taking any overlap into consideration.
|
||||||
|
* @note s->buffer must overlap with buf or they can't be joined and the function fails
|
||||||
|
* @note This function is NOT part of the public API
|
||||||
|
*
|
||||||
|
* @param s The read-only ByteIOContext to rewind
|
||||||
|
* @param buf The probe buffer containing the first buf_size bytes of the file
|
||||||
|
* @param buf_size The size of buf
|
||||||
|
* @return 0 in case of success, a negative value corresponding to an
|
||||||
|
* AVERROR code in case of failure
|
||||||
|
*/
|
||||||
|
int ff_rewind_with_probe_data(ByteIOContext *s, unsigned char *buf, int buf_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and initializes a ByteIOContext for accessing the
|
||||||
|
* resource indicated by url.
|
||||||
|
* @note When the resource indicated by url has been opened in
|
||||||
|
* read+write mode, the ByteIOContext can be used only for writing.
|
||||||
|
*
|
||||||
|
* @param s Used to return the pointer to the created ByteIOContext.
|
||||||
|
* In case of failure the pointed to value is set to NULL.
|
||||||
|
* @param flags flags which control how the resource indicated by url
|
||||||
|
* is to be opened
|
||||||
|
* @return 0 in case of success, a negative value corresponding to an
|
||||||
|
* AVERROR code in case of failure
|
||||||
|
*/
|
||||||
|
int url_fopen(ByteIOContext **s, const char *url, int flags);
|
||||||
|
|
||||||
|
int url_fclose(ByteIOContext *s);
|
||||||
|
URLContext *url_fileno(ByteIOContext *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the maximum packet size associated to packetized buffered file
|
||||||
|
* handle. If the file is not packetized (stream like http or file on
|
||||||
|
* disk), then 0 is returned.
|
||||||
|
*
|
||||||
|
* @param s buffered file handle
|
||||||
|
* @return maximum packet size in bytes
|
||||||
|
*/
|
||||||
|
int url_fget_max_packet_size(ByteIOContext *s);
|
||||||
|
|
||||||
|
int url_open_buf(ByteIOContext **s, uint8_t *buf, int buf_size, int flags);
|
||||||
|
|
||||||
|
/** return the written or read size */
|
||||||
|
int url_close_buf(ByteIOContext *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a write only memory stream.
|
||||||
|
*
|
||||||
|
* @param s new IO context
|
||||||
|
* @return zero if no error.
|
||||||
|
*/
|
||||||
|
int url_open_dyn_buf(ByteIOContext **s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a write only packetized memory stream with a maximum packet
|
||||||
|
* size of 'max_packet_size'. The stream is stored in a memory buffer
|
||||||
|
* with a big endian 4 byte header giving the packet size in bytes.
|
||||||
|
*
|
||||||
|
* @param s new IO context
|
||||||
|
* @param max_packet_size maximum packet size (must be > 0)
|
||||||
|
* @return zero if no error.
|
||||||
|
*/
|
||||||
|
int url_open_dyn_packet_buf(ByteIOContext **s, int max_packet_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the written size and a pointer to the buffer. The buffer
|
||||||
|
* must be freed with av_free().
|
||||||
|
* @param s IO context
|
||||||
|
* @param pbuffer pointer to a byte buffer
|
||||||
|
* @return the length of the byte buffer
|
||||||
|
*/
|
||||||
|
int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer);
|
||||||
|
|
||||||
|
unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf,
|
||||||
|
unsigned int len);
|
||||||
|
unsigned long get_checksum(ByteIOContext *s);
|
||||||
|
void init_checksum(ByteIOContext *s,
|
||||||
|
unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len),
|
||||||
|
unsigned long checksum);
|
||||||
|
|
||||||
|
/* udp.c */
|
||||||
|
int udp_set_remote_url(URLContext *h, const char *uri);
|
||||||
|
int udp_get_local_port(URLContext *h);
|
||||||
|
#if (LIBAVFORMAT_VERSION_MAJOR <= 52)
|
||||||
|
int udp_get_file_handle(URLContext *h);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* AVFORMAT_AVIO_H */
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2006 Mans Rullgard
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_ADLER32_H
|
||||||
|
#define AVUTIL_ADLER32_H
|
||||||
|
|
||||||
|
#include <msc_stdint.h>
|
||||||
|
#include "attributes.h"
|
||||||
|
|
||||||
|
unsigned long av_adler32_update(unsigned long adler, const uint8_t *buf,
|
||||||
|
unsigned int len) av_pure;
|
||||||
|
|
||||||
|
#endif /* AVUTIL_ADLER32_H */
|
||||||
+113
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Macro definitions for various function/variable attributes
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_ATTRIBUTES_H
|
||||||
|
#define AVUTIL_ATTRIBUTES_H
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
# define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > x || __GNUC__ == x && __GNUC_MINOR__ >= y)
|
||||||
|
#else
|
||||||
|
# define AV_GCC_VERSION_AT_LEAST(x,y) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef av_always_inline
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(3,1)
|
||||||
|
# define av_always_inline __attribute__((always_inline)) inline
|
||||||
|
#else
|
||||||
|
# define av_always_inline inline
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef av_noinline
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(3,1)
|
||||||
|
# define av_noinline __attribute__((noinline))
|
||||||
|
#else
|
||||||
|
# define av_noinline
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef av_pure
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(3,1)
|
||||||
|
# define av_pure __attribute__((pure))
|
||||||
|
#else
|
||||||
|
# define av_pure
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef av_const
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(2,6)
|
||||||
|
# define av_const __attribute__((const))
|
||||||
|
#else
|
||||||
|
# define av_const
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef av_cold
|
||||||
|
#if (!defined(__ICC) || __ICC > 1110) && AV_GCC_VERSION_AT_LEAST(4,3)
|
||||||
|
# define av_cold __attribute__((cold))
|
||||||
|
#else
|
||||||
|
# define av_cold
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef av_flatten
|
||||||
|
#if (!defined(__ICC) || __ICC > 1110) && AV_GCC_VERSION_AT_LEAST(4,1)
|
||||||
|
# define av_flatten __attribute__((flatten))
|
||||||
|
#else
|
||||||
|
# define av_flatten
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef attribute_deprecated
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(3,1)
|
||||||
|
# define attribute_deprecated __attribute__((deprecated))
|
||||||
|
#else
|
||||||
|
# define attribute_deprecated
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef av_unused
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# define av_unused __attribute__((unused))
|
||||||
|
#else
|
||||||
|
# define av_unused
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef av_uninit
|
||||||
|
#if defined(__GNUC__) && !defined(__ICC)
|
||||||
|
# define av_uninit(x) x=x
|
||||||
|
#else
|
||||||
|
# define av_uninit(x) x
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
# define av_builtin_constant_p __builtin_constant_p
|
||||||
|
#else
|
||||||
|
# define av_builtin_constant_p(x) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* AVUTIL_ATTRIBUTES_H */
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/* Generated by ffconf */
|
||||||
|
#ifndef AVUTIL_AVCONFIG_H
|
||||||
|
#define AVUTIL_AVCONFIG_H
|
||||||
|
#define AV_HAVE_BIGENDIAN 0
|
||||||
|
#endif /* AVUTIL_AVCONFIG_H */
|
||||||
+117
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2007 Mans Rullgard
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_AVSTRING_H
|
||||||
|
#define AVUTIL_AVSTRING_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return non-zero if pfx is a prefix of str. If it is, *ptr is set to
|
||||||
|
* the address of the first character in str after the prefix.
|
||||||
|
*
|
||||||
|
* @param str input string
|
||||||
|
* @param pfx prefix to test
|
||||||
|
* @param ptr updated if the prefix is matched inside str
|
||||||
|
* @return non-zero if the prefix matches, zero otherwise
|
||||||
|
*/
|
||||||
|
int av_strstart(const char *str, const char *pfx, const char **ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return non-zero if pfx is a prefix of str independent of case. If
|
||||||
|
* it is, *ptr is set to the address of the first character in str
|
||||||
|
* after the prefix.
|
||||||
|
*
|
||||||
|
* @param str input string
|
||||||
|
* @param pfx prefix to test
|
||||||
|
* @param ptr updated if the prefix is matched inside str
|
||||||
|
* @return non-zero if the prefix matches, zero otherwise
|
||||||
|
*/
|
||||||
|
int av_stristart(const char *str, const char *pfx, const char **ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locate the first case-independent occurrence in the string haystack
|
||||||
|
* of the string needle. A zero-length string needle is considered to
|
||||||
|
* match at the start of haystack.
|
||||||
|
*
|
||||||
|
* This function is a case-insensitive version of the standard strstr().
|
||||||
|
*
|
||||||
|
* @param haystack string to search in
|
||||||
|
* @param needle string to search for
|
||||||
|
* @return pointer to the located match within haystack
|
||||||
|
* or a null pointer if no match
|
||||||
|
*/
|
||||||
|
char *av_stristr(const char *haystack, const char *needle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the string src to dst, but no more than size - 1 bytes, and
|
||||||
|
* null-terminate dst.
|
||||||
|
*
|
||||||
|
* This function is the same as BSD strlcpy().
|
||||||
|
*
|
||||||
|
* @param dst destination buffer
|
||||||
|
* @param src source string
|
||||||
|
* @param size size of destination buffer
|
||||||
|
* @return the length of src
|
||||||
|
*
|
||||||
|
* WARNING: since the return value is the length of src, src absolutely
|
||||||
|
* _must_ be a properly 0-terminated string, otherwise this will read beyond
|
||||||
|
* the end of the buffer and possibly crash.
|
||||||
|
*/
|
||||||
|
size_t av_strlcpy(char *dst, const char *src, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the string src to the string dst, but to a total length of
|
||||||
|
* no more than size - 1 bytes, and null-terminate dst.
|
||||||
|
*
|
||||||
|
* This function is similar to BSD strlcat(), but differs when
|
||||||
|
* size <= strlen(dst).
|
||||||
|
*
|
||||||
|
* @param dst destination buffer
|
||||||
|
* @param src source string
|
||||||
|
* @param size size of destination buffer
|
||||||
|
* @return the total length of src and dst
|
||||||
|
*
|
||||||
|
* WARNING: since the return value use the length of src and dst, these absolutely
|
||||||
|
* _must_ be a properly 0-terminated strings, otherwise this will read beyond
|
||||||
|
* the end of the buffer and possibly crash.
|
||||||
|
*/
|
||||||
|
size_t av_strlcat(char *dst, const char *src, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append output to a string, according to a format. Never write out of
|
||||||
|
* the destination buffer, and always put a terminating 0 within
|
||||||
|
* the buffer.
|
||||||
|
* @param dst destination buffer (string to which the output is
|
||||||
|
* appended)
|
||||||
|
* @param size total size of the destination buffer
|
||||||
|
* @param fmt printf-compatible format string, specifying how the
|
||||||
|
* following parameters are used
|
||||||
|
* @return the length of the string that would have been generated
|
||||||
|
* if enough space had been available
|
||||||
|
*/
|
||||||
|
size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a number to a av_malloced string.
|
||||||
|
*/
|
||||||
|
char *av_d2str(double d);
|
||||||
|
|
||||||
|
#endif /* AVUTIL_AVSTRING_H */
|
||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_AVUTIL_H
|
||||||
|
#define AVUTIL_AVUTIL_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* external API header
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define AV_STRINGIFY(s) AV_TOSTRING(s)
|
||||||
|
#define AV_TOSTRING(s) #s
|
||||||
|
|
||||||
|
#define AV_GLUE(a, b) a ## b
|
||||||
|
#define AV_JOIN(a, b) AV_GLUE(a, b)
|
||||||
|
|
||||||
|
#define AV_PRAGMA(s) _Pragma(#s)
|
||||||
|
|
||||||
|
#define AV_VERSION_INT(a, b, c) (a<<16 | b<<8 | c)
|
||||||
|
#define AV_VERSION_DOT(a, b, c) a ##.## b ##.## c
|
||||||
|
#define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c)
|
||||||
|
|
||||||
|
#define LIBAVUTIL_VERSION_MAJOR 50
|
||||||
|
#define LIBAVUTIL_VERSION_MINOR 15
|
||||||
|
#define LIBAVUTIL_VERSION_MICRO 1
|
||||||
|
|
||||||
|
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
|
||||||
|
LIBAVUTIL_VERSION_MINOR, \
|
||||||
|
LIBAVUTIL_VERSION_MICRO)
|
||||||
|
#define LIBAVUTIL_VERSION AV_VERSION(LIBAVUTIL_VERSION_MAJOR, \
|
||||||
|
LIBAVUTIL_VERSION_MINOR, \
|
||||||
|
LIBAVUTIL_VERSION_MICRO)
|
||||||
|
#define LIBAVUTIL_BUILD LIBAVUTIL_VERSION_INT
|
||||||
|
|
||||||
|
#define LIBAVUTIL_IDENT "Lavu" AV_STRINGIFY(LIBAVUTIL_VERSION)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the LIBAVUTIL_VERSION_INT constant.
|
||||||
|
*/
|
||||||
|
unsigned avutil_version(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the libavutil build-time configuration.
|
||||||
|
*/
|
||||||
|
const char *avutil_configuration(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the libavutil license.
|
||||||
|
*/
|
||||||
|
const char *avutil_license(void);
|
||||||
|
|
||||||
|
enum AVMediaType {
|
||||||
|
AVMEDIA_TYPE_UNKNOWN = -1,
|
||||||
|
AVMEDIA_TYPE_VIDEO,
|
||||||
|
AVMEDIA_TYPE_AUDIO,
|
||||||
|
AVMEDIA_TYPE_DATA,
|
||||||
|
AVMEDIA_TYPE_SUBTITLE,
|
||||||
|
AVMEDIA_TYPE_ATTACHMENT,
|
||||||
|
AVMEDIA_TYPE_NB
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "mathematics.h"
|
||||||
|
#include "rational.h"
|
||||||
|
#include "intfloat_readwrite.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "pixfmt.h"
|
||||||
|
|
||||||
|
#endif /* AVUTIL_AVUTIL_H */
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_BASE64_H
|
||||||
|
#define AVUTIL_BASE64_H
|
||||||
|
|
||||||
|
#include <msc_stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes the base64-encoded string in in and puts the decoded
|
||||||
|
* data in out.
|
||||||
|
*
|
||||||
|
* @param out_size size in bytes of the out buffer, it should be at
|
||||||
|
* least 3/4 of the length of in
|
||||||
|
* @return the number of bytes written, or a negative value in case of
|
||||||
|
* error
|
||||||
|
*/
|
||||||
|
int av_base64_decode(uint8_t *out, const char *in, int out_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes in base64 the data in in and puts the resulting string
|
||||||
|
* in out.
|
||||||
|
*
|
||||||
|
* @param out_size size in bytes of the out string, it should be at
|
||||||
|
* least ((in_size + 2) / 3) * 4 + 1
|
||||||
|
* @param in_size size in bytes of the in buffer
|
||||||
|
* @return the string containing the encoded data, or NULL in case of
|
||||||
|
* error
|
||||||
|
*/
|
||||||
|
char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size);
|
||||||
|
|
||||||
|
#endif /* AVUTIL_BASE64_H */
|
||||||
+312
@@ -0,0 +1,312 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* common internal and external API header
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_COMMON_H
|
||||||
|
#define AVUTIL_COMMON_H
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#include <msc_inttypes.h>
|
||||||
|
#else
|
||||||
|
#include <inttypes.h>
|
||||||
|
#endif
|
||||||
|
#include <limits.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "attributes.h"
|
||||||
|
|
||||||
|
//rounded division & shift
|
||||||
|
#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b))
|
||||||
|
/* assume b>0 */
|
||||||
|
#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b))
|
||||||
|
#define FFABS(a) ((a) >= 0 ? (a) : (-(a)))
|
||||||
|
#define FFSIGN(a) ((a) > 0 ? 1 : -1)
|
||||||
|
|
||||||
|
#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
|
||||||
|
#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c)
|
||||||
|
#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
|
||||||
|
#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c)
|
||||||
|
|
||||||
|
#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)
|
||||||
|
#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
|
||||||
|
#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1))
|
||||||
|
|
||||||
|
/* misc math functions */
|
||||||
|
extern const uint8_t ff_log2_tab[256];
|
||||||
|
|
||||||
|
extern const uint8_t av_reverse[256];
|
||||||
|
|
||||||
|
static inline av_const int av_log2_c(unsigned int v)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
if (v & 0xffff0000) {
|
||||||
|
v >>= 16;
|
||||||
|
n += 16;
|
||||||
|
}
|
||||||
|
if (v & 0xff00) {
|
||||||
|
v >>= 8;
|
||||||
|
n += 8;
|
||||||
|
}
|
||||||
|
n += ff_log2_tab[v];
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline av_const int av_log2_16bit_c(unsigned int v)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
if (v & 0xff00) {
|
||||||
|
v >>= 8;
|
||||||
|
n += 8;
|
||||||
|
}
|
||||||
|
n += ff_log2_tab[v];
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_AV_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
# include "intmath.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef av_log2
|
||||||
|
# define av_log2 av_log2_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_log2_16bit
|
||||||
|
# define av_log2_16bit av_log2_16bit_c
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clips a signed integer value into the amin-amax range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @param amin minimum value of the clip range
|
||||||
|
* @param amax maximum value of the clip range
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static inline av_const int av_clip(int a, int amin, int amax)
|
||||||
|
{
|
||||||
|
if (a < amin) return amin;
|
||||||
|
else if (a > amax) return amax;
|
||||||
|
else return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clips a signed integer value into the 0-255 range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static inline av_const uint8_t av_clip_uint8(int a)
|
||||||
|
{
|
||||||
|
if (a&(~0xFF)) return (-a)>>31;
|
||||||
|
else return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clips a signed integer value into the 0-65535 range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static inline av_const uint16_t av_clip_uint16(int a)
|
||||||
|
{
|
||||||
|
if (a&(~0xFFFF)) return (-a)>>31;
|
||||||
|
else return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clips a signed integer value into the -32768,32767 range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static inline av_const int16_t av_clip_int16(int a)
|
||||||
|
{
|
||||||
|
if ((a+0x8000) & ~0xFFFF) return (a>>31) ^ 0x7FFF;
|
||||||
|
else return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clips a signed 64-bit integer value into the -2147483648,2147483647 range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static inline av_const int32_t av_clipl_int32(int64_t a)
|
||||||
|
{
|
||||||
|
if ((a+0x80000000u) & ~UINT64_C(0xFFFFFFFF)) return (a>>63) ^ 0x7FFFFFFF;
|
||||||
|
else return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clips a float value into the amin-amax range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @param amin minimum value of the clip range
|
||||||
|
* @param amax maximum value of the clip range
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static inline av_const float av_clipf(float a, float amin, float amax)
|
||||||
|
{
|
||||||
|
if (a < amin) return amin;
|
||||||
|
else if (a > amax) return amax;
|
||||||
|
else return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Computes ceil(log2(x)).
|
||||||
|
* @param x value used to compute ceil(log2(x))
|
||||||
|
* @return computed ceiling of log2(x)
|
||||||
|
*/
|
||||||
|
static inline av_const int av_ceil_log2(int x)
|
||||||
|
{
|
||||||
|
return av_log2((x - 1) << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
|
||||||
|
#define MKBETAG(a,b,c,d) (d | (c << 8) | (b << 16) | (a << 24))
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \def GET_UTF8(val, GET_BYTE, ERROR)
|
||||||
|
* Converts a UTF-8 character (up to 4 bytes long) to its 32-bit UCS-4 encoded form
|
||||||
|
* \param val is the output and should be of type uint32_t. It holds the converted
|
||||||
|
* UCS-4 character and should be a left value.
|
||||||
|
* \param GET_BYTE gets UTF-8 encoded bytes from any proper source. It can be
|
||||||
|
* a function or a statement whose return value or evaluated value is of type
|
||||||
|
* uint8_t. It will be executed up to 4 times for values in the valid UTF-8 range,
|
||||||
|
* and up to 7 times in the general case.
|
||||||
|
* \param ERROR action that should be taken when an invalid UTF-8 byte is returned
|
||||||
|
* from GET_BYTE. It should be a statement that jumps out of the macro,
|
||||||
|
* like exit(), goto, return, break, or continue.
|
||||||
|
*/
|
||||||
|
#define GET_UTF8(val, GET_BYTE, ERROR)\
|
||||||
|
val= GET_BYTE;\
|
||||||
|
{\
|
||||||
|
int ones= 7 - av_log2(val ^ 255);\
|
||||||
|
if(ones==1)\
|
||||||
|
ERROR\
|
||||||
|
val&= 127>>ones;\
|
||||||
|
while(--ones > 0){\
|
||||||
|
int tmp= GET_BYTE - 128;\
|
||||||
|
if(tmp>>6)\
|
||||||
|
ERROR\
|
||||||
|
val= (val<<6) + tmp;\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \def GET_UTF16(val, GET_16BIT, ERROR)
|
||||||
|
* Converts a UTF-16 character (2 or 4 bytes) to its 32-bit UCS-4 encoded form
|
||||||
|
* \param val is the output and should be of type uint32_t. It holds the converted
|
||||||
|
* UCS-4 character and should be a left value.
|
||||||
|
* \param GET_16BIT gets two bytes of UTF-16 encoded data converted to native endianness.
|
||||||
|
* It can be a function or a statement whose return value or evaluated value is of type
|
||||||
|
* uint16_t. It will be executed up to 2 times.
|
||||||
|
* \param ERROR action that should be taken when an invalid UTF-16 surrogate is
|
||||||
|
* returned from GET_BYTE. It should be a statement that jumps out of the macro,
|
||||||
|
* like exit(), goto, return, break, or continue.
|
||||||
|
*/
|
||||||
|
#define GET_UTF16(val, GET_16BIT, ERROR)\
|
||||||
|
val = GET_16BIT;\
|
||||||
|
{\
|
||||||
|
unsigned int hi = val - 0xD800;\
|
||||||
|
if (hi < 0x800) {\
|
||||||
|
val = GET_16BIT - 0xDC00;\
|
||||||
|
if (val > 0x3FFU || hi > 0x3FFU)\
|
||||||
|
ERROR\
|
||||||
|
val += (hi<<10) + 0x10000;\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \def PUT_UTF8(val, tmp, PUT_BYTE)
|
||||||
|
* Converts a 32-bit Unicode character to its UTF-8 encoded form (up to 4 bytes long).
|
||||||
|
* \param val is an input-only argument and should be of type uint32_t. It holds
|
||||||
|
* a UCS-4 encoded Unicode character that is to be converted to UTF-8. If
|
||||||
|
* val is given as a function it is executed only once.
|
||||||
|
* \param tmp is a temporary variable and should be of type uint8_t. It
|
||||||
|
* represents an intermediate value during conversion that is to be
|
||||||
|
* output by PUT_BYTE.
|
||||||
|
* \param PUT_BYTE writes the converted UTF-8 bytes to any proper destination.
|
||||||
|
* It could be a function or a statement, and uses tmp as the input byte.
|
||||||
|
* For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be
|
||||||
|
* executed up to 4 times for values in the valid UTF-8 range and up to
|
||||||
|
* 7 times in the general case, depending on the length of the converted
|
||||||
|
* Unicode character.
|
||||||
|
*/
|
||||||
|
#define PUT_UTF8(val, tmp, PUT_BYTE)\
|
||||||
|
{\
|
||||||
|
int bytes, shift;\
|
||||||
|
uint32_t in = val;\
|
||||||
|
if (in < 0x80) {\
|
||||||
|
tmp = in;\
|
||||||
|
PUT_BYTE\
|
||||||
|
} else {\
|
||||||
|
bytes = (av_log2(in) + 4) / 5;\
|
||||||
|
shift = (bytes - 1) * 6;\
|
||||||
|
tmp = (256 - (256 >> bytes)) | (in >> shift);\
|
||||||
|
PUT_BYTE\
|
||||||
|
while (shift >= 6) {\
|
||||||
|
shift -= 6;\
|
||||||
|
tmp = 0x80 | ((in >> shift) & 0x3f);\
|
||||||
|
PUT_BYTE\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \def PUT_UTF16(val, tmp, PUT_16BIT)
|
||||||
|
* Converts a 32-bit Unicode character to its UTF-16 encoded form (2 or 4 bytes).
|
||||||
|
* \param val is an input-only argument and should be of type uint32_t. It holds
|
||||||
|
* a UCS-4 encoded Unicode character that is to be converted to UTF-16. If
|
||||||
|
* val is given as a function it is executed only once.
|
||||||
|
* \param tmp is a temporary variable and should be of type uint16_t. It
|
||||||
|
* represents an intermediate value during conversion that is to be
|
||||||
|
* output by PUT_16BIT.
|
||||||
|
* \param PUT_16BIT writes the converted UTF-16 data to any proper destination
|
||||||
|
* in desired endianness. It could be a function or a statement, and uses tmp
|
||||||
|
* as the input byte. For example, PUT_BYTE could be "*output++ = tmp;"
|
||||||
|
* PUT_BYTE will be executed 1 or 2 times depending on input character.
|
||||||
|
*/
|
||||||
|
#define PUT_UTF16(val, tmp, PUT_16BIT)\
|
||||||
|
{\
|
||||||
|
uint32_t in = val;\
|
||||||
|
if (in < 0x10000) {\
|
||||||
|
tmp = in;\
|
||||||
|
PUT_16BIT\
|
||||||
|
} else {\
|
||||||
|
tmp = 0xD800 | ((in - 0x10000) >> 10);\
|
||||||
|
PUT_16BIT\
|
||||||
|
tmp = 0xDC00 | ((in - 0x10000) & 0x3FF);\
|
||||||
|
PUT_16BIT\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "mem.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_AV_CONFIG_H
|
||||||
|
# include "internal.h"
|
||||||
|
#endif /* HAVE_AV_CONFIG_H */
|
||||||
|
|
||||||
|
#endif /* AVUTIL_COMMON_H */
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_CRC_H
|
||||||
|
#define AVUTIL_CRC_H
|
||||||
|
|
||||||
|
#include <msc_stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "attributes.h"
|
||||||
|
|
||||||
|
typedef uint32_t AVCRC;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AV_CRC_8_ATM,
|
||||||
|
AV_CRC_16_ANSI,
|
||||||
|
AV_CRC_16_CCITT,
|
||||||
|
AV_CRC_32_IEEE,
|
||||||
|
AV_CRC_32_IEEE_LE, /*< reversed bitorder version of AV_CRC_32_IEEE */
|
||||||
|
AV_CRC_MAX, /*< Not part of public API! Do not use outside libavutil. */
|
||||||
|
}AVCRCId;
|
||||||
|
|
||||||
|
int av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size);
|
||||||
|
const AVCRC *av_crc_get_table(AVCRCId crc_id);
|
||||||
|
uint32_t av_crc(const AVCRC *ctx, uint32_t start_crc, const uint8_t *buffer, size_t length) av_pure;
|
||||||
|
|
||||||
|
#endif /* AVUTIL_CRC_H */
|
||||||
|
|
||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* error code definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_ERROR_H
|
||||||
|
#define AVUTIL_ERROR_H
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include "avutil.h"
|
||||||
|
|
||||||
|
/* error handling */
|
||||||
|
#if EDOM > 0
|
||||||
|
#define AVERROR(e) (-(e)) ///< Returns a negative error code from a POSIX error code, to return from library functions.
|
||||||
|
#define AVUNERROR(e) (-(e)) ///< Returns a POSIX error code from a library function error return value.
|
||||||
|
#else
|
||||||
|
/* Some platforms have E* and errno already negated. */
|
||||||
|
#define AVERROR(e) (e)
|
||||||
|
#define AVUNERROR(e) (e)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LIBAVUTIL_VERSION_MAJOR < 51
|
||||||
|
#define AVERROR_INVALIDDATA AVERROR(EINVAL) ///< Invalid data found when processing input
|
||||||
|
#define AVERROR_IO AVERROR(EIO) ///< I/O error
|
||||||
|
#define AVERROR_NOENT AVERROR(ENOENT) ///< No such file or directory
|
||||||
|
#define AVERROR_NOFMT AVERROR(EILSEQ) ///< Unknown format
|
||||||
|
#define AVERROR_NOMEM AVERROR(ENOMEM) ///< Not enough memory
|
||||||
|
#define AVERROR_NOTSUPP AVERROR(ENOSYS) ///< Operation not supported
|
||||||
|
#define AVERROR_NUMEXPECTED AVERROR(EDOM) ///< Number syntax expected in filename
|
||||||
|
#define AVERROR_UNKNOWN AVERROR(EINVAL) ///< Unknown error
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AVERROR_EOF AVERROR(EPIPE) ///< End of file
|
||||||
|
|
||||||
|
#define AVERROR_PATCHWELCOME (-MKTAG('P','A','W','E')) ///< Not yet implemented in FFmpeg, patches welcome
|
||||||
|
|
||||||
|
#if LIBAVUTIL_VERSION_MAJOR > 50
|
||||||
|
#define AVERROR_INVALIDDATA (-MKTAG('I','N','D','A')) ///< Invalid data found when processing input
|
||||||
|
#define AVERROR_NUMEXPECTED (-MKTAG('N','U','E','X')) ///< Number syntax expected in filename
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts a description of the AVERROR code errnum in errbuf.
|
||||||
|
* In case of failure the global variable errno is set to indicate the
|
||||||
|
* error. Even in case of failure av_strerror() will print a generic
|
||||||
|
* error message indicating the errnum provided to errbuf.
|
||||||
|
*
|
||||||
|
* @param errbuf_size the size in bytes of errbuf
|
||||||
|
* @return 0 on success, a negative value if a description for errnum
|
||||||
|
* cannot be found
|
||||||
|
*/
|
||||||
|
int av_strerror(int errnum, char *errbuf, size_t errbuf_size);
|
||||||
|
|
||||||
|
#endif /* AVUTIL_ERROR_H */
|
||||||
+116
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* a very simple circular buffer FIFO implementation
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_FIFO_H
|
||||||
|
#define AVUTIL_FIFO_H
|
||||||
|
|
||||||
|
#include <msc_stdint.h>
|
||||||
|
|
||||||
|
typedef struct AVFifoBuffer {
|
||||||
|
uint8_t *buffer;
|
||||||
|
uint8_t *rptr, *wptr, *end;
|
||||||
|
uint32_t rndx, wndx;
|
||||||
|
} AVFifoBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes an AVFifoBuffer.
|
||||||
|
* @param size of FIFO
|
||||||
|
* @return AVFifoBuffer or NULL in case of memory allocation failure
|
||||||
|
*/
|
||||||
|
AVFifoBuffer *av_fifo_alloc(unsigned int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees an AVFifoBuffer.
|
||||||
|
* @param *f AVFifoBuffer to free
|
||||||
|
*/
|
||||||
|
void av_fifo_free(AVFifoBuffer *f);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the AVFifoBuffer to the state right after av_fifo_alloc, in particular it is emptied.
|
||||||
|
* @param *f AVFifoBuffer to reset
|
||||||
|
*/
|
||||||
|
void av_fifo_reset(AVFifoBuffer *f);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the amount of data in bytes in the AVFifoBuffer, that is the
|
||||||
|
* amount of data you can read from it.
|
||||||
|
* @param *f AVFifoBuffer to read from
|
||||||
|
* @return size
|
||||||
|
*/
|
||||||
|
int av_fifo_size(AVFifoBuffer *f);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the amount of space in bytes in the AVFifoBuffer, that is the
|
||||||
|
* amount of data you can write into it.
|
||||||
|
* @param *f AVFifoBuffer to write into
|
||||||
|
* @return size
|
||||||
|
*/
|
||||||
|
int av_fifo_space(AVFifoBuffer *f);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Feeds data from an AVFifoBuffer to a user-supplied callback.
|
||||||
|
* @param *f AVFifoBuffer to read from
|
||||||
|
* @param buf_size number of bytes to read
|
||||||
|
* @param *func generic read function
|
||||||
|
* @param *dest data destination
|
||||||
|
*/
|
||||||
|
int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Feeds data from a user-supplied callback to an AVFifoBuffer.
|
||||||
|
* @param *f AVFifoBuffer to write to
|
||||||
|
* @param *src data source; non-const since it may be used as a
|
||||||
|
* modifiable context by the function defined in func
|
||||||
|
* @param size number of bytes to write
|
||||||
|
* @param *func generic write function; the first parameter is src,
|
||||||
|
* the second is dest_buf, the third is dest_buf_size.
|
||||||
|
* func must return the number of bytes written to dest_buf, or <= 0 to
|
||||||
|
* indicate no more data available to write.
|
||||||
|
* If func is NULL, src is interpreted as a simple byte array for source data.
|
||||||
|
* @return the number of bytes written to the FIFO
|
||||||
|
*/
|
||||||
|
int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resizes an AVFifoBuffer.
|
||||||
|
* @param *f AVFifoBuffer to resize
|
||||||
|
* @param size new AVFifoBuffer size in bytes
|
||||||
|
* @return <0 for failure, >=0 otherwise
|
||||||
|
*/
|
||||||
|
int av_fifo_realloc2(AVFifoBuffer *f, unsigned int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and discards the specified amount of data from an AVFifoBuffer.
|
||||||
|
* @param *f AVFifoBuffer to read from
|
||||||
|
* @param size amount of data to read in bytes
|
||||||
|
*/
|
||||||
|
void av_fifo_drain(AVFifoBuffer *f, int size);
|
||||||
|
|
||||||
|
static inline uint8_t av_fifo_peek(AVFifoBuffer *f, int offs)
|
||||||
|
{
|
||||||
|
uint8_t *ptr = f->rptr + offs;
|
||||||
|
if (ptr >= f->end)
|
||||||
|
ptr -= f->end - f->buffer;
|
||||||
|
return *ptr;
|
||||||
|
}
|
||||||
|
#endif /* AVUTIL_FIFO_H */
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_INTFLOAT_READWRITE_H
|
||||||
|
#define AVUTIL_INTFLOAT_READWRITE_H
|
||||||
|
|
||||||
|
#include <msc_stdint.h>
|
||||||
|
#include "attributes.h"
|
||||||
|
|
||||||
|
/* IEEE 80 bits extended float */
|
||||||
|
typedef struct AVExtFloat {
|
||||||
|
uint8_t exponent[2];
|
||||||
|
uint8_t mantissa[8];
|
||||||
|
} AVExtFloat;
|
||||||
|
|
||||||
|
double av_int2dbl(int64_t v) av_const;
|
||||||
|
float av_int2flt(int32_t v) av_const;
|
||||||
|
double av_ext2dbl(const AVExtFloat ext) av_const;
|
||||||
|
int64_t av_dbl2int(double d) av_const;
|
||||||
|
int32_t av_flt2int(float d) av_const;
|
||||||
|
AVExtFloat av_dbl2ext(double d) av_const;
|
||||||
|
|
||||||
|
#endif /* AVUTIL_INTFLOAT_READWRITE_H */
|
||||||
+123
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_LOG_H
|
||||||
|
#define AVUTIL_LOG_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "avutil.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the class of an AVClass context structure. That is an
|
||||||
|
* arbitrary struct of which the first field is a pointer to an
|
||||||
|
* AVClass struct (e.g. AVCodecContext, AVFormatContext etc.).
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/**
|
||||||
|
* The name of the class; usually it is the same name as the
|
||||||
|
* context structure type to which the AVClass is associated.
|
||||||
|
*/
|
||||||
|
const char* class_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A pointer to a function which returns the name of a context
|
||||||
|
* instance ctx associated with the class.
|
||||||
|
*/
|
||||||
|
const char* (*item_name)(void* ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a pointer to the first option specified in the class if any or NULL
|
||||||
|
*
|
||||||
|
* @see av_set_default_options()
|
||||||
|
*/
|
||||||
|
const struct AVOption *option;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LIBAVUTIL_VERSION with which this structure was created.
|
||||||
|
* This is used to allow fields to be added without requiring major
|
||||||
|
* version bumps everywhere.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int version;
|
||||||
|
} AVClass;
|
||||||
|
|
||||||
|
/* av_log API */
|
||||||
|
|
||||||
|
#define AV_LOG_QUIET -8
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Something went really wrong and we will crash now.
|
||||||
|
*/
|
||||||
|
#define AV_LOG_PANIC 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Something went wrong and recovery is not possible.
|
||||||
|
* For example, no header was found for a format which depends
|
||||||
|
* on headers or an illegal combination of parameters is used.
|
||||||
|
*/
|
||||||
|
#define AV_LOG_FATAL 8
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Something went wrong and cannot losslessly be recovered.
|
||||||
|
* However, not all future data is affected.
|
||||||
|
*/
|
||||||
|
#define AV_LOG_ERROR 16
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Something somehow does not look correct. This may or may not
|
||||||
|
* lead to problems. An example would be the use of '-vstrict -2'.
|
||||||
|
*/
|
||||||
|
#define AV_LOG_WARNING 24
|
||||||
|
|
||||||
|
#define AV_LOG_INFO 32
|
||||||
|
#define AV_LOG_VERBOSE 40
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stuff which is only useful for libav* developers.
|
||||||
|
*/
|
||||||
|
#define AV_LOG_DEBUG 48
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the specified message to the log if the level is less than or equal
|
||||||
|
* to the current av_log_level. By default, all logging messages are sent to
|
||||||
|
* stderr. This behavior can be altered by setting a different av_vlog callback
|
||||||
|
* function.
|
||||||
|
*
|
||||||
|
* @param avcl A pointer to an arbitrary struct of which the first field is a
|
||||||
|
* pointer to an AVClass struct.
|
||||||
|
* @param level The importance level of the message, lower values signifying
|
||||||
|
* higher importance.
|
||||||
|
* @param fmt The format string (printf-compatible) that specifies how
|
||||||
|
* subsequent arguments are converted to output.
|
||||||
|
* @see av_vlog
|
||||||
|
*/
|
||||||
|
#ifdef __GNUC__
|
||||||
|
void av_log(void*, int level, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 3, 4)));
|
||||||
|
#else
|
||||||
|
void av_log(void*, int level, const char *fmt, ...);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void av_vlog(void*, int level, const char *fmt, va_list);
|
||||||
|
int av_log_get_level(void);
|
||||||
|
void av_log_set_level(int);
|
||||||
|
void av_log_set_callback(void (*)(void*, int, const char*, va_list));
|
||||||
|
void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl);
|
||||||
|
|
||||||
|
#endif /* AVUTIL_LOG_H */
|
||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* LZO 1x decompression
|
||||||
|
* copyright (c) 2006 Reimar Doeffinger
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_LZO_H
|
||||||
|
#define AVUTIL_LZO_H
|
||||||
|
|
||||||
|
#include <msc_stdint.h>
|
||||||
|
|
||||||
|
/** \defgroup errflags Error flags returned by av_lzo1x_decode
|
||||||
|
* \{ */
|
||||||
|
//! end of the input buffer reached before decoding finished
|
||||||
|
#define AV_LZO_INPUT_DEPLETED 1
|
||||||
|
//! decoded data did not fit into output buffer
|
||||||
|
#define AV_LZO_OUTPUT_FULL 2
|
||||||
|
//! a reference to previously decoded data was wrong
|
||||||
|
#define AV_LZO_INVALID_BACKPTR 4
|
||||||
|
//! a non-specific error in the compressed bitstream
|
||||||
|
#define AV_LZO_ERROR 8
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
#define AV_LZO_INPUT_PADDING 8
|
||||||
|
#define AV_LZO_OUTPUT_PADDING 12
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Decodes LZO 1x compressed data.
|
||||||
|
* \param out output buffer
|
||||||
|
* \param outlen size of output buffer, number of bytes left are returned here
|
||||||
|
* \param in input buffer
|
||||||
|
* \param inlen size of input buffer, number of bytes left are returned here
|
||||||
|
* \return 0 on success, otherwise a combination of the error flags above
|
||||||
|
*
|
||||||
|
* Make sure all buffers are appropriately padded, in must provide
|
||||||
|
* AV_LZO_INPUT_PADDING, out must provide AV_LZO_OUTPUT_PADDING additional bytes.
|
||||||
|
*/
|
||||||
|
int av_lzo1x_decode(void *out, int *outlen, const void *in, int *inlen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief deliberately overlapping memcpy implementation
|
||||||
|
* \param dst destination buffer; must be padded with 12 additional bytes
|
||||||
|
* \param back how many bytes back we start (the initial size of the overlapping window)
|
||||||
|
* \param cnt number of bytes to copy, must be >= 0
|
||||||
|
*
|
||||||
|
* cnt > back is valid, this will copy the bytes we just copied,
|
||||||
|
* thus creating a repeating pattern with a period length of back.
|
||||||
|
*/
|
||||||
|
void av_memcpy_backptr(uint8_t *dst, int back, int cnt);
|
||||||
|
|
||||||
|
#endif /* AVUTIL_LZO_H */
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_MATHEMATICS_H
|
||||||
|
#define AVUTIL_MATHEMATICS_H
|
||||||
|
|
||||||
|
#include <msc_stdint.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "attributes.h"
|
||||||
|
#include "rational.h"
|
||||||
|
|
||||||
|
#ifndef M_E
|
||||||
|
#define M_E 2.7182818284590452354 /* e */
|
||||||
|
#endif
|
||||||
|
#ifndef M_LN2
|
||||||
|
#define M_LN2 0.69314718055994530942 /* log_e 2 */
|
||||||
|
#endif
|
||||||
|
#ifndef M_LN10
|
||||||
|
#define M_LN10 2.30258509299404568402 /* log_e 10 */
|
||||||
|
#endif
|
||||||
|
#ifndef M_LOG2_10
|
||||||
|
#define M_LOG2_10 3.32192809488736234787 /* log_2 10 */
|
||||||
|
#endif
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.14159265358979323846 /* pi */
|
||||||
|
#endif
|
||||||
|
#ifndef M_SQRT1_2
|
||||||
|
#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
|
||||||
|
#endif
|
||||||
|
#ifndef M_SQRT2
|
||||||
|
#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
|
||||||
|
#endif
|
||||||
|
#ifndef NAN
|
||||||
|
#define NAN (0.0/0.0)
|
||||||
|
#endif
|
||||||
|
#ifndef INFINITY
|
||||||
|
#define INFINITY (1.0/0.0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum AVRounding {
|
||||||
|
AV_ROUND_ZERO = 0, ///< Round toward zero.
|
||||||
|
AV_ROUND_INF = 1, ///< Round away from zero.
|
||||||
|
AV_ROUND_DOWN = 2, ///< Round toward -infinity.
|
||||||
|
AV_ROUND_UP = 3, ///< Round toward +infinity.
|
||||||
|
AV_ROUND_NEAR_INF = 5, ///< Round to nearest and halfway cases away from zero.
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the greatest common divisor of a and b.
|
||||||
|
* If both a and b are 0 or either or both are <0 then behavior is
|
||||||
|
* undefined.
|
||||||
|
*/
|
||||||
|
int64_t av_const av_gcd(int64_t a, int64_t b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rescales a 64-bit integer with rounding to nearest.
|
||||||
|
* A simple a*b/c isn't possible as it can overflow.
|
||||||
|
*/
|
||||||
|
int64_t av_rescale(int64_t a, int64_t b, int64_t c) av_const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rescales a 64-bit integer with specified rounding.
|
||||||
|
* A simple a*b/c isn't possible as it can overflow.
|
||||||
|
*/
|
||||||
|
int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding) av_const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rescales a 64-bit integer by 2 rational numbers.
|
||||||
|
*/
|
||||||
|
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares 2 timestamps each in its own timebases.
|
||||||
|
* The result of the function is undefined if one of the timestamps
|
||||||
|
* is outside the int64_t range when represented in the others timebase.
|
||||||
|
* @return -1 if ts_a is before ts_b, 1 if ts_a is after ts_b or 0 if they represent the same position
|
||||||
|
*/
|
||||||
|
int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* AVUTIL_MATHEMATICS_H */
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_MD5_H
|
||||||
|
#define AVUTIL_MD5_H
|
||||||
|
|
||||||
|
#include <msc_stdint.h>
|
||||||
|
|
||||||
|
extern const int av_md5_size;
|
||||||
|
|
||||||
|
struct AVMD5;
|
||||||
|
|
||||||
|
void av_md5_init(struct AVMD5 *ctx);
|
||||||
|
void av_md5_update(struct AVMD5 *ctx, const uint8_t *src, const int len);
|
||||||
|
void av_md5_final(struct AVMD5 *ctx, uint8_t *dst);
|
||||||
|
void av_md5_sum(uint8_t *dst, const uint8_t *src, const int len);
|
||||||
|
|
||||||
|
#endif /* AVUTIL_MD5_H */
|
||||||
|
|
||||||
+125
@@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* memory handling functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_MEM_H
|
||||||
|
#define AVUTIL_MEM_H
|
||||||
|
|
||||||
|
#include "attributes.h"
|
||||||
|
|
||||||
|
#if defined(__ICC) || defined(__SUNPRO_C)
|
||||||
|
#define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v
|
||||||
|
#define DECLARE_ASM_CONST(n,t,v) const t __attribute__ ((aligned (n))) v
|
||||||
|
#elif defined(__TI_COMPILER_VERSION__)
|
||||||
|
#define DECLARE_ALIGNED(n,t,v) \
|
||||||
|
AV_PRAGMA(DATA_ALIGN(v,n)) \
|
||||||
|
t __attribute__((aligned(n))) v
|
||||||
|
#define DECLARE_ASM_CONST(n,t,v) \
|
||||||
|
AV_PRAGMA(DATA_ALIGN(v,n)) \
|
||||||
|
static const t __attribute__((aligned(n))) v
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v
|
||||||
|
#define DECLARE_ASM_CONST(n,t,v) static const t attribute_used __attribute__ ((aligned (n))) v
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#define DECLARE_ALIGNED(n,t,v) __declspec(align(n)) t v
|
||||||
|
#define DECLARE_ASM_CONST(n,t,v) __declspec(align(n)) static const t v
|
||||||
|
#else
|
||||||
|
#define DECLARE_ALIGNED(n,t,v) t v
|
||||||
|
#define DECLARE_ASM_CONST(n,t,v) static const t v
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(3,1)
|
||||||
|
#define av_malloc_attrib __attribute__((__malloc__))
|
||||||
|
#else
|
||||||
|
#define av_malloc_attrib
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (!defined(__ICC) || __ICC > 1110) && AV_GCC_VERSION_AT_LEAST(4,3)
|
||||||
|
#define av_alloc_size(n) __attribute__((alloc_size(n)))
|
||||||
|
#else
|
||||||
|
#define av_alloc_size(n)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates a block of size bytes with alignment suitable for all
|
||||||
|
* memory accesses (including vectors if available on the CPU).
|
||||||
|
* @param size Size in bytes for the memory block to be allocated.
|
||||||
|
* @return Pointer to the allocated block, NULL if the block cannot
|
||||||
|
* be allocated.
|
||||||
|
* @see av_mallocz()
|
||||||
|
*/
|
||||||
|
void *av_malloc(unsigned int size) av_malloc_attrib av_alloc_size(1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates or reallocates a block of memory.
|
||||||
|
* If ptr is NULL and size > 0, allocates a new block. If
|
||||||
|
* size is zero, frees the memory block pointed to by ptr.
|
||||||
|
* @param size Size in bytes for the memory block to be allocated or
|
||||||
|
* reallocated.
|
||||||
|
* @param ptr Pointer to a memory block already allocated with
|
||||||
|
* av_malloc(z)() or av_realloc() or NULL.
|
||||||
|
* @return Pointer to a newly reallocated block or NULL if the block
|
||||||
|
* cannot be reallocated or the function is used to free the memory block.
|
||||||
|
* @see av_fast_realloc()
|
||||||
|
*/
|
||||||
|
void *av_realloc(void *ptr, unsigned int size) av_alloc_size(2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees a memory block which has been allocated with av_malloc(z)() or
|
||||||
|
* av_realloc().
|
||||||
|
* @param ptr Pointer to the memory block which should be freed.
|
||||||
|
* @note ptr = NULL is explicitly allowed.
|
||||||
|
* @note It is recommended that you use av_freep() instead.
|
||||||
|
* @see av_freep()
|
||||||
|
*/
|
||||||
|
void av_free(void *ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates a block of size bytes with alignment suitable for all
|
||||||
|
* memory accesses (including vectors if available on the CPU) and
|
||||||
|
* zeroes all the bytes of the block.
|
||||||
|
* @param size Size in bytes for the memory block to be allocated.
|
||||||
|
* @return Pointer to the allocated block, NULL if it cannot be allocated.
|
||||||
|
* @see av_malloc()
|
||||||
|
*/
|
||||||
|
void *av_mallocz(unsigned int size) av_malloc_attrib av_alloc_size(1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duplicates the string s.
|
||||||
|
* @param s string to be duplicated
|
||||||
|
* @return Pointer to a newly allocated string containing a
|
||||||
|
* copy of s or NULL if the string cannot be allocated.
|
||||||
|
*/
|
||||||
|
char *av_strdup(const char *s) av_malloc_attrib;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees a memory block which has been allocated with av_malloc(z)() or
|
||||||
|
* av_realloc() and set the pointer pointing to it to NULL.
|
||||||
|
* @param ptr Pointer to the pointer to the memory block which should
|
||||||
|
* be freed.
|
||||||
|
* @see av_free()
|
||||||
|
*/
|
||||||
|
void av_freep(void *ptr);
|
||||||
|
|
||||||
|
#endif /* AVUTIL_MEM_H */
|
||||||
+154
@@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* pixel format descriptor
|
||||||
|
* Copyright (c) 2009 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_PIXDESC_H
|
||||||
|
#define AVUTIL_PIXDESC_H
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
typedef struct AVComponentDescriptor{
|
||||||
|
uint16_t plane :2; ///< which of the 4 planes contains the component
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of elements between 2 horizontally consecutive pixels minus 1.
|
||||||
|
* Elements are bits for bitstream formats, bytes otherwise.
|
||||||
|
*/
|
||||||
|
uint16_t step_minus1 :3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of elements before the component of the first pixel plus 1.
|
||||||
|
* Elements are bits for bitstream formats, bytes otherwise.
|
||||||
|
*/
|
||||||
|
uint16_t offset_plus1 :3;
|
||||||
|
uint16_t shift :3; ///< number of least significant bits that must be shifted away to get the value
|
||||||
|
uint16_t depth_minus1 :4; ///< number of bits in the component minus 1
|
||||||
|
}AVComponentDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Descriptor that unambiguously describes how the bits of a pixel are
|
||||||
|
* stored in the up to 4 data planes of an image. It also stores the
|
||||||
|
* subsampling factors and number of components.
|
||||||
|
*
|
||||||
|
* @note This is separate of the colorspace (RGB, YCbCr, YPbPr, JPEG-style YUV
|
||||||
|
* and all the YUV variants) AVPixFmtDescriptor just stores how values
|
||||||
|
* are stored not what these values represent.
|
||||||
|
*/
|
||||||
|
typedef struct AVPixFmtDescriptor{
|
||||||
|
const char *name;
|
||||||
|
uint8_t nb_components; ///< The number of components each pixel has, (1-4)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Amount to shift the luma width right to find the chroma width.
|
||||||
|
* For YV12 this is 1 for example.
|
||||||
|
* chroma_width = -((-luma_width) >> log2_chroma_w)
|
||||||
|
* The note above is needed to ensure rounding up.
|
||||||
|
* This value only refers to the chroma components.
|
||||||
|
*/
|
||||||
|
uint8_t log2_chroma_w; ///< chroma_width = -((-luma_width )>>log2_chroma_w)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Amount to shift the luma height right to find the chroma height.
|
||||||
|
* For YV12 this is 1 for example.
|
||||||
|
* chroma_height= -((-luma_height) >> log2_chroma_h)
|
||||||
|
* The note above is needed to ensure rounding up.
|
||||||
|
* This value only refers to the chroma components.
|
||||||
|
*/
|
||||||
|
uint8_t log2_chroma_h;
|
||||||
|
uint8_t flags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters that describe how pixels are packed. If the format
|
||||||
|
* has chroma components, they must be stored in comp[1] and
|
||||||
|
* comp[2].
|
||||||
|
*/
|
||||||
|
AVComponentDescriptor comp[4];
|
||||||
|
}AVPixFmtDescriptor;
|
||||||
|
|
||||||
|
#define PIX_FMT_BE 1 ///< Pixel format is big-endian.
|
||||||
|
#define PIX_FMT_PAL 2 ///< Pixel format has a palette in data[1], values are indexes in this palette.
|
||||||
|
#define PIX_FMT_BITSTREAM 4 ///< All values of a component are bit-wise packed end to end.
|
||||||
|
#define PIX_FMT_HWACCEL 8 ///< Pixel format is an HW accelerated format.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array of all the pixel format descriptors.
|
||||||
|
*/
|
||||||
|
extern const AVPixFmtDescriptor av_pix_fmt_descriptors[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a line from an image, and writes the values of the
|
||||||
|
* pixel format component c to dst.
|
||||||
|
*
|
||||||
|
* @param data the array containing the pointers to the planes of the image
|
||||||
|
* @param linesizes the array containing the linesizes of the image
|
||||||
|
* @param desc the pixel format descriptor for the image
|
||||||
|
* @param x the horizontal coordinate of the first pixel to read
|
||||||
|
* @param y the vertical coordinate of the first pixel to read
|
||||||
|
* @param w the width of the line to read, that is the number of
|
||||||
|
* values to write to dst
|
||||||
|
* @param read_pal_component if not zero and the format is a paletted
|
||||||
|
* format writes the values corresponding to the palette
|
||||||
|
* component c in data[1] to dst, rather than the palette indexes in
|
||||||
|
* data[0]. The behavior is undefined if the format is not paletted.
|
||||||
|
*/
|
||||||
|
void read_line(uint16_t *dst, const uint8_t *data[4], const int linesize[4],
|
||||||
|
const AVPixFmtDescriptor *desc, int x, int y, int c, int w, int read_pal_component);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the values from src to the pixel format component c of an
|
||||||
|
* image line.
|
||||||
|
*
|
||||||
|
* @param src array containing the values to write
|
||||||
|
* @param data the array containing the pointers to the planes of the
|
||||||
|
* image to write into. It is supposed to be zeroed.
|
||||||
|
* @param linesizes the array containing the linesizes of the image
|
||||||
|
* @param desc the pixel format descriptor for the image
|
||||||
|
* @param x the horizontal coordinate of the first pixel to write
|
||||||
|
* @param y the vertical coordinate of the first pixel to write
|
||||||
|
* @param w the width of the line to write, that is the number of
|
||||||
|
* values to write to the image line
|
||||||
|
*/
|
||||||
|
void write_line(const uint16_t *src, uint8_t *data[4], const int linesize[4],
|
||||||
|
const AVPixFmtDescriptor *desc, int x, int y, int c, int w);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the pixel format corresponding to name.
|
||||||
|
*
|
||||||
|
* If there is no pixel format with name name, then looks for a
|
||||||
|
* pixel format with the name corresponding to the native endian
|
||||||
|
* format of name.
|
||||||
|
* For example in a little-endian system, first looks for "gray16",
|
||||||
|
* then for "gray16le".
|
||||||
|
*
|
||||||
|
* Finally if no pixel format has been found, returns PIX_FMT_NONE.
|
||||||
|
*/
|
||||||
|
enum PixelFormat av_get_pix_fmt(const char *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of bits per pixel used by the pixel format
|
||||||
|
* described by pixdesc.
|
||||||
|
*
|
||||||
|
* The returned number of bits refers to the number of bits actually
|
||||||
|
* used for storing the pixel information, that is padding bits are
|
||||||
|
* not counted.
|
||||||
|
*/
|
||||||
|
int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc);
|
||||||
|
|
||||||
|
#endif /* AVUTIL_PIXDESC_H */
|
||||||
+163
@@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_PIXFMT_H
|
||||||
|
#define AVUTIL_PIXFMT_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* pixel format definitions
|
||||||
|
*
|
||||||
|
* @warning This file has to be considered an internal but installed
|
||||||
|
* header, so it should not be directly included in your projects.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libavutil/avconfig.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pixel format. Notes:
|
||||||
|
*
|
||||||
|
* PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA
|
||||||
|
* color is put together as:
|
||||||
|
* (A << 24) | (R << 16) | (G << 8) | B
|
||||||
|
* This is stored as BGRA on little-endian CPU architectures and ARGB on
|
||||||
|
* big-endian CPUs.
|
||||||
|
*
|
||||||
|
* When the pixel format is palettized RGB (PIX_FMT_PAL8), the palettized
|
||||||
|
* image data is stored in AVFrame.data[0]. The palette is transported in
|
||||||
|
* AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is
|
||||||
|
* formatted the same as in PIX_FMT_RGB32 described above (i.e., it is
|
||||||
|
* also endian-specific). Note also that the individual RGB palette
|
||||||
|
* components stored in AVFrame.data[1] should be in the range 0..255.
|
||||||
|
* This is important as many custom PAL8 video codecs that were designed
|
||||||
|
* to run on the IBM VGA graphics adapter use 6-bit palette components.
|
||||||
|
*
|
||||||
|
* For all the 8bit per pixel formats, an RGB32 palette is in data[1] like
|
||||||
|
* for pal8. This palette is filled in automatically by the function
|
||||||
|
* allocating the picture.
|
||||||
|
*
|
||||||
|
* Note, make sure that all newly added big endian formats have pix_fmt&1==1
|
||||||
|
* and that all newly added little endian formats have pix_fmt&1==0
|
||||||
|
* this allows simpler detection of big vs little endian.
|
||||||
|
*/
|
||||||
|
enum PixelFormat {
|
||||||
|
PIX_FMT_NONE= -1,
|
||||||
|
PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
|
||||||
|
PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
|
||||||
|
PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB...
|
||||||
|
PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR...
|
||||||
|
PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
|
||||||
|
PIX_FMT_YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
|
||||||
|
PIX_FMT_YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
|
||||||
|
PIX_FMT_YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
|
||||||
|
PIX_FMT_GRAY8, ///< Y , 8bpp
|
||||||
|
PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb
|
||||||
|
PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb
|
||||||
|
PIX_FMT_PAL8, ///< 8 bit with PIX_FMT_RGB32 palette
|
||||||
|
PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG)
|
||||||
|
PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG)
|
||||||
|
PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG)
|
||||||
|
PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing
|
||||||
|
PIX_FMT_XVMC_MPEG2_IDCT,
|
||||||
|
PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
|
||||||
|
PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
|
||||||
|
PIX_FMT_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
|
||||||
|
PIX_FMT_BGR4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits
|
||||||
|
PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb)
|
||||||
|
PIX_FMT_RGB8, ///< packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
|
||||||
|
PIX_FMT_RGB4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits
|
||||||
|
PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb)
|
||||||
|
PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V)
|
||||||
|
PIX_FMT_NV21, ///< as above, but U and V bytes are swapped
|
||||||
|
|
||||||
|
PIX_FMT_ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
|
||||||
|
PIX_FMT_RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
|
||||||
|
PIX_FMT_ABGR, ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
|
||||||
|
PIX_FMT_BGRA, ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
|
||||||
|
|
||||||
|
PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian
|
||||||
|
PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian
|
||||||
|
PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
|
||||||
|
PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG)
|
||||||
|
PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
|
||||||
|
PIX_FMT_VDPAU_H264,///< H.264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
|
||||||
|
PIX_FMT_VDPAU_MPEG1,///< MPEG-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
|
||||||
|
PIX_FMT_VDPAU_MPEG2,///< MPEG-2 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
|
||||||
|
PIX_FMT_VDPAU_WMV3,///< WMV3 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
|
||||||
|
PIX_FMT_VDPAU_VC1, ///< VC-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
|
||||||
|
PIX_FMT_RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian
|
||||||
|
PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian
|
||||||
|
|
||||||
|
PIX_FMT_RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
|
||||||
|
PIX_FMT_RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
|
||||||
|
PIX_FMT_RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), big-endian, most significant bit to 0
|
||||||
|
PIX_FMT_RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), little-endian, most significant bit to 0
|
||||||
|
|
||||||
|
PIX_FMT_BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian
|
||||||
|
PIX_FMT_BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian
|
||||||
|
PIX_FMT_BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), big-endian, most significant bit to 1
|
||||||
|
PIX_FMT_BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), little-endian, most significant bit to 1
|
||||||
|
|
||||||
|
PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers
|
||||||
|
PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers
|
||||||
|
PIX_FMT_VAAPI_VLD, ///< HW decoding through VA API, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
|
||||||
|
|
||||||
|
PIX_FMT_YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
|
||||||
|
PIX_FMT_YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
|
||||||
|
PIX_FMT_YUV422P16LE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
|
||||||
|
PIX_FMT_YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
|
||||||
|
PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
|
||||||
|
PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
|
||||||
|
PIX_FMT_VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
|
||||||
|
PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer
|
||||||
|
|
||||||
|
PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0
|
||||||
|
PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), little-endian, most significant bits to 0
|
||||||
|
PIX_FMT_BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), big-endian, most significant bits to 1
|
||||||
|
PIX_FMT_BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), little-endian, most significant bits to 1
|
||||||
|
PIX_FMT_Y400A, ///< 8bit gray, 8bit alpha
|
||||||
|
PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
|
||||||
|
};
|
||||||
|
|
||||||
|
#if AV_HAVE_BIGENDIAN
|
||||||
|
# define PIX_FMT_NE(be, le) PIX_FMT_##be
|
||||||
|
#else
|
||||||
|
# define PIX_FMT_NE(be, le) PIX_FMT_##le
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PIX_FMT_RGB32 PIX_FMT_NE(ARGB, BGRA)
|
||||||
|
#define PIX_FMT_RGB32_1 PIX_FMT_NE(RGBA, ABGR)
|
||||||
|
#define PIX_FMT_BGR32 PIX_FMT_NE(ABGR, RGBA)
|
||||||
|
#define PIX_FMT_BGR32_1 PIX_FMT_NE(BGRA, ARGB)
|
||||||
|
|
||||||
|
#define PIX_FMT_GRAY16 PIX_FMT_NE(GRAY16BE, GRAY16LE)
|
||||||
|
#define PIX_FMT_RGB48 PIX_FMT_NE(RGB48BE, RGB48LE)
|
||||||
|
#define PIX_FMT_RGB565 PIX_FMT_NE(RGB565BE, RGB565LE)
|
||||||
|
#define PIX_FMT_RGB555 PIX_FMT_NE(RGB555BE, RGB555LE)
|
||||||
|
#define PIX_FMT_RGB444 PIX_FMT_NE(RGB444BE, RGB444LE)
|
||||||
|
#define PIX_FMT_BGR565 PIX_FMT_NE(BGR565BE, BGR565LE)
|
||||||
|
#define PIX_FMT_BGR555 PIX_FMT_NE(BGR555BE, BGR555LE)
|
||||||
|
#define PIX_FMT_BGR444 PIX_FMT_NE(BGR444BE, BGR444LE)
|
||||||
|
|
||||||
|
#define PIX_FMT_YUV420P16 PIX_FMT_NE(YUV420P16BE, YUV420P16LE)
|
||||||
|
#define PIX_FMT_YUV422P16 PIX_FMT_NE(YUV422P16BE, YUV422P16LE)
|
||||||
|
#define PIX_FMT_YUV444P16 PIX_FMT_NE(YUV444P16BE, YUV444P16LE)
|
||||||
|
|
||||||
|
#endif /* AVUTIL_PIXFMT_H */
|
||||||
+129
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* rational numbers
|
||||||
|
* Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* rational numbers
|
||||||
|
* @author Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_RATIONAL_H
|
||||||
|
#define AVUTIL_RATIONAL_H
|
||||||
|
|
||||||
|
#include <msc_stdint.h>
|
||||||
|
#include "attributes.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rational number numerator/denominator
|
||||||
|
*/
|
||||||
|
typedef struct AVRational{
|
||||||
|
int num; ///< numerator
|
||||||
|
int den; ///< denominator
|
||||||
|
} AVRational;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares two rationals.
|
||||||
|
* @param a first rational
|
||||||
|
* @param b second rational
|
||||||
|
* @return 0 if a==b, 1 if a>b and -1 if a<b
|
||||||
|
*/
|
||||||
|
static inline int av_cmp_q(AVRational a, AVRational b){
|
||||||
|
const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den;
|
||||||
|
|
||||||
|
if(tmp) return (tmp>>63)|1;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts rational to double.
|
||||||
|
* @param a rational to convert
|
||||||
|
* @return (double) a
|
||||||
|
*/
|
||||||
|
static inline double av_q2d(AVRational a){
|
||||||
|
return a.num / (double) a.den;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduces a fraction.
|
||||||
|
* This is useful for framerate calculations.
|
||||||
|
* @param dst_num destination numerator
|
||||||
|
* @param dst_den destination denominator
|
||||||
|
* @param num source numerator
|
||||||
|
* @param den source denominator
|
||||||
|
* @param max the maximum allowed for dst_num & dst_den
|
||||||
|
* @return 1 if exact, 0 otherwise
|
||||||
|
*/
|
||||||
|
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplies two rationals.
|
||||||
|
* @param b first rational
|
||||||
|
* @param c second rational
|
||||||
|
* @return b*c
|
||||||
|
*/
|
||||||
|
AVRational av_mul_q(AVRational b, AVRational c) av_const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Divides one rational by another.
|
||||||
|
* @param b first rational
|
||||||
|
* @param c second rational
|
||||||
|
* @return b/c
|
||||||
|
*/
|
||||||
|
AVRational av_div_q(AVRational b, AVRational c) av_const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds two rationals.
|
||||||
|
* @param b first rational
|
||||||
|
* @param c second rational
|
||||||
|
* @return b+c
|
||||||
|
*/
|
||||||
|
AVRational av_add_q(AVRational b, AVRational c) av_const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtracts one rational from another.
|
||||||
|
* @param b first rational
|
||||||
|
* @param c second rational
|
||||||
|
* @return b-c
|
||||||
|
*/
|
||||||
|
AVRational av_sub_q(AVRational b, AVRational c) av_const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a double precision floating point number to a rational.
|
||||||
|
* @param d double to convert
|
||||||
|
* @param max the maximum allowed numerator and denominator
|
||||||
|
* @return (AVRational) d
|
||||||
|
*/
|
||||||
|
AVRational av_d2q(double d, int max) av_const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 1 if q1 is nearer to q than q2, -1 if q2 is nearer
|
||||||
|
* than q1, 0 if they have the same distance.
|
||||||
|
*/
|
||||||
|
int av_nearer_q(AVRational q, AVRational q1, AVRational q2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the nearest value in q_list to q.
|
||||||
|
* @param q_list an array of rationals terminated by {0, 0}
|
||||||
|
* @return the index of the nearest value found in the array
|
||||||
|
*/
|
||||||
|
int av_find_nearest_q_idx(AVRational q, const AVRational* q_list);
|
||||||
|
|
||||||
|
#endif /* AVUTIL_RATIONAL_H */
|
||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_SHA1_H
|
||||||
|
#define AVUTIL_SHA1_H
|
||||||
|
|
||||||
|
#include <msc_stdint.h>
|
||||||
|
|
||||||
|
extern const int av_sha1_size;
|
||||||
|
|
||||||
|
struct AVSHA1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes SHA-1 hashing.
|
||||||
|
*
|
||||||
|
* @param context pointer to the function context (of size av_sha_size)
|
||||||
|
* @deprecated use av_sha_init() instead
|
||||||
|
*/
|
||||||
|
void av_sha1_init(struct AVSHA1* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates hash value.
|
||||||
|
*
|
||||||
|
* @param context hash function context
|
||||||
|
* @param data input data to update hash with
|
||||||
|
* @param len input data length
|
||||||
|
* @deprecated use av_sha_update() instead
|
||||||
|
*/
|
||||||
|
void av_sha1_update(struct AVSHA1* context, const uint8_t* data, unsigned int len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finishes hashing and output digest value.
|
||||||
|
*
|
||||||
|
* @param context hash function context
|
||||||
|
* @param digest buffer where output digest value is stored
|
||||||
|
* @deprecated use av_sha_final() instead
|
||||||
|
*/
|
||||||
|
void av_sha1_final(struct AVSHA1* context, uint8_t digest[20]);
|
||||||
|
|
||||||
|
#endif /* AVUTIL_SHA1_H */
|
||||||
+330
@@ -0,0 +1,330 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg 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.
|
||||||
|
*
|
||||||
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SWSCALE_SWSCALE_H
|
||||||
|
#define SWSCALE_SWSCALE_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief
|
||||||
|
* external api for the swscale stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libavutil/avutil.h"
|
||||||
|
|
||||||
|
#define LIBSWSCALE_VERSION_MAJOR 0
|
||||||
|
#define LIBSWSCALE_VERSION_MINOR 11
|
||||||
|
#define LIBSWSCALE_VERSION_MICRO 0
|
||||||
|
|
||||||
|
#define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \
|
||||||
|
LIBSWSCALE_VERSION_MINOR, \
|
||||||
|
LIBSWSCALE_VERSION_MICRO)
|
||||||
|
#define LIBSWSCALE_VERSION AV_VERSION(LIBSWSCALE_VERSION_MAJOR, \
|
||||||
|
LIBSWSCALE_VERSION_MINOR, \
|
||||||
|
LIBSWSCALE_VERSION_MICRO)
|
||||||
|
#define LIBSWSCALE_BUILD LIBSWSCALE_VERSION_INT
|
||||||
|
|
||||||
|
#define LIBSWSCALE_IDENT "SwS" AV_STRINGIFY(LIBSWSCALE_VERSION)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the LIBSWSCALE_VERSION_INT constant.
|
||||||
|
*/
|
||||||
|
unsigned swscale_version(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the libswscale build-time configuration.
|
||||||
|
*/
|
||||||
|
const char *swscale_configuration(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the libswscale license.
|
||||||
|
*/
|
||||||
|
const char *swscale_license(void);
|
||||||
|
|
||||||
|
/* values for the flags, the stuff on the command line is different */
|
||||||
|
#define SWS_FAST_BILINEAR 1
|
||||||
|
#define SWS_BILINEAR 2
|
||||||
|
#define SWS_BICUBIC 4
|
||||||
|
#define SWS_X 8
|
||||||
|
#define SWS_POINT 0x10
|
||||||
|
#define SWS_AREA 0x20
|
||||||
|
#define SWS_BICUBLIN 0x40
|
||||||
|
#define SWS_GAUSS 0x80
|
||||||
|
#define SWS_SINC 0x100
|
||||||
|
#define SWS_LANCZOS 0x200
|
||||||
|
#define SWS_SPLINE 0x400
|
||||||
|
|
||||||
|
#define SWS_SRC_V_CHR_DROP_MASK 0x30000
|
||||||
|
#define SWS_SRC_V_CHR_DROP_SHIFT 16
|
||||||
|
|
||||||
|
#define SWS_PARAM_DEFAULT 123456
|
||||||
|
|
||||||
|
#define SWS_PRINT_INFO 0x1000
|
||||||
|
|
||||||
|
//the following 3 flags are not completely implemented
|
||||||
|
//internal chrominace subsampling info
|
||||||
|
#define SWS_FULL_CHR_H_INT 0x2000
|
||||||
|
//input subsampling info
|
||||||
|
#define SWS_FULL_CHR_H_INP 0x4000
|
||||||
|
#define SWS_DIRECT_BGR 0x8000
|
||||||
|
#define SWS_ACCURATE_RND 0x40000
|
||||||
|
#define SWS_BITEXACT 0x80000
|
||||||
|
|
||||||
|
#define SWS_CPU_CAPS_MMX 0x80000000
|
||||||
|
#define SWS_CPU_CAPS_MMX2 0x20000000
|
||||||
|
#define SWS_CPU_CAPS_3DNOW 0x40000000
|
||||||
|
#define SWS_CPU_CAPS_ALTIVEC 0x10000000
|
||||||
|
#define SWS_CPU_CAPS_BFIN 0x01000000
|
||||||
|
|
||||||
|
#define SWS_MAX_REDUCE_CUTOFF 0.002
|
||||||
|
|
||||||
|
#define SWS_CS_ITU709 1
|
||||||
|
#define SWS_CS_FCC 4
|
||||||
|
#define SWS_CS_ITU601 5
|
||||||
|
#define SWS_CS_ITU624 5
|
||||||
|
#define SWS_CS_SMPTE170M 5
|
||||||
|
#define SWS_CS_SMPTE240M 7
|
||||||
|
#define SWS_CS_DEFAULT 5
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pointer to yuv<->rgb coefficients for the given colorspace
|
||||||
|
* suitable for sws_setColorspaceDetails().
|
||||||
|
*
|
||||||
|
* @param colorspace One of the SWS_CS_* macros. If invalid,
|
||||||
|
* SWS_CS_DEFAULT is used.
|
||||||
|
*/
|
||||||
|
const int *sws_getCoefficients(int colorspace);
|
||||||
|
|
||||||
|
|
||||||
|
// when used for filters they must have an odd number of elements
|
||||||
|
// coeffs cannot be shared between vectors
|
||||||
|
typedef struct {
|
||||||
|
double *coeff; ///< pointer to the list of coefficients
|
||||||
|
int length; ///< number of coefficients in the vector
|
||||||
|
} SwsVector;
|
||||||
|
|
||||||
|
// vectors can be shared
|
||||||
|
typedef struct {
|
||||||
|
SwsVector *lumH;
|
||||||
|
SwsVector *lumV;
|
||||||
|
SwsVector *chrH;
|
||||||
|
SwsVector *chrV;
|
||||||
|
} SwsFilter;
|
||||||
|
|
||||||
|
struct SwsContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a positive value if pix_fmt is a supported input format, 0
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
int sws_isSupportedInput(enum PixelFormat pix_fmt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a positive value if pix_fmt is a supported output format, 0
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
int sws_isSupportedOutput(enum PixelFormat pix_fmt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees the swscaler context swsContext.
|
||||||
|
* If swsContext is NULL, then does nothing.
|
||||||
|
*/
|
||||||
|
void sws_freeContext(struct SwsContext *swsContext);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates and returns a SwsContext. You need it to perform
|
||||||
|
* scaling/conversion operations using sws_scale().
|
||||||
|
*
|
||||||
|
* @param srcW the width of the source image
|
||||||
|
* @param srcH the height of the source image
|
||||||
|
* @param srcFormat the source image format
|
||||||
|
* @param dstW the width of the destination image
|
||||||
|
* @param dstH the height of the destination image
|
||||||
|
* @param dstFormat the destination image format
|
||||||
|
* @param flags specify which algorithm and options to use for rescaling
|
||||||
|
* @return a pointer to an allocated context, or NULL in case of error
|
||||||
|
*/
|
||||||
|
struct SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat,
|
||||||
|
int dstW, int dstH, enum PixelFormat dstFormat,
|
||||||
|
int flags, SwsFilter *srcFilter,
|
||||||
|
SwsFilter *dstFilter, const double *param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scales the image slice in srcSlice and puts the resulting scaled
|
||||||
|
* slice in the image in dst. A slice is a sequence of consecutive
|
||||||
|
* rows in an image.
|
||||||
|
*
|
||||||
|
* Slices have to be provided in sequential order, either in
|
||||||
|
* top-bottom or bottom-top order. If slices are provided in
|
||||||
|
* non-sequential order the behavior of the function is undefined.
|
||||||
|
*
|
||||||
|
* @param context the scaling context previously created with
|
||||||
|
* sws_getContext()
|
||||||
|
* @param srcSlice the array containing the pointers to the planes of
|
||||||
|
* the source slice
|
||||||
|
* @param srcStride the array containing the strides for each plane of
|
||||||
|
* the source image
|
||||||
|
* @param srcSliceY the position in the source image of the slice to
|
||||||
|
* process, that is the number (counted starting from
|
||||||
|
* zero) in the image of the first row of the slice
|
||||||
|
* @param srcSliceH the height of the source slice, that is the number
|
||||||
|
* of rows in the slice
|
||||||
|
* @param dst the array containing the pointers to the planes of
|
||||||
|
* the destination image
|
||||||
|
* @param dstStride the array containing the strides for each plane of
|
||||||
|
* the destination image
|
||||||
|
* @return the height of the output slice
|
||||||
|
*/
|
||||||
|
int sws_scale(struct SwsContext *context, const uint8_t* const srcSlice[], const int srcStride[],
|
||||||
|
int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[]);
|
||||||
|
#if LIBSWSCALE_VERSION_MAJOR < 1
|
||||||
|
/**
|
||||||
|
* @deprecated Use sws_scale() instead.
|
||||||
|
*/
|
||||||
|
int sws_scale_ordered(struct SwsContext *context, const uint8_t* const src[],
|
||||||
|
int srcStride[], int srcSliceY, int srcSliceH,
|
||||||
|
uint8_t* dst[], int dstStride[]) attribute_deprecated;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param inv_table the yuv2rgb coefficients, normally ff_yuv2rgb_coeffs[x]
|
||||||
|
* @param fullRange if 1 then the luma range is 0..255 if 0 it is 16..235
|
||||||
|
* @return -1 if not supported
|
||||||
|
*/
|
||||||
|
int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],
|
||||||
|
int srcRange, const int table[4], int dstRange,
|
||||||
|
int brightness, int contrast, int saturation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return -1 if not supported
|
||||||
|
*/
|
||||||
|
int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table,
|
||||||
|
int *srcRange, int **table, int *dstRange,
|
||||||
|
int *brightness, int *contrast, int *saturation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates and returns an uninitialized vector with length coefficients.
|
||||||
|
*/
|
||||||
|
SwsVector *sws_allocVec(int length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a normalized Gaussian curve used to filter stuff
|
||||||
|
* quality=3 is high quality, lower is lower quality.
|
||||||
|
*/
|
||||||
|
SwsVector *sws_getGaussianVec(double variance, double quality);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates and returns a vector with length coefficients, all
|
||||||
|
* with the same value c.
|
||||||
|
*/
|
||||||
|
SwsVector *sws_getConstVec(double c, int length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates and returns a vector with just one coefficient, with
|
||||||
|
* value 1.0.
|
||||||
|
*/
|
||||||
|
SwsVector *sws_getIdentityVec(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scales all the coefficients of a by the scalar value.
|
||||||
|
*/
|
||||||
|
void sws_scaleVec(SwsVector *a, double scalar);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scales all the coefficients of a so that their sum equals height.
|
||||||
|
*/
|
||||||
|
void sws_normalizeVec(SwsVector *a, double height);
|
||||||
|
void sws_convVec(SwsVector *a, SwsVector *b);
|
||||||
|
void sws_addVec(SwsVector *a, SwsVector *b);
|
||||||
|
void sws_subVec(SwsVector *a, SwsVector *b);
|
||||||
|
void sws_shiftVec(SwsVector *a, int shift);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates and returns a clone of the vector a, that is a vector
|
||||||
|
* with the same coefficients as a.
|
||||||
|
*/
|
||||||
|
SwsVector *sws_cloneVec(SwsVector *a);
|
||||||
|
|
||||||
|
#if LIBSWSCALE_VERSION_MAJOR < 1
|
||||||
|
/**
|
||||||
|
* @deprecated Use sws_printVec2() instead.
|
||||||
|
*/
|
||||||
|
attribute_deprecated void sws_printVec(SwsVector *a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints with av_log() a textual representation of the vector a
|
||||||
|
* if log_level <= av_log_level.
|
||||||
|
*/
|
||||||
|
void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level);
|
||||||
|
|
||||||
|
void sws_freeVec(SwsVector *a);
|
||||||
|
|
||||||
|
SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur,
|
||||||
|
float lumaSharpen, float chromaSharpen,
|
||||||
|
float chromaHShift, float chromaVShift,
|
||||||
|
int verbose);
|
||||||
|
void sws_freeFilter(SwsFilter *filter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if context can be reused, otherwise reallocates a new
|
||||||
|
* one.
|
||||||
|
*
|
||||||
|
* If context is NULL, just calls sws_getContext() to get a new
|
||||||
|
* context. Otherwise, checks if the parameters are the ones already
|
||||||
|
* saved in context. If that is the case, returns the current
|
||||||
|
* context. Otherwise, frees context and gets a new context with
|
||||||
|
* the new parameters.
|
||||||
|
*
|
||||||
|
* Be warned that srcFilter and dstFilter are not checked, they
|
||||||
|
* are assumed to remain the same.
|
||||||
|
*/
|
||||||
|
struct SwsContext *sws_getCachedContext(struct SwsContext *context,
|
||||||
|
int srcW, int srcH, enum PixelFormat srcFormat,
|
||||||
|
int dstW, int dstH, enum PixelFormat dstFormat,
|
||||||
|
int flags, SwsFilter *srcFilter,
|
||||||
|
SwsFilter *dstFilter, const double *param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an 8bit paletted frame into a frame with a color depth of 32-bits.
|
||||||
|
*
|
||||||
|
* The output frame will have the same packed format as the palette.
|
||||||
|
*
|
||||||
|
* @param src source frame buffer
|
||||||
|
* @param dst destination frame buffer
|
||||||
|
* @param num_pixels number of pixels to convert
|
||||||
|
* @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src
|
||||||
|
*/
|
||||||
|
void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an 8bit paletted frame into a frame with a color depth of 24 bits.
|
||||||
|
*
|
||||||
|
* With the palette format "ABCD", the destination frame ends up with the format "ABC".
|
||||||
|
*
|
||||||
|
* @param src source frame buffer
|
||||||
|
* @param dst destination frame buffer
|
||||||
|
* @param num_pixels number of pixels to convert
|
||||||
|
* @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src
|
||||||
|
*/
|
||||||
|
void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* SWSCALE_SWSCALE_H */
|
||||||
Vendored
-1214
File diff suppressed because it is too large
Load Diff
-12305
File diff suppressed because it is too large
Load Diff
-126
@@ -1,126 +0,0 @@
|
|||||||
/**********************************************************************************
|
|
||||||
* Copyright (c) 2008-2012 The Khronos Group Inc.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and/or associated documentation files (the
|
|
||||||
* "Materials"), to deal in the Materials without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Materials, and to
|
|
||||||
* permit persons to whom the Materials are 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 Materials.
|
|
||||||
*
|
|
||||||
* THE MATERIALS ARE 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
||||||
**********************************************************************************/
|
|
||||||
|
|
||||||
/* $Revision: 11708 $ on $Date: 2010-06-13 23:36:24 -0700 (Sun, 13 Jun 2010) $ */
|
|
||||||
|
|
||||||
#ifndef __OPENCL_CL_D3D10_H
|
|
||||||
#define __OPENCL_CL_D3D10_H
|
|
||||||
|
|
||||||
#include <d3d10.h>
|
|
||||||
#include <CL/cl.h>
|
|
||||||
#include <CL/cl_platform.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* cl_khr_d3d10_sharing */
|
|
||||||
#define cl_khr_d3d10_sharing 1
|
|
||||||
|
|
||||||
typedef cl_uint cl_d3d10_device_source_khr;
|
|
||||||
typedef cl_uint cl_d3d10_device_set_khr;
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// Error Codes
|
|
||||||
#define CL_INVALID_D3D10_DEVICE_KHR -1002
|
|
||||||
#define CL_INVALID_D3D10_RESOURCE_KHR -1003
|
|
||||||
#define CL_D3D10_RESOURCE_ALREADY_ACQUIRED_KHR -1004
|
|
||||||
#define CL_D3D10_RESOURCE_NOT_ACQUIRED_KHR -1005
|
|
||||||
|
|
||||||
// cl_d3d10_device_source_nv
|
|
||||||
#define CL_D3D10_DEVICE_KHR 0x4010
|
|
||||||
#define CL_D3D10_DXGI_ADAPTER_KHR 0x4011
|
|
||||||
|
|
||||||
// cl_d3d10_device_set_nv
|
|
||||||
#define CL_PREFERRED_DEVICES_FOR_D3D10_KHR 0x4012
|
|
||||||
#define CL_ALL_DEVICES_FOR_D3D10_KHR 0x4013
|
|
||||||
|
|
||||||
// cl_context_info
|
|
||||||
#define CL_CONTEXT_D3D10_DEVICE_KHR 0x4014
|
|
||||||
#define CL_CONTEXT_D3D10_PREFER_SHARED_RESOURCES_KHR 0x402C
|
|
||||||
|
|
||||||
// cl_mem_info
|
|
||||||
#define CL_MEM_D3D10_RESOURCE_KHR 0x4015
|
|
||||||
|
|
||||||
// cl_image_info
|
|
||||||
#define CL_IMAGE_D3D10_SUBRESOURCE_KHR 0x4016
|
|
||||||
|
|
||||||
// cl_command_type
|
|
||||||
#define CL_COMMAND_ACQUIRE_D3D10_OBJECTS_KHR 0x4017
|
|
||||||
#define CL_COMMAND_RELEASE_D3D10_OBJECTS_KHR 0x4018
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetDeviceIDsFromD3D10KHR_fn)(
|
|
||||||
cl_platform_id platform,
|
|
||||||
cl_d3d10_device_source_khr d3d_device_source,
|
|
||||||
void * d3d_object,
|
|
||||||
cl_d3d10_device_set_khr d3d_device_set,
|
|
||||||
cl_uint num_entries,
|
|
||||||
cl_device_id * devices,
|
|
||||||
cl_uint * num_devices) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D10BufferKHR_fn)(
|
|
||||||
cl_context context,
|
|
||||||
cl_mem_flags flags,
|
|
||||||
ID3D10Buffer * resource,
|
|
||||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D10Texture2DKHR_fn)(
|
|
||||||
cl_context context,
|
|
||||||
cl_mem_flags flags,
|
|
||||||
ID3D10Texture2D * resource,
|
|
||||||
UINT subresource,
|
|
||||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D10Texture3DKHR_fn)(
|
|
||||||
cl_context context,
|
|
||||||
cl_mem_flags flags,
|
|
||||||
ID3D10Texture3D * resource,
|
|
||||||
UINT subresource,
|
|
||||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueAcquireD3D10ObjectsKHR_fn)(
|
|
||||||
cl_command_queue command_queue,
|
|
||||||
cl_uint num_objects,
|
|
||||||
const cl_mem * mem_objects,
|
|
||||||
cl_uint num_events_in_wait_list,
|
|
||||||
const cl_event * event_wait_list,
|
|
||||||
cl_event * event) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReleaseD3D10ObjectsKHR_fn)(
|
|
||||||
cl_command_queue command_queue,
|
|
||||||
cl_uint num_objects,
|
|
||||||
const cl_mem * mem_objects,
|
|
||||||
cl_uint num_events_in_wait_list,
|
|
||||||
const cl_event * event_wait_list,
|
|
||||||
cl_event * event) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // __OPENCL_CL_D3D10_H
|
|
||||||
|
|
||||||
-126
@@ -1,126 +0,0 @@
|
|||||||
/**********************************************************************************
|
|
||||||
* Copyright (c) 2008-2012 The Khronos Group Inc.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and/or associated documentation files (the
|
|
||||||
* "Materials"), to deal in the Materials without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Materials, and to
|
|
||||||
* permit persons to whom the Materials are 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 Materials.
|
|
||||||
*
|
|
||||||
* THE MATERIALS ARE 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
||||||
**********************************************************************************/
|
|
||||||
|
|
||||||
/* $Revision: 11708 $ on $Date: 2010-06-13 23:36:24 -0700 (Sun, 13 Jun 2010) $ */
|
|
||||||
|
|
||||||
#ifndef __OPENCL_CL_D3D11_H
|
|
||||||
#define __OPENCL_CL_D3D11_H
|
|
||||||
|
|
||||||
#include <d3d11.h>
|
|
||||||
#include <CL/cl.h>
|
|
||||||
#include <CL/cl_platform.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* cl_khr_d3d11_sharing */
|
|
||||||
#define cl_khr_d3d11_sharing 1
|
|
||||||
|
|
||||||
typedef cl_uint cl_d3d11_device_source_khr;
|
|
||||||
typedef cl_uint cl_d3d11_device_set_khr;
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// Error Codes
|
|
||||||
#define CL_INVALID_D3D11_DEVICE_KHR -1006
|
|
||||||
#define CL_INVALID_D3D11_RESOURCE_KHR -1007
|
|
||||||
#define CL_D3D11_RESOURCE_ALREADY_ACQUIRED_KHR -1008
|
|
||||||
#define CL_D3D11_RESOURCE_NOT_ACQUIRED_KHR -1009
|
|
||||||
|
|
||||||
// cl_d3d11_device_source
|
|
||||||
#define CL_D3D11_DEVICE_KHR 0x4019
|
|
||||||
#define CL_D3D11_DXGI_ADAPTER_KHR 0x401A
|
|
||||||
|
|
||||||
// cl_d3d11_device_set
|
|
||||||
#define CL_PREFERRED_DEVICES_FOR_D3D11_KHR 0x401B
|
|
||||||
#define CL_ALL_DEVICES_FOR_D3D11_KHR 0x401C
|
|
||||||
|
|
||||||
// cl_context_info
|
|
||||||
#define CL_CONTEXT_D3D11_DEVICE_KHR 0x401D
|
|
||||||
#define CL_CONTEXT_D3D11_PREFER_SHARED_RESOURCES_KHR 0x402D
|
|
||||||
|
|
||||||
// cl_mem_info
|
|
||||||
#define CL_MEM_D3D11_RESOURCE_KHR 0x401E
|
|
||||||
|
|
||||||
// cl_image_info
|
|
||||||
#define CL_IMAGE_D3D11_SUBRESOURCE_KHR 0x401F
|
|
||||||
|
|
||||||
// cl_command_type
|
|
||||||
#define CL_COMMAND_ACQUIRE_D3D11_OBJECTS_KHR 0x4020
|
|
||||||
#define CL_COMMAND_RELEASE_D3D11_OBJECTS_KHR 0x4021
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetDeviceIDsFromD3D11KHR_fn)(
|
|
||||||
cl_platform_id platform,
|
|
||||||
cl_d3d11_device_source_khr d3d_device_source,
|
|
||||||
void * d3d_object,
|
|
||||||
cl_d3d11_device_set_khr d3d_device_set,
|
|
||||||
cl_uint num_entries,
|
|
||||||
cl_device_id * devices,
|
|
||||||
cl_uint * num_devices) CL_API_SUFFIX__VERSION_1_2;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D11BufferKHR_fn)(
|
|
||||||
cl_context context,
|
|
||||||
cl_mem_flags flags,
|
|
||||||
ID3D11Buffer * resource,
|
|
||||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_2;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D11Texture2DKHR_fn)(
|
|
||||||
cl_context context,
|
|
||||||
cl_mem_flags flags,
|
|
||||||
ID3D11Texture2D * resource,
|
|
||||||
UINT subresource,
|
|
||||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_2;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D11Texture3DKHR_fn)(
|
|
||||||
cl_context context,
|
|
||||||
cl_mem_flags flags,
|
|
||||||
ID3D11Texture3D * resource,
|
|
||||||
UINT subresource,
|
|
||||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_2;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueAcquireD3D11ObjectsKHR_fn)(
|
|
||||||
cl_command_queue command_queue,
|
|
||||||
cl_uint num_objects,
|
|
||||||
const cl_mem * mem_objects,
|
|
||||||
cl_uint num_events_in_wait_list,
|
|
||||||
const cl_event * event_wait_list,
|
|
||||||
cl_event * event) CL_API_SUFFIX__VERSION_1_2;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReleaseD3D11ObjectsKHR_fn)(
|
|
||||||
cl_command_queue command_queue,
|
|
||||||
cl_uint num_objects,
|
|
||||||
const cl_mem * mem_objects,
|
|
||||||
cl_uint num_events_in_wait_list,
|
|
||||||
const cl_event * event_wait_list,
|
|
||||||
cl_event * event) CL_API_SUFFIX__VERSION_1_2;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // __OPENCL_CL_D3D11_H
|
|
||||||
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
/**********************************************************************************
|
|
||||||
* Copyright (c) 2008-2012 The Khronos Group Inc.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and/or associated documentation files (the
|
|
||||||
* "Materials"), to deal in the Materials without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Materials, and to
|
|
||||||
* permit persons to whom the Materials are 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 Materials.
|
|
||||||
*
|
|
||||||
* THE MATERIALS ARE 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
||||||
**********************************************************************************/
|
|
||||||
|
|
||||||
/* $Revision: 11708 $ on $Date: 2010-06-13 23:36:24 -0700 (Sun, 13 Jun 2010) $ */
|
|
||||||
|
|
||||||
#ifndef __OPENCL_CL_DX9_MEDIA_SHARING_H
|
|
||||||
#define __OPENCL_CL_DX9_MEDIA_SHARING_H
|
|
||||||
|
|
||||||
#include <CL/cl.h>
|
|
||||||
#include <CL/cl_platform.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
/* cl_khr_dx9_media_sharing */
|
|
||||||
#define cl_khr_dx9_media_sharing 1
|
|
||||||
|
|
||||||
typedef cl_uint cl_dx9_media_adapter_type_khr;
|
|
||||||
typedef cl_uint cl_dx9_media_adapter_set_khr;
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include <d3d9.h>
|
|
||||||
typedef struct _cl_dx9_surface_info_khr
|
|
||||||
{
|
|
||||||
IDirect3DSurface9 *resource;
|
|
||||||
HANDLE shared_handle;
|
|
||||||
} cl_dx9_surface_info_khr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// Error Codes
|
|
||||||
#define CL_INVALID_DX9_MEDIA_ADAPTER_KHR -1010
|
|
||||||
#define CL_INVALID_DX9_MEDIA_SURFACE_KHR -1011
|
|
||||||
#define CL_DX9_MEDIA_SURFACE_ALREADY_ACQUIRED_KHR -1012
|
|
||||||
#define CL_DX9_MEDIA_SURFACE_NOT_ACQUIRED_KHR -1013
|
|
||||||
|
|
||||||
// cl_media_adapter_type_khr
|
|
||||||
#define CL_ADAPTER_D3D9_KHR 0x2020
|
|
||||||
#define CL_ADAPTER_D3D9EX_KHR 0x2021
|
|
||||||
#define CL_ADAPTER_DXVA_KHR 0x2022
|
|
||||||
|
|
||||||
// cl_media_adapter_set_khr
|
|
||||||
#define CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR 0x2023
|
|
||||||
#define CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR 0x2024
|
|
||||||
|
|
||||||
// cl_context_info
|
|
||||||
#define CL_CONTEXT_ADAPTER_D3D9_KHR 0x2025
|
|
||||||
#define CL_CONTEXT_ADAPTER_D3D9EX_KHR 0x2026
|
|
||||||
#define CL_CONTEXT_ADAPTER_DXVA_KHR 0x2027
|
|
||||||
|
|
||||||
// cl_mem_info
|
|
||||||
#define CL_MEM_DX9_MEDIA_ADAPTER_TYPE_KHR 0x2028
|
|
||||||
#define CL_MEM_DX9_MEDIA_SURFACE_INFO_KHR 0x2029
|
|
||||||
|
|
||||||
// cl_image_info
|
|
||||||
#define CL_IMAGE_DX9_MEDIA_PLANE_KHR 0x202A
|
|
||||||
|
|
||||||
// cl_command_type
|
|
||||||
#define CL_COMMAND_ACQUIRE_DX9_MEDIA_SURFACES_KHR 0x202B
|
|
||||||
#define CL_COMMAND_RELEASE_DX9_MEDIA_SURFACES_KHR 0x202C
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetDeviceIDsFromDX9MediaAdapterKHR_fn)(
|
|
||||||
cl_platform_id platform,
|
|
||||||
cl_uint num_media_adapters,
|
|
||||||
cl_dx9_media_adapter_type_khr * media_adapter_type,
|
|
||||||
void * media_adapters,
|
|
||||||
cl_dx9_media_adapter_set_khr media_adapter_set,
|
|
||||||
cl_uint num_entries,
|
|
||||||
cl_device_id * devices,
|
|
||||||
cl_uint * num_devices) CL_API_SUFFIX__VERSION_1_2;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromDX9MediaSurfaceKHR_fn)(
|
|
||||||
cl_context context,
|
|
||||||
cl_mem_flags flags,
|
|
||||||
cl_dx9_media_adapter_type_khr adapter_type,
|
|
||||||
void * surface_info,
|
|
||||||
cl_uint plane,
|
|
||||||
cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_2;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueAcquireDX9MediaSurfacesKHR_fn)(
|
|
||||||
cl_command_queue command_queue,
|
|
||||||
cl_uint num_objects,
|
|
||||||
const cl_mem * mem_objects,
|
|
||||||
cl_uint num_events_in_wait_list,
|
|
||||||
const cl_event * event_wait_list,
|
|
||||||
cl_event * event) CL_API_SUFFIX__VERSION_1_2;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReleaseDX9MediaSurfacesKHR_fn)(
|
|
||||||
cl_command_queue command_queue,
|
|
||||||
cl_uint num_objects,
|
|
||||||
const cl_mem * mem_objects,
|
|
||||||
cl_uint num_events_in_wait_list,
|
|
||||||
const cl_event * event_wait_list,
|
|
||||||
cl_event * event) CL_API_SUFFIX__VERSION_1_2;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // __OPENCL_CL_DX9_MEDIA_SHARING_H
|
|
||||||
|
|
||||||
-131
@@ -1,131 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright (c) 2008-2010 The Khronos Group Inc.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and/or associated documentation files (the
|
|
||||||
* "Materials"), to deal in the Materials without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Materials, and to
|
|
||||||
* permit persons to whom the Materials are 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 Materials.
|
|
||||||
*
|
|
||||||
* THE MATERIALS ARE 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#ifndef __OPENCL_CL_EGL_H
|
|
||||||
#define __OPENCL_CL_EGL_H
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
|
|
||||||
#else
|
|
||||||
#include <CL/cl.h>
|
|
||||||
#include <EGL/egl.h>
|
|
||||||
#include <EGL/eglext.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Command type for events created with clEnqueueAcquireEGLObjectsKHR */
|
|
||||||
#define CL_COMMAND_EGL_FENCE_SYNC_OBJECT_KHR 0x202F
|
|
||||||
#define CL_COMMAND_ACQUIRE_EGL_OBJECTS_KHR 0x202D
|
|
||||||
#define CL_COMMAND_RELEASE_EGL_OBJECTS_KHR 0x202E
|
|
||||||
|
|
||||||
/* Error type for clCreateFromEGLImageKHR */
|
|
||||||
#define CL_INVALID_EGL_OBJECT_KHR -1093
|
|
||||||
#define CL_EGL_RESOURCE_NOT_ACQUIRED_KHR -1092
|
|
||||||
|
|
||||||
/* CLeglImageKHR is an opaque handle to an EGLImage */
|
|
||||||
typedef void* CLeglImageKHR;
|
|
||||||
|
|
||||||
/* CLeglDisplayKHR is an opaque handle to an EGLDisplay */
|
|
||||||
typedef void* CLeglDisplayKHR;
|
|
||||||
|
|
||||||
/* properties passed to clCreateFromEGLImageKHR */
|
|
||||||
typedef intptr_t cl_egl_image_properties_khr;
|
|
||||||
|
|
||||||
|
|
||||||
#define cl_khr_egl_image 1
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_mem CL_API_CALL
|
|
||||||
clCreateFromEGLImageKHR(cl_context /* context */,
|
|
||||||
CLeglDisplayKHR /* egldisplay */,
|
|
||||||
CLeglImageKHR /* eglimage */,
|
|
||||||
cl_mem_flags /* flags */,
|
|
||||||
const cl_egl_image_properties_khr * /* properties */,
|
|
||||||
cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromEGLImageKHR_fn)(
|
|
||||||
cl_context context,
|
|
||||||
CLeglDisplayKHR egldisplay,
|
|
||||||
CLeglImageKHR eglimage,
|
|
||||||
cl_mem_flags flags,
|
|
||||||
const cl_egl_image_properties_khr * properties,
|
|
||||||
cl_int * errcode_ret);
|
|
||||||
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
|
||||||
clEnqueueAcquireEGLObjectsKHR(cl_command_queue /* command_queue */,
|
|
||||||
cl_uint /* num_objects */,
|
|
||||||
const cl_mem * /* mem_objects */,
|
|
||||||
cl_uint /* num_events_in_wait_list */,
|
|
||||||
const cl_event * /* event_wait_list */,
|
|
||||||
cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueAcquireEGLObjectsKHR_fn)(
|
|
||||||
cl_command_queue command_queue,
|
|
||||||
cl_uint num_objects,
|
|
||||||
const cl_mem * mem_objects,
|
|
||||||
cl_uint num_events_in_wait_list,
|
|
||||||
const cl_event * event_wait_list,
|
|
||||||
cl_event * event);
|
|
||||||
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
|
||||||
clEnqueueReleaseEGLObjectsKHR(cl_command_queue /* command_queue */,
|
|
||||||
cl_uint /* num_objects */,
|
|
||||||
const cl_mem * /* mem_objects */,
|
|
||||||
cl_uint /* num_events_in_wait_list */,
|
|
||||||
const cl_event * /* event_wait_list */,
|
|
||||||
cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReleaseEGLObjectsKHR_fn)(
|
|
||||||
cl_command_queue command_queue,
|
|
||||||
cl_uint num_objects,
|
|
||||||
const cl_mem * mem_objects,
|
|
||||||
cl_uint num_events_in_wait_list,
|
|
||||||
const cl_event * event_wait_list,
|
|
||||||
cl_event * event);
|
|
||||||
|
|
||||||
|
|
||||||
#define cl_khr_egl_event 1
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_event CL_API_CALL
|
|
||||||
clCreateEventFromEGLSyncKHR(cl_context /* context */,
|
|
||||||
EGLSyncKHR /* sync */,
|
|
||||||
EGLDisplay /* display */,
|
|
||||||
cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_event (CL_API_CALL *clCreateEventFromEGLSyncKHR_fn)(
|
|
||||||
cl_context context,
|
|
||||||
EGLSyncKHR sync,
|
|
||||||
EGLDisplay display,
|
|
||||||
cl_int * errcode_ret);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __OPENCL_CL_EGL_H */
|
|
||||||
-306
@@ -1,306 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright (c) 2008-2013 The Khronos Group Inc.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and/or associated documentation files (the
|
|
||||||
* "Materials"), to deal in the Materials without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Materials, and to
|
|
||||||
* permit persons to whom the Materials are 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 Materials.
|
|
||||||
*
|
|
||||||
* THE MATERIALS ARE 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
/* $Revision: 11928 $ on $Date: 2010-07-13 09:04:56 -0700 (Tue, 13 Jul 2010) $ */
|
|
||||||
|
|
||||||
/* cl_ext.h contains OpenCL extensions which don't have external */
|
|
||||||
/* (OpenGL, D3D) dependencies. */
|
|
||||||
|
|
||||||
#ifndef __CL_EXT_H
|
|
||||||
#define __CL_EXT_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include <OpenCL/cl.h>
|
|
||||||
#include <AvailabilityMacros.h>
|
|
||||||
#else
|
|
||||||
#include <CL/cl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* cl_khr_fp16 extension - no extension #define since it has no functions */
|
|
||||||
#define CL_DEVICE_HALF_FP_CONFIG 0x1033
|
|
||||||
|
|
||||||
/* Memory object destruction
|
|
||||||
*
|
|
||||||
* Apple extension for use to manage externally allocated buffers used with cl_mem objects with CL_MEM_USE_HOST_PTR
|
|
||||||
*
|
|
||||||
* Registers a user callback function that will be called when the memory object is deleted and its resources
|
|
||||||
* freed. Each call to clSetMemObjectCallbackFn registers the specified user callback function on a callback
|
|
||||||
* stack associated with memobj. The registered user callback functions are called in the reverse order in
|
|
||||||
* which they were registered. The user callback functions are called and then the memory object is deleted
|
|
||||||
* and its resources freed. This provides a mechanism for the application (and libraries) using memobj to be
|
|
||||||
* notified when the memory referenced by host_ptr, specified when the memory object is created and used as
|
|
||||||
* the storage bits for the memory object, can be reused or freed.
|
|
||||||
*
|
|
||||||
* The application may not call CL api's with the cl_mem object passed to the pfn_notify.
|
|
||||||
*
|
|
||||||
* Please check for the "cl_APPLE_SetMemObjectDestructor" extension using clGetDeviceInfo(CL_DEVICE_EXTENSIONS)
|
|
||||||
* before using.
|
|
||||||
*/
|
|
||||||
#define cl_APPLE_SetMemObjectDestructor 1
|
|
||||||
cl_int CL_API_ENTRY clSetMemObjectDestructorAPPLE( cl_mem /* memobj */,
|
|
||||||
void (* /*pfn_notify*/)( cl_mem /* memobj */, void* /*user_data*/),
|
|
||||||
void * /*user_data */ ) CL_EXT_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
|
|
||||||
/* Context Logging Functions
|
|
||||||
*
|
|
||||||
* The next three convenience functions are intended to be used as the pfn_notify parameter to clCreateContext().
|
|
||||||
* Please check for the "cl_APPLE_ContextLoggingFunctions" extension using clGetDeviceInfo(CL_DEVICE_EXTENSIONS)
|
|
||||||
* before using.
|
|
||||||
*
|
|
||||||
* clLogMessagesToSystemLog fowards on all log messages to the Apple System Logger
|
|
||||||
*/
|
|
||||||
#define cl_APPLE_ContextLoggingFunctions 1
|
|
||||||
extern void CL_API_ENTRY clLogMessagesToSystemLogAPPLE( const char * /* errstr */,
|
|
||||||
const void * /* private_info */,
|
|
||||||
size_t /* cb */,
|
|
||||||
void * /* user_data */ ) CL_EXT_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
/* clLogMessagesToStdout sends all log messages to the file descriptor stdout */
|
|
||||||
extern void CL_API_ENTRY clLogMessagesToStdoutAPPLE( const char * /* errstr */,
|
|
||||||
const void * /* private_info */,
|
|
||||||
size_t /* cb */,
|
|
||||||
void * /* user_data */ ) CL_EXT_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
/* clLogMessagesToStderr sends all log messages to the file descriptor stderr */
|
|
||||||
extern void CL_API_ENTRY clLogMessagesToStderrAPPLE( const char * /* errstr */,
|
|
||||||
const void * /* private_info */,
|
|
||||||
size_t /* cb */,
|
|
||||||
void * /* user_data */ ) CL_EXT_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
|
|
||||||
/************************
|
|
||||||
* cl_khr_icd extension *
|
|
||||||
************************/
|
|
||||||
#define cl_khr_icd 1
|
|
||||||
|
|
||||||
/* cl_platform_info */
|
|
||||||
#define CL_PLATFORM_ICD_SUFFIX_KHR 0x0920
|
|
||||||
|
|
||||||
/* Additional Error Codes */
|
|
||||||
#define CL_PLATFORM_NOT_FOUND_KHR -1001
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
|
||||||
clIcdGetPlatformIDsKHR(cl_uint /* num_entries */,
|
|
||||||
cl_platform_id * /* platforms */,
|
|
||||||
cl_uint * /* num_platforms */);
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int (CL_API_CALL *clIcdGetPlatformIDsKHR_fn)(
|
|
||||||
cl_uint /* num_entries */,
|
|
||||||
cl_platform_id * /* platforms */,
|
|
||||||
cl_uint * /* num_platforms */);
|
|
||||||
|
|
||||||
|
|
||||||
/* Extension: cl_khr_image2D_buffer
|
|
||||||
*
|
|
||||||
* This extension allows a 2D image to be created from a cl_mem buffer without a copy.
|
|
||||||
* The type associated with a 2D image created from a buffer in an OpenCL program is image2d_t.
|
|
||||||
* Both the sampler and sampler-less read_image built-in functions are supported for 2D images
|
|
||||||
* and 2D images created from a buffer. Similarly, the write_image built-ins are also supported
|
|
||||||
* for 2D images created from a buffer.
|
|
||||||
*
|
|
||||||
* When the 2D image from buffer is created, the client must specify the width,
|
|
||||||
* height, image format (i.e. channel order and channel data type) and optionally the row pitch
|
|
||||||
*
|
|
||||||
* The pitch specified must be a multiple of CL_DEVICE_IMAGE_PITCH_ALIGNMENT pixels.
|
|
||||||
* The base address of the buffer must be aligned to CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT pixels.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*************************************
|
|
||||||
* cl_khr_initalize_memory extension *
|
|
||||||
*************************************/
|
|
||||||
|
|
||||||
#define CL_CONTEXT_MEMORY_INITIALIZE_KHR 0x200E
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************
|
|
||||||
* cl_khr_terminate_context extension *
|
|
||||||
**************************************/
|
|
||||||
|
|
||||||
#define CL_DEVICE_TERMINATE_CAPABILITY_KHR 0x200F
|
|
||||||
#define CL_CONTEXT_TERMINATE_KHR 0x2010
|
|
||||||
|
|
||||||
#define cl_khr_terminate_context 1
|
|
||||||
extern CL_API_ENTRY cl_int CL_API_CALL clTerminateContextKHR(cl_context /* context */) CL_EXT_SUFFIX__VERSION_1_2;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int (CL_API_CALL *clTerminateContextKHR_fn)(cl_context /* context */) CL_EXT_SUFFIX__VERSION_1_2;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Extension: cl_khr_spir
|
|
||||||
*
|
|
||||||
* This extension adds support to create an OpenCL program object from a
|
|
||||||
* Standard Portable Intermediate Representation (SPIR) instance
|
|
||||||
*/
|
|
||||||
|
|
||||||
/******************************************
|
|
||||||
* cl_nv_device_attribute_query extension *
|
|
||||||
******************************************/
|
|
||||||
/* cl_nv_device_attribute_query extension - no extension #define since it has no functions */
|
|
||||||
#define CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV 0x4000
|
|
||||||
#define CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV 0x4001
|
|
||||||
#define CL_DEVICE_REGISTERS_PER_BLOCK_NV 0x4002
|
|
||||||
#define CL_DEVICE_WARP_SIZE_NV 0x4003
|
|
||||||
#define CL_DEVICE_GPU_OVERLAP_NV 0x4004
|
|
||||||
#define CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV 0x4005
|
|
||||||
#define CL_DEVICE_INTEGRATED_MEMORY_NV 0x4006
|
|
||||||
|
|
||||||
/*********************************
|
|
||||||
* cl_amd_device_attribute_query *
|
|
||||||
*********************************/
|
|
||||||
#define CL_DEVICE_PROFILING_TIMER_OFFSET_AMD 0x4036
|
|
||||||
|
|
||||||
#ifdef CL_VERSION_1_1
|
|
||||||
/***********************************
|
|
||||||
* cl_ext_device_fission extension *
|
|
||||||
***********************************/
|
|
||||||
#define cl_ext_device_fission 1
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
|
||||||
clReleaseDeviceEXT( cl_device_id /*device*/ ) CL_EXT_SUFFIX__VERSION_1_1;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int
|
|
||||||
(CL_API_CALL *clReleaseDeviceEXT_fn)( cl_device_id /*device*/ ) CL_EXT_SUFFIX__VERSION_1_1;
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
|
||||||
clRetainDeviceEXT( cl_device_id /*device*/ ) CL_EXT_SUFFIX__VERSION_1_1;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int
|
|
||||||
(CL_API_CALL *clRetainDeviceEXT_fn)( cl_device_id /*device*/ ) CL_EXT_SUFFIX__VERSION_1_1;
|
|
||||||
|
|
||||||
typedef cl_ulong cl_device_partition_property_ext;
|
|
||||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
|
||||||
clCreateSubDevicesEXT( cl_device_id /*in_device*/,
|
|
||||||
const cl_device_partition_property_ext * /* properties */,
|
|
||||||
cl_uint /*num_entries*/,
|
|
||||||
cl_device_id * /*out_devices*/,
|
|
||||||
cl_uint * /*num_devices*/ ) CL_EXT_SUFFIX__VERSION_1_1;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int
|
|
||||||
( CL_API_CALL * clCreateSubDevicesEXT_fn)( cl_device_id /*in_device*/,
|
|
||||||
const cl_device_partition_property_ext * /* properties */,
|
|
||||||
cl_uint /*num_entries*/,
|
|
||||||
cl_device_id * /*out_devices*/,
|
|
||||||
cl_uint * /*num_devices*/ ) CL_EXT_SUFFIX__VERSION_1_1;
|
|
||||||
|
|
||||||
/* cl_device_partition_property_ext */
|
|
||||||
#define CL_DEVICE_PARTITION_EQUALLY_EXT 0x4050
|
|
||||||
#define CL_DEVICE_PARTITION_BY_COUNTS_EXT 0x4051
|
|
||||||
#define CL_DEVICE_PARTITION_BY_NAMES_EXT 0x4052
|
|
||||||
#define CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN_EXT 0x4053
|
|
||||||
|
|
||||||
/* clDeviceGetInfo selectors */
|
|
||||||
#define CL_DEVICE_PARENT_DEVICE_EXT 0x4054
|
|
||||||
#define CL_DEVICE_PARTITION_TYPES_EXT 0x4055
|
|
||||||
#define CL_DEVICE_AFFINITY_DOMAINS_EXT 0x4056
|
|
||||||
#define CL_DEVICE_REFERENCE_COUNT_EXT 0x4057
|
|
||||||
#define CL_DEVICE_PARTITION_STYLE_EXT 0x4058
|
|
||||||
|
|
||||||
/* error codes */
|
|
||||||
#define CL_DEVICE_PARTITION_FAILED_EXT -1057
|
|
||||||
#define CL_INVALID_PARTITION_COUNT_EXT -1058
|
|
||||||
#define CL_INVALID_PARTITION_NAME_EXT -1059
|
|
||||||
|
|
||||||
/* CL_AFFINITY_DOMAINs */
|
|
||||||
#define CL_AFFINITY_DOMAIN_L1_CACHE_EXT 0x1
|
|
||||||
#define CL_AFFINITY_DOMAIN_L2_CACHE_EXT 0x2
|
|
||||||
#define CL_AFFINITY_DOMAIN_L3_CACHE_EXT 0x3
|
|
||||||
#define CL_AFFINITY_DOMAIN_L4_CACHE_EXT 0x4
|
|
||||||
#define CL_AFFINITY_DOMAIN_NUMA_EXT 0x10
|
|
||||||
#define CL_AFFINITY_DOMAIN_NEXT_FISSIONABLE_EXT 0x100
|
|
||||||
|
|
||||||
/* cl_device_partition_property_ext list terminators */
|
|
||||||
#define CL_PROPERTIES_LIST_END_EXT ((cl_device_partition_property_ext) 0)
|
|
||||||
#define CL_PARTITION_BY_COUNTS_LIST_END_EXT ((cl_device_partition_property_ext) 0)
|
|
||||||
#define CL_PARTITION_BY_NAMES_LIST_END_EXT ((cl_device_partition_property_ext) 0 - 1)
|
|
||||||
|
|
||||||
/*********************************
|
|
||||||
* cl_qcom_ext_host_ptr extension
|
|
||||||
*********************************/
|
|
||||||
|
|
||||||
#define CL_MEM_EXT_HOST_PTR_QCOM (1 << 29)
|
|
||||||
|
|
||||||
#define CL_DEVICE_EXT_MEM_PADDING_IN_BYTES_QCOM 0x40A0
|
|
||||||
#define CL_DEVICE_PAGE_SIZE_QCOM 0x40A1
|
|
||||||
#define CL_IMAGE_ROW_ALIGNMENT_QCOM 0x40A2
|
|
||||||
#define CL_IMAGE_SLICE_ALIGNMENT_QCOM 0x40A3
|
|
||||||
#define CL_MEM_HOST_UNCACHED_QCOM 0x40A4
|
|
||||||
#define CL_MEM_HOST_WRITEBACK_QCOM 0x40A5
|
|
||||||
#define CL_MEM_HOST_WRITETHROUGH_QCOM 0x40A6
|
|
||||||
#define CL_MEM_HOST_WRITE_COMBINING_QCOM 0x40A7
|
|
||||||
|
|
||||||
typedef cl_uint cl_image_pitch_info_qcom;
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
|
||||||
clGetDeviceImageInfoQCOM(cl_device_id device,
|
|
||||||
size_t image_width,
|
|
||||||
size_t image_height,
|
|
||||||
const cl_image_format *image_format,
|
|
||||||
cl_image_pitch_info_qcom param_name,
|
|
||||||
size_t param_value_size,
|
|
||||||
void *param_value,
|
|
||||||
size_t *param_value_size_ret);
|
|
||||||
|
|
||||||
typedef struct _cl_mem_ext_host_ptr
|
|
||||||
{
|
|
||||||
// Type of external memory allocation.
|
|
||||||
// Legal values will be defined in layered extensions.
|
|
||||||
cl_uint allocation_type;
|
|
||||||
|
|
||||||
// Host cache policy for this external memory allocation.
|
|
||||||
cl_uint host_cache_policy;
|
|
||||||
|
|
||||||
} cl_mem_ext_host_ptr;
|
|
||||||
|
|
||||||
/*********************************
|
|
||||||
* cl_qcom_ion_host_ptr extension
|
|
||||||
*********************************/
|
|
||||||
|
|
||||||
#define CL_MEM_ION_HOST_PTR_QCOM 0x40A8
|
|
||||||
|
|
||||||
typedef struct _cl_mem_ion_host_ptr
|
|
||||||
{
|
|
||||||
// Type of external memory allocation.
|
|
||||||
// Must be CL_MEM_ION_HOST_PTR_QCOM for ION allocations.
|
|
||||||
cl_mem_ext_host_ptr ext_host_ptr;
|
|
||||||
|
|
||||||
// ION file descriptor
|
|
||||||
int ion_filedesc;
|
|
||||||
|
|
||||||
// Host pointer to the ION allocated memory
|
|
||||||
void* ion_hostptr;
|
|
||||||
|
|
||||||
} cl_mem_ion_host_ptr;
|
|
||||||
|
|
||||||
#endif /* CL_VERSION_1_1 */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* __CL_EXT_H */
|
|
||||||
-162
@@ -1,162 +0,0 @@
|
|||||||
/**********************************************************************************
|
|
||||||
* Copyright (c) 2008 - 2012 The Khronos Group Inc.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and/or associated documentation files (the
|
|
||||||
* "Materials"), to deal in the Materials without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Materials, and to
|
|
||||||
* permit persons to whom the Materials are 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 Materials.
|
|
||||||
*
|
|
||||||
* THE MATERIALS ARE 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
||||||
**********************************************************************************/
|
|
||||||
|
|
||||||
#ifndef __OPENCL_CL_GL_H
|
|
||||||
#define __OPENCL_CL_GL_H
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include <OpenCL/cl.h>
|
|
||||||
#else
|
|
||||||
#include <CL/cl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef cl_uint cl_gl_object_type;
|
|
||||||
typedef cl_uint cl_gl_texture_info;
|
|
||||||
typedef cl_uint cl_gl_platform_info;
|
|
||||||
typedef struct __GLsync *cl_GLsync;
|
|
||||||
|
|
||||||
/* cl_gl_object_type = 0x2000 - 0x200F enum values are currently taken */
|
|
||||||
#define CL_GL_OBJECT_BUFFER 0x2000
|
|
||||||
#define CL_GL_OBJECT_TEXTURE2D 0x2001
|
|
||||||
#define CL_GL_OBJECT_TEXTURE3D 0x2002
|
|
||||||
#define CL_GL_OBJECT_RENDERBUFFER 0x2003
|
|
||||||
#define CL_GL_OBJECT_TEXTURE2D_ARRAY 0x200E
|
|
||||||
#define CL_GL_OBJECT_TEXTURE1D 0x200F
|
|
||||||
#define CL_GL_OBJECT_TEXTURE1D_ARRAY 0x2010
|
|
||||||
#define CL_GL_OBJECT_TEXTURE_BUFFER 0x2011
|
|
||||||
|
|
||||||
/* cl_gl_texture_info */
|
|
||||||
#define CL_GL_TEXTURE_TARGET 0x2004
|
|
||||||
#define CL_GL_MIPMAP_LEVEL 0x2005
|
|
||||||
#define CL_GL_NUM_SAMPLES 0x2012
|
|
||||||
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_mem CL_API_CALL
|
|
||||||
clCreateFromGLBuffer(cl_context /* context */,
|
|
||||||
cl_mem_flags /* flags */,
|
|
||||||
cl_GLuint /* bufobj */,
|
|
||||||
int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_mem CL_API_CALL
|
|
||||||
clCreateFromGLTexture(cl_context /* context */,
|
|
||||||
cl_mem_flags /* flags */,
|
|
||||||
cl_GLenum /* target */,
|
|
||||||
cl_GLint /* miplevel */,
|
|
||||||
cl_GLuint /* texture */,
|
|
||||||
cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2;
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_mem CL_API_CALL
|
|
||||||
clCreateFromGLRenderbuffer(cl_context /* context */,
|
|
||||||
cl_mem_flags /* flags */,
|
|
||||||
cl_GLuint /* renderbuffer */,
|
|
||||||
cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
|
||||||
clGetGLObjectInfo(cl_mem /* memobj */,
|
|
||||||
cl_gl_object_type * /* gl_object_type */,
|
|
||||||
cl_GLuint * /* gl_object_name */) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
|
||||||
clGetGLTextureInfo(cl_mem /* memobj */,
|
|
||||||
cl_gl_texture_info /* param_name */,
|
|
||||||
size_t /* param_value_size */,
|
|
||||||
void * /* param_value */,
|
|
||||||
size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
|
||||||
clEnqueueAcquireGLObjects(cl_command_queue /* command_queue */,
|
|
||||||
cl_uint /* num_objects */,
|
|
||||||
const cl_mem * /* mem_objects */,
|
|
||||||
cl_uint /* num_events_in_wait_list */,
|
|
||||||
const cl_event * /* event_wait_list */,
|
|
||||||
cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
|
||||||
clEnqueueReleaseGLObjects(cl_command_queue /* command_queue */,
|
|
||||||
cl_uint /* num_objects */,
|
|
||||||
const cl_mem * /* mem_objects */,
|
|
||||||
cl_uint /* num_events_in_wait_list */,
|
|
||||||
const cl_event * /* event_wait_list */,
|
|
||||||
cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
|
|
||||||
// Deprecated OpenCL 1.1 APIs
|
|
||||||
extern CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem CL_API_CALL
|
|
||||||
clCreateFromGLTexture2D(cl_context /* context */,
|
|
||||||
cl_mem_flags /* flags */,
|
|
||||||
cl_GLenum /* target */,
|
|
||||||
cl_GLint /* miplevel */,
|
|
||||||
cl_GLuint /* texture */,
|
|
||||||
cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
|
|
||||||
|
|
||||||
extern CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem CL_API_CALL
|
|
||||||
clCreateFromGLTexture3D(cl_context /* context */,
|
|
||||||
cl_mem_flags /* flags */,
|
|
||||||
cl_GLenum /* target */,
|
|
||||||
cl_GLint /* miplevel */,
|
|
||||||
cl_GLuint /* texture */,
|
|
||||||
cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
|
|
||||||
|
|
||||||
/* cl_khr_gl_sharing extension */
|
|
||||||
|
|
||||||
#define cl_khr_gl_sharing 1
|
|
||||||
|
|
||||||
typedef cl_uint cl_gl_context_info;
|
|
||||||
|
|
||||||
/* Additional Error Codes */
|
|
||||||
#define CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR -1000
|
|
||||||
|
|
||||||
/* cl_gl_context_info */
|
|
||||||
#define CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR 0x2006
|
|
||||||
#define CL_DEVICES_FOR_GL_CONTEXT_KHR 0x2007
|
|
||||||
|
|
||||||
/* Additional cl_context_properties */
|
|
||||||
#define CL_GL_CONTEXT_KHR 0x2008
|
|
||||||
#define CL_EGL_DISPLAY_KHR 0x2009
|
|
||||||
#define CL_GLX_DISPLAY_KHR 0x200A
|
|
||||||
#define CL_WGL_HDC_KHR 0x200B
|
|
||||||
#define CL_CGL_SHAREGROUP_KHR 0x200C
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_int CL_API_CALL
|
|
||||||
clGetGLContextInfoKHR(const cl_context_properties * /* properties */,
|
|
||||||
cl_gl_context_info /* param_name */,
|
|
||||||
size_t /* param_value_size */,
|
|
||||||
void * /* param_value */,
|
|
||||||
size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
|
|
||||||
|
|
||||||
typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetGLContextInfoKHR_fn)(
|
|
||||||
const cl_context_properties * properties,
|
|
||||||
cl_gl_context_info param_name,
|
|
||||||
size_t param_value_size,
|
|
||||||
void * param_value,
|
|
||||||
size_t * param_value_size_ret);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __OPENCL_CL_GL_H */
|
|
||||||
-69
@@ -1,69 +0,0 @@
|
|||||||
/**********************************************************************************
|
|
||||||
* Copyright (c) 2008-2012 The Khronos Group Inc.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and/or associated documentation files (the
|
|
||||||
* "Materials"), to deal in the Materials without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Materials, and to
|
|
||||||
* permit persons to whom the Materials are 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 Materials.
|
|
||||||
*
|
|
||||||
* THE MATERIALS ARE 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
||||||
**********************************************************************************/
|
|
||||||
|
|
||||||
/* $Revision: 11708 $ on $Date: 2010-06-13 23:36:24 -0700 (Sun, 13 Jun 2010) $ */
|
|
||||||
|
|
||||||
/* cl_gl_ext.h contains vendor (non-KHR) OpenCL extensions which have */
|
|
||||||
/* OpenGL dependencies. */
|
|
||||||
|
|
||||||
#ifndef __OPENCL_CL_GL_EXT_H
|
|
||||||
#define __OPENCL_CL_GL_EXT_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include <OpenCL/cl_gl.h>
|
|
||||||
#else
|
|
||||||
#include <CL/cl_gl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For each extension, follow this template
|
|
||||||
* cl_VEN_extname extension */
|
|
||||||
/* #define cl_VEN_extname 1
|
|
||||||
* ... define new types, if any
|
|
||||||
* ... define new tokens, if any
|
|
||||||
* ... define new APIs, if any
|
|
||||||
*
|
|
||||||
* If you need GLtypes here, mirror them with a cl_GLtype, rather than including a GL header
|
|
||||||
* This allows us to avoid having to decide whether to include GL headers or GLES here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* cl_khr_gl_event extension
|
|
||||||
* See section 9.9 in the OpenCL 1.1 spec for more information
|
|
||||||
*/
|
|
||||||
#define CL_COMMAND_GL_FENCE_SYNC_OBJECT_KHR 0x200D
|
|
||||||
|
|
||||||
extern CL_API_ENTRY cl_event CL_API_CALL
|
|
||||||
clCreateEventFromGLsyncKHR(cl_context /* context */,
|
|
||||||
cl_GLsync /* cl_GLsync */,
|
|
||||||
cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_1_1;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __OPENCL_CL_GL_EXT_H */
|
|
||||||
-1254
File diff suppressed because it is too large
Load Diff
-54
@@ -1,54 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright (c) 2008-2012 The Khronos Group Inc.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and/or associated documentation files (the
|
|
||||||
* "Materials"), to deal in the Materials without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Materials, and to
|
|
||||||
* permit persons to whom the Materials are 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 Materials.
|
|
||||||
*
|
|
||||||
* THE MATERIALS ARE 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
/* $Revision: 11708 $ on $Date: 2010-06-13 23:36:24 -0700 (Sun, 13 Jun 2010) $ */
|
|
||||||
|
|
||||||
#ifndef __OPENCL_H
|
|
||||||
#define __OPENCL_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
|
|
||||||
#include <OpenCL/cl.h>
|
|
||||||
#include <OpenCL/cl_gl.h>
|
|
||||||
#include <OpenCL/cl_gl_ext.h>
|
|
||||||
#include <OpenCL/cl_ext.h>
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include <CL/cl.h>
|
|
||||||
#include <CL/cl_gl.h>
|
|
||||||
#include <CL/cl_gl_ext.h>
|
|
||||||
#include <CL/cl_ext.h>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __OPENCL_H */
|
|
||||||
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
downloads/
|
|
||||||
unpack/
|
|
||||||
Vendored
-110
@@ -1,110 +0,0 @@
|
|||||||
#
|
|
||||||
# The script downloads ICV package
|
|
||||||
#
|
|
||||||
# On return this will define:
|
|
||||||
# OPENCV_ICV_PATH - path to unpacked downloaded package
|
|
||||||
#
|
|
||||||
|
|
||||||
function(_icv_downloader)
|
|
||||||
# Commit SHA in the opencv_3rdparty repo
|
|
||||||
set(IPPICV_BINARIES_COMMIT "81a676001ca8075ada498583e4166079e5744668")
|
|
||||||
# Define actual ICV versions
|
|
||||||
if(APPLE)
|
|
||||||
set(OPENCV_ICV_PACKAGE_NAME "ippicv_macosx_20151201.tgz")
|
|
||||||
set(OPENCV_ICV_PACKAGE_HASH "4ff1fde9a7cfdfe7250bfcd8334e0f2f")
|
|
||||||
set(OPENCV_ICV_PLATFORM "macosx")
|
|
||||||
set(OPENCV_ICV_PACKAGE_SUBDIR "/ippicv_osx")
|
|
||||||
elseif(UNIX)
|
|
||||||
if(ANDROID AND NOT (ANDROID_ABI STREQUAL x86 OR ANDROID_ABI STREQUAL x86_64))
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
set(OPENCV_ICV_PACKAGE_NAME "ippicv_linux_20151201.tgz")
|
|
||||||
set(OPENCV_ICV_PACKAGE_HASH "808b791a6eac9ed78d32a7666804320e")
|
|
||||||
set(OPENCV_ICV_PLATFORM "linux")
|
|
||||||
set(OPENCV_ICV_PACKAGE_SUBDIR "/ippicv_lnx")
|
|
||||||
elseif(WIN32 AND NOT ARM)
|
|
||||||
set(OPENCV_ICV_PACKAGE_NAME "ippicv_windows_20151201.zip")
|
|
||||||
set(OPENCV_ICV_PACKAGE_HASH "04e81ce5d0e329c3fbc606ae32cad44d")
|
|
||||||
set(OPENCV_ICV_PLATFORM "windows")
|
|
||||||
set(OPENCV_ICV_PACKAGE_SUBDIR "/ippicv_win")
|
|
||||||
else()
|
|
||||||
return() # Not supported
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(OPENCV_ICV_UNPACK_PATH "${CMAKE_CURRENT_LIST_DIR}/unpack")
|
|
||||||
set(OPENCV_ICV_PATH "${OPENCV_ICV_UNPACK_PATH}${OPENCV_ICV_PACKAGE_SUBDIR}")
|
|
||||||
|
|
||||||
if(DEFINED OPENCV_ICV_PACKAGE_DOWNLOADED
|
|
||||||
AND OPENCV_ICV_PACKAGE_DOWNLOADED STREQUAL OPENCV_ICV_PACKAGE_HASH
|
|
||||||
AND EXISTS ${OPENCV_ICV_PATH})
|
|
||||||
# Package has been downloaded and checked by the previous build
|
|
||||||
set(OPENCV_ICV_PATH "${OPENCV_ICV_PATH}" PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
else()
|
|
||||||
if(EXISTS ${OPENCV_ICV_UNPACK_PATH})
|
|
||||||
message(STATUS "ICV: Removing previous unpacked package: ${OPENCV_ICV_UNPACK_PATH}")
|
|
||||||
file(REMOVE_RECURSE ${OPENCV_ICV_UNPACK_PATH})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
unset(OPENCV_ICV_PACKAGE_DOWNLOADED CACHE)
|
|
||||||
|
|
||||||
set(OPENCV_ICV_PACKAGE_ARCHIVE "${CMAKE_CURRENT_LIST_DIR}/downloads/${OPENCV_ICV_PLATFORM}-${OPENCV_ICV_PACKAGE_HASH}/${OPENCV_ICV_PACKAGE_NAME}")
|
|
||||||
get_filename_component(OPENCV_ICV_PACKAGE_ARCHIVE_DIR "${OPENCV_ICV_PACKAGE_ARCHIVE}" PATH)
|
|
||||||
if(EXISTS "${OPENCV_ICV_PACKAGE_ARCHIVE}")
|
|
||||||
file(MD5 "${OPENCV_ICV_PACKAGE_ARCHIVE}" archive_md5)
|
|
||||||
if(NOT archive_md5 STREQUAL OPENCV_ICV_PACKAGE_HASH)
|
|
||||||
message(WARNING "ICV: Local copy of ICV package has invalid MD5 hash: ${archive_md5} (expected: ${OPENCV_ICV_PACKAGE_HASH})")
|
|
||||||
file(REMOVE "${OPENCV_ICV_PACKAGE_ARCHIVE}")
|
|
||||||
file(REMOVE_RECURSE "${OPENCV_ICV_PACKAGE_ARCHIVE_DIR}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT EXISTS "${OPENCV_ICV_PACKAGE_ARCHIVE}")
|
|
||||||
if(NOT DEFINED OPENCV_ICV_URL)
|
|
||||||
if(DEFINED ENV{OPENCV_ICV_URL})
|
|
||||||
set(OPENCV_ICV_URL $ENV{OPENCV_ICV_URL})
|
|
||||||
else()
|
|
||||||
set(OPENCV_ICV_URL "https://raw.githubusercontent.com/Itseez/opencv_3rdparty/${IPPICV_BINARIES_COMMIT}/ippicv")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
file(MAKE_DIRECTORY ${OPENCV_ICV_PACKAGE_ARCHIVE_DIR})
|
|
||||||
message(STATUS "ICV: Downloading ${OPENCV_ICV_PACKAGE_NAME}...")
|
|
||||||
file(DOWNLOAD "${OPENCV_ICV_URL}/${OPENCV_ICV_PACKAGE_NAME}" "${OPENCV_ICV_PACKAGE_ARCHIVE}"
|
|
||||||
TIMEOUT 600 STATUS __status
|
|
||||||
EXPECTED_MD5 ${OPENCV_ICV_PACKAGE_HASH})
|
|
||||||
if(NOT __status EQUAL 0)
|
|
||||||
message(FATAL_ERROR "ICV: Failed to download ICV package: ${OPENCV_ICV_PACKAGE_NAME}. Status=${__status}")
|
|
||||||
else()
|
|
||||||
# Don't remove this code, because EXPECTED_MD5 parameter doesn't fail "file(DOWNLOAD)" step
|
|
||||||
# on wrong hash
|
|
||||||
file(MD5 "${OPENCV_ICV_PACKAGE_ARCHIVE}" archive_md5)
|
|
||||||
if(NOT archive_md5 STREQUAL OPENCV_ICV_PACKAGE_HASH)
|
|
||||||
message(FATAL_ERROR "ICV: Downloaded copy of ICV package has invalid MD5 hash: ${archive_md5} (expected: ${OPENCV_ICV_PACKAGE_HASH})")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
ocv_assert(EXISTS "${OPENCV_ICV_PACKAGE_ARCHIVE}")
|
|
||||||
ocv_assert(NOT EXISTS "${OPENCV_ICV_UNPACK_PATH}")
|
|
||||||
file(MAKE_DIRECTORY ${OPENCV_ICV_UNPACK_PATH})
|
|
||||||
ocv_assert(EXISTS "${OPENCV_ICV_UNPACK_PATH}")
|
|
||||||
|
|
||||||
message(STATUS "ICV: Unpacking ${OPENCV_ICV_PACKAGE_NAME} to ${OPENCV_ICV_UNPACK_PATH}...")
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xz "${OPENCV_ICV_PACKAGE_ARCHIVE}"
|
|
||||||
WORKING_DIRECTORY "${OPENCV_ICV_UNPACK_PATH}"
|
|
||||||
RESULT_VARIABLE __result)
|
|
||||||
|
|
||||||
if(NOT __result EQUAL 0)
|
|
||||||
message(FATAL_ERROR "ICV: Failed to unpack ICV package from ${OPENCV_ICV_PACKAGE_ARCHIVE} to ${OPENCV_ICV_UNPACK_PATH} with error ${__result}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
ocv_assert(EXISTS "${OPENCV_ICV_PATH}")
|
|
||||||
|
|
||||||
set(OPENCV_ICV_PACKAGE_DOWNLOADED "${OPENCV_ICV_PACKAGE_HASH}" CACHE INTERNAL "ICV package hash")
|
|
||||||
|
|
||||||
message(STATUS "ICV: Package successfully downloaded")
|
|
||||||
set(OPENCV_ICV_PATH "${OPENCV_ICV_PATH}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
_icv_downloader()
|
|
||||||
Vendored
-33
@@ -1,33 +0,0 @@
|
|||||||
Jinja is written and maintained by the Jinja Team and various
|
|
||||||
contributors:
|
|
||||||
|
|
||||||
Lead Developer:
|
|
||||||
|
|
||||||
- Armin Ronacher <armin.ronacher@active-4.com>
|
|
||||||
|
|
||||||
Developers:
|
|
||||||
|
|
||||||
- Christoph Hack
|
|
||||||
- Georg Brandl
|
|
||||||
|
|
||||||
Contributors:
|
|
||||||
|
|
||||||
- Bryan McLemore
|
|
||||||
- Mickaël Guérin <kael@crocobox.org>
|
|
||||||
- Cameron Knight
|
|
||||||
- Lawrence Journal-World.
|
|
||||||
- David Cramer
|
|
||||||
|
|
||||||
Patches and suggestions:
|
|
||||||
|
|
||||||
- Ronny Pfannschmidt
|
|
||||||
- Axel Böhm
|
|
||||||
- Alexey Melchakov
|
|
||||||
- Bryan McLemore
|
|
||||||
- Clovis Fabricio (nosklo)
|
|
||||||
- Cameron Knight
|
|
||||||
- Peter van Dijk (Habbie)
|
|
||||||
- Stefan Ebner
|
|
||||||
- Rene Leonhardt
|
|
||||||
- Thomas Waldmann
|
|
||||||
- Cory Benfield (Lukasa)
|
|
||||||
Vendored
-31
@@ -1,31 +0,0 @@
|
|||||||
Copyright (c) 2009 by the Jinja Team, see AUTHORS for more details.
|
|
||||||
|
|
||||||
Some rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following
|
|
||||||
disclaimer in the documentation and/or other materials provided
|
|
||||||
with the distribution.
|
|
||||||
|
|
||||||
* The names of the contributors may not be used to endorse or
|
|
||||||
promote products derived from this software without specific
|
|
||||||
prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
Vendored
-69
@@ -1,69 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2
|
|
||||||
~~~~~~
|
|
||||||
|
|
||||||
Jinja2 is a template engine written in pure Python. It provides a
|
|
||||||
Django inspired non-XML syntax but supports inline expressions and
|
|
||||||
an optional sandboxed environment.
|
|
||||||
|
|
||||||
Nutshell
|
|
||||||
--------
|
|
||||||
|
|
||||||
Here a small example of a Jinja2 template::
|
|
||||||
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
{% block title %}Memberlist{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
<ul>
|
|
||||||
{% for user in users %}
|
|
||||||
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
__docformat__ = 'restructuredtext en'
|
|
||||||
__version__ = '2.7.1'
|
|
||||||
|
|
||||||
# high level interface
|
|
||||||
from jinja2.environment import Environment, Template
|
|
||||||
|
|
||||||
# loaders
|
|
||||||
from jinja2.loaders import BaseLoader, FileSystemLoader, PackageLoader, \
|
|
||||||
DictLoader, FunctionLoader, PrefixLoader, ChoiceLoader, \
|
|
||||||
ModuleLoader
|
|
||||||
|
|
||||||
# bytecode caches
|
|
||||||
from jinja2.bccache import BytecodeCache, FileSystemBytecodeCache, \
|
|
||||||
MemcachedBytecodeCache
|
|
||||||
|
|
||||||
# undefined types
|
|
||||||
from jinja2.runtime import Undefined, DebugUndefined, StrictUndefined
|
|
||||||
|
|
||||||
# exceptions
|
|
||||||
from jinja2.exceptions import TemplateError, UndefinedError, \
|
|
||||||
TemplateNotFound, TemplatesNotFound, TemplateSyntaxError, \
|
|
||||||
TemplateAssertionError
|
|
||||||
|
|
||||||
# decorators and public utilities
|
|
||||||
from jinja2.filters import environmentfilter, contextfilter, \
|
|
||||||
evalcontextfilter
|
|
||||||
from jinja2.utils import Markup, escape, clear_caches, \
|
|
||||||
environmentfunction, evalcontextfunction, contextfunction, \
|
|
||||||
is_undefined
|
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
'Environment', 'Template', 'BaseLoader', 'FileSystemLoader',
|
|
||||||
'PackageLoader', 'DictLoader', 'FunctionLoader', 'PrefixLoader',
|
|
||||||
'ChoiceLoader', 'BytecodeCache', 'FileSystemBytecodeCache',
|
|
||||||
'MemcachedBytecodeCache', 'Undefined', 'DebugUndefined',
|
|
||||||
'StrictUndefined', 'TemplateError', 'UndefinedError', 'TemplateNotFound',
|
|
||||||
'TemplatesNotFound', 'TemplateSyntaxError', 'TemplateAssertionError',
|
|
||||||
'ModuleLoader', 'environmentfilter', 'contextfilter', 'Markup', 'escape',
|
|
||||||
'environmentfunction', 'contextfunction', 'clear_caches', 'is_undefined',
|
|
||||||
'evalcontextfilter', 'evalcontextfunction'
|
|
||||||
]
|
|
||||||
Vendored
-150
@@ -1,150 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2._compat
|
|
||||||
~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Some py2/py3 compatibility support based on a stripped down
|
|
||||||
version of six so we don't have to depend on a specific version
|
|
||||||
of it.
|
|
||||||
|
|
||||||
:copyright: Copyright 2013 by the Jinja team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
import sys
|
|
||||||
|
|
||||||
PY2 = sys.version_info[0] == 2
|
|
||||||
PYPY = hasattr(sys, 'pypy_translation_info')
|
|
||||||
_identity = lambda x: x
|
|
||||||
|
|
||||||
|
|
||||||
if not PY2:
|
|
||||||
unichr = chr
|
|
||||||
range_type = range
|
|
||||||
text_type = str
|
|
||||||
string_types = (str,)
|
|
||||||
|
|
||||||
iterkeys = lambda d: iter(d.keys())
|
|
||||||
itervalues = lambda d: iter(d.values())
|
|
||||||
iteritems = lambda d: iter(d.items())
|
|
||||||
|
|
||||||
import pickle
|
|
||||||
from io import BytesIO, StringIO
|
|
||||||
NativeStringIO = StringIO
|
|
||||||
|
|
||||||
def reraise(tp, value, tb=None):
|
|
||||||
if value.__traceback__ is not tb:
|
|
||||||
raise value.with_traceback(tb)
|
|
||||||
raise value
|
|
||||||
|
|
||||||
ifilter = filter
|
|
||||||
imap = map
|
|
||||||
izip = zip
|
|
||||||
intern = sys.intern
|
|
||||||
|
|
||||||
implements_iterator = _identity
|
|
||||||
implements_to_string = _identity
|
|
||||||
encode_filename = _identity
|
|
||||||
get_next = lambda x: x.__next__
|
|
||||||
|
|
||||||
else:
|
|
||||||
unichr = unichr
|
|
||||||
text_type = unicode
|
|
||||||
range_type = xrange
|
|
||||||
string_types = (str, unicode)
|
|
||||||
|
|
||||||
iterkeys = lambda d: d.iterkeys()
|
|
||||||
itervalues = lambda d: d.itervalues()
|
|
||||||
iteritems = lambda d: d.iteritems()
|
|
||||||
|
|
||||||
import cPickle as pickle
|
|
||||||
from cStringIO import StringIO as BytesIO, StringIO
|
|
||||||
NativeStringIO = BytesIO
|
|
||||||
|
|
||||||
exec('def reraise(tp, value, tb=None):\n raise tp, value, tb')
|
|
||||||
|
|
||||||
from itertools import imap, izip, ifilter
|
|
||||||
intern = intern
|
|
||||||
|
|
||||||
def implements_iterator(cls):
|
|
||||||
cls.next = cls.__next__
|
|
||||||
del cls.__next__
|
|
||||||
return cls
|
|
||||||
|
|
||||||
def implements_to_string(cls):
|
|
||||||
cls.__unicode__ = cls.__str__
|
|
||||||
cls.__str__ = lambda x: x.__unicode__().encode('utf-8')
|
|
||||||
return cls
|
|
||||||
|
|
||||||
get_next = lambda x: x.next
|
|
||||||
|
|
||||||
def encode_filename(filename):
|
|
||||||
if isinstance(filename, unicode):
|
|
||||||
return filename.encode('utf-8')
|
|
||||||
return filename
|
|
||||||
|
|
||||||
try:
|
|
||||||
next = next
|
|
||||||
except NameError:
|
|
||||||
def next(it):
|
|
||||||
return it.next()
|
|
||||||
|
|
||||||
|
|
||||||
def with_metaclass(meta, *bases):
|
|
||||||
# This requires a bit of explanation: the basic idea is to make a
|
|
||||||
# dummy metaclass for one level of class instanciation that replaces
|
|
||||||
# itself with the actual metaclass. Because of internal type checks
|
|
||||||
# we also need to make sure that we downgrade the custom metaclass
|
|
||||||
# for one level to something closer to type (that's why __call__ and
|
|
||||||
# __init__ comes back from type etc.).
|
|
||||||
#
|
|
||||||
# This has the advantage over six.with_metaclass in that it does not
|
|
||||||
# introduce dummy classes into the final MRO.
|
|
||||||
class metaclass(meta):
|
|
||||||
__call__ = type.__call__
|
|
||||||
__init__ = type.__init__
|
|
||||||
def __new__(cls, name, this_bases, d):
|
|
||||||
if this_bases is None:
|
|
||||||
return type.__new__(cls, name, (), d)
|
|
||||||
return meta(name, bases, d)
|
|
||||||
return metaclass('temporary_class', None, {})
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
from collections import Mapping as mapping_types
|
|
||||||
except ImportError:
|
|
||||||
import UserDict
|
|
||||||
mapping_types = (UserDict.UserDict, UserDict.DictMixin, dict)
|
|
||||||
|
|
||||||
|
|
||||||
# common types. These do exist in the special types module too which however
|
|
||||||
# does not exist in IronPython out of the box. Also that way we don't have
|
|
||||||
# to deal with implementation specific stuff here
|
|
||||||
class _C(object):
|
|
||||||
def method(self): pass
|
|
||||||
def _func():
|
|
||||||
yield None
|
|
||||||
function_type = type(_func)
|
|
||||||
generator_type = type(_func())
|
|
||||||
method_type = type(_C().method)
|
|
||||||
code_type = type(_C.method.__code__)
|
|
||||||
try:
|
|
||||||
raise TypeError()
|
|
||||||
except TypeError:
|
|
||||||
_tb = sys.exc_info()[2]
|
|
||||||
traceback_type = type(_tb)
|
|
||||||
frame_type = type(_tb.tb_frame)
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
from urllib.parse import quote_from_bytes as url_quote
|
|
||||||
except ImportError:
|
|
||||||
from urllib import quote as url_quote
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
from thread import allocate_lock
|
|
||||||
except ImportError:
|
|
||||||
try:
|
|
||||||
from threading import Lock as allocate_lock
|
|
||||||
except ImportError:
|
|
||||||
from dummy_thread import allocate_lock
|
|
||||||
Vendored
-132
File diff suppressed because one or more lines are too long
Vendored
-311
@@ -1,311 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.bccache
|
|
||||||
~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
This module implements the bytecode cache system Jinja is optionally
|
|
||||||
using. This is useful if you have very complex template situations and
|
|
||||||
the compiliation of all those templates slow down your application too
|
|
||||||
much.
|
|
||||||
|
|
||||||
Situations where this is useful are often forking web applications that
|
|
||||||
are initialized on the first request.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD.
|
|
||||||
"""
|
|
||||||
from os import path, listdir
|
|
||||||
import sys
|
|
||||||
import marshal
|
|
||||||
import tempfile
|
|
||||||
import fnmatch
|
|
||||||
from hashlib import sha1
|
|
||||||
from jinja2.utils import open_if_exists
|
|
||||||
from jinja2._compat import BytesIO, pickle, PY2, text_type
|
|
||||||
|
|
||||||
|
|
||||||
# marshal works better on 3.x, one hack less required
|
|
||||||
if not PY2:
|
|
||||||
marshal_dump = marshal.dump
|
|
||||||
marshal_load = marshal.load
|
|
||||||
else:
|
|
||||||
|
|
||||||
def marshal_dump(code, f):
|
|
||||||
if isinstance(f, file):
|
|
||||||
marshal.dump(code, f)
|
|
||||||
else:
|
|
||||||
f.write(marshal.dumps(code))
|
|
||||||
|
|
||||||
def marshal_load(f):
|
|
||||||
if isinstance(f, file):
|
|
||||||
return marshal.load(f)
|
|
||||||
return marshal.loads(f.read())
|
|
||||||
|
|
||||||
|
|
||||||
bc_version = 2
|
|
||||||
|
|
||||||
# magic version used to only change with new jinja versions. With 2.6
|
|
||||||
# we change this to also take Python version changes into account. The
|
|
||||||
# reason for this is that Python tends to segfault if fed earlier bytecode
|
|
||||||
# versions because someone thought it would be a good idea to reuse opcodes
|
|
||||||
# or make Python incompatible with earlier versions.
|
|
||||||
bc_magic = 'j2'.encode('ascii') + \
|
|
||||||
pickle.dumps(bc_version, 2) + \
|
|
||||||
pickle.dumps((sys.version_info[0] << 24) | sys.version_info[1])
|
|
||||||
|
|
||||||
|
|
||||||
class Bucket(object):
|
|
||||||
"""Buckets are used to store the bytecode for one template. It's created
|
|
||||||
and initialized by the bytecode cache and passed to the loading functions.
|
|
||||||
|
|
||||||
The buckets get an internal checksum from the cache assigned and use this
|
|
||||||
to automatically reject outdated cache material. Individual bytecode
|
|
||||||
cache subclasses don't have to care about cache invalidation.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, environment, key, checksum):
|
|
||||||
self.environment = environment
|
|
||||||
self.key = key
|
|
||||||
self.checksum = checksum
|
|
||||||
self.reset()
|
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
"""Resets the bucket (unloads the bytecode)."""
|
|
||||||
self.code = None
|
|
||||||
|
|
||||||
def load_bytecode(self, f):
|
|
||||||
"""Loads bytecode from a file or file like object."""
|
|
||||||
# make sure the magic header is correct
|
|
||||||
magic = f.read(len(bc_magic))
|
|
||||||
if magic != bc_magic:
|
|
||||||
self.reset()
|
|
||||||
return
|
|
||||||
# the source code of the file changed, we need to reload
|
|
||||||
checksum = pickle.load(f)
|
|
||||||
if self.checksum != checksum:
|
|
||||||
self.reset()
|
|
||||||
return
|
|
||||||
self.code = marshal_load(f)
|
|
||||||
|
|
||||||
def write_bytecode(self, f):
|
|
||||||
"""Dump the bytecode into the file or file like object passed."""
|
|
||||||
if self.code is None:
|
|
||||||
raise TypeError('can\'t write empty bucket')
|
|
||||||
f.write(bc_magic)
|
|
||||||
pickle.dump(self.checksum, f, 2)
|
|
||||||
marshal_dump(self.code, f)
|
|
||||||
|
|
||||||
def bytecode_from_string(self, string):
|
|
||||||
"""Load bytecode from a string."""
|
|
||||||
self.load_bytecode(BytesIO(string))
|
|
||||||
|
|
||||||
def bytecode_to_string(self):
|
|
||||||
"""Return the bytecode as string."""
|
|
||||||
out = BytesIO()
|
|
||||||
self.write_bytecode(out)
|
|
||||||
return out.getvalue()
|
|
||||||
|
|
||||||
|
|
||||||
class BytecodeCache(object):
|
|
||||||
"""To implement your own bytecode cache you have to subclass this class
|
|
||||||
and override :meth:`load_bytecode` and :meth:`dump_bytecode`. Both of
|
|
||||||
these methods are passed a :class:`~jinja2.bccache.Bucket`.
|
|
||||||
|
|
||||||
A very basic bytecode cache that saves the bytecode on the file system::
|
|
||||||
|
|
||||||
from os import path
|
|
||||||
|
|
||||||
class MyCache(BytecodeCache):
|
|
||||||
|
|
||||||
def __init__(self, directory):
|
|
||||||
self.directory = directory
|
|
||||||
|
|
||||||
def load_bytecode(self, bucket):
|
|
||||||
filename = path.join(self.directory, bucket.key)
|
|
||||||
if path.exists(filename):
|
|
||||||
with open(filename, 'rb') as f:
|
|
||||||
bucket.load_bytecode(f)
|
|
||||||
|
|
||||||
def dump_bytecode(self, bucket):
|
|
||||||
filename = path.join(self.directory, bucket.key)
|
|
||||||
with open(filename, 'wb') as f:
|
|
||||||
bucket.write_bytecode(f)
|
|
||||||
|
|
||||||
A more advanced version of a filesystem based bytecode cache is part of
|
|
||||||
Jinja2.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def load_bytecode(self, bucket):
|
|
||||||
"""Subclasses have to override this method to load bytecode into a
|
|
||||||
bucket. If they are not able to find code in the cache for the
|
|
||||||
bucket, it must not do anything.
|
|
||||||
"""
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
def dump_bytecode(self, bucket):
|
|
||||||
"""Subclasses have to override this method to write the bytecode
|
|
||||||
from a bucket back to the cache. If it unable to do so it must not
|
|
||||||
fail silently but raise an exception.
|
|
||||||
"""
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
"""Clears the cache. This method is not used by Jinja2 but should be
|
|
||||||
implemented to allow applications to clear the bytecode cache used
|
|
||||||
by a particular environment.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def get_cache_key(self, name, filename=None):
|
|
||||||
"""Returns the unique hash key for this template name."""
|
|
||||||
hash = sha1(name.encode('utf-8'))
|
|
||||||
if filename is not None:
|
|
||||||
filename = '|' + filename
|
|
||||||
if isinstance(filename, text_type):
|
|
||||||
filename = filename.encode('utf-8')
|
|
||||||
hash.update(filename)
|
|
||||||
return hash.hexdigest()
|
|
||||||
|
|
||||||
def get_source_checksum(self, source):
|
|
||||||
"""Returns a checksum for the source."""
|
|
||||||
return sha1(source.encode('utf-8')).hexdigest()
|
|
||||||
|
|
||||||
def get_bucket(self, environment, name, filename, source):
|
|
||||||
"""Return a cache bucket for the given template. All arguments are
|
|
||||||
mandatory but filename may be `None`.
|
|
||||||
"""
|
|
||||||
key = self.get_cache_key(name, filename)
|
|
||||||
checksum = self.get_source_checksum(source)
|
|
||||||
bucket = Bucket(environment, key, checksum)
|
|
||||||
self.load_bytecode(bucket)
|
|
||||||
return bucket
|
|
||||||
|
|
||||||
def set_bucket(self, bucket):
|
|
||||||
"""Put the bucket into the cache."""
|
|
||||||
self.dump_bytecode(bucket)
|
|
||||||
|
|
||||||
|
|
||||||
class FileSystemBytecodeCache(BytecodeCache):
|
|
||||||
"""A bytecode cache that stores bytecode on the filesystem. It accepts
|
|
||||||
two arguments: The directory where the cache items are stored and a
|
|
||||||
pattern string that is used to build the filename.
|
|
||||||
|
|
||||||
If no directory is specified the system temporary items folder is used.
|
|
||||||
|
|
||||||
The pattern can be used to have multiple separate caches operate on the
|
|
||||||
same directory. The default pattern is ``'__jinja2_%s.cache'``. ``%s``
|
|
||||||
is replaced with the cache key.
|
|
||||||
|
|
||||||
>>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache')
|
|
||||||
|
|
||||||
This bytecode cache supports clearing of the cache using the clear method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, directory=None, pattern='__jinja2_%s.cache'):
|
|
||||||
if directory is None:
|
|
||||||
directory = tempfile.gettempdir()
|
|
||||||
self.directory = directory
|
|
||||||
self.pattern = pattern
|
|
||||||
|
|
||||||
def _get_cache_filename(self, bucket):
|
|
||||||
return path.join(self.directory, self.pattern % bucket.key)
|
|
||||||
|
|
||||||
def load_bytecode(self, bucket):
|
|
||||||
f = open_if_exists(self._get_cache_filename(bucket), 'rb')
|
|
||||||
if f is not None:
|
|
||||||
try:
|
|
||||||
bucket.load_bytecode(f)
|
|
||||||
finally:
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
def dump_bytecode(self, bucket):
|
|
||||||
f = open(self._get_cache_filename(bucket), 'wb')
|
|
||||||
try:
|
|
||||||
bucket.write_bytecode(f)
|
|
||||||
finally:
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
# imported lazily here because google app-engine doesn't support
|
|
||||||
# write access on the file system and the function does not exist
|
|
||||||
# normally.
|
|
||||||
from os import remove
|
|
||||||
files = fnmatch.filter(listdir(self.directory), self.pattern % '*')
|
|
||||||
for filename in files:
|
|
||||||
try:
|
|
||||||
remove(path.join(self.directory, filename))
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class MemcachedBytecodeCache(BytecodeCache):
|
|
||||||
"""This class implements a bytecode cache that uses a memcache cache for
|
|
||||||
storing the information. It does not enforce a specific memcache library
|
|
||||||
(tummy's memcache or cmemcache) but will accept any class that provides
|
|
||||||
the minimal interface required.
|
|
||||||
|
|
||||||
Libraries compatible with this class:
|
|
||||||
|
|
||||||
- `werkzeug <http://werkzeug.pocoo.org/>`_.contrib.cache
|
|
||||||
- `python-memcached <http://www.tummy.com/Community/software/python-memcached/>`_
|
|
||||||
- `cmemcache <http://gijsbert.org/cmemcache/>`_
|
|
||||||
|
|
||||||
(Unfortunately the django cache interface is not compatible because it
|
|
||||||
does not support storing binary data, only unicode. You can however pass
|
|
||||||
the underlying cache client to the bytecode cache which is available
|
|
||||||
as `django.core.cache.cache._client`.)
|
|
||||||
|
|
||||||
The minimal interface for the client passed to the constructor is this:
|
|
||||||
|
|
||||||
.. class:: MinimalClientInterface
|
|
||||||
|
|
||||||
.. method:: set(key, value[, timeout])
|
|
||||||
|
|
||||||
Stores the bytecode in the cache. `value` is a string and
|
|
||||||
`timeout` the timeout of the key. If timeout is not provided
|
|
||||||
a default timeout or no timeout should be assumed, if it's
|
|
||||||
provided it's an integer with the number of seconds the cache
|
|
||||||
item should exist.
|
|
||||||
|
|
||||||
.. method:: get(key)
|
|
||||||
|
|
||||||
Returns the value for the cache key. If the item does not
|
|
||||||
exist in the cache the return value must be `None`.
|
|
||||||
|
|
||||||
The other arguments to the constructor are the prefix for all keys that
|
|
||||||
is added before the actual cache key and the timeout for the bytecode in
|
|
||||||
the cache system. We recommend a high (or no) timeout.
|
|
||||||
|
|
||||||
This bytecode cache does not support clearing of used items in the cache.
|
|
||||||
The clear method is a no-operation function.
|
|
||||||
|
|
||||||
.. versionadded:: 2.7
|
|
||||||
Added support for ignoring memcache errors through the
|
|
||||||
`ignore_memcache_errors` parameter.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, client, prefix='jinja2/bytecode/', timeout=None,
|
|
||||||
ignore_memcache_errors=True):
|
|
||||||
self.client = client
|
|
||||||
self.prefix = prefix
|
|
||||||
self.timeout = timeout
|
|
||||||
self.ignore_memcache_errors = ignore_memcache_errors
|
|
||||||
|
|
||||||
def load_bytecode(self, bucket):
|
|
||||||
try:
|
|
||||||
code = self.client.get(self.prefix + bucket.key)
|
|
||||||
except Exception:
|
|
||||||
if not self.ignore_memcache_errors:
|
|
||||||
raise
|
|
||||||
code = None
|
|
||||||
if code is not None:
|
|
||||||
bucket.bytecode_from_string(code)
|
|
||||||
|
|
||||||
def dump_bytecode(self, bucket):
|
|
||||||
args = (self.prefix + bucket.key, bucket.bytecode_to_string())
|
|
||||||
if self.timeout is not None:
|
|
||||||
args += (self.timeout,)
|
|
||||||
try:
|
|
||||||
self.client.set(*args)
|
|
||||||
except Exception:
|
|
||||||
if not self.ignore_memcache_errors:
|
|
||||||
raise
|
|
||||||
Vendored
-1640
File diff suppressed because it is too large
Load Diff
Vendored
-32
@@ -1,32 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja.constants
|
|
||||||
~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Various constants.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
#: list of lorem ipsum words used by the lipsum() helper function
|
|
||||||
LOREM_IPSUM_WORDS = u'''\
|
|
||||||
a ac accumsan ad adipiscing aenean aliquam aliquet amet ante aptent arcu at
|
|
||||||
auctor augue bibendum blandit class commodo condimentum congue consectetuer
|
|
||||||
consequat conubia convallis cras cubilia cum curabitur curae cursus dapibus
|
|
||||||
diam dictum dictumst dignissim dis dolor donec dui duis egestas eget eleifend
|
|
||||||
elementum elit enim erat eros est et etiam eu euismod facilisi facilisis fames
|
|
||||||
faucibus felis fermentum feugiat fringilla fusce gravida habitant habitasse hac
|
|
||||||
hendrerit hymenaeos iaculis id imperdiet in inceptos integer interdum ipsum
|
|
||||||
justo lacinia lacus laoreet lectus leo libero ligula litora lobortis lorem
|
|
||||||
luctus maecenas magna magnis malesuada massa mattis mauris metus mi molestie
|
|
||||||
mollis montes morbi mus nam nascetur natoque nec neque netus nibh nisi nisl non
|
|
||||||
nonummy nostra nulla nullam nunc odio orci ornare parturient pede pellentesque
|
|
||||||
penatibus per pharetra phasellus placerat platea porta porttitor posuere
|
|
||||||
potenti praesent pretium primis proin pulvinar purus quam quis quisque rhoncus
|
|
||||||
ridiculus risus rutrum sagittis sapien scelerisque sed sem semper senectus sit
|
|
||||||
sociis sociosqu sodales sollicitudin suscipit suspendisse taciti tellus tempor
|
|
||||||
tempus tincidunt torquent tortor tristique turpis ullamcorper ultrices
|
|
||||||
ultricies urna ut varius vehicula vel velit venenatis vestibulum vitae vivamus
|
|
||||||
viverra volutpat vulputate'''
|
|
||||||
Vendored
-337
@@ -1,337 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.debug
|
|
||||||
~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Implements the debug interface for Jinja. This module does some pretty
|
|
||||||
ugly stuff with the Python traceback system in order to achieve tracebacks
|
|
||||||
with correct line numbers, locals and contents.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
import sys
|
|
||||||
import traceback
|
|
||||||
from types import TracebackType
|
|
||||||
from jinja2.utils import missing, internal_code
|
|
||||||
from jinja2.exceptions import TemplateSyntaxError
|
|
||||||
from jinja2._compat import iteritems, reraise, code_type
|
|
||||||
|
|
||||||
# on pypy we can take advantage of transparent proxies
|
|
||||||
try:
|
|
||||||
from __pypy__ import tproxy
|
|
||||||
except ImportError:
|
|
||||||
tproxy = None
|
|
||||||
|
|
||||||
|
|
||||||
# how does the raise helper look like?
|
|
||||||
try:
|
|
||||||
exec("raise TypeError, 'foo'")
|
|
||||||
except SyntaxError:
|
|
||||||
raise_helper = 'raise __jinja_exception__[1]'
|
|
||||||
except TypeError:
|
|
||||||
raise_helper = 'raise __jinja_exception__[0], __jinja_exception__[1]'
|
|
||||||
|
|
||||||
|
|
||||||
class TracebackFrameProxy(object):
|
|
||||||
"""Proxies a traceback frame."""
|
|
||||||
|
|
||||||
def __init__(self, tb):
|
|
||||||
self.tb = tb
|
|
||||||
self._tb_next = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def tb_next(self):
|
|
||||||
return self._tb_next
|
|
||||||
|
|
||||||
def set_next(self, next):
|
|
||||||
if tb_set_next is not None:
|
|
||||||
try:
|
|
||||||
tb_set_next(self.tb, next and next.tb or None)
|
|
||||||
except Exception:
|
|
||||||
# this function can fail due to all the hackery it does
|
|
||||||
# on various python implementations. We just catch errors
|
|
||||||
# down and ignore them if necessary.
|
|
||||||
pass
|
|
||||||
self._tb_next = next
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_jinja_frame(self):
|
|
||||||
return '__jinja_template__' in self.tb.tb_frame.f_globals
|
|
||||||
|
|
||||||
def __getattr__(self, name):
|
|
||||||
return getattr(self.tb, name)
|
|
||||||
|
|
||||||
|
|
||||||
def make_frame_proxy(frame):
|
|
||||||
proxy = TracebackFrameProxy(frame)
|
|
||||||
if tproxy is None:
|
|
||||||
return proxy
|
|
||||||
def operation_handler(operation, *args, **kwargs):
|
|
||||||
if operation in ('__getattribute__', '__getattr__'):
|
|
||||||
return getattr(proxy, args[0])
|
|
||||||
elif operation == '__setattr__':
|
|
||||||
proxy.__setattr__(*args, **kwargs)
|
|
||||||
else:
|
|
||||||
return getattr(proxy, operation)(*args, **kwargs)
|
|
||||||
return tproxy(TracebackType, operation_handler)
|
|
||||||
|
|
||||||
|
|
||||||
class ProcessedTraceback(object):
|
|
||||||
"""Holds a Jinja preprocessed traceback for printing or reraising."""
|
|
||||||
|
|
||||||
def __init__(self, exc_type, exc_value, frames):
|
|
||||||
assert frames, 'no frames for this traceback?'
|
|
||||||
self.exc_type = exc_type
|
|
||||||
self.exc_value = exc_value
|
|
||||||
self.frames = frames
|
|
||||||
|
|
||||||
# newly concatenate the frames (which are proxies)
|
|
||||||
prev_tb = None
|
|
||||||
for tb in self.frames:
|
|
||||||
if prev_tb is not None:
|
|
||||||
prev_tb.set_next(tb)
|
|
||||||
prev_tb = tb
|
|
||||||
prev_tb.set_next(None)
|
|
||||||
|
|
||||||
def render_as_text(self, limit=None):
|
|
||||||
"""Return a string with the traceback."""
|
|
||||||
lines = traceback.format_exception(self.exc_type, self.exc_value,
|
|
||||||
self.frames[0], limit=limit)
|
|
||||||
return ''.join(lines).rstrip()
|
|
||||||
|
|
||||||
def render_as_html(self, full=False):
|
|
||||||
"""Return a unicode string with the traceback as rendered HTML."""
|
|
||||||
from jinja2.debugrenderer import render_traceback
|
|
||||||
return u'%s\n\n<!--\n%s\n-->' % (
|
|
||||||
render_traceback(self, full=full),
|
|
||||||
self.render_as_text().decode('utf-8', 'replace')
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_template_syntax_error(self):
|
|
||||||
"""`True` if this is a template syntax error."""
|
|
||||||
return isinstance(self.exc_value, TemplateSyntaxError)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def exc_info(self):
|
|
||||||
"""Exception info tuple with a proxy around the frame objects."""
|
|
||||||
return self.exc_type, self.exc_value, self.frames[0]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def standard_exc_info(self):
|
|
||||||
"""Standard python exc_info for re-raising"""
|
|
||||||
tb = self.frames[0]
|
|
||||||
# the frame will be an actual traceback (or transparent proxy) if
|
|
||||||
# we are on pypy or a python implementation with support for tproxy
|
|
||||||
if type(tb) is not TracebackType:
|
|
||||||
tb = tb.tb
|
|
||||||
return self.exc_type, self.exc_value, tb
|
|
||||||
|
|
||||||
|
|
||||||
def make_traceback(exc_info, source_hint=None):
|
|
||||||
"""Creates a processed traceback object from the exc_info."""
|
|
||||||
exc_type, exc_value, tb = exc_info
|
|
||||||
if isinstance(exc_value, TemplateSyntaxError):
|
|
||||||
exc_info = translate_syntax_error(exc_value, source_hint)
|
|
||||||
initial_skip = 0
|
|
||||||
else:
|
|
||||||
initial_skip = 1
|
|
||||||
return translate_exception(exc_info, initial_skip)
|
|
||||||
|
|
||||||
|
|
||||||
def translate_syntax_error(error, source=None):
|
|
||||||
"""Rewrites a syntax error to please traceback systems."""
|
|
||||||
error.source = source
|
|
||||||
error.translated = True
|
|
||||||
exc_info = (error.__class__, error, None)
|
|
||||||
filename = error.filename
|
|
||||||
if filename is None:
|
|
||||||
filename = '<unknown>'
|
|
||||||
return fake_exc_info(exc_info, filename, error.lineno)
|
|
||||||
|
|
||||||
|
|
||||||
def translate_exception(exc_info, initial_skip=0):
|
|
||||||
"""If passed an exc_info it will automatically rewrite the exceptions
|
|
||||||
all the way down to the correct line numbers and frames.
|
|
||||||
"""
|
|
||||||
tb = exc_info[2]
|
|
||||||
frames = []
|
|
||||||
|
|
||||||
# skip some internal frames if wanted
|
|
||||||
for x in range(initial_skip):
|
|
||||||
if tb is not None:
|
|
||||||
tb = tb.tb_next
|
|
||||||
initial_tb = tb
|
|
||||||
|
|
||||||
while tb is not None:
|
|
||||||
# skip frames decorated with @internalcode. These are internal
|
|
||||||
# calls we can't avoid and that are useless in template debugging
|
|
||||||
# output.
|
|
||||||
if tb.tb_frame.f_code in internal_code:
|
|
||||||
tb = tb.tb_next
|
|
||||||
continue
|
|
||||||
|
|
||||||
# save a reference to the next frame if we override the current
|
|
||||||
# one with a faked one.
|
|
||||||
next = tb.tb_next
|
|
||||||
|
|
||||||
# fake template exceptions
|
|
||||||
template = tb.tb_frame.f_globals.get('__jinja_template__')
|
|
||||||
if template is not None:
|
|
||||||
lineno = template.get_corresponding_lineno(tb.tb_lineno)
|
|
||||||
tb = fake_exc_info(exc_info[:2] + (tb,), template.filename,
|
|
||||||
lineno)[2]
|
|
||||||
|
|
||||||
frames.append(make_frame_proxy(tb))
|
|
||||||
tb = next
|
|
||||||
|
|
||||||
# if we don't have any exceptions in the frames left, we have to
|
|
||||||
# reraise it unchanged.
|
|
||||||
# XXX: can we backup here? when could this happen?
|
|
||||||
if not frames:
|
|
||||||
reraise(exc_info[0], exc_info[1], exc_info[2])
|
|
||||||
|
|
||||||
return ProcessedTraceback(exc_info[0], exc_info[1], frames)
|
|
||||||
|
|
||||||
|
|
||||||
def fake_exc_info(exc_info, filename, lineno):
|
|
||||||
"""Helper for `translate_exception`."""
|
|
||||||
exc_type, exc_value, tb = exc_info
|
|
||||||
|
|
||||||
# figure the real context out
|
|
||||||
if tb is not None:
|
|
||||||
real_locals = tb.tb_frame.f_locals.copy()
|
|
||||||
ctx = real_locals.get('context')
|
|
||||||
if ctx:
|
|
||||||
locals = ctx.get_all()
|
|
||||||
else:
|
|
||||||
locals = {}
|
|
||||||
for name, value in iteritems(real_locals):
|
|
||||||
if name.startswith('l_') and value is not missing:
|
|
||||||
locals[name[2:]] = value
|
|
||||||
|
|
||||||
# if there is a local called __jinja_exception__, we get
|
|
||||||
# rid of it to not break the debug functionality.
|
|
||||||
locals.pop('__jinja_exception__', None)
|
|
||||||
else:
|
|
||||||
locals = {}
|
|
||||||
|
|
||||||
# assamble fake globals we need
|
|
||||||
globals = {
|
|
||||||
'__name__': filename,
|
|
||||||
'__file__': filename,
|
|
||||||
'__jinja_exception__': exc_info[:2],
|
|
||||||
|
|
||||||
# we don't want to keep the reference to the template around
|
|
||||||
# to not cause circular dependencies, but we mark it as Jinja
|
|
||||||
# frame for the ProcessedTraceback
|
|
||||||
'__jinja_template__': None
|
|
||||||
}
|
|
||||||
|
|
||||||
# and fake the exception
|
|
||||||
code = compile('\n' * (lineno - 1) + raise_helper, filename, 'exec')
|
|
||||||
|
|
||||||
# if it's possible, change the name of the code. This won't work
|
|
||||||
# on some python environments such as google appengine
|
|
||||||
try:
|
|
||||||
if tb is None:
|
|
||||||
location = 'template'
|
|
||||||
else:
|
|
||||||
function = tb.tb_frame.f_code.co_name
|
|
||||||
if function == 'root':
|
|
||||||
location = 'top-level template code'
|
|
||||||
elif function.startswith('block_'):
|
|
||||||
location = 'block "%s"' % function[6:]
|
|
||||||
else:
|
|
||||||
location = 'template'
|
|
||||||
code = code_type(0, code.co_nlocals, code.co_stacksize,
|
|
||||||
code.co_flags, code.co_code, code.co_consts,
|
|
||||||
code.co_names, code.co_varnames, filename,
|
|
||||||
location, code.co_firstlineno,
|
|
||||||
code.co_lnotab, (), ())
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# execute the code and catch the new traceback
|
|
||||||
try:
|
|
||||||
exec(code, globals, locals)
|
|
||||||
except:
|
|
||||||
exc_info = sys.exc_info()
|
|
||||||
new_tb = exc_info[2].tb_next
|
|
||||||
|
|
||||||
# return without this frame
|
|
||||||
return exc_info[:2] + (new_tb,)
|
|
||||||
|
|
||||||
|
|
||||||
def _init_ugly_crap():
|
|
||||||
"""This function implements a few ugly things so that we can patch the
|
|
||||||
traceback objects. The function returned allows resetting `tb_next` on
|
|
||||||
any python traceback object. Do not attempt to use this on non cpython
|
|
||||||
interpreters
|
|
||||||
"""
|
|
||||||
import ctypes
|
|
||||||
from types import TracebackType
|
|
||||||
|
|
||||||
# figure out side of _Py_ssize_t
|
|
||||||
if hasattr(ctypes.pythonapi, 'Py_InitModule4_64'):
|
|
||||||
_Py_ssize_t = ctypes.c_int64
|
|
||||||
else:
|
|
||||||
_Py_ssize_t = ctypes.c_int
|
|
||||||
|
|
||||||
# regular python
|
|
||||||
class _PyObject(ctypes.Structure):
|
|
||||||
pass
|
|
||||||
_PyObject._fields_ = [
|
|
||||||
('ob_refcnt', _Py_ssize_t),
|
|
||||||
('ob_type', ctypes.POINTER(_PyObject))
|
|
||||||
]
|
|
||||||
|
|
||||||
# python with trace
|
|
||||||
if hasattr(sys, 'getobjects'):
|
|
||||||
class _PyObject(ctypes.Structure):
|
|
||||||
pass
|
|
||||||
_PyObject._fields_ = [
|
|
||||||
('_ob_next', ctypes.POINTER(_PyObject)),
|
|
||||||
('_ob_prev', ctypes.POINTER(_PyObject)),
|
|
||||||
('ob_refcnt', _Py_ssize_t),
|
|
||||||
('ob_type', ctypes.POINTER(_PyObject))
|
|
||||||
]
|
|
||||||
|
|
||||||
class _Traceback(_PyObject):
|
|
||||||
pass
|
|
||||||
_Traceback._fields_ = [
|
|
||||||
('tb_next', ctypes.POINTER(_Traceback)),
|
|
||||||
('tb_frame', ctypes.POINTER(_PyObject)),
|
|
||||||
('tb_lasti', ctypes.c_int),
|
|
||||||
('tb_lineno', ctypes.c_int)
|
|
||||||
]
|
|
||||||
|
|
||||||
def tb_set_next(tb, next):
|
|
||||||
"""Set the tb_next attribute of a traceback object."""
|
|
||||||
if not (isinstance(tb, TracebackType) and
|
|
||||||
(next is None or isinstance(next, TracebackType))):
|
|
||||||
raise TypeError('tb_set_next arguments must be traceback objects')
|
|
||||||
obj = _Traceback.from_address(id(tb))
|
|
||||||
if tb.tb_next is not None:
|
|
||||||
old = _Traceback.from_address(id(tb.tb_next))
|
|
||||||
old.ob_refcnt -= 1
|
|
||||||
if next is None:
|
|
||||||
obj.tb_next = ctypes.POINTER(_Traceback)()
|
|
||||||
else:
|
|
||||||
next = _Traceback.from_address(id(next))
|
|
||||||
next.ob_refcnt += 1
|
|
||||||
obj.tb_next = ctypes.pointer(next)
|
|
||||||
|
|
||||||
return tb_set_next
|
|
||||||
|
|
||||||
|
|
||||||
# try to get a tb_set_next implementation if we don't have transparent
|
|
||||||
# proxies.
|
|
||||||
tb_set_next = None
|
|
||||||
if tproxy is None:
|
|
||||||
try:
|
|
||||||
tb_set_next = _init_ugly_crap()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
del _init_ugly_crap
|
|
||||||
Vendored
-43
@@ -1,43 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.defaults
|
|
||||||
~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Jinja default filters and tags.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
from jinja2._compat import range_type
|
|
||||||
from jinja2.utils import generate_lorem_ipsum, Cycler, Joiner
|
|
||||||
|
|
||||||
|
|
||||||
# defaults for the parser / lexer
|
|
||||||
BLOCK_START_STRING = '{%'
|
|
||||||
BLOCK_END_STRING = '%}'
|
|
||||||
VARIABLE_START_STRING = '{{'
|
|
||||||
VARIABLE_END_STRING = '}}'
|
|
||||||
COMMENT_START_STRING = '{#'
|
|
||||||
COMMENT_END_STRING = '#}'
|
|
||||||
LINE_STATEMENT_PREFIX = None
|
|
||||||
LINE_COMMENT_PREFIX = None
|
|
||||||
TRIM_BLOCKS = False
|
|
||||||
LSTRIP_BLOCKS = False
|
|
||||||
NEWLINE_SEQUENCE = '\n'
|
|
||||||
KEEP_TRAILING_NEWLINE = False
|
|
||||||
|
|
||||||
|
|
||||||
# default filters, tests and namespace
|
|
||||||
from jinja2.filters import FILTERS as DEFAULT_FILTERS
|
|
||||||
from jinja2.tests import TESTS as DEFAULT_TESTS
|
|
||||||
DEFAULT_NAMESPACE = {
|
|
||||||
'range': range_type,
|
|
||||||
'dict': lambda **kw: kw,
|
|
||||||
'lipsum': generate_lorem_ipsum,
|
|
||||||
'cycler': Cycler,
|
|
||||||
'joiner': Joiner
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# export all constants
|
|
||||||
__all__ = tuple(x for x in locals().keys() if x.isupper())
|
|
||||||
Vendored
-1191
File diff suppressed because it is too large
Load Diff
Vendored
-146
@@ -1,146 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.exceptions
|
|
||||||
~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Jinja exceptions.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
from jinja2._compat import imap, text_type, PY2, implements_to_string
|
|
||||||
|
|
||||||
|
|
||||||
class TemplateError(Exception):
|
|
||||||
"""Baseclass for all template errors."""
|
|
||||||
|
|
||||||
if PY2:
|
|
||||||
def __init__(self, message=None):
|
|
||||||
if message is not None:
|
|
||||||
message = text_type(message).encode('utf-8')
|
|
||||||
Exception.__init__(self, message)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def message(self):
|
|
||||||
if self.args:
|
|
||||||
message = self.args[0]
|
|
||||||
if message is not None:
|
|
||||||
return message.decode('utf-8', 'replace')
|
|
||||||
|
|
||||||
def __unicode__(self):
|
|
||||||
return self.message or u''
|
|
||||||
else:
|
|
||||||
def __init__(self, message=None):
|
|
||||||
Exception.__init__(self, message)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def message(self):
|
|
||||||
if self.args:
|
|
||||||
message = self.args[0]
|
|
||||||
if message is not None:
|
|
||||||
return message
|
|
||||||
|
|
||||||
|
|
||||||
@implements_to_string
|
|
||||||
class TemplateNotFound(IOError, LookupError, TemplateError):
|
|
||||||
"""Raised if a template does not exist."""
|
|
||||||
|
|
||||||
# looks weird, but removes the warning descriptor that just
|
|
||||||
# bogusly warns us about message being deprecated
|
|
||||||
message = None
|
|
||||||
|
|
||||||
def __init__(self, name, message=None):
|
|
||||||
IOError.__init__(self)
|
|
||||||
if message is None:
|
|
||||||
message = name
|
|
||||||
self.message = message
|
|
||||||
self.name = name
|
|
||||||
self.templates = [name]
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.message
|
|
||||||
|
|
||||||
|
|
||||||
class TemplatesNotFound(TemplateNotFound):
|
|
||||||
"""Like :class:`TemplateNotFound` but raised if multiple templates
|
|
||||||
are selected. This is a subclass of :class:`TemplateNotFound`
|
|
||||||
exception, so just catching the base exception will catch both.
|
|
||||||
|
|
||||||
.. versionadded:: 2.2
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, names=(), message=None):
|
|
||||||
if message is None:
|
|
||||||
message = u'none of the templates given were found: ' + \
|
|
||||||
u', '.join(imap(text_type, names))
|
|
||||||
TemplateNotFound.__init__(self, names and names[-1] or None, message)
|
|
||||||
self.templates = list(names)
|
|
||||||
|
|
||||||
|
|
||||||
@implements_to_string
|
|
||||||
class TemplateSyntaxError(TemplateError):
|
|
||||||
"""Raised to tell the user that there is a problem with the template."""
|
|
||||||
|
|
||||||
def __init__(self, message, lineno, name=None, filename=None):
|
|
||||||
TemplateError.__init__(self, message)
|
|
||||||
self.lineno = lineno
|
|
||||||
self.name = name
|
|
||||||
self.filename = filename
|
|
||||||
self.source = None
|
|
||||||
|
|
||||||
# this is set to True if the debug.translate_syntax_error
|
|
||||||
# function translated the syntax error into a new traceback
|
|
||||||
self.translated = False
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
# for translated errors we only return the message
|
|
||||||
if self.translated:
|
|
||||||
return self.message
|
|
||||||
|
|
||||||
# otherwise attach some stuff
|
|
||||||
location = 'line %d' % self.lineno
|
|
||||||
name = self.filename or self.name
|
|
||||||
if name:
|
|
||||||
location = 'File "%s", %s' % (name, location)
|
|
||||||
lines = [self.message, ' ' + location]
|
|
||||||
|
|
||||||
# if the source is set, add the line to the output
|
|
||||||
if self.source is not None:
|
|
||||||
try:
|
|
||||||
line = self.source.splitlines()[self.lineno - 1]
|
|
||||||
except IndexError:
|
|
||||||
line = None
|
|
||||||
if line:
|
|
||||||
lines.append(' ' + line.strip())
|
|
||||||
|
|
||||||
return u'\n'.join(lines)
|
|
||||||
|
|
||||||
|
|
||||||
class TemplateAssertionError(TemplateSyntaxError):
|
|
||||||
"""Like a template syntax error, but covers cases where something in the
|
|
||||||
template caused an error at compile time that wasn't necessarily caused
|
|
||||||
by a syntax error. However it's a direct subclass of
|
|
||||||
:exc:`TemplateSyntaxError` and has the same attributes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class TemplateRuntimeError(TemplateError):
|
|
||||||
"""A generic runtime error in the template engine. Under some situations
|
|
||||||
Jinja may raise this exception.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class UndefinedError(TemplateRuntimeError):
|
|
||||||
"""Raised if a template tries to operate on :class:`Undefined`."""
|
|
||||||
|
|
||||||
|
|
||||||
class SecurityError(TemplateRuntimeError):
|
|
||||||
"""Raised if a template tries to do something insecure if the
|
|
||||||
sandbox is enabled.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class FilterArgumentError(TemplateRuntimeError):
|
|
||||||
"""This error is raised if a filter was called with inappropriate
|
|
||||||
arguments
|
|
||||||
"""
|
|
||||||
Vendored
-636
@@ -1,636 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.ext
|
|
||||||
~~~~~~~~~~
|
|
||||||
|
|
||||||
Jinja extensions allow to add custom tags similar to the way django custom
|
|
||||||
tags work. By default two example extensions exist: an i18n and a cache
|
|
||||||
extension.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD.
|
|
||||||
"""
|
|
||||||
from jinja2 import nodes
|
|
||||||
from jinja2.defaults import BLOCK_START_STRING, \
|
|
||||||
BLOCK_END_STRING, VARIABLE_START_STRING, VARIABLE_END_STRING, \
|
|
||||||
COMMENT_START_STRING, COMMENT_END_STRING, LINE_STATEMENT_PREFIX, \
|
|
||||||
LINE_COMMENT_PREFIX, TRIM_BLOCKS, NEWLINE_SEQUENCE, \
|
|
||||||
KEEP_TRAILING_NEWLINE, LSTRIP_BLOCKS
|
|
||||||
from jinja2.environment import Environment
|
|
||||||
from jinja2.runtime import concat
|
|
||||||
from jinja2.exceptions import TemplateAssertionError, TemplateSyntaxError
|
|
||||||
from jinja2.utils import contextfunction, import_string, Markup
|
|
||||||
from jinja2._compat import next, with_metaclass, string_types, iteritems
|
|
||||||
|
|
||||||
|
|
||||||
# the only real useful gettext functions for a Jinja template. Note
|
|
||||||
# that ugettext must be assigned to gettext as Jinja doesn't support
|
|
||||||
# non unicode strings.
|
|
||||||
GETTEXT_FUNCTIONS = ('_', 'gettext', 'ngettext')
|
|
||||||
|
|
||||||
|
|
||||||
class ExtensionRegistry(type):
|
|
||||||
"""Gives the extension an unique identifier."""
|
|
||||||
|
|
||||||
def __new__(cls, name, bases, d):
|
|
||||||
rv = type.__new__(cls, name, bases, d)
|
|
||||||
rv.identifier = rv.__module__ + '.' + rv.__name__
|
|
||||||
return rv
|
|
||||||
|
|
||||||
|
|
||||||
class Extension(with_metaclass(ExtensionRegistry, object)):
|
|
||||||
"""Extensions can be used to add extra functionality to the Jinja template
|
|
||||||
system at the parser level. Custom extensions are bound to an environment
|
|
||||||
but may not store environment specific data on `self`. The reason for
|
|
||||||
this is that an extension can be bound to another environment (for
|
|
||||||
overlays) by creating a copy and reassigning the `environment` attribute.
|
|
||||||
|
|
||||||
As extensions are created by the environment they cannot accept any
|
|
||||||
arguments for configuration. One may want to work around that by using
|
|
||||||
a factory function, but that is not possible as extensions are identified
|
|
||||||
by their import name. The correct way to configure the extension is
|
|
||||||
storing the configuration values on the environment. Because this way the
|
|
||||||
environment ends up acting as central configuration storage the
|
|
||||||
attributes may clash which is why extensions have to ensure that the names
|
|
||||||
they choose for configuration are not too generic. ``prefix`` for example
|
|
||||||
is a terrible name, ``fragment_cache_prefix`` on the other hand is a good
|
|
||||||
name as includes the name of the extension (fragment cache).
|
|
||||||
"""
|
|
||||||
|
|
||||||
#: if this extension parses this is the list of tags it's listening to.
|
|
||||||
tags = set()
|
|
||||||
|
|
||||||
#: the priority of that extension. This is especially useful for
|
|
||||||
#: extensions that preprocess values. A lower value means higher
|
|
||||||
#: priority.
|
|
||||||
#:
|
|
||||||
#: .. versionadded:: 2.4
|
|
||||||
priority = 100
|
|
||||||
|
|
||||||
def __init__(self, environment):
|
|
||||||
self.environment = environment
|
|
||||||
|
|
||||||
def bind(self, environment):
|
|
||||||
"""Create a copy of this extension bound to another environment."""
|
|
||||||
rv = object.__new__(self.__class__)
|
|
||||||
rv.__dict__.update(self.__dict__)
|
|
||||||
rv.environment = environment
|
|
||||||
return rv
|
|
||||||
|
|
||||||
def preprocess(self, source, name, filename=None):
|
|
||||||
"""This method is called before the actual lexing and can be used to
|
|
||||||
preprocess the source. The `filename` is optional. The return value
|
|
||||||
must be the preprocessed source.
|
|
||||||
"""
|
|
||||||
return source
|
|
||||||
|
|
||||||
def filter_stream(self, stream):
|
|
||||||
"""It's passed a :class:`~jinja2.lexer.TokenStream` that can be used
|
|
||||||
to filter tokens returned. This method has to return an iterable of
|
|
||||||
:class:`~jinja2.lexer.Token`\s, but it doesn't have to return a
|
|
||||||
:class:`~jinja2.lexer.TokenStream`.
|
|
||||||
|
|
||||||
In the `ext` folder of the Jinja2 source distribution there is a file
|
|
||||||
called `inlinegettext.py` which implements a filter that utilizes this
|
|
||||||
method.
|
|
||||||
"""
|
|
||||||
return stream
|
|
||||||
|
|
||||||
def parse(self, parser):
|
|
||||||
"""If any of the :attr:`tags` matched this method is called with the
|
|
||||||
parser as first argument. The token the parser stream is pointing at
|
|
||||||
is the name token that matched. This method has to return one or a
|
|
||||||
list of multiple nodes.
|
|
||||||
"""
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
def attr(self, name, lineno=None):
|
|
||||||
"""Return an attribute node for the current extension. This is useful
|
|
||||||
to pass constants on extensions to generated template code.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
self.attr('_my_attribute', lineno=lineno)
|
|
||||||
"""
|
|
||||||
return nodes.ExtensionAttribute(self.identifier, name, lineno=lineno)
|
|
||||||
|
|
||||||
def call_method(self, name, args=None, kwargs=None, dyn_args=None,
|
|
||||||
dyn_kwargs=None, lineno=None):
|
|
||||||
"""Call a method of the extension. This is a shortcut for
|
|
||||||
:meth:`attr` + :class:`jinja2.nodes.Call`.
|
|
||||||
"""
|
|
||||||
if args is None:
|
|
||||||
args = []
|
|
||||||
if kwargs is None:
|
|
||||||
kwargs = []
|
|
||||||
return nodes.Call(self.attr(name, lineno=lineno), args, kwargs,
|
|
||||||
dyn_args, dyn_kwargs, lineno=lineno)
|
|
||||||
|
|
||||||
|
|
||||||
@contextfunction
|
|
||||||
def _gettext_alias(__context, *args, **kwargs):
|
|
||||||
return __context.call(__context.resolve('gettext'), *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def _make_new_gettext(func):
|
|
||||||
@contextfunction
|
|
||||||
def gettext(__context, __string, **variables):
|
|
||||||
rv = __context.call(func, __string)
|
|
||||||
if __context.eval_ctx.autoescape:
|
|
||||||
rv = Markup(rv)
|
|
||||||
return rv % variables
|
|
||||||
return gettext
|
|
||||||
|
|
||||||
|
|
||||||
def _make_new_ngettext(func):
|
|
||||||
@contextfunction
|
|
||||||
def ngettext(__context, __singular, __plural, __num, **variables):
|
|
||||||
variables.setdefault('num', __num)
|
|
||||||
rv = __context.call(func, __singular, __plural, __num)
|
|
||||||
if __context.eval_ctx.autoescape:
|
|
||||||
rv = Markup(rv)
|
|
||||||
return rv % variables
|
|
||||||
return ngettext
|
|
||||||
|
|
||||||
|
|
||||||
class InternationalizationExtension(Extension):
|
|
||||||
"""This extension adds gettext support to Jinja2."""
|
|
||||||
tags = set(['trans'])
|
|
||||||
|
|
||||||
# TODO: the i18n extension is currently reevaluating values in a few
|
|
||||||
# situations. Take this example:
|
|
||||||
# {% trans count=something() %}{{ count }} foo{% pluralize
|
|
||||||
# %}{{ count }} fooss{% endtrans %}
|
|
||||||
# something is called twice here. One time for the gettext value and
|
|
||||||
# the other time for the n-parameter of the ngettext function.
|
|
||||||
|
|
||||||
def __init__(self, environment):
|
|
||||||
Extension.__init__(self, environment)
|
|
||||||
environment.globals['_'] = _gettext_alias
|
|
||||||
environment.extend(
|
|
||||||
install_gettext_translations=self._install,
|
|
||||||
install_null_translations=self._install_null,
|
|
||||||
install_gettext_callables=self._install_callables,
|
|
||||||
uninstall_gettext_translations=self._uninstall,
|
|
||||||
extract_translations=self._extract,
|
|
||||||
newstyle_gettext=False
|
|
||||||
)
|
|
||||||
|
|
||||||
def _install(self, translations, newstyle=None):
|
|
||||||
gettext = getattr(translations, 'ugettext', None)
|
|
||||||
if gettext is None:
|
|
||||||
gettext = translations.gettext
|
|
||||||
ngettext = getattr(translations, 'ungettext', None)
|
|
||||||
if ngettext is None:
|
|
||||||
ngettext = translations.ngettext
|
|
||||||
self._install_callables(gettext, ngettext, newstyle)
|
|
||||||
|
|
||||||
def _install_null(self, newstyle=None):
|
|
||||||
self._install_callables(
|
|
||||||
lambda x: x,
|
|
||||||
lambda s, p, n: (n != 1 and (p,) or (s,))[0],
|
|
||||||
newstyle
|
|
||||||
)
|
|
||||||
|
|
||||||
def _install_callables(self, gettext, ngettext, newstyle=None):
|
|
||||||
if newstyle is not None:
|
|
||||||
self.environment.newstyle_gettext = newstyle
|
|
||||||
if self.environment.newstyle_gettext:
|
|
||||||
gettext = _make_new_gettext(gettext)
|
|
||||||
ngettext = _make_new_ngettext(ngettext)
|
|
||||||
self.environment.globals.update(
|
|
||||||
gettext=gettext,
|
|
||||||
ngettext=ngettext
|
|
||||||
)
|
|
||||||
|
|
||||||
def _uninstall(self, translations):
|
|
||||||
for key in 'gettext', 'ngettext':
|
|
||||||
self.environment.globals.pop(key, None)
|
|
||||||
|
|
||||||
def _extract(self, source, gettext_functions=GETTEXT_FUNCTIONS):
|
|
||||||
if isinstance(source, string_types):
|
|
||||||
source = self.environment.parse(source)
|
|
||||||
return extract_from_ast(source, gettext_functions)
|
|
||||||
|
|
||||||
def parse(self, parser):
|
|
||||||
"""Parse a translatable tag."""
|
|
||||||
lineno = next(parser.stream).lineno
|
|
||||||
num_called_num = False
|
|
||||||
|
|
||||||
# find all the variables referenced. Additionally a variable can be
|
|
||||||
# defined in the body of the trans block too, but this is checked at
|
|
||||||
# a later state.
|
|
||||||
plural_expr = None
|
|
||||||
plural_expr_assignment = None
|
|
||||||
variables = {}
|
|
||||||
while parser.stream.current.type != 'block_end':
|
|
||||||
if variables:
|
|
||||||
parser.stream.expect('comma')
|
|
||||||
|
|
||||||
# skip colon for python compatibility
|
|
||||||
if parser.stream.skip_if('colon'):
|
|
||||||
break
|
|
||||||
|
|
||||||
name = parser.stream.expect('name')
|
|
||||||
if name.value in variables:
|
|
||||||
parser.fail('translatable variable %r defined twice.' %
|
|
||||||
name.value, name.lineno,
|
|
||||||
exc=TemplateAssertionError)
|
|
||||||
|
|
||||||
# expressions
|
|
||||||
if parser.stream.current.type == 'assign':
|
|
||||||
next(parser.stream)
|
|
||||||
variables[name.value] = var = parser.parse_expression()
|
|
||||||
else:
|
|
||||||
variables[name.value] = var = nodes.Name(name.value, 'load')
|
|
||||||
|
|
||||||
if plural_expr is None:
|
|
||||||
if isinstance(var, nodes.Call):
|
|
||||||
plural_expr = nodes.Name('_trans', 'load')
|
|
||||||
variables[name.value] = plural_expr
|
|
||||||
plural_expr_assignment = nodes.Assign(
|
|
||||||
nodes.Name('_trans', 'store'), var)
|
|
||||||
else:
|
|
||||||
plural_expr = var
|
|
||||||
num_called_num = name.value == 'num'
|
|
||||||
|
|
||||||
parser.stream.expect('block_end')
|
|
||||||
|
|
||||||
plural = plural_names = None
|
|
||||||
have_plural = False
|
|
||||||
referenced = set()
|
|
||||||
|
|
||||||
# now parse until endtrans or pluralize
|
|
||||||
singular_names, singular = self._parse_block(parser, True)
|
|
||||||
if singular_names:
|
|
||||||
referenced.update(singular_names)
|
|
||||||
if plural_expr is None:
|
|
||||||
plural_expr = nodes.Name(singular_names[0], 'load')
|
|
||||||
num_called_num = singular_names[0] == 'num'
|
|
||||||
|
|
||||||
# if we have a pluralize block, we parse that too
|
|
||||||
if parser.stream.current.test('name:pluralize'):
|
|
||||||
have_plural = True
|
|
||||||
next(parser.stream)
|
|
||||||
if parser.stream.current.type != 'block_end':
|
|
||||||
name = parser.stream.expect('name')
|
|
||||||
if name.value not in variables:
|
|
||||||
parser.fail('unknown variable %r for pluralization' %
|
|
||||||
name.value, name.lineno,
|
|
||||||
exc=TemplateAssertionError)
|
|
||||||
plural_expr = variables[name.value]
|
|
||||||
num_called_num = name.value == 'num'
|
|
||||||
parser.stream.expect('block_end')
|
|
||||||
plural_names, plural = self._parse_block(parser, False)
|
|
||||||
next(parser.stream)
|
|
||||||
referenced.update(plural_names)
|
|
||||||
else:
|
|
||||||
next(parser.stream)
|
|
||||||
|
|
||||||
# register free names as simple name expressions
|
|
||||||
for var in referenced:
|
|
||||||
if var not in variables:
|
|
||||||
variables[var] = nodes.Name(var, 'load')
|
|
||||||
|
|
||||||
if not have_plural:
|
|
||||||
plural_expr = None
|
|
||||||
elif plural_expr is None:
|
|
||||||
parser.fail('pluralize without variables', lineno)
|
|
||||||
|
|
||||||
node = self._make_node(singular, plural, variables, plural_expr,
|
|
||||||
bool(referenced),
|
|
||||||
num_called_num and have_plural)
|
|
||||||
node.set_lineno(lineno)
|
|
||||||
if plural_expr_assignment is not None:
|
|
||||||
return [plural_expr_assignment, node]
|
|
||||||
else:
|
|
||||||
return node
|
|
||||||
|
|
||||||
def _parse_block(self, parser, allow_pluralize):
|
|
||||||
"""Parse until the next block tag with a given name."""
|
|
||||||
referenced = []
|
|
||||||
buf = []
|
|
||||||
while 1:
|
|
||||||
if parser.stream.current.type == 'data':
|
|
||||||
buf.append(parser.stream.current.value.replace('%', '%%'))
|
|
||||||
next(parser.stream)
|
|
||||||
elif parser.stream.current.type == 'variable_begin':
|
|
||||||
next(parser.stream)
|
|
||||||
name = parser.stream.expect('name').value
|
|
||||||
referenced.append(name)
|
|
||||||
buf.append('%%(%s)s' % name)
|
|
||||||
parser.stream.expect('variable_end')
|
|
||||||
elif parser.stream.current.type == 'block_begin':
|
|
||||||
next(parser.stream)
|
|
||||||
if parser.stream.current.test('name:endtrans'):
|
|
||||||
break
|
|
||||||
elif parser.stream.current.test('name:pluralize'):
|
|
||||||
if allow_pluralize:
|
|
||||||
break
|
|
||||||
parser.fail('a translatable section can have only one '
|
|
||||||
'pluralize section')
|
|
||||||
parser.fail('control structures in translatable sections are '
|
|
||||||
'not allowed')
|
|
||||||
elif parser.stream.eos:
|
|
||||||
parser.fail('unclosed translation block')
|
|
||||||
else:
|
|
||||||
assert False, 'internal parser error'
|
|
||||||
|
|
||||||
return referenced, concat(buf)
|
|
||||||
|
|
||||||
def _make_node(self, singular, plural, variables, plural_expr,
|
|
||||||
vars_referenced, num_called_num):
|
|
||||||
"""Generates a useful node from the data provided."""
|
|
||||||
# no variables referenced? no need to escape for old style
|
|
||||||
# gettext invocations only if there are vars.
|
|
||||||
if not vars_referenced and not self.environment.newstyle_gettext:
|
|
||||||
singular = singular.replace('%%', '%')
|
|
||||||
if plural:
|
|
||||||
plural = plural.replace('%%', '%')
|
|
||||||
|
|
||||||
# singular only:
|
|
||||||
if plural_expr is None:
|
|
||||||
gettext = nodes.Name('gettext', 'load')
|
|
||||||
node = nodes.Call(gettext, [nodes.Const(singular)],
|
|
||||||
[], None, None)
|
|
||||||
|
|
||||||
# singular and plural
|
|
||||||
else:
|
|
||||||
ngettext = nodes.Name('ngettext', 'load')
|
|
||||||
node = nodes.Call(ngettext, [
|
|
||||||
nodes.Const(singular),
|
|
||||||
nodes.Const(plural),
|
|
||||||
plural_expr
|
|
||||||
], [], None, None)
|
|
||||||
|
|
||||||
# in case newstyle gettext is used, the method is powerful
|
|
||||||
# enough to handle the variable expansion and autoescape
|
|
||||||
# handling itself
|
|
||||||
if self.environment.newstyle_gettext:
|
|
||||||
for key, value in iteritems(variables):
|
|
||||||
# the function adds that later anyways in case num was
|
|
||||||
# called num, so just skip it.
|
|
||||||
if num_called_num and key == 'num':
|
|
||||||
continue
|
|
||||||
node.kwargs.append(nodes.Keyword(key, value))
|
|
||||||
|
|
||||||
# otherwise do that here
|
|
||||||
else:
|
|
||||||
# mark the return value as safe if we are in an
|
|
||||||
# environment with autoescaping turned on
|
|
||||||
node = nodes.MarkSafeIfAutoescape(node)
|
|
||||||
if variables:
|
|
||||||
node = nodes.Mod(node, nodes.Dict([
|
|
||||||
nodes.Pair(nodes.Const(key), value)
|
|
||||||
for key, value in variables.items()
|
|
||||||
]))
|
|
||||||
return nodes.Output([node])
|
|
||||||
|
|
||||||
|
|
||||||
class ExprStmtExtension(Extension):
|
|
||||||
"""Adds a `do` tag to Jinja2 that works like the print statement just
|
|
||||||
that it doesn't print the return value.
|
|
||||||
"""
|
|
||||||
tags = set(['do'])
|
|
||||||
|
|
||||||
def parse(self, parser):
|
|
||||||
node = nodes.ExprStmt(lineno=next(parser.stream).lineno)
|
|
||||||
node.node = parser.parse_tuple()
|
|
||||||
return node
|
|
||||||
|
|
||||||
|
|
||||||
class LoopControlExtension(Extension):
|
|
||||||
"""Adds break and continue to the template engine."""
|
|
||||||
tags = set(['break', 'continue'])
|
|
||||||
|
|
||||||
def parse(self, parser):
|
|
||||||
token = next(parser.stream)
|
|
||||||
if token.value == 'break':
|
|
||||||
return nodes.Break(lineno=token.lineno)
|
|
||||||
return nodes.Continue(lineno=token.lineno)
|
|
||||||
|
|
||||||
|
|
||||||
class WithExtension(Extension):
|
|
||||||
"""Adds support for a django-like with block."""
|
|
||||||
tags = set(['with'])
|
|
||||||
|
|
||||||
def parse(self, parser):
|
|
||||||
node = nodes.Scope(lineno=next(parser.stream).lineno)
|
|
||||||
assignments = []
|
|
||||||
while parser.stream.current.type != 'block_end':
|
|
||||||
lineno = parser.stream.current.lineno
|
|
||||||
if assignments:
|
|
||||||
parser.stream.expect('comma')
|
|
||||||
target = parser.parse_assign_target()
|
|
||||||
parser.stream.expect('assign')
|
|
||||||
expr = parser.parse_expression()
|
|
||||||
assignments.append(nodes.Assign(target, expr, lineno=lineno))
|
|
||||||
node.body = assignments + \
|
|
||||||
list(parser.parse_statements(('name:endwith',),
|
|
||||||
drop_needle=True))
|
|
||||||
return node
|
|
||||||
|
|
||||||
|
|
||||||
class AutoEscapeExtension(Extension):
|
|
||||||
"""Changes auto escape rules for a scope."""
|
|
||||||
tags = set(['autoescape'])
|
|
||||||
|
|
||||||
def parse(self, parser):
|
|
||||||
node = nodes.ScopedEvalContextModifier(lineno=next(parser.stream).lineno)
|
|
||||||
node.options = [
|
|
||||||
nodes.Keyword('autoescape', parser.parse_expression())
|
|
||||||
]
|
|
||||||
node.body = parser.parse_statements(('name:endautoescape',),
|
|
||||||
drop_needle=True)
|
|
||||||
return nodes.Scope([node])
|
|
||||||
|
|
||||||
|
|
||||||
def extract_from_ast(node, gettext_functions=GETTEXT_FUNCTIONS,
|
|
||||||
babel_style=True):
|
|
||||||
"""Extract localizable strings from the given template node. Per
|
|
||||||
default this function returns matches in babel style that means non string
|
|
||||||
parameters as well as keyword arguments are returned as `None`. This
|
|
||||||
allows Babel to figure out what you really meant if you are using
|
|
||||||
gettext functions that allow keyword arguments for placeholder expansion.
|
|
||||||
If you don't want that behavior set the `babel_style` parameter to `False`
|
|
||||||
which causes only strings to be returned and parameters are always stored
|
|
||||||
in tuples. As a consequence invalid gettext calls (calls without a single
|
|
||||||
string parameter or string parameters after non-string parameters) are
|
|
||||||
skipped.
|
|
||||||
|
|
||||||
This example explains the behavior:
|
|
||||||
|
|
||||||
>>> from jinja2 import Environment
|
|
||||||
>>> env = Environment()
|
|
||||||
>>> node = env.parse('{{ (_("foo"), _(), ngettext("foo", "bar", 42)) }}')
|
|
||||||
>>> list(extract_from_ast(node))
|
|
||||||
[(1, '_', 'foo'), (1, '_', ()), (1, 'ngettext', ('foo', 'bar', None))]
|
|
||||||
>>> list(extract_from_ast(node, babel_style=False))
|
|
||||||
[(1, '_', ('foo',)), (1, 'ngettext', ('foo', 'bar'))]
|
|
||||||
|
|
||||||
For every string found this function yields a ``(lineno, function,
|
|
||||||
message)`` tuple, where:
|
|
||||||
|
|
||||||
* ``lineno`` is the number of the line on which the string was found,
|
|
||||||
* ``function`` is the name of the ``gettext`` function used (if the
|
|
||||||
string was extracted from embedded Python code), and
|
|
||||||
* ``message`` is the string itself (a ``unicode`` object, or a tuple
|
|
||||||
of ``unicode`` objects for functions with multiple string arguments).
|
|
||||||
|
|
||||||
This extraction function operates on the AST and is because of that unable
|
|
||||||
to extract any comments. For comment support you have to use the babel
|
|
||||||
extraction interface or extract comments yourself.
|
|
||||||
"""
|
|
||||||
for node in node.find_all(nodes.Call):
|
|
||||||
if not isinstance(node.node, nodes.Name) or \
|
|
||||||
node.node.name not in gettext_functions:
|
|
||||||
continue
|
|
||||||
|
|
||||||
strings = []
|
|
||||||
for arg in node.args:
|
|
||||||
if isinstance(arg, nodes.Const) and \
|
|
||||||
isinstance(arg.value, string_types):
|
|
||||||
strings.append(arg.value)
|
|
||||||
else:
|
|
||||||
strings.append(None)
|
|
||||||
|
|
||||||
for arg in node.kwargs:
|
|
||||||
strings.append(None)
|
|
||||||
if node.dyn_args is not None:
|
|
||||||
strings.append(None)
|
|
||||||
if node.dyn_kwargs is not None:
|
|
||||||
strings.append(None)
|
|
||||||
|
|
||||||
if not babel_style:
|
|
||||||
strings = tuple(x for x in strings if x is not None)
|
|
||||||
if not strings:
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
if len(strings) == 1:
|
|
||||||
strings = strings[0]
|
|
||||||
else:
|
|
||||||
strings = tuple(strings)
|
|
||||||
yield node.lineno, node.node.name, strings
|
|
||||||
|
|
||||||
|
|
||||||
class _CommentFinder(object):
|
|
||||||
"""Helper class to find comments in a token stream. Can only
|
|
||||||
find comments for gettext calls forwards. Once the comment
|
|
||||||
from line 4 is found, a comment for line 1 will not return a
|
|
||||||
usable value.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, tokens, comment_tags):
|
|
||||||
self.tokens = tokens
|
|
||||||
self.comment_tags = comment_tags
|
|
||||||
self.offset = 0
|
|
||||||
self.last_lineno = 0
|
|
||||||
|
|
||||||
def find_backwards(self, offset):
|
|
||||||
try:
|
|
||||||
for _, token_type, token_value in \
|
|
||||||
reversed(self.tokens[self.offset:offset]):
|
|
||||||
if token_type in ('comment', 'linecomment'):
|
|
||||||
try:
|
|
||||||
prefix, comment = token_value.split(None, 1)
|
|
||||||
except ValueError:
|
|
||||||
continue
|
|
||||||
if prefix in self.comment_tags:
|
|
||||||
return [comment.rstrip()]
|
|
||||||
return []
|
|
||||||
finally:
|
|
||||||
self.offset = offset
|
|
||||||
|
|
||||||
def find_comments(self, lineno):
|
|
||||||
if not self.comment_tags or self.last_lineno > lineno:
|
|
||||||
return []
|
|
||||||
for idx, (token_lineno, _, _) in enumerate(self.tokens[self.offset:]):
|
|
||||||
if token_lineno > lineno:
|
|
||||||
return self.find_backwards(self.offset + idx)
|
|
||||||
return self.find_backwards(len(self.tokens))
|
|
||||||
|
|
||||||
|
|
||||||
def babel_extract(fileobj, keywords, comment_tags, options):
|
|
||||||
"""Babel extraction method for Jinja templates.
|
|
||||||
|
|
||||||
.. versionchanged:: 2.3
|
|
||||||
Basic support for translation comments was added. If `comment_tags`
|
|
||||||
is now set to a list of keywords for extraction, the extractor will
|
|
||||||
try to find the best preceeding comment that begins with one of the
|
|
||||||
keywords. For best results, make sure to not have more than one
|
|
||||||
gettext call in one line of code and the matching comment in the
|
|
||||||
same line or the line before.
|
|
||||||
|
|
||||||
.. versionchanged:: 2.5.1
|
|
||||||
The `newstyle_gettext` flag can be set to `True` to enable newstyle
|
|
||||||
gettext calls.
|
|
||||||
|
|
||||||
.. versionchanged:: 2.7
|
|
||||||
A `silent` option can now be provided. If set to `False` template
|
|
||||||
syntax errors are propagated instead of being ignored.
|
|
||||||
|
|
||||||
:param fileobj: the file-like object the messages should be extracted from
|
|
||||||
:param keywords: a list of keywords (i.e. function names) that should be
|
|
||||||
recognized as translation functions
|
|
||||||
:param comment_tags: a list of translator tags to search for and include
|
|
||||||
in the results.
|
|
||||||
:param options: a dictionary of additional options (optional)
|
|
||||||
:return: an iterator over ``(lineno, funcname, message, comments)`` tuples.
|
|
||||||
(comments will be empty currently)
|
|
||||||
"""
|
|
||||||
extensions = set()
|
|
||||||
for extension in options.get('extensions', '').split(','):
|
|
||||||
extension = extension.strip()
|
|
||||||
if not extension:
|
|
||||||
continue
|
|
||||||
extensions.add(import_string(extension))
|
|
||||||
if InternationalizationExtension not in extensions:
|
|
||||||
extensions.add(InternationalizationExtension)
|
|
||||||
|
|
||||||
def getbool(options, key, default=False):
|
|
||||||
return options.get(key, str(default)).lower() in \
|
|
||||||
('1', 'on', 'yes', 'true')
|
|
||||||
|
|
||||||
silent = getbool(options, 'silent', True)
|
|
||||||
environment = Environment(
|
|
||||||
options.get('block_start_string', BLOCK_START_STRING),
|
|
||||||
options.get('block_end_string', BLOCK_END_STRING),
|
|
||||||
options.get('variable_start_string', VARIABLE_START_STRING),
|
|
||||||
options.get('variable_end_string', VARIABLE_END_STRING),
|
|
||||||
options.get('comment_start_string', COMMENT_START_STRING),
|
|
||||||
options.get('comment_end_string', COMMENT_END_STRING),
|
|
||||||
options.get('line_statement_prefix') or LINE_STATEMENT_PREFIX,
|
|
||||||
options.get('line_comment_prefix') or LINE_COMMENT_PREFIX,
|
|
||||||
getbool(options, 'trim_blocks', TRIM_BLOCKS),
|
|
||||||
getbool(options, 'lstrip_blocks', LSTRIP_BLOCKS),
|
|
||||||
NEWLINE_SEQUENCE,
|
|
||||||
getbool(options, 'keep_trailing_newline', KEEP_TRAILING_NEWLINE),
|
|
||||||
frozenset(extensions),
|
|
||||||
cache_size=0,
|
|
||||||
auto_reload=False
|
|
||||||
)
|
|
||||||
|
|
||||||
if getbool(options, 'newstyle_gettext'):
|
|
||||||
environment.newstyle_gettext = True
|
|
||||||
|
|
||||||
source = fileobj.read().decode(options.get('encoding', 'utf-8'))
|
|
||||||
try:
|
|
||||||
node = environment.parse(source)
|
|
||||||
tokens = list(environment.lex(environment.preprocess(source)))
|
|
||||||
except TemplateSyntaxError as e:
|
|
||||||
if not silent:
|
|
||||||
raise
|
|
||||||
# skip templates with syntax errors
|
|
||||||
return
|
|
||||||
|
|
||||||
finder = _CommentFinder(tokens, comment_tags)
|
|
||||||
for lineno, func, message in extract_from_ast(node, keywords):
|
|
||||||
yield lineno, func, message, finder.find_comments(lineno)
|
|
||||||
|
|
||||||
|
|
||||||
#: nicer import names
|
|
||||||
i18n = InternationalizationExtension
|
|
||||||
do = ExprStmtExtension
|
|
||||||
loopcontrols = LoopControlExtension
|
|
||||||
with_ = WithExtension
|
|
||||||
autoescape = AutoEscapeExtension
|
|
||||||
Vendored
-987
@@ -1,987 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.filters
|
|
||||||
~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Bundled jinja filters.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
import re
|
|
||||||
import math
|
|
||||||
|
|
||||||
from random import choice
|
|
||||||
from operator import itemgetter
|
|
||||||
from itertools import groupby
|
|
||||||
from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode, \
|
|
||||||
unicode_urlencode
|
|
||||||
from jinja2.runtime import Undefined
|
|
||||||
from jinja2.exceptions import FilterArgumentError
|
|
||||||
from jinja2._compat import next, imap, string_types, text_type, iteritems
|
|
||||||
|
|
||||||
|
|
||||||
_word_re = re.compile(r'\w+(?u)')
|
|
||||||
|
|
||||||
|
|
||||||
def contextfilter(f):
|
|
||||||
"""Decorator for marking context dependent filters. The current
|
|
||||||
:class:`Context` will be passed as first argument.
|
|
||||||
"""
|
|
||||||
f.contextfilter = True
|
|
||||||
return f
|
|
||||||
|
|
||||||
|
|
||||||
def evalcontextfilter(f):
|
|
||||||
"""Decorator for marking eval-context dependent filters. An eval
|
|
||||||
context object is passed as first argument. For more information
|
|
||||||
about the eval context, see :ref:`eval-context`.
|
|
||||||
|
|
||||||
.. versionadded:: 2.4
|
|
||||||
"""
|
|
||||||
f.evalcontextfilter = True
|
|
||||||
return f
|
|
||||||
|
|
||||||
|
|
||||||
def environmentfilter(f):
|
|
||||||
"""Decorator for marking evironment dependent filters. The current
|
|
||||||
:class:`Environment` is passed to the filter as first argument.
|
|
||||||
"""
|
|
||||||
f.environmentfilter = True
|
|
||||||
return f
|
|
||||||
|
|
||||||
|
|
||||||
def make_attrgetter(environment, attribute):
|
|
||||||
"""Returns a callable that looks up the given attribute from a
|
|
||||||
passed object with the rules of the environment. Dots are allowed
|
|
||||||
to access attributes of attributes. Integer parts in paths are
|
|
||||||
looked up as integers.
|
|
||||||
"""
|
|
||||||
if not isinstance(attribute, string_types) \
|
|
||||||
or ('.' not in attribute and not attribute.isdigit()):
|
|
||||||
return lambda x: environment.getitem(x, attribute)
|
|
||||||
attribute = attribute.split('.')
|
|
||||||
def attrgetter(item):
|
|
||||||
for part in attribute:
|
|
||||||
if part.isdigit():
|
|
||||||
part = int(part)
|
|
||||||
item = environment.getitem(item, part)
|
|
||||||
return item
|
|
||||||
return attrgetter
|
|
||||||
|
|
||||||
|
|
||||||
def do_forceescape(value):
|
|
||||||
"""Enforce HTML escaping. This will probably double escape variables."""
|
|
||||||
if hasattr(value, '__html__'):
|
|
||||||
value = value.__html__()
|
|
||||||
return escape(text_type(value))
|
|
||||||
|
|
||||||
|
|
||||||
def do_urlencode(value):
|
|
||||||
"""Escape strings for use in URLs (uses UTF-8 encoding). It accepts both
|
|
||||||
dictionaries and regular strings as well as pairwise iterables.
|
|
||||||
|
|
||||||
.. versionadded:: 2.7
|
|
||||||
"""
|
|
||||||
itemiter = None
|
|
||||||
if isinstance(value, dict):
|
|
||||||
itemiter = iteritems(value)
|
|
||||||
elif not isinstance(value, string_types):
|
|
||||||
try:
|
|
||||||
itemiter = iter(value)
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
if itemiter is None:
|
|
||||||
return unicode_urlencode(value)
|
|
||||||
return u'&'.join(unicode_urlencode(k) + '=' +
|
|
||||||
unicode_urlencode(v) for k, v in itemiter)
|
|
||||||
|
|
||||||
|
|
||||||
@evalcontextfilter
|
|
||||||
def do_replace(eval_ctx, s, old, new, count=None):
|
|
||||||
"""Return a copy of the value with all occurrences of a substring
|
|
||||||
replaced with a new one. The first argument is the substring
|
|
||||||
that should be replaced, the second is the replacement string.
|
|
||||||
If the optional third argument ``count`` is given, only the first
|
|
||||||
``count`` occurrences are replaced:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{{ "Hello World"|replace("Hello", "Goodbye") }}
|
|
||||||
-> Goodbye World
|
|
||||||
|
|
||||||
{{ "aaaaargh"|replace("a", "d'oh, ", 2) }}
|
|
||||||
-> d'oh, d'oh, aaargh
|
|
||||||
"""
|
|
||||||
if count is None:
|
|
||||||
count = -1
|
|
||||||
if not eval_ctx.autoescape:
|
|
||||||
return text_type(s).replace(text_type(old), text_type(new), count)
|
|
||||||
if hasattr(old, '__html__') or hasattr(new, '__html__') and \
|
|
||||||
not hasattr(s, '__html__'):
|
|
||||||
s = escape(s)
|
|
||||||
else:
|
|
||||||
s = soft_unicode(s)
|
|
||||||
return s.replace(soft_unicode(old), soft_unicode(new), count)
|
|
||||||
|
|
||||||
|
|
||||||
def do_upper(s):
|
|
||||||
"""Convert a value to uppercase."""
|
|
||||||
return soft_unicode(s).upper()
|
|
||||||
|
|
||||||
|
|
||||||
def do_lower(s):
|
|
||||||
"""Convert a value to lowercase."""
|
|
||||||
return soft_unicode(s).lower()
|
|
||||||
|
|
||||||
|
|
||||||
@evalcontextfilter
|
|
||||||
def do_xmlattr(_eval_ctx, d, autospace=True):
|
|
||||||
"""Create an SGML/XML attribute string based on the items in a dict.
|
|
||||||
All values that are neither `none` nor `undefined` are automatically
|
|
||||||
escaped:
|
|
||||||
|
|
||||||
.. sourcecode:: html+jinja
|
|
||||||
|
|
||||||
<ul{{ {'class': 'my_list', 'missing': none,
|
|
||||||
'id': 'list-%d'|format(variable)}|xmlattr }}>
|
|
||||||
...
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
Results in something like this:
|
|
||||||
|
|
||||||
.. sourcecode:: html
|
|
||||||
|
|
||||||
<ul class="my_list" id="list-42">
|
|
||||||
...
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
As you can see it automatically prepends a space in front of the item
|
|
||||||
if the filter returned something unless the second parameter is false.
|
|
||||||
"""
|
|
||||||
rv = u' '.join(
|
|
||||||
u'%s="%s"' % (escape(key), escape(value))
|
|
||||||
for key, value in iteritems(d)
|
|
||||||
if value is not None and not isinstance(value, Undefined)
|
|
||||||
)
|
|
||||||
if autospace and rv:
|
|
||||||
rv = u' ' + rv
|
|
||||||
if _eval_ctx.autoescape:
|
|
||||||
rv = Markup(rv)
|
|
||||||
return rv
|
|
||||||
|
|
||||||
|
|
||||||
def do_capitalize(s):
|
|
||||||
"""Capitalize a value. The first character will be uppercase, all others
|
|
||||||
lowercase.
|
|
||||||
"""
|
|
||||||
return soft_unicode(s).capitalize()
|
|
||||||
|
|
||||||
|
|
||||||
def do_title(s):
|
|
||||||
"""Return a titlecased version of the value. I.e. words will start with
|
|
||||||
uppercase letters, all remaining characters are lowercase.
|
|
||||||
"""
|
|
||||||
rv = []
|
|
||||||
for item in re.compile(r'([-\s]+)(?u)').split(s):
|
|
||||||
if not item:
|
|
||||||
continue
|
|
||||||
rv.append(item[0].upper() + item[1:].lower())
|
|
||||||
return ''.join(rv)
|
|
||||||
|
|
||||||
|
|
||||||
def do_dictsort(value, case_sensitive=False, by='key'):
|
|
||||||
"""Sort a dict and yield (key, value) pairs. Because python dicts are
|
|
||||||
unsorted you may want to use this function to order them by either
|
|
||||||
key or value:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{% for item in mydict|dictsort %}
|
|
||||||
sort the dict by key, case insensitive
|
|
||||||
|
|
||||||
{% for item in mydict|dictsort(true) %}
|
|
||||||
sort the dict by key, case sensitive
|
|
||||||
|
|
||||||
{% for item in mydict|dictsort(false, 'value') %}
|
|
||||||
sort the dict by key, case insensitive, sorted
|
|
||||||
normally and ordered by value.
|
|
||||||
"""
|
|
||||||
if by == 'key':
|
|
||||||
pos = 0
|
|
||||||
elif by == 'value':
|
|
||||||
pos = 1
|
|
||||||
else:
|
|
||||||
raise FilterArgumentError('You can only sort by either '
|
|
||||||
'"key" or "value"')
|
|
||||||
def sort_func(item):
|
|
||||||
value = item[pos]
|
|
||||||
if isinstance(value, string_types) and not case_sensitive:
|
|
||||||
value = value.lower()
|
|
||||||
return value
|
|
||||||
|
|
||||||
return sorted(value.items(), key=sort_func)
|
|
||||||
|
|
||||||
|
|
||||||
@environmentfilter
|
|
||||||
def do_sort(environment, value, reverse=False, case_sensitive=False,
|
|
||||||
attribute=None):
|
|
||||||
"""Sort an iterable. Per default it sorts ascending, if you pass it
|
|
||||||
true as first argument it will reverse the sorting.
|
|
||||||
|
|
||||||
If the iterable is made of strings the third parameter can be used to
|
|
||||||
control the case sensitiveness of the comparison which is disabled by
|
|
||||||
default.
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{% for item in iterable|sort %}
|
|
||||||
...
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
It is also possible to sort by an attribute (for example to sort
|
|
||||||
by the date of an object) by specifying the `attribute` parameter:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{% for item in iterable|sort(attribute='date') %}
|
|
||||||
...
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
.. versionchanged:: 2.6
|
|
||||||
The `attribute` parameter was added.
|
|
||||||
"""
|
|
||||||
if not case_sensitive:
|
|
||||||
def sort_func(item):
|
|
||||||
if isinstance(item, string_types):
|
|
||||||
item = item.lower()
|
|
||||||
return item
|
|
||||||
else:
|
|
||||||
sort_func = None
|
|
||||||
if attribute is not None:
|
|
||||||
getter = make_attrgetter(environment, attribute)
|
|
||||||
def sort_func(item, processor=sort_func or (lambda x: x)):
|
|
||||||
return processor(getter(item))
|
|
||||||
return sorted(value, key=sort_func, reverse=reverse)
|
|
||||||
|
|
||||||
|
|
||||||
def do_default(value, default_value=u'', boolean=False):
|
|
||||||
"""If the value is undefined it will return the passed default value,
|
|
||||||
otherwise the value of the variable:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{{ my_variable|default('my_variable is not defined') }}
|
|
||||||
|
|
||||||
This will output the value of ``my_variable`` if the variable was
|
|
||||||
defined, otherwise ``'my_variable is not defined'``. If you want
|
|
||||||
to use default with variables that evaluate to false you have to
|
|
||||||
set the second parameter to `true`:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{{ ''|default('the string was empty', true) }}
|
|
||||||
"""
|
|
||||||
if isinstance(value, Undefined) or (boolean and not value):
|
|
||||||
return default_value
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
@evalcontextfilter
|
|
||||||
def do_join(eval_ctx, value, d=u'', attribute=None):
|
|
||||||
"""Return a string which is the concatenation of the strings in the
|
|
||||||
sequence. The separator between elements is an empty string per
|
|
||||||
default, you can define it with the optional parameter:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{{ [1, 2, 3]|join('|') }}
|
|
||||||
-> 1|2|3
|
|
||||||
|
|
||||||
{{ [1, 2, 3]|join }}
|
|
||||||
-> 123
|
|
||||||
|
|
||||||
It is also possible to join certain attributes of an object:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{{ users|join(', ', attribute='username') }}
|
|
||||||
|
|
||||||
.. versionadded:: 2.6
|
|
||||||
The `attribute` parameter was added.
|
|
||||||
"""
|
|
||||||
if attribute is not None:
|
|
||||||
value = imap(make_attrgetter(eval_ctx.environment, attribute), value)
|
|
||||||
|
|
||||||
# no automatic escaping? joining is a lot eaiser then
|
|
||||||
if not eval_ctx.autoescape:
|
|
||||||
return text_type(d).join(imap(text_type, value))
|
|
||||||
|
|
||||||
# if the delimiter doesn't have an html representation we check
|
|
||||||
# if any of the items has. If yes we do a coercion to Markup
|
|
||||||
if not hasattr(d, '__html__'):
|
|
||||||
value = list(value)
|
|
||||||
do_escape = False
|
|
||||||
for idx, item in enumerate(value):
|
|
||||||
if hasattr(item, '__html__'):
|
|
||||||
do_escape = True
|
|
||||||
else:
|
|
||||||
value[idx] = text_type(item)
|
|
||||||
if do_escape:
|
|
||||||
d = escape(d)
|
|
||||||
else:
|
|
||||||
d = text_type(d)
|
|
||||||
return d.join(value)
|
|
||||||
|
|
||||||
# no html involved, to normal joining
|
|
||||||
return soft_unicode(d).join(imap(soft_unicode, value))
|
|
||||||
|
|
||||||
|
|
||||||
def do_center(value, width=80):
|
|
||||||
"""Centers the value in a field of a given width."""
|
|
||||||
return text_type(value).center(width)
|
|
||||||
|
|
||||||
|
|
||||||
@environmentfilter
|
|
||||||
def do_first(environment, seq):
|
|
||||||
"""Return the first item of a sequence."""
|
|
||||||
try:
|
|
||||||
return next(iter(seq))
|
|
||||||
except StopIteration:
|
|
||||||
return environment.undefined('No first item, sequence was empty.')
|
|
||||||
|
|
||||||
|
|
||||||
@environmentfilter
|
|
||||||
def do_last(environment, seq):
|
|
||||||
"""Return the last item of a sequence."""
|
|
||||||
try:
|
|
||||||
return next(iter(reversed(seq)))
|
|
||||||
except StopIteration:
|
|
||||||
return environment.undefined('No last item, sequence was empty.')
|
|
||||||
|
|
||||||
|
|
||||||
@environmentfilter
|
|
||||||
def do_random(environment, seq):
|
|
||||||
"""Return a random item from the sequence."""
|
|
||||||
try:
|
|
||||||
return choice(seq)
|
|
||||||
except IndexError:
|
|
||||||
return environment.undefined('No random item, sequence was empty.')
|
|
||||||
|
|
||||||
|
|
||||||
def do_filesizeformat(value, binary=False):
|
|
||||||
"""Format the value like a 'human-readable' file size (i.e. 13 kB,
|
|
||||||
4.1 MB, 102 Bytes, etc). Per default decimal prefixes are used (Mega,
|
|
||||||
Giga, etc.), if the second parameter is set to `True` the binary
|
|
||||||
prefixes are used (Mebi, Gibi).
|
|
||||||
"""
|
|
||||||
bytes = float(value)
|
|
||||||
base = binary and 1024 or 1000
|
|
||||||
prefixes = [
|
|
||||||
(binary and 'KiB' or 'kB'),
|
|
||||||
(binary and 'MiB' or 'MB'),
|
|
||||||
(binary and 'GiB' or 'GB'),
|
|
||||||
(binary and 'TiB' or 'TB'),
|
|
||||||
(binary and 'PiB' or 'PB'),
|
|
||||||
(binary and 'EiB' or 'EB'),
|
|
||||||
(binary and 'ZiB' or 'ZB'),
|
|
||||||
(binary and 'YiB' or 'YB')
|
|
||||||
]
|
|
||||||
if bytes == 1:
|
|
||||||
return '1 Byte'
|
|
||||||
elif bytes < base:
|
|
||||||
return '%d Bytes' % bytes
|
|
||||||
else:
|
|
||||||
for i, prefix in enumerate(prefixes):
|
|
||||||
unit = base ** (i + 2)
|
|
||||||
if bytes < unit:
|
|
||||||
return '%.1f %s' % ((base * bytes / unit), prefix)
|
|
||||||
return '%.1f %s' % ((base * bytes / unit), prefix)
|
|
||||||
|
|
||||||
|
|
||||||
def do_pprint(value, verbose=False):
|
|
||||||
"""Pretty print a variable. Useful for debugging.
|
|
||||||
|
|
||||||
With Jinja 1.2 onwards you can pass it a parameter. If this parameter
|
|
||||||
is truthy the output will be more verbose (this requires `pretty`)
|
|
||||||
"""
|
|
||||||
return pformat(value, verbose=verbose)
|
|
||||||
|
|
||||||
|
|
||||||
@evalcontextfilter
|
|
||||||
def do_urlize(eval_ctx, value, trim_url_limit=None, nofollow=False):
|
|
||||||
"""Converts URLs in plain text into clickable links.
|
|
||||||
|
|
||||||
If you pass the filter an additional integer it will shorten the urls
|
|
||||||
to that number. Also a third argument exists that makes the urls
|
|
||||||
"nofollow":
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{{ mytext|urlize(40, true) }}
|
|
||||||
links are shortened to 40 chars and defined with rel="nofollow"
|
|
||||||
"""
|
|
||||||
rv = urlize(value, trim_url_limit, nofollow)
|
|
||||||
if eval_ctx.autoescape:
|
|
||||||
rv = Markup(rv)
|
|
||||||
return rv
|
|
||||||
|
|
||||||
|
|
||||||
def do_indent(s, width=4, indentfirst=False):
|
|
||||||
"""Return a copy of the passed string, each line indented by
|
|
||||||
4 spaces. The first line is not indented. If you want to
|
|
||||||
change the number of spaces or indent the first line too
|
|
||||||
you can pass additional parameters to the filter:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{{ mytext|indent(2, true) }}
|
|
||||||
indent by two spaces and indent the first line too.
|
|
||||||
"""
|
|
||||||
indention = u' ' * width
|
|
||||||
rv = (u'\n' + indention).join(s.splitlines())
|
|
||||||
if indentfirst:
|
|
||||||
rv = indention + rv
|
|
||||||
return rv
|
|
||||||
|
|
||||||
|
|
||||||
def do_truncate(s, length=255, killwords=False, end='...'):
|
|
||||||
"""Return a truncated copy of the string. The length is specified
|
|
||||||
with the first parameter which defaults to ``255``. If the second
|
|
||||||
parameter is ``true`` the filter will cut the text at length. Otherwise
|
|
||||||
it will discard the last word. If the text was in fact
|
|
||||||
truncated it will append an ellipsis sign (``"..."``). If you want a
|
|
||||||
different ellipsis sign than ``"..."`` you can specify it using the
|
|
||||||
third parameter.
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{{ "foo bar"|truncate(5) }}
|
|
||||||
-> "foo ..."
|
|
||||||
{{ "foo bar"|truncate(5, True) }}
|
|
||||||
-> "foo b..."
|
|
||||||
"""
|
|
||||||
if len(s) <= length:
|
|
||||||
return s
|
|
||||||
elif killwords:
|
|
||||||
return s[:length] + end
|
|
||||||
words = s.split(' ')
|
|
||||||
result = []
|
|
||||||
m = 0
|
|
||||||
for word in words:
|
|
||||||
m += len(word) + 1
|
|
||||||
if m > length:
|
|
||||||
break
|
|
||||||
result.append(word)
|
|
||||||
result.append(end)
|
|
||||||
return u' '.join(result)
|
|
||||||
|
|
||||||
@environmentfilter
|
|
||||||
def do_wordwrap(environment, s, width=79, break_long_words=True,
|
|
||||||
wrapstring=None):
|
|
||||||
"""
|
|
||||||
Return a copy of the string passed to the filter wrapped after
|
|
||||||
``79`` characters. You can override this default using the first
|
|
||||||
parameter. If you set the second parameter to `false` Jinja will not
|
|
||||||
split words apart if they are longer than `width`. By default, the newlines
|
|
||||||
will be the default newlines for the environment, but this can be changed
|
|
||||||
using the wrapstring keyword argument.
|
|
||||||
|
|
||||||
.. versionadded:: 2.7
|
|
||||||
Added support for the `wrapstring` parameter.
|
|
||||||
"""
|
|
||||||
if not wrapstring:
|
|
||||||
wrapstring = environment.newline_sequence
|
|
||||||
import textwrap
|
|
||||||
return wrapstring.join(textwrap.wrap(s, width=width, expand_tabs=False,
|
|
||||||
replace_whitespace=False,
|
|
||||||
break_long_words=break_long_words))
|
|
||||||
|
|
||||||
|
|
||||||
def do_wordcount(s):
|
|
||||||
"""Count the words in that string."""
|
|
||||||
return len(_word_re.findall(s))
|
|
||||||
|
|
||||||
|
|
||||||
def do_int(value, default=0):
|
|
||||||
"""Convert the value into an integer. If the
|
|
||||||
conversion doesn't work it will return ``0``. You can
|
|
||||||
override this default using the first parameter.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return int(value)
|
|
||||||
except (TypeError, ValueError):
|
|
||||||
# this quirk is necessary so that "42.23"|int gives 42.
|
|
||||||
try:
|
|
||||||
return int(float(value))
|
|
||||||
except (TypeError, ValueError):
|
|
||||||
return default
|
|
||||||
|
|
||||||
|
|
||||||
def do_float(value, default=0.0):
|
|
||||||
"""Convert the value into a floating point number. If the
|
|
||||||
conversion doesn't work it will return ``0.0``. You can
|
|
||||||
override this default using the first parameter.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return float(value)
|
|
||||||
except (TypeError, ValueError):
|
|
||||||
return default
|
|
||||||
|
|
||||||
|
|
||||||
def do_format(value, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
Apply python string formatting on an object:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{{ "%s - %s"|format("Hello?", "Foo!") }}
|
|
||||||
-> Hello? - Foo!
|
|
||||||
"""
|
|
||||||
if args and kwargs:
|
|
||||||
raise FilterArgumentError('can\'t handle positional and keyword '
|
|
||||||
'arguments at the same time')
|
|
||||||
return soft_unicode(value) % (kwargs or args)
|
|
||||||
|
|
||||||
|
|
||||||
def do_trim(value):
|
|
||||||
"""Strip leading and trailing whitespace."""
|
|
||||||
return soft_unicode(value).strip()
|
|
||||||
|
|
||||||
|
|
||||||
def do_striptags(value):
|
|
||||||
"""Strip SGML/XML tags and replace adjacent whitespace by one space.
|
|
||||||
"""
|
|
||||||
if hasattr(value, '__html__'):
|
|
||||||
value = value.__html__()
|
|
||||||
return Markup(text_type(value)).striptags()
|
|
||||||
|
|
||||||
|
|
||||||
def do_slice(value, slices, fill_with=None):
|
|
||||||
"""Slice an iterator and return a list of lists containing
|
|
||||||
those items. Useful if you want to create a div containing
|
|
||||||
three ul tags that represent columns:
|
|
||||||
|
|
||||||
.. sourcecode:: html+jinja
|
|
||||||
|
|
||||||
<div class="columwrapper">
|
|
||||||
{%- for column in items|slice(3) %}
|
|
||||||
<ul class="column-{{ loop.index }}">
|
|
||||||
{%- for item in column %}
|
|
||||||
<li>{{ item }}</li>
|
|
||||||
{%- endfor %}
|
|
||||||
</ul>
|
|
||||||
{%- endfor %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
If you pass it a second argument it's used to fill missing
|
|
||||||
values on the last iteration.
|
|
||||||
"""
|
|
||||||
seq = list(value)
|
|
||||||
length = len(seq)
|
|
||||||
items_per_slice = length // slices
|
|
||||||
slices_with_extra = length % slices
|
|
||||||
offset = 0
|
|
||||||
for slice_number in range(slices):
|
|
||||||
start = offset + slice_number * items_per_slice
|
|
||||||
if slice_number < slices_with_extra:
|
|
||||||
offset += 1
|
|
||||||
end = offset + (slice_number + 1) * items_per_slice
|
|
||||||
tmp = seq[start:end]
|
|
||||||
if fill_with is not None and slice_number >= slices_with_extra:
|
|
||||||
tmp.append(fill_with)
|
|
||||||
yield tmp
|
|
||||||
|
|
||||||
|
|
||||||
def do_batch(value, linecount, fill_with=None):
|
|
||||||
"""
|
|
||||||
A filter that batches items. It works pretty much like `slice`
|
|
||||||
just the other way round. It returns a list of lists with the
|
|
||||||
given number of items. If you provide a second parameter this
|
|
||||||
is used to fill up missing items. See this example:
|
|
||||||
|
|
||||||
.. sourcecode:: html+jinja
|
|
||||||
|
|
||||||
<table>
|
|
||||||
{%- for row in items|batch(3, ' ') %}
|
|
||||||
<tr>
|
|
||||||
{%- for column in row %}
|
|
||||||
<td>{{ column }}</td>
|
|
||||||
{%- endfor %}
|
|
||||||
</tr>
|
|
||||||
{%- endfor %}
|
|
||||||
</table>
|
|
||||||
"""
|
|
||||||
result = []
|
|
||||||
tmp = []
|
|
||||||
for item in value:
|
|
||||||
if len(tmp) == linecount:
|
|
||||||
yield tmp
|
|
||||||
tmp = []
|
|
||||||
tmp.append(item)
|
|
||||||
if tmp:
|
|
||||||
if fill_with is not None and len(tmp) < linecount:
|
|
||||||
tmp += [fill_with] * (linecount - len(tmp))
|
|
||||||
yield tmp
|
|
||||||
|
|
||||||
|
|
||||||
def do_round(value, precision=0, method='common'):
|
|
||||||
"""Round the number to a given precision. The first
|
|
||||||
parameter specifies the precision (default is ``0``), the
|
|
||||||
second the rounding method:
|
|
||||||
|
|
||||||
- ``'common'`` rounds either up or down
|
|
||||||
- ``'ceil'`` always rounds up
|
|
||||||
- ``'floor'`` always rounds down
|
|
||||||
|
|
||||||
If you don't specify a method ``'common'`` is used.
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{{ 42.55|round }}
|
|
||||||
-> 43.0
|
|
||||||
{{ 42.55|round(1, 'floor') }}
|
|
||||||
-> 42.5
|
|
||||||
|
|
||||||
Note that even if rounded to 0 precision, a float is returned. If
|
|
||||||
you need a real integer, pipe it through `int`:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{{ 42.55|round|int }}
|
|
||||||
-> 43
|
|
||||||
"""
|
|
||||||
if not method in ('common', 'ceil', 'floor'):
|
|
||||||
raise FilterArgumentError('method must be common, ceil or floor')
|
|
||||||
if method == 'common':
|
|
||||||
return round(value, precision)
|
|
||||||
func = getattr(math, method)
|
|
||||||
return func(value * (10 ** precision)) / (10 ** precision)
|
|
||||||
|
|
||||||
|
|
||||||
@environmentfilter
|
|
||||||
def do_groupby(environment, value, attribute):
|
|
||||||
"""Group a sequence of objects by a common attribute.
|
|
||||||
|
|
||||||
If you for example have a list of dicts or objects that represent persons
|
|
||||||
with `gender`, `first_name` and `last_name` attributes and you want to
|
|
||||||
group all users by genders you can do something like the following
|
|
||||||
snippet:
|
|
||||||
|
|
||||||
.. sourcecode:: html+jinja
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
{% for group in persons|groupby('gender') %}
|
|
||||||
<li>{{ group.grouper }}<ul>
|
|
||||||
{% for person in group.list %}
|
|
||||||
<li>{{ person.first_name }} {{ person.last_name }}</li>
|
|
||||||
{% endfor %}</ul></li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
Additionally it's possible to use tuple unpacking for the grouper and
|
|
||||||
list:
|
|
||||||
|
|
||||||
.. sourcecode:: html+jinja
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
{% for grouper, list in persons|groupby('gender') %}
|
|
||||||
...
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
As you can see the item we're grouping by is stored in the `grouper`
|
|
||||||
attribute and the `list` contains all the objects that have this grouper
|
|
||||||
in common.
|
|
||||||
|
|
||||||
.. versionchanged:: 2.6
|
|
||||||
It's now possible to use dotted notation to group by the child
|
|
||||||
attribute of another attribute.
|
|
||||||
"""
|
|
||||||
expr = make_attrgetter(environment, attribute)
|
|
||||||
return sorted(map(_GroupTuple, groupby(sorted(value, key=expr), expr)))
|
|
||||||
|
|
||||||
|
|
||||||
class _GroupTuple(tuple):
|
|
||||||
__slots__ = ()
|
|
||||||
grouper = property(itemgetter(0))
|
|
||||||
list = property(itemgetter(1))
|
|
||||||
|
|
||||||
def __new__(cls, xxx_todo_changeme):
|
|
||||||
(key, value) = xxx_todo_changeme
|
|
||||||
return tuple.__new__(cls, (key, list(value)))
|
|
||||||
|
|
||||||
|
|
||||||
@environmentfilter
|
|
||||||
def do_sum(environment, iterable, attribute=None, start=0):
|
|
||||||
"""Returns the sum of a sequence of numbers plus the value of parameter
|
|
||||||
'start' (which defaults to 0). When the sequence is empty it returns
|
|
||||||
start.
|
|
||||||
|
|
||||||
It is also possible to sum up only certain attributes:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
Total: {{ items|sum(attribute='price') }}
|
|
||||||
|
|
||||||
.. versionchanged:: 2.6
|
|
||||||
The `attribute` parameter was added to allow suming up over
|
|
||||||
attributes. Also the `start` parameter was moved on to the right.
|
|
||||||
"""
|
|
||||||
if attribute is not None:
|
|
||||||
iterable = imap(make_attrgetter(environment, attribute), iterable)
|
|
||||||
return sum(iterable, start)
|
|
||||||
|
|
||||||
|
|
||||||
def do_list(value):
|
|
||||||
"""Convert the value into a list. If it was a string the returned list
|
|
||||||
will be a list of characters.
|
|
||||||
"""
|
|
||||||
return list(value)
|
|
||||||
|
|
||||||
|
|
||||||
def do_mark_safe(value):
|
|
||||||
"""Mark the value as safe which means that in an environment with automatic
|
|
||||||
escaping enabled this variable will not be escaped.
|
|
||||||
"""
|
|
||||||
return Markup(value)
|
|
||||||
|
|
||||||
|
|
||||||
def do_mark_unsafe(value):
|
|
||||||
"""Mark a value as unsafe. This is the reverse operation for :func:`safe`."""
|
|
||||||
return text_type(value)
|
|
||||||
|
|
||||||
|
|
||||||
def do_reverse(value):
|
|
||||||
"""Reverse the object or return an iterator the iterates over it the other
|
|
||||||
way round.
|
|
||||||
"""
|
|
||||||
if isinstance(value, string_types):
|
|
||||||
return value[::-1]
|
|
||||||
try:
|
|
||||||
return reversed(value)
|
|
||||||
except TypeError:
|
|
||||||
try:
|
|
||||||
rv = list(value)
|
|
||||||
rv.reverse()
|
|
||||||
return rv
|
|
||||||
except TypeError:
|
|
||||||
raise FilterArgumentError('argument must be iterable')
|
|
||||||
|
|
||||||
|
|
||||||
@environmentfilter
|
|
||||||
def do_attr(environment, obj, name):
|
|
||||||
"""Get an attribute of an object. ``foo|attr("bar")`` works like
|
|
||||||
``foo["bar"]`` just that always an attribute is returned and items are not
|
|
||||||
looked up.
|
|
||||||
|
|
||||||
See :ref:`Notes on subscriptions <notes-on-subscriptions>` for more details.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
name = str(name)
|
|
||||||
except UnicodeError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
value = getattr(obj, name)
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if environment.sandboxed and not \
|
|
||||||
environment.is_safe_attribute(obj, name, value):
|
|
||||||
return environment.unsafe_undefined(obj, name)
|
|
||||||
return value
|
|
||||||
return environment.undefined(obj=obj, name=name)
|
|
||||||
|
|
||||||
|
|
||||||
@contextfilter
|
|
||||||
def do_map(*args, **kwargs):
|
|
||||||
"""Applies a filter on a sequence of objects or looks up an attribute.
|
|
||||||
This is useful when dealing with lists of objects but you are really
|
|
||||||
only interested in a certain value of it.
|
|
||||||
|
|
||||||
The basic usage is mapping on an attribute. Imagine you have a list
|
|
||||||
of users but you are only interested in a list of usernames:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
Users on this page: {{ users|map(attribute='username')|join(', ') }}
|
|
||||||
|
|
||||||
Alternatively you can let it invoke a filter by passing the name of the
|
|
||||||
filter and the arguments afterwards. A good example would be applying a
|
|
||||||
text conversion filter on a sequence:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
Users on this page: {{ titles|map('lower')|join(', ') }}
|
|
||||||
|
|
||||||
.. versionadded:: 2.7
|
|
||||||
"""
|
|
||||||
context = args[0]
|
|
||||||
seq = args[1]
|
|
||||||
|
|
||||||
if len(args) == 2 and 'attribute' in kwargs:
|
|
||||||
attribute = kwargs.pop('attribute')
|
|
||||||
if kwargs:
|
|
||||||
raise FilterArgumentError('Unexpected keyword argument %r' %
|
|
||||||
next(iter(kwargs)))
|
|
||||||
func = make_attrgetter(context.environment, attribute)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
name = args[2]
|
|
||||||
args = args[3:]
|
|
||||||
except LookupError:
|
|
||||||
raise FilterArgumentError('map requires a filter argument')
|
|
||||||
func = lambda item: context.environment.call_filter(
|
|
||||||
name, item, args, kwargs, context=context)
|
|
||||||
|
|
||||||
if seq:
|
|
||||||
for item in seq:
|
|
||||||
yield func(item)
|
|
||||||
|
|
||||||
|
|
||||||
@contextfilter
|
|
||||||
def do_select(*args, **kwargs):
|
|
||||||
"""Filters a sequence of objects by appying a test to either the object
|
|
||||||
or the attribute and only selecting the ones with the test succeeding.
|
|
||||||
|
|
||||||
Example usage:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{{ numbers|select("odd") }}
|
|
||||||
|
|
||||||
.. versionadded:: 2.7
|
|
||||||
"""
|
|
||||||
return _select_or_reject(args, kwargs, lambda x: x, False)
|
|
||||||
|
|
||||||
|
|
||||||
@contextfilter
|
|
||||||
def do_reject(*args, **kwargs):
|
|
||||||
"""Filters a sequence of objects by appying a test to either the object
|
|
||||||
or the attribute and rejecting the ones with the test succeeding.
|
|
||||||
|
|
||||||
Example usage:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{{ numbers|reject("odd") }}
|
|
||||||
|
|
||||||
.. versionadded:: 2.7
|
|
||||||
"""
|
|
||||||
return _select_or_reject(args, kwargs, lambda x: not x, False)
|
|
||||||
|
|
||||||
|
|
||||||
@contextfilter
|
|
||||||
def do_selectattr(*args, **kwargs):
|
|
||||||
"""Filters a sequence of objects by appying a test to either the object
|
|
||||||
or the attribute and only selecting the ones with the test succeeding.
|
|
||||||
|
|
||||||
Example usage:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{{ users|selectattr("is_active") }}
|
|
||||||
{{ users|selectattr("email", "none") }}
|
|
||||||
|
|
||||||
.. versionadded:: 2.7
|
|
||||||
"""
|
|
||||||
return _select_or_reject(args, kwargs, lambda x: x, True)
|
|
||||||
|
|
||||||
|
|
||||||
@contextfilter
|
|
||||||
def do_rejectattr(*args, **kwargs):
|
|
||||||
"""Filters a sequence of objects by appying a test to either the object
|
|
||||||
or the attribute and rejecting the ones with the test succeeding.
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{{ users|rejectattr("is_active") }}
|
|
||||||
{{ users|rejectattr("email", "none") }}
|
|
||||||
|
|
||||||
.. versionadded:: 2.7
|
|
||||||
"""
|
|
||||||
return _select_or_reject(args, kwargs, lambda x: not x, True)
|
|
||||||
|
|
||||||
|
|
||||||
def _select_or_reject(args, kwargs, modfunc, lookup_attr):
|
|
||||||
context = args[0]
|
|
||||||
seq = args[1]
|
|
||||||
if lookup_attr:
|
|
||||||
try:
|
|
||||||
attr = args[2]
|
|
||||||
except LookupError:
|
|
||||||
raise FilterArgumentError('Missing parameter for attribute name')
|
|
||||||
transfunc = make_attrgetter(context.environment, attr)
|
|
||||||
off = 1
|
|
||||||
else:
|
|
||||||
off = 0
|
|
||||||
transfunc = lambda x: x
|
|
||||||
|
|
||||||
try:
|
|
||||||
name = args[2 + off]
|
|
||||||
args = args[3 + off:]
|
|
||||||
func = lambda item: context.environment.call_test(
|
|
||||||
name, item, args, kwargs)
|
|
||||||
except LookupError:
|
|
||||||
func = bool
|
|
||||||
|
|
||||||
if seq:
|
|
||||||
for item in seq:
|
|
||||||
if modfunc(func(transfunc(item))):
|
|
||||||
yield item
|
|
||||||
|
|
||||||
|
|
||||||
FILTERS = {
|
|
||||||
'attr': do_attr,
|
|
||||||
'replace': do_replace,
|
|
||||||
'upper': do_upper,
|
|
||||||
'lower': do_lower,
|
|
||||||
'escape': escape,
|
|
||||||
'e': escape,
|
|
||||||
'forceescape': do_forceescape,
|
|
||||||
'capitalize': do_capitalize,
|
|
||||||
'title': do_title,
|
|
||||||
'default': do_default,
|
|
||||||
'd': do_default,
|
|
||||||
'join': do_join,
|
|
||||||
'count': len,
|
|
||||||
'dictsort': do_dictsort,
|
|
||||||
'sort': do_sort,
|
|
||||||
'length': len,
|
|
||||||
'reverse': do_reverse,
|
|
||||||
'center': do_center,
|
|
||||||
'indent': do_indent,
|
|
||||||
'title': do_title,
|
|
||||||
'capitalize': do_capitalize,
|
|
||||||
'first': do_first,
|
|
||||||
'last': do_last,
|
|
||||||
'map': do_map,
|
|
||||||
'random': do_random,
|
|
||||||
'reject': do_reject,
|
|
||||||
'rejectattr': do_rejectattr,
|
|
||||||
'filesizeformat': do_filesizeformat,
|
|
||||||
'pprint': do_pprint,
|
|
||||||
'truncate': do_truncate,
|
|
||||||
'wordwrap': do_wordwrap,
|
|
||||||
'wordcount': do_wordcount,
|
|
||||||
'int': do_int,
|
|
||||||
'float': do_float,
|
|
||||||
'string': soft_unicode,
|
|
||||||
'list': do_list,
|
|
||||||
'urlize': do_urlize,
|
|
||||||
'format': do_format,
|
|
||||||
'trim': do_trim,
|
|
||||||
'striptags': do_striptags,
|
|
||||||
'select': do_select,
|
|
||||||
'selectattr': do_selectattr,
|
|
||||||
'slice': do_slice,
|
|
||||||
'batch': do_batch,
|
|
||||||
'sum': do_sum,
|
|
||||||
'abs': abs,
|
|
||||||
'round': do_round,
|
|
||||||
'groupby': do_groupby,
|
|
||||||
'safe': do_mark_safe,
|
|
||||||
'xmlattr': do_xmlattr,
|
|
||||||
'urlencode': do_urlencode
|
|
||||||
}
|
|
||||||
Vendored
-733
@@ -1,733 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.lexer
|
|
||||||
~~~~~~~~~~~~
|
|
||||||
|
|
||||||
This module implements a Jinja / Python combination lexer. The
|
|
||||||
`Lexer` class provided by this module is used to do some preprocessing
|
|
||||||
for Jinja.
|
|
||||||
|
|
||||||
On the one hand it filters out invalid operators like the bitshift
|
|
||||||
operators we don't allow in templates. On the other hand it separates
|
|
||||||
template code and python code in expressions.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
import re
|
|
||||||
|
|
||||||
from operator import itemgetter
|
|
||||||
from collections import deque
|
|
||||||
from jinja2.exceptions import TemplateSyntaxError
|
|
||||||
from jinja2.utils import LRUCache
|
|
||||||
from jinja2._compat import next, iteritems, implements_iterator, text_type, \
|
|
||||||
intern
|
|
||||||
|
|
||||||
|
|
||||||
# cache for the lexers. Exists in order to be able to have multiple
|
|
||||||
# environments with the same lexer
|
|
||||||
_lexer_cache = LRUCache(50)
|
|
||||||
|
|
||||||
# static regular expressions
|
|
||||||
whitespace_re = re.compile(r'\s+', re.U)
|
|
||||||
string_re = re.compile(r"('([^'\\]*(?:\\.[^'\\]*)*)'"
|
|
||||||
r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
|
|
||||||
integer_re = re.compile(r'\d+')
|
|
||||||
|
|
||||||
# we use the unicode identifier rule if this python version is able
|
|
||||||
# to handle unicode identifiers, otherwise the standard ASCII one.
|
|
||||||
try:
|
|
||||||
compile('föö', '<unknown>', 'eval')
|
|
||||||
except SyntaxError:
|
|
||||||
name_re = re.compile(r'\b[a-zA-Z_][a-zA-Z0-9_]*\b')
|
|
||||||
else:
|
|
||||||
from jinja2 import _stringdefs
|
|
||||||
name_re = re.compile(r'[%s][%s]*' % (_stringdefs.xid_start,
|
|
||||||
_stringdefs.xid_continue))
|
|
||||||
|
|
||||||
float_re = re.compile(r'(?<!\.)\d+\.\d+')
|
|
||||||
newline_re = re.compile(r'(\r\n|\r|\n)')
|
|
||||||
|
|
||||||
# internal the tokens and keep references to them
|
|
||||||
TOKEN_ADD = intern('add')
|
|
||||||
TOKEN_ASSIGN = intern('assign')
|
|
||||||
TOKEN_COLON = intern('colon')
|
|
||||||
TOKEN_COMMA = intern('comma')
|
|
||||||
TOKEN_DIV = intern('div')
|
|
||||||
TOKEN_DOT = intern('dot')
|
|
||||||
TOKEN_EQ = intern('eq')
|
|
||||||
TOKEN_FLOORDIV = intern('floordiv')
|
|
||||||
TOKEN_GT = intern('gt')
|
|
||||||
TOKEN_GTEQ = intern('gteq')
|
|
||||||
TOKEN_LBRACE = intern('lbrace')
|
|
||||||
TOKEN_LBRACKET = intern('lbracket')
|
|
||||||
TOKEN_LPAREN = intern('lparen')
|
|
||||||
TOKEN_LT = intern('lt')
|
|
||||||
TOKEN_LTEQ = intern('lteq')
|
|
||||||
TOKEN_MOD = intern('mod')
|
|
||||||
TOKEN_MUL = intern('mul')
|
|
||||||
TOKEN_NE = intern('ne')
|
|
||||||
TOKEN_PIPE = intern('pipe')
|
|
||||||
TOKEN_POW = intern('pow')
|
|
||||||
TOKEN_RBRACE = intern('rbrace')
|
|
||||||
TOKEN_RBRACKET = intern('rbracket')
|
|
||||||
TOKEN_RPAREN = intern('rparen')
|
|
||||||
TOKEN_SEMICOLON = intern('semicolon')
|
|
||||||
TOKEN_SUB = intern('sub')
|
|
||||||
TOKEN_TILDE = intern('tilde')
|
|
||||||
TOKEN_WHITESPACE = intern('whitespace')
|
|
||||||
TOKEN_FLOAT = intern('float')
|
|
||||||
TOKEN_INTEGER = intern('integer')
|
|
||||||
TOKEN_NAME = intern('name')
|
|
||||||
TOKEN_STRING = intern('string')
|
|
||||||
TOKEN_OPERATOR = intern('operator')
|
|
||||||
TOKEN_BLOCK_BEGIN = intern('block_begin')
|
|
||||||
TOKEN_BLOCK_END = intern('block_end')
|
|
||||||
TOKEN_VARIABLE_BEGIN = intern('variable_begin')
|
|
||||||
TOKEN_VARIABLE_END = intern('variable_end')
|
|
||||||
TOKEN_RAW_BEGIN = intern('raw_begin')
|
|
||||||
TOKEN_RAW_END = intern('raw_end')
|
|
||||||
TOKEN_COMMENT_BEGIN = intern('comment_begin')
|
|
||||||
TOKEN_COMMENT_END = intern('comment_end')
|
|
||||||
TOKEN_COMMENT = intern('comment')
|
|
||||||
TOKEN_LINESTATEMENT_BEGIN = intern('linestatement_begin')
|
|
||||||
TOKEN_LINESTATEMENT_END = intern('linestatement_end')
|
|
||||||
TOKEN_LINECOMMENT_BEGIN = intern('linecomment_begin')
|
|
||||||
TOKEN_LINECOMMENT_END = intern('linecomment_end')
|
|
||||||
TOKEN_LINECOMMENT = intern('linecomment')
|
|
||||||
TOKEN_DATA = intern('data')
|
|
||||||
TOKEN_INITIAL = intern('initial')
|
|
||||||
TOKEN_EOF = intern('eof')
|
|
||||||
|
|
||||||
# bind operators to token types
|
|
||||||
operators = {
|
|
||||||
'+': TOKEN_ADD,
|
|
||||||
'-': TOKEN_SUB,
|
|
||||||
'/': TOKEN_DIV,
|
|
||||||
'//': TOKEN_FLOORDIV,
|
|
||||||
'*': TOKEN_MUL,
|
|
||||||
'%': TOKEN_MOD,
|
|
||||||
'**': TOKEN_POW,
|
|
||||||
'~': TOKEN_TILDE,
|
|
||||||
'[': TOKEN_LBRACKET,
|
|
||||||
']': TOKEN_RBRACKET,
|
|
||||||
'(': TOKEN_LPAREN,
|
|
||||||
')': TOKEN_RPAREN,
|
|
||||||
'{': TOKEN_LBRACE,
|
|
||||||
'}': TOKEN_RBRACE,
|
|
||||||
'==': TOKEN_EQ,
|
|
||||||
'!=': TOKEN_NE,
|
|
||||||
'>': TOKEN_GT,
|
|
||||||
'>=': TOKEN_GTEQ,
|
|
||||||
'<': TOKEN_LT,
|
|
||||||
'<=': TOKEN_LTEQ,
|
|
||||||
'=': TOKEN_ASSIGN,
|
|
||||||
'.': TOKEN_DOT,
|
|
||||||
':': TOKEN_COLON,
|
|
||||||
'|': TOKEN_PIPE,
|
|
||||||
',': TOKEN_COMMA,
|
|
||||||
';': TOKEN_SEMICOLON
|
|
||||||
}
|
|
||||||
|
|
||||||
reverse_operators = dict([(v, k) for k, v in iteritems(operators)])
|
|
||||||
assert len(operators) == len(reverse_operators), 'operators dropped'
|
|
||||||
operator_re = re.compile('(%s)' % '|'.join(re.escape(x) for x in
|
|
||||||
sorted(operators, key=lambda x: -len(x))))
|
|
||||||
|
|
||||||
ignored_tokens = frozenset([TOKEN_COMMENT_BEGIN, TOKEN_COMMENT,
|
|
||||||
TOKEN_COMMENT_END, TOKEN_WHITESPACE,
|
|
||||||
TOKEN_WHITESPACE, TOKEN_LINECOMMENT_BEGIN,
|
|
||||||
TOKEN_LINECOMMENT_END, TOKEN_LINECOMMENT])
|
|
||||||
ignore_if_empty = frozenset([TOKEN_WHITESPACE, TOKEN_DATA,
|
|
||||||
TOKEN_COMMENT, TOKEN_LINECOMMENT])
|
|
||||||
|
|
||||||
|
|
||||||
def _describe_token_type(token_type):
|
|
||||||
if token_type in reverse_operators:
|
|
||||||
return reverse_operators[token_type]
|
|
||||||
return {
|
|
||||||
TOKEN_COMMENT_BEGIN: 'begin of comment',
|
|
||||||
TOKEN_COMMENT_END: 'end of comment',
|
|
||||||
TOKEN_COMMENT: 'comment',
|
|
||||||
TOKEN_LINECOMMENT: 'comment',
|
|
||||||
TOKEN_BLOCK_BEGIN: 'begin of statement block',
|
|
||||||
TOKEN_BLOCK_END: 'end of statement block',
|
|
||||||
TOKEN_VARIABLE_BEGIN: 'begin of print statement',
|
|
||||||
TOKEN_VARIABLE_END: 'end of print statement',
|
|
||||||
TOKEN_LINESTATEMENT_BEGIN: 'begin of line statement',
|
|
||||||
TOKEN_LINESTATEMENT_END: 'end of line statement',
|
|
||||||
TOKEN_DATA: 'template data / text',
|
|
||||||
TOKEN_EOF: 'end of template'
|
|
||||||
}.get(token_type, token_type)
|
|
||||||
|
|
||||||
|
|
||||||
def describe_token(token):
|
|
||||||
"""Returns a description of the token."""
|
|
||||||
if token.type == 'name':
|
|
||||||
return token.value
|
|
||||||
return _describe_token_type(token.type)
|
|
||||||
|
|
||||||
|
|
||||||
def describe_token_expr(expr):
|
|
||||||
"""Like `describe_token` but for token expressions."""
|
|
||||||
if ':' in expr:
|
|
||||||
type, value = expr.split(':', 1)
|
|
||||||
if type == 'name':
|
|
||||||
return value
|
|
||||||
else:
|
|
||||||
type = expr
|
|
||||||
return _describe_token_type(type)
|
|
||||||
|
|
||||||
|
|
||||||
def count_newlines(value):
|
|
||||||
"""Count the number of newline characters in the string. This is
|
|
||||||
useful for extensions that filter a stream.
|
|
||||||
"""
|
|
||||||
return len(newline_re.findall(value))
|
|
||||||
|
|
||||||
|
|
||||||
def compile_rules(environment):
|
|
||||||
"""Compiles all the rules from the environment into a list of rules."""
|
|
||||||
e = re.escape
|
|
||||||
rules = [
|
|
||||||
(len(environment.comment_start_string), 'comment',
|
|
||||||
e(environment.comment_start_string)),
|
|
||||||
(len(environment.block_start_string), 'block',
|
|
||||||
e(environment.block_start_string)),
|
|
||||||
(len(environment.variable_start_string), 'variable',
|
|
||||||
e(environment.variable_start_string))
|
|
||||||
]
|
|
||||||
|
|
||||||
if environment.line_statement_prefix is not None:
|
|
||||||
rules.append((len(environment.line_statement_prefix), 'linestatement',
|
|
||||||
r'^[ \t\v]*' + e(environment.line_statement_prefix)))
|
|
||||||
if environment.line_comment_prefix is not None:
|
|
||||||
rules.append((len(environment.line_comment_prefix), 'linecomment',
|
|
||||||
r'(?:^|(?<=\S))[^\S\r\n]*' +
|
|
||||||
e(environment.line_comment_prefix)))
|
|
||||||
|
|
||||||
return [x[1:] for x in sorted(rules, reverse=True)]
|
|
||||||
|
|
||||||
|
|
||||||
class Failure(object):
|
|
||||||
"""Class that raises a `TemplateSyntaxError` if called.
|
|
||||||
Used by the `Lexer` to specify known errors.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, message, cls=TemplateSyntaxError):
|
|
||||||
self.message = message
|
|
||||||
self.error_class = cls
|
|
||||||
|
|
||||||
def __call__(self, lineno, filename):
|
|
||||||
raise self.error_class(self.message, lineno, filename)
|
|
||||||
|
|
||||||
|
|
||||||
class Token(tuple):
|
|
||||||
"""Token class."""
|
|
||||||
__slots__ = ()
|
|
||||||
lineno, type, value = (property(itemgetter(x)) for x in range(3))
|
|
||||||
|
|
||||||
def __new__(cls, lineno, type, value):
|
|
||||||
return tuple.__new__(cls, (lineno, intern(str(type)), value))
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.type in reverse_operators:
|
|
||||||
return reverse_operators[self.type]
|
|
||||||
elif self.type == 'name':
|
|
||||||
return self.value
|
|
||||||
return self.type
|
|
||||||
|
|
||||||
def test(self, expr):
|
|
||||||
"""Test a token against a token expression. This can either be a
|
|
||||||
token type or ``'token_type:token_value'``. This can only test
|
|
||||||
against string values and types.
|
|
||||||
"""
|
|
||||||
# here we do a regular string equality check as test_any is usually
|
|
||||||
# passed an iterable of not interned strings.
|
|
||||||
if self.type == expr:
|
|
||||||
return True
|
|
||||||
elif ':' in expr:
|
|
||||||
return expr.split(':', 1) == [self.type, self.value]
|
|
||||||
return False
|
|
||||||
|
|
||||||
def test_any(self, *iterable):
|
|
||||||
"""Test against multiple token expressions."""
|
|
||||||
for expr in iterable:
|
|
||||||
if self.test(expr):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return 'Token(%r, %r, %r)' % (
|
|
||||||
self.lineno,
|
|
||||||
self.type,
|
|
||||||
self.value
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@implements_iterator
|
|
||||||
class TokenStreamIterator(object):
|
|
||||||
"""The iterator for tokenstreams. Iterate over the stream
|
|
||||||
until the eof token is reached.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, stream):
|
|
||||||
self.stream = stream
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __next__(self):
|
|
||||||
token = self.stream.current
|
|
||||||
if token.type is TOKEN_EOF:
|
|
||||||
self.stream.close()
|
|
||||||
raise StopIteration()
|
|
||||||
next(self.stream)
|
|
||||||
return token
|
|
||||||
|
|
||||||
|
|
||||||
@implements_iterator
|
|
||||||
class TokenStream(object):
|
|
||||||
"""A token stream is an iterable that yields :class:`Token`\s. The
|
|
||||||
parser however does not iterate over it but calls :meth:`next` to go
|
|
||||||
one token ahead. The current active token is stored as :attr:`current`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, generator, name, filename):
|
|
||||||
self._iter = iter(generator)
|
|
||||||
self._pushed = deque()
|
|
||||||
self.name = name
|
|
||||||
self.filename = filename
|
|
||||||
self.closed = False
|
|
||||||
self.current = Token(1, TOKEN_INITIAL, '')
|
|
||||||
next(self)
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
return TokenStreamIterator(self)
|
|
||||||
|
|
||||||
def __bool__(self):
|
|
||||||
return bool(self._pushed) or self.current.type is not TOKEN_EOF
|
|
||||||
__nonzero__ = __bool__ # py2
|
|
||||||
|
|
||||||
eos = property(lambda x: not x, doc="Are we at the end of the stream?")
|
|
||||||
|
|
||||||
def push(self, token):
|
|
||||||
"""Push a token back to the stream."""
|
|
||||||
self._pushed.append(token)
|
|
||||||
|
|
||||||
def look(self):
|
|
||||||
"""Look at the next token."""
|
|
||||||
old_token = next(self)
|
|
||||||
result = self.current
|
|
||||||
self.push(result)
|
|
||||||
self.current = old_token
|
|
||||||
return result
|
|
||||||
|
|
||||||
def skip(self, n=1):
|
|
||||||
"""Got n tokens ahead."""
|
|
||||||
for x in range(n):
|
|
||||||
next(self)
|
|
||||||
|
|
||||||
def next_if(self, expr):
|
|
||||||
"""Perform the token test and return the token if it matched.
|
|
||||||
Otherwise the return value is `None`.
|
|
||||||
"""
|
|
||||||
if self.current.test(expr):
|
|
||||||
return next(self)
|
|
||||||
|
|
||||||
def skip_if(self, expr):
|
|
||||||
"""Like :meth:`next_if` but only returns `True` or `False`."""
|
|
||||||
return self.next_if(expr) is not None
|
|
||||||
|
|
||||||
def __next__(self):
|
|
||||||
"""Go one token ahead and return the old one"""
|
|
||||||
rv = self.current
|
|
||||||
if self._pushed:
|
|
||||||
self.current = self._pushed.popleft()
|
|
||||||
elif self.current.type is not TOKEN_EOF:
|
|
||||||
try:
|
|
||||||
self.current = next(self._iter)
|
|
||||||
except StopIteration:
|
|
||||||
self.close()
|
|
||||||
return rv
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
"""Close the stream."""
|
|
||||||
self.current = Token(self.current.lineno, TOKEN_EOF, '')
|
|
||||||
self._iter = None
|
|
||||||
self.closed = True
|
|
||||||
|
|
||||||
def expect(self, expr):
|
|
||||||
"""Expect a given token type and return it. This accepts the same
|
|
||||||
argument as :meth:`jinja2.lexer.Token.test`.
|
|
||||||
"""
|
|
||||||
if not self.current.test(expr):
|
|
||||||
expr = describe_token_expr(expr)
|
|
||||||
if self.current.type is TOKEN_EOF:
|
|
||||||
raise TemplateSyntaxError('unexpected end of template, '
|
|
||||||
'expected %r.' % expr,
|
|
||||||
self.current.lineno,
|
|
||||||
self.name, self.filename)
|
|
||||||
raise TemplateSyntaxError("expected token %r, got %r" %
|
|
||||||
(expr, describe_token(self.current)),
|
|
||||||
self.current.lineno,
|
|
||||||
self.name, self.filename)
|
|
||||||
try:
|
|
||||||
return self.current
|
|
||||||
finally:
|
|
||||||
next(self)
|
|
||||||
|
|
||||||
|
|
||||||
def get_lexer(environment):
|
|
||||||
"""Return a lexer which is probably cached."""
|
|
||||||
key = (environment.block_start_string,
|
|
||||||
environment.block_end_string,
|
|
||||||
environment.variable_start_string,
|
|
||||||
environment.variable_end_string,
|
|
||||||
environment.comment_start_string,
|
|
||||||
environment.comment_end_string,
|
|
||||||
environment.line_statement_prefix,
|
|
||||||
environment.line_comment_prefix,
|
|
||||||
environment.trim_blocks,
|
|
||||||
environment.lstrip_blocks,
|
|
||||||
environment.newline_sequence,
|
|
||||||
environment.keep_trailing_newline)
|
|
||||||
lexer = _lexer_cache.get(key)
|
|
||||||
if lexer is None:
|
|
||||||
lexer = Lexer(environment)
|
|
||||||
_lexer_cache[key] = lexer
|
|
||||||
return lexer
|
|
||||||
|
|
||||||
|
|
||||||
class Lexer(object):
|
|
||||||
"""Class that implements a lexer for a given environment. Automatically
|
|
||||||
created by the environment class, usually you don't have to do that.
|
|
||||||
|
|
||||||
Note that the lexer is not automatically bound to an environment.
|
|
||||||
Multiple environments can share the same lexer.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, environment):
|
|
||||||
# shortcuts
|
|
||||||
c = lambda x: re.compile(x, re.M | re.S)
|
|
||||||
e = re.escape
|
|
||||||
|
|
||||||
# lexing rules for tags
|
|
||||||
tag_rules = [
|
|
||||||
(whitespace_re, TOKEN_WHITESPACE, None),
|
|
||||||
(float_re, TOKEN_FLOAT, None),
|
|
||||||
(integer_re, TOKEN_INTEGER, None),
|
|
||||||
(name_re, TOKEN_NAME, None),
|
|
||||||
(string_re, TOKEN_STRING, None),
|
|
||||||
(operator_re, TOKEN_OPERATOR, None)
|
|
||||||
]
|
|
||||||
|
|
||||||
# assemble the root lexing rule. because "|" is ungreedy
|
|
||||||
# we have to sort by length so that the lexer continues working
|
|
||||||
# as expected when we have parsing rules like <% for block and
|
|
||||||
# <%= for variables. (if someone wants asp like syntax)
|
|
||||||
# variables are just part of the rules if variable processing
|
|
||||||
# is required.
|
|
||||||
root_tag_rules = compile_rules(environment)
|
|
||||||
|
|
||||||
# block suffix if trimming is enabled
|
|
||||||
block_suffix_re = environment.trim_blocks and '\\n?' or ''
|
|
||||||
|
|
||||||
# strip leading spaces if lstrip_blocks is enabled
|
|
||||||
prefix_re = {}
|
|
||||||
if environment.lstrip_blocks:
|
|
||||||
# use '{%+' to manually disable lstrip_blocks behavior
|
|
||||||
no_lstrip_re = e('+')
|
|
||||||
# detect overlap between block and variable or comment strings
|
|
||||||
block_diff = c(r'^%s(.*)' % e(environment.block_start_string))
|
|
||||||
# make sure we don't mistake a block for a variable or a comment
|
|
||||||
m = block_diff.match(environment.comment_start_string)
|
|
||||||
no_lstrip_re += m and r'|%s' % e(m.group(1)) or ''
|
|
||||||
m = block_diff.match(environment.variable_start_string)
|
|
||||||
no_lstrip_re += m and r'|%s' % e(m.group(1)) or ''
|
|
||||||
|
|
||||||
# detect overlap between comment and variable strings
|
|
||||||
comment_diff = c(r'^%s(.*)' % e(environment.comment_start_string))
|
|
||||||
m = comment_diff.match(environment.variable_start_string)
|
|
||||||
no_variable_re = m and r'(?!%s)' % e(m.group(1)) or ''
|
|
||||||
|
|
||||||
lstrip_re = r'^[ \t]*'
|
|
||||||
block_prefix_re = r'%s%s(?!%s)|%s\+?' % (
|
|
||||||
lstrip_re,
|
|
||||||
e(environment.block_start_string),
|
|
||||||
no_lstrip_re,
|
|
||||||
e(environment.block_start_string),
|
|
||||||
)
|
|
||||||
comment_prefix_re = r'%s%s%s|%s\+?' % (
|
|
||||||
lstrip_re,
|
|
||||||
e(environment.comment_start_string),
|
|
||||||
no_variable_re,
|
|
||||||
e(environment.comment_start_string),
|
|
||||||
)
|
|
||||||
prefix_re['block'] = block_prefix_re
|
|
||||||
prefix_re['comment'] = comment_prefix_re
|
|
||||||
else:
|
|
||||||
block_prefix_re = '%s' % e(environment.block_start_string)
|
|
||||||
|
|
||||||
self.newline_sequence = environment.newline_sequence
|
|
||||||
self.keep_trailing_newline = environment.keep_trailing_newline
|
|
||||||
|
|
||||||
# global lexing rules
|
|
||||||
self.rules = {
|
|
||||||
'root': [
|
|
||||||
# directives
|
|
||||||
(c('(.*?)(?:%s)' % '|'.join(
|
|
||||||
[r'(?P<raw_begin>(?:\s*%s\-|%s)\s*raw\s*(?:\-%s\s*|%s))' % (
|
|
||||||
e(environment.block_start_string),
|
|
||||||
block_prefix_re,
|
|
||||||
e(environment.block_end_string),
|
|
||||||
e(environment.block_end_string)
|
|
||||||
)] + [
|
|
||||||
r'(?P<%s_begin>\s*%s\-|%s)' % (n, r, prefix_re.get(n,r))
|
|
||||||
for n, r in root_tag_rules
|
|
||||||
])), (TOKEN_DATA, '#bygroup'), '#bygroup'),
|
|
||||||
# data
|
|
||||||
(c('.+'), TOKEN_DATA, None)
|
|
||||||
],
|
|
||||||
# comments
|
|
||||||
TOKEN_COMMENT_BEGIN: [
|
|
||||||
(c(r'(.*?)((?:\-%s\s*|%s)%s)' % (
|
|
||||||
e(environment.comment_end_string),
|
|
||||||
e(environment.comment_end_string),
|
|
||||||
block_suffix_re
|
|
||||||
)), (TOKEN_COMMENT, TOKEN_COMMENT_END), '#pop'),
|
|
||||||
(c('(.)'), (Failure('Missing end of comment tag'),), None)
|
|
||||||
],
|
|
||||||
# blocks
|
|
||||||
TOKEN_BLOCK_BEGIN: [
|
|
||||||
(c('(?:\-%s\s*|%s)%s' % (
|
|
||||||
e(environment.block_end_string),
|
|
||||||
e(environment.block_end_string),
|
|
||||||
block_suffix_re
|
|
||||||
)), TOKEN_BLOCK_END, '#pop'),
|
|
||||||
] + tag_rules,
|
|
||||||
# variables
|
|
||||||
TOKEN_VARIABLE_BEGIN: [
|
|
||||||
(c('\-%s\s*|%s' % (
|
|
||||||
e(environment.variable_end_string),
|
|
||||||
e(environment.variable_end_string)
|
|
||||||
)), TOKEN_VARIABLE_END, '#pop')
|
|
||||||
] + tag_rules,
|
|
||||||
# raw block
|
|
||||||
TOKEN_RAW_BEGIN: [
|
|
||||||
(c('(.*?)((?:\s*%s\-|%s)\s*endraw\s*(?:\-%s\s*|%s%s))' % (
|
|
||||||
e(environment.block_start_string),
|
|
||||||
block_prefix_re,
|
|
||||||
e(environment.block_end_string),
|
|
||||||
e(environment.block_end_string),
|
|
||||||
block_suffix_re
|
|
||||||
)), (TOKEN_DATA, TOKEN_RAW_END), '#pop'),
|
|
||||||
(c('(.)'), (Failure('Missing end of raw directive'),), None)
|
|
||||||
],
|
|
||||||
# line statements
|
|
||||||
TOKEN_LINESTATEMENT_BEGIN: [
|
|
||||||
(c(r'\s*(\n|$)'), TOKEN_LINESTATEMENT_END, '#pop')
|
|
||||||
] + tag_rules,
|
|
||||||
# line comments
|
|
||||||
TOKEN_LINECOMMENT_BEGIN: [
|
|
||||||
(c(r'(.*?)()(?=\n|$)'), (TOKEN_LINECOMMENT,
|
|
||||||
TOKEN_LINECOMMENT_END), '#pop')
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
def _normalize_newlines(self, value):
|
|
||||||
"""Called for strings and template data to normalize it to unicode."""
|
|
||||||
return newline_re.sub(self.newline_sequence, value)
|
|
||||||
|
|
||||||
def tokenize(self, source, name=None, filename=None, state=None):
|
|
||||||
"""Calls tokeniter + tokenize and wraps it in a token stream.
|
|
||||||
"""
|
|
||||||
stream = self.tokeniter(source, name, filename, state)
|
|
||||||
return TokenStream(self.wrap(stream, name, filename), name, filename)
|
|
||||||
|
|
||||||
def wrap(self, stream, name=None, filename=None):
|
|
||||||
"""This is called with the stream as returned by `tokenize` and wraps
|
|
||||||
every token in a :class:`Token` and converts the value.
|
|
||||||
"""
|
|
||||||
for lineno, token, value in stream:
|
|
||||||
if token in ignored_tokens:
|
|
||||||
continue
|
|
||||||
elif token == 'linestatement_begin':
|
|
||||||
token = 'block_begin'
|
|
||||||
elif token == 'linestatement_end':
|
|
||||||
token = 'block_end'
|
|
||||||
# we are not interested in those tokens in the parser
|
|
||||||
elif token in ('raw_begin', 'raw_end'):
|
|
||||||
continue
|
|
||||||
elif token == 'data':
|
|
||||||
value = self._normalize_newlines(value)
|
|
||||||
elif token == 'keyword':
|
|
||||||
token = value
|
|
||||||
elif token == 'name':
|
|
||||||
value = str(value)
|
|
||||||
elif token == 'string':
|
|
||||||
# try to unescape string
|
|
||||||
try:
|
|
||||||
value = self._normalize_newlines(value[1:-1]) \
|
|
||||||
.encode('ascii', 'backslashreplace') \
|
|
||||||
.decode('unicode-escape')
|
|
||||||
except Exception as e:
|
|
||||||
msg = str(e).split(':')[-1].strip()
|
|
||||||
raise TemplateSyntaxError(msg, lineno, name, filename)
|
|
||||||
# if we can express it as bytestring (ascii only)
|
|
||||||
# we do that for support of semi broken APIs
|
|
||||||
# as datetime.datetime.strftime. On python 3 this
|
|
||||||
# call becomes a noop thanks to 2to3
|
|
||||||
try:
|
|
||||||
value = str(value)
|
|
||||||
except UnicodeError:
|
|
||||||
pass
|
|
||||||
elif token == 'integer':
|
|
||||||
value = int(value)
|
|
||||||
elif token == 'float':
|
|
||||||
value = float(value)
|
|
||||||
elif token == 'operator':
|
|
||||||
token = operators[value]
|
|
||||||
yield Token(lineno, token, value)
|
|
||||||
|
|
||||||
def tokeniter(self, source, name, filename=None, state=None):
|
|
||||||
"""This method tokenizes the text and returns the tokens in a
|
|
||||||
generator. Use this method if you just want to tokenize a template.
|
|
||||||
"""
|
|
||||||
source = text_type(source)
|
|
||||||
lines = source.splitlines()
|
|
||||||
if self.keep_trailing_newline and source:
|
|
||||||
for newline in ('\r\n', '\r', '\n'):
|
|
||||||
if source.endswith(newline):
|
|
||||||
lines.append('')
|
|
||||||
break
|
|
||||||
source = '\n'.join(lines)
|
|
||||||
pos = 0
|
|
||||||
lineno = 1
|
|
||||||
stack = ['root']
|
|
||||||
if state is not None and state != 'root':
|
|
||||||
assert state in ('variable', 'block'), 'invalid state'
|
|
||||||
stack.append(state + '_begin')
|
|
||||||
else:
|
|
||||||
state = 'root'
|
|
||||||
statetokens = self.rules[stack[-1]]
|
|
||||||
source_length = len(source)
|
|
||||||
|
|
||||||
balancing_stack = []
|
|
||||||
|
|
||||||
while 1:
|
|
||||||
# tokenizer loop
|
|
||||||
for regex, tokens, new_state in statetokens:
|
|
||||||
m = regex.match(source, pos)
|
|
||||||
# if no match we try again with the next rule
|
|
||||||
if m is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# we only match blocks and variables if braces / parentheses
|
|
||||||
# are balanced. continue parsing with the lower rule which
|
|
||||||
# is the operator rule. do this only if the end tags look
|
|
||||||
# like operators
|
|
||||||
if balancing_stack and \
|
|
||||||
tokens in ('variable_end', 'block_end',
|
|
||||||
'linestatement_end'):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# tuples support more options
|
|
||||||
if isinstance(tokens, tuple):
|
|
||||||
for idx, token in enumerate(tokens):
|
|
||||||
# failure group
|
|
||||||
if token.__class__ is Failure:
|
|
||||||
raise token(lineno, filename)
|
|
||||||
# bygroup is a bit more complex, in that case we
|
|
||||||
# yield for the current token the first named
|
|
||||||
# group that matched
|
|
||||||
elif token == '#bygroup':
|
|
||||||
for key, value in iteritems(m.groupdict()):
|
|
||||||
if value is not None:
|
|
||||||
yield lineno, key, value
|
|
||||||
lineno += value.count('\n')
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
raise RuntimeError('%r wanted to resolve '
|
|
||||||
'the token dynamically'
|
|
||||||
' but no group matched'
|
|
||||||
% regex)
|
|
||||||
# normal group
|
|
||||||
else:
|
|
||||||
data = m.group(idx + 1)
|
|
||||||
if data or token not in ignore_if_empty:
|
|
||||||
yield lineno, token, data
|
|
||||||
lineno += data.count('\n')
|
|
||||||
|
|
||||||
# strings as token just are yielded as it.
|
|
||||||
else:
|
|
||||||
data = m.group()
|
|
||||||
# update brace/parentheses balance
|
|
||||||
if tokens == 'operator':
|
|
||||||
if data == '{':
|
|
||||||
balancing_stack.append('}')
|
|
||||||
elif data == '(':
|
|
||||||
balancing_stack.append(')')
|
|
||||||
elif data == '[':
|
|
||||||
balancing_stack.append(']')
|
|
||||||
elif data in ('}', ')', ']'):
|
|
||||||
if not balancing_stack:
|
|
||||||
raise TemplateSyntaxError('unexpected \'%s\'' %
|
|
||||||
data, lineno, name,
|
|
||||||
filename)
|
|
||||||
expected_op = balancing_stack.pop()
|
|
||||||
if expected_op != data:
|
|
||||||
raise TemplateSyntaxError('unexpected \'%s\', '
|
|
||||||
'expected \'%s\'' %
|
|
||||||
(data, expected_op),
|
|
||||||
lineno, name,
|
|
||||||
filename)
|
|
||||||
# yield items
|
|
||||||
if data or tokens not in ignore_if_empty:
|
|
||||||
yield lineno, tokens, data
|
|
||||||
lineno += data.count('\n')
|
|
||||||
|
|
||||||
# fetch new position into new variable so that we can check
|
|
||||||
# if there is a internal parsing error which would result
|
|
||||||
# in an infinite loop
|
|
||||||
pos2 = m.end()
|
|
||||||
|
|
||||||
# handle state changes
|
|
||||||
if new_state is not None:
|
|
||||||
# remove the uppermost state
|
|
||||||
if new_state == '#pop':
|
|
||||||
stack.pop()
|
|
||||||
# resolve the new state by group checking
|
|
||||||
elif new_state == '#bygroup':
|
|
||||||
for key, value in iteritems(m.groupdict()):
|
|
||||||
if value is not None:
|
|
||||||
stack.append(key)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
raise RuntimeError('%r wanted to resolve the '
|
|
||||||
'new state dynamically but'
|
|
||||||
' no group matched' %
|
|
||||||
regex)
|
|
||||||
# direct state name given
|
|
||||||
else:
|
|
||||||
stack.append(new_state)
|
|
||||||
statetokens = self.rules[stack[-1]]
|
|
||||||
# we are still at the same position and no stack change.
|
|
||||||
# this means a loop without break condition, avoid that and
|
|
||||||
# raise error
|
|
||||||
elif pos2 == pos:
|
|
||||||
raise RuntimeError('%r yielded empty string without '
|
|
||||||
'stack change' % regex)
|
|
||||||
# publish new function and start again
|
|
||||||
pos = pos2
|
|
||||||
break
|
|
||||||
# if loop terminated without break we haven't found a single match
|
|
||||||
# either we are at the end of the file or we have a problem
|
|
||||||
else:
|
|
||||||
# end of text
|
|
||||||
if pos >= source_length:
|
|
||||||
return
|
|
||||||
# something went wrong
|
|
||||||
raise TemplateSyntaxError('unexpected char %r at %d' %
|
|
||||||
(source[pos], pos), lineno,
|
|
||||||
name, filename)
|
|
||||||
Vendored
-471
@@ -1,471 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.loaders
|
|
||||||
~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Jinja loader classes.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import weakref
|
|
||||||
from types import ModuleType
|
|
||||||
from os import path
|
|
||||||
from hashlib import sha1
|
|
||||||
from jinja2.exceptions import TemplateNotFound
|
|
||||||
from jinja2.utils import open_if_exists, internalcode
|
|
||||||
from jinja2._compat import string_types, iteritems
|
|
||||||
|
|
||||||
|
|
||||||
def split_template_path(template):
|
|
||||||
"""Split a path into segments and perform a sanity check. If it detects
|
|
||||||
'..' in the path it will raise a `TemplateNotFound` error.
|
|
||||||
"""
|
|
||||||
pieces = []
|
|
||||||
for piece in template.split('/'):
|
|
||||||
if path.sep in piece \
|
|
||||||
or (path.altsep and path.altsep in piece) or \
|
|
||||||
piece == path.pardir:
|
|
||||||
raise TemplateNotFound(template)
|
|
||||||
elif piece and piece != '.':
|
|
||||||
pieces.append(piece)
|
|
||||||
return pieces
|
|
||||||
|
|
||||||
|
|
||||||
class BaseLoader(object):
|
|
||||||
"""Baseclass for all loaders. Subclass this and override `get_source` to
|
|
||||||
implement a custom loading mechanism. The environment provides a
|
|
||||||
`get_template` method that calls the loader's `load` method to get the
|
|
||||||
:class:`Template` object.
|
|
||||||
|
|
||||||
A very basic example for a loader that looks up templates on the file
|
|
||||||
system could look like this::
|
|
||||||
|
|
||||||
from jinja2 import BaseLoader, TemplateNotFound
|
|
||||||
from os.path import join, exists, getmtime
|
|
||||||
|
|
||||||
class MyLoader(BaseLoader):
|
|
||||||
|
|
||||||
def __init__(self, path):
|
|
||||||
self.path = path
|
|
||||||
|
|
||||||
def get_source(self, environment, template):
|
|
||||||
path = join(self.path, template)
|
|
||||||
if not exists(path):
|
|
||||||
raise TemplateNotFound(template)
|
|
||||||
mtime = getmtime(path)
|
|
||||||
with file(path) as f:
|
|
||||||
source = f.read().decode('utf-8')
|
|
||||||
return source, path, lambda: mtime == getmtime(path)
|
|
||||||
"""
|
|
||||||
|
|
||||||
#: if set to `False` it indicates that the loader cannot provide access
|
|
||||||
#: to the source of templates.
|
|
||||||
#:
|
|
||||||
#: .. versionadded:: 2.4
|
|
||||||
has_source_access = True
|
|
||||||
|
|
||||||
def get_source(self, environment, template):
|
|
||||||
"""Get the template source, filename and reload helper for a template.
|
|
||||||
It's passed the environment and template name and has to return a
|
|
||||||
tuple in the form ``(source, filename, uptodate)`` or raise a
|
|
||||||
`TemplateNotFound` error if it can't locate the template.
|
|
||||||
|
|
||||||
The source part of the returned tuple must be the source of the
|
|
||||||
template as unicode string or a ASCII bytestring. The filename should
|
|
||||||
be the name of the file on the filesystem if it was loaded from there,
|
|
||||||
otherwise `None`. The filename is used by python for the tracebacks
|
|
||||||
if no loader extension is used.
|
|
||||||
|
|
||||||
The last item in the tuple is the `uptodate` function. If auto
|
|
||||||
reloading is enabled it's always called to check if the template
|
|
||||||
changed. No arguments are passed so the function must store the
|
|
||||||
old state somewhere (for example in a closure). If it returns `False`
|
|
||||||
the template will be reloaded.
|
|
||||||
"""
|
|
||||||
if not self.has_source_access:
|
|
||||||
raise RuntimeError('%s cannot provide access to the source' %
|
|
||||||
self.__class__.__name__)
|
|
||||||
raise TemplateNotFound(template)
|
|
||||||
|
|
||||||
def list_templates(self):
|
|
||||||
"""Iterates over all templates. If the loader does not support that
|
|
||||||
it should raise a :exc:`TypeError` which is the default behavior.
|
|
||||||
"""
|
|
||||||
raise TypeError('this loader cannot iterate over all templates')
|
|
||||||
|
|
||||||
@internalcode
|
|
||||||
def load(self, environment, name, globals=None):
|
|
||||||
"""Loads a template. This method looks up the template in the cache
|
|
||||||
or loads one by calling :meth:`get_source`. Subclasses should not
|
|
||||||
override this method as loaders working on collections of other
|
|
||||||
loaders (such as :class:`PrefixLoader` or :class:`ChoiceLoader`)
|
|
||||||
will not call this method but `get_source` directly.
|
|
||||||
"""
|
|
||||||
code = None
|
|
||||||
if globals is None:
|
|
||||||
globals = {}
|
|
||||||
|
|
||||||
# first we try to get the source for this template together
|
|
||||||
# with the filename and the uptodate function.
|
|
||||||
source, filename, uptodate = self.get_source(environment, name)
|
|
||||||
|
|
||||||
# try to load the code from the bytecode cache if there is a
|
|
||||||
# bytecode cache configured.
|
|
||||||
bcc = environment.bytecode_cache
|
|
||||||
if bcc is not None:
|
|
||||||
bucket = bcc.get_bucket(environment, name, filename, source)
|
|
||||||
code = bucket.code
|
|
||||||
|
|
||||||
# if we don't have code so far (not cached, no longer up to
|
|
||||||
# date) etc. we compile the template
|
|
||||||
if code is None:
|
|
||||||
code = environment.compile(source, name, filename)
|
|
||||||
|
|
||||||
# if the bytecode cache is available and the bucket doesn't
|
|
||||||
# have a code so far, we give the bucket the new code and put
|
|
||||||
# it back to the bytecode cache.
|
|
||||||
if bcc is not None and bucket.code is None:
|
|
||||||
bucket.code = code
|
|
||||||
bcc.set_bucket(bucket)
|
|
||||||
|
|
||||||
return environment.template_class.from_code(environment, code,
|
|
||||||
globals, uptodate)
|
|
||||||
|
|
||||||
|
|
||||||
class FileSystemLoader(BaseLoader):
|
|
||||||
"""Loads templates from the file system. This loader can find templates
|
|
||||||
in folders on the file system and is the preferred way to load them.
|
|
||||||
|
|
||||||
The loader takes the path to the templates as string, or if multiple
|
|
||||||
locations are wanted a list of them which is then looked up in the
|
|
||||||
given order:
|
|
||||||
|
|
||||||
>>> loader = FileSystemLoader('/path/to/templates')
|
|
||||||
>>> loader = FileSystemLoader(['/path/to/templates', '/other/path'])
|
|
||||||
|
|
||||||
Per default the template encoding is ``'utf-8'`` which can be changed
|
|
||||||
by setting the `encoding` parameter to something else.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, searchpath, encoding='utf-8'):
|
|
||||||
if isinstance(searchpath, string_types):
|
|
||||||
searchpath = [searchpath]
|
|
||||||
self.searchpath = list(searchpath)
|
|
||||||
self.encoding = encoding
|
|
||||||
|
|
||||||
def get_source(self, environment, template):
|
|
||||||
pieces = split_template_path(template)
|
|
||||||
for searchpath in self.searchpath:
|
|
||||||
filename = path.join(searchpath, *pieces)
|
|
||||||
f = open_if_exists(filename)
|
|
||||||
if f is None:
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
contents = f.read().decode(self.encoding)
|
|
||||||
finally:
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
mtime = path.getmtime(filename)
|
|
||||||
def uptodate():
|
|
||||||
try:
|
|
||||||
return path.getmtime(filename) == mtime
|
|
||||||
except OSError:
|
|
||||||
return False
|
|
||||||
return contents, filename, uptodate
|
|
||||||
raise TemplateNotFound(template)
|
|
||||||
|
|
||||||
def list_templates(self):
|
|
||||||
found = set()
|
|
||||||
for searchpath in self.searchpath:
|
|
||||||
for dirpath, dirnames, filenames in os.walk(searchpath):
|
|
||||||
for filename in filenames:
|
|
||||||
template = os.path.join(dirpath, filename) \
|
|
||||||
[len(searchpath):].strip(os.path.sep) \
|
|
||||||
.replace(os.path.sep, '/')
|
|
||||||
if template[:2] == './':
|
|
||||||
template = template[2:]
|
|
||||||
if template not in found:
|
|
||||||
found.add(template)
|
|
||||||
return sorted(found)
|
|
||||||
|
|
||||||
|
|
||||||
class PackageLoader(BaseLoader):
|
|
||||||
"""Load templates from python eggs or packages. It is constructed with
|
|
||||||
the name of the python package and the path to the templates in that
|
|
||||||
package::
|
|
||||||
|
|
||||||
loader = PackageLoader('mypackage', 'views')
|
|
||||||
|
|
||||||
If the package path is not given, ``'templates'`` is assumed.
|
|
||||||
|
|
||||||
Per default the template encoding is ``'utf-8'`` which can be changed
|
|
||||||
by setting the `encoding` parameter to something else. Due to the nature
|
|
||||||
of eggs it's only possible to reload templates if the package was loaded
|
|
||||||
from the file system and not a zip file.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, package_name, package_path='templates',
|
|
||||||
encoding='utf-8'):
|
|
||||||
from pkg_resources import DefaultProvider, ResourceManager, \
|
|
||||||
get_provider
|
|
||||||
provider = get_provider(package_name)
|
|
||||||
self.encoding = encoding
|
|
||||||
self.manager = ResourceManager()
|
|
||||||
self.filesystem_bound = isinstance(provider, DefaultProvider)
|
|
||||||
self.provider = provider
|
|
||||||
self.package_path = package_path
|
|
||||||
|
|
||||||
def get_source(self, environment, template):
|
|
||||||
pieces = split_template_path(template)
|
|
||||||
p = '/'.join((self.package_path,) + tuple(pieces))
|
|
||||||
if not self.provider.has_resource(p):
|
|
||||||
raise TemplateNotFound(template)
|
|
||||||
|
|
||||||
filename = uptodate = None
|
|
||||||
if self.filesystem_bound:
|
|
||||||
filename = self.provider.get_resource_filename(self.manager, p)
|
|
||||||
mtime = path.getmtime(filename)
|
|
||||||
def uptodate():
|
|
||||||
try:
|
|
||||||
return path.getmtime(filename) == mtime
|
|
||||||
except OSError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
source = self.provider.get_resource_string(self.manager, p)
|
|
||||||
return source.decode(self.encoding), filename, uptodate
|
|
||||||
|
|
||||||
def list_templates(self):
|
|
||||||
path = self.package_path
|
|
||||||
if path[:2] == './':
|
|
||||||
path = path[2:]
|
|
||||||
elif path == '.':
|
|
||||||
path = ''
|
|
||||||
offset = len(path)
|
|
||||||
results = []
|
|
||||||
def _walk(path):
|
|
||||||
for filename in self.provider.resource_listdir(path):
|
|
||||||
fullname = path + '/' + filename
|
|
||||||
if self.provider.resource_isdir(fullname):
|
|
||||||
_walk(fullname)
|
|
||||||
else:
|
|
||||||
results.append(fullname[offset:].lstrip('/'))
|
|
||||||
_walk(path)
|
|
||||||
results.sort()
|
|
||||||
return results
|
|
||||||
|
|
||||||
|
|
||||||
class DictLoader(BaseLoader):
|
|
||||||
"""Loads a template from a python dict. It's passed a dict of unicode
|
|
||||||
strings bound to template names. This loader is useful for unittesting:
|
|
||||||
|
|
||||||
>>> loader = DictLoader({'index.html': 'source here'})
|
|
||||||
|
|
||||||
Because auto reloading is rarely useful this is disabled per default.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, mapping):
|
|
||||||
self.mapping = mapping
|
|
||||||
|
|
||||||
def get_source(self, environment, template):
|
|
||||||
if template in self.mapping:
|
|
||||||
source = self.mapping[template]
|
|
||||||
return source, None, lambda: source == self.mapping.get(template)
|
|
||||||
raise TemplateNotFound(template)
|
|
||||||
|
|
||||||
def list_templates(self):
|
|
||||||
return sorted(self.mapping)
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionLoader(BaseLoader):
|
|
||||||
"""A loader that is passed a function which does the loading. The
|
|
||||||
function becomes the name of the template passed and has to return either
|
|
||||||
an unicode string with the template source, a tuple in the form ``(source,
|
|
||||||
filename, uptodatefunc)`` or `None` if the template does not exist.
|
|
||||||
|
|
||||||
>>> def load_template(name):
|
|
||||||
... if name == 'index.html':
|
|
||||||
... return '...'
|
|
||||||
...
|
|
||||||
>>> loader = FunctionLoader(load_template)
|
|
||||||
|
|
||||||
The `uptodatefunc` is a function that is called if autoreload is enabled
|
|
||||||
and has to return `True` if the template is still up to date. For more
|
|
||||||
details have a look at :meth:`BaseLoader.get_source` which has the same
|
|
||||||
return value.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, load_func):
|
|
||||||
self.load_func = load_func
|
|
||||||
|
|
||||||
def get_source(self, environment, template):
|
|
||||||
rv = self.load_func(template)
|
|
||||||
if rv is None:
|
|
||||||
raise TemplateNotFound(template)
|
|
||||||
elif isinstance(rv, string_types):
|
|
||||||
return rv, None, None
|
|
||||||
return rv
|
|
||||||
|
|
||||||
|
|
||||||
class PrefixLoader(BaseLoader):
|
|
||||||
"""A loader that is passed a dict of loaders where each loader is bound
|
|
||||||
to a prefix. The prefix is delimited from the template by a slash per
|
|
||||||
default, which can be changed by setting the `delimiter` argument to
|
|
||||||
something else::
|
|
||||||
|
|
||||||
loader = PrefixLoader({
|
|
||||||
'app1': PackageLoader('mypackage.app1'),
|
|
||||||
'app2': PackageLoader('mypackage.app2')
|
|
||||||
})
|
|
||||||
|
|
||||||
By loading ``'app1/index.html'`` the file from the app1 package is loaded,
|
|
||||||
by loading ``'app2/index.html'`` the file from the second.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, mapping, delimiter='/'):
|
|
||||||
self.mapping = mapping
|
|
||||||
self.delimiter = delimiter
|
|
||||||
|
|
||||||
def get_loader(self, template):
|
|
||||||
try:
|
|
||||||
prefix, name = template.split(self.delimiter, 1)
|
|
||||||
loader = self.mapping[prefix]
|
|
||||||
except (ValueError, KeyError):
|
|
||||||
raise TemplateNotFound(template)
|
|
||||||
return loader, name
|
|
||||||
|
|
||||||
def get_source(self, environment, template):
|
|
||||||
loader, name = self.get_loader(template)
|
|
||||||
try:
|
|
||||||
return loader.get_source(environment, name)
|
|
||||||
except TemplateNotFound:
|
|
||||||
# re-raise the exception with the correct fileame here.
|
|
||||||
# (the one that includes the prefix)
|
|
||||||
raise TemplateNotFound(template)
|
|
||||||
|
|
||||||
@internalcode
|
|
||||||
def load(self, environment, name, globals=None):
|
|
||||||
loader, local_name = self.get_loader(name)
|
|
||||||
try:
|
|
||||||
return loader.load(environment, local_name)
|
|
||||||
except TemplateNotFound:
|
|
||||||
# re-raise the exception with the correct fileame here.
|
|
||||||
# (the one that includes the prefix)
|
|
||||||
raise TemplateNotFound(name)
|
|
||||||
|
|
||||||
def list_templates(self):
|
|
||||||
result = []
|
|
||||||
for prefix, loader in iteritems(self.mapping):
|
|
||||||
for template in loader.list_templates():
|
|
||||||
result.append(prefix + self.delimiter + template)
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
class ChoiceLoader(BaseLoader):
|
|
||||||
"""This loader works like the `PrefixLoader` just that no prefix is
|
|
||||||
specified. If a template could not be found by one loader the next one
|
|
||||||
is tried.
|
|
||||||
|
|
||||||
>>> loader = ChoiceLoader([
|
|
||||||
... FileSystemLoader('/path/to/user/templates'),
|
|
||||||
... FileSystemLoader('/path/to/system/templates')
|
|
||||||
... ])
|
|
||||||
|
|
||||||
This is useful if you want to allow users to override builtin templates
|
|
||||||
from a different location.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, loaders):
|
|
||||||
self.loaders = loaders
|
|
||||||
|
|
||||||
def get_source(self, environment, template):
|
|
||||||
for loader in self.loaders:
|
|
||||||
try:
|
|
||||||
return loader.get_source(environment, template)
|
|
||||||
except TemplateNotFound:
|
|
||||||
pass
|
|
||||||
raise TemplateNotFound(template)
|
|
||||||
|
|
||||||
@internalcode
|
|
||||||
def load(self, environment, name, globals=None):
|
|
||||||
for loader in self.loaders:
|
|
||||||
try:
|
|
||||||
return loader.load(environment, name, globals)
|
|
||||||
except TemplateNotFound:
|
|
||||||
pass
|
|
||||||
raise TemplateNotFound(name)
|
|
||||||
|
|
||||||
def list_templates(self):
|
|
||||||
found = set()
|
|
||||||
for loader in self.loaders:
|
|
||||||
found.update(loader.list_templates())
|
|
||||||
return sorted(found)
|
|
||||||
|
|
||||||
|
|
||||||
class _TemplateModule(ModuleType):
|
|
||||||
"""Like a normal module but with support for weak references"""
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleLoader(BaseLoader):
|
|
||||||
"""This loader loads templates from precompiled templates.
|
|
||||||
|
|
||||||
Example usage:
|
|
||||||
|
|
||||||
>>> loader = ChoiceLoader([
|
|
||||||
... ModuleLoader('/path/to/compiled/templates'),
|
|
||||||
... FileSystemLoader('/path/to/templates')
|
|
||||||
... ])
|
|
||||||
|
|
||||||
Templates can be precompiled with :meth:`Environment.compile_templates`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
has_source_access = False
|
|
||||||
|
|
||||||
def __init__(self, path):
|
|
||||||
package_name = '_jinja2_module_templates_%x' % id(self)
|
|
||||||
|
|
||||||
# create a fake module that looks for the templates in the
|
|
||||||
# path given.
|
|
||||||
mod = _TemplateModule(package_name)
|
|
||||||
if isinstance(path, string_types):
|
|
||||||
path = [path]
|
|
||||||
else:
|
|
||||||
path = list(path)
|
|
||||||
mod.__path__ = path
|
|
||||||
|
|
||||||
sys.modules[package_name] = weakref.proxy(mod,
|
|
||||||
lambda x: sys.modules.pop(package_name, None))
|
|
||||||
|
|
||||||
# the only strong reference, the sys.modules entry is weak
|
|
||||||
# so that the garbage collector can remove it once the
|
|
||||||
# loader that created it goes out of business.
|
|
||||||
self.module = mod
|
|
||||||
self.package_name = package_name
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_template_key(name):
|
|
||||||
return 'tmpl_' + sha1(name.encode('utf-8')).hexdigest()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_module_filename(name):
|
|
||||||
return ModuleLoader.get_template_key(name) + '.py'
|
|
||||||
|
|
||||||
@internalcode
|
|
||||||
def load(self, environment, name, globals=None):
|
|
||||||
key = self.get_template_key(name)
|
|
||||||
module = '%s.%s' % (self.package_name, key)
|
|
||||||
mod = getattr(self.module, module, None)
|
|
||||||
if mod is None:
|
|
||||||
try:
|
|
||||||
mod = __import__(module, None, None, ['root'])
|
|
||||||
except ImportError:
|
|
||||||
raise TemplateNotFound(name)
|
|
||||||
|
|
||||||
# remove the entry from sys.modules, we only want the attribute
|
|
||||||
# on the module object we have stored on the loader.
|
|
||||||
sys.modules.pop(module, None)
|
|
||||||
|
|
||||||
return environment.template_class.from_module_dict(
|
|
||||||
environment, mod.__dict__, globals)
|
|
||||||
-234
@@ -1,234 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
markupsafe
|
|
||||||
~~~~~~~~~~
|
|
||||||
|
|
||||||
Implements a Markup string.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by Armin Ronacher.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
import re
|
|
||||||
from ._compat import text_type, string_types, int_types, \
|
|
||||||
unichr, PY2
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['Markup', 'soft_unicode', 'escape', 'escape_silent']
|
|
||||||
|
|
||||||
|
|
||||||
_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
|
|
||||||
_entity_re = re.compile(r'&([^;]+);')
|
|
||||||
|
|
||||||
|
|
||||||
class Markup(text_type):
|
|
||||||
r"""Marks a string as being safe for inclusion in HTML/XML output without
|
|
||||||
needing to be escaped. This implements the `__html__` interface a couple
|
|
||||||
of frameworks and web applications use. :class:`Markup` is a direct
|
|
||||||
subclass of `unicode` and provides all the methods of `unicode` just that
|
|
||||||
it escapes arguments passed and always returns `Markup`.
|
|
||||||
|
|
||||||
The `escape` function returns markup objects so that double escaping can't
|
|
||||||
happen.
|
|
||||||
|
|
||||||
The constructor of the :class:`Markup` class can be used for three
|
|
||||||
different things: When passed an unicode object it's assumed to be safe,
|
|
||||||
when passed an object with an HTML representation (has an `__html__`
|
|
||||||
method) that representation is used, otherwise the object passed is
|
|
||||||
converted into a unicode string and then assumed to be safe:
|
|
||||||
|
|
||||||
>>> Markup("Hello <em>World</em>!")
|
|
||||||
Markup(u'Hello <em>World</em>!')
|
|
||||||
>>> class Foo(object):
|
|
||||||
... def __html__(self):
|
|
||||||
... return '<a href="#">foo</a>'
|
|
||||||
...
|
|
||||||
>>> Markup(Foo())
|
|
||||||
Markup(u'<a href="#">foo</a>')
|
|
||||||
|
|
||||||
If you want object passed being always treated as unsafe you can use the
|
|
||||||
:meth:`escape` classmethod to create a :class:`Markup` object:
|
|
||||||
|
|
||||||
>>> Markup.escape("Hello <em>World</em>!")
|
|
||||||
Markup(u'Hello <em>World</em>!')
|
|
||||||
|
|
||||||
Operations on a markup string are markup aware which means that all
|
|
||||||
arguments are passed through the :func:`escape` function:
|
|
||||||
|
|
||||||
>>> em = Markup("<em>%s</em>")
|
|
||||||
>>> em % "foo & bar"
|
|
||||||
Markup(u'<em>foo & bar</em>')
|
|
||||||
>>> strong = Markup("<strong>%(text)s</strong>")
|
|
||||||
>>> strong % {'text': '<blink>hacker here</blink>'}
|
|
||||||
Markup(u'<strong><blink>hacker here</blink></strong>')
|
|
||||||
>>> Markup("<em>Hello</em> ") + "<foo>"
|
|
||||||
Markup(u'<em>Hello</em> <foo>')
|
|
||||||
"""
|
|
||||||
__slots__ = ()
|
|
||||||
|
|
||||||
def __new__(cls, base=u'', encoding=None, errors='strict'):
|
|
||||||
if hasattr(base, '__html__'):
|
|
||||||
base = base.__html__()
|
|
||||||
if encoding is None:
|
|
||||||
return text_type.__new__(cls, base)
|
|
||||||
return text_type.__new__(cls, base, encoding, errors)
|
|
||||||
|
|
||||||
def __html__(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __add__(self, other):
|
|
||||||
if isinstance(other, string_types) or hasattr(other, '__html__'):
|
|
||||||
return self.__class__(super(Markup, self).__add__(self.escape(other)))
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
def __radd__(self, other):
|
|
||||||
if hasattr(other, '__html__') or isinstance(other, string_types):
|
|
||||||
return self.escape(other).__add__(self)
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
def __mul__(self, num):
|
|
||||||
if isinstance(num, int_types):
|
|
||||||
return self.__class__(text_type.__mul__(self, num))
|
|
||||||
return NotImplemented
|
|
||||||
__rmul__ = __mul__
|
|
||||||
|
|
||||||
def __mod__(self, arg):
|
|
||||||
if isinstance(arg, tuple):
|
|
||||||
arg = tuple(_MarkupEscapeHelper(x, self.escape) for x in arg)
|
|
||||||
else:
|
|
||||||
arg = _MarkupEscapeHelper(arg, self.escape)
|
|
||||||
return self.__class__(text_type.__mod__(self, arg))
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return '%s(%s)' % (
|
|
||||||
self.__class__.__name__,
|
|
||||||
text_type.__repr__(self)
|
|
||||||
)
|
|
||||||
|
|
||||||
def join(self, seq):
|
|
||||||
return self.__class__(text_type.join(self, map(self.escape, seq)))
|
|
||||||
join.__doc__ = text_type.join.__doc__
|
|
||||||
|
|
||||||
def split(self, *args, **kwargs):
|
|
||||||
return list(map(self.__class__, text_type.split(self, *args, **kwargs)))
|
|
||||||
split.__doc__ = text_type.split.__doc__
|
|
||||||
|
|
||||||
def rsplit(self, *args, **kwargs):
|
|
||||||
return list(map(self.__class__, text_type.rsplit(self, *args, **kwargs)))
|
|
||||||
rsplit.__doc__ = text_type.rsplit.__doc__
|
|
||||||
|
|
||||||
def splitlines(self, *args, **kwargs):
|
|
||||||
return list(map(self.__class__, text_type.splitlines(self, *args, **kwargs)))
|
|
||||||
splitlines.__doc__ = text_type.splitlines.__doc__
|
|
||||||
|
|
||||||
def unescape(self):
|
|
||||||
r"""Unescape markup again into an text_type string. This also resolves
|
|
||||||
known HTML4 and XHTML entities:
|
|
||||||
|
|
||||||
>>> Markup("Main » <em>About</em>").unescape()
|
|
||||||
u'Main \xbb <em>About</em>'
|
|
||||||
"""
|
|
||||||
from _constants import HTML_ENTITIES
|
|
||||||
def handle_match(m):
|
|
||||||
name = m.group(1)
|
|
||||||
if name in HTML_ENTITIES:
|
|
||||||
return unichr(HTML_ENTITIES[name])
|
|
||||||
try:
|
|
||||||
if name[:2] in ('#x', '#X'):
|
|
||||||
return unichr(int(name[2:], 16))
|
|
||||||
elif name.startswith('#'):
|
|
||||||
return unichr(int(name[1:]))
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
return u''
|
|
||||||
return _entity_re.sub(handle_match, text_type(self))
|
|
||||||
|
|
||||||
def striptags(self):
|
|
||||||
r"""Unescape markup into an text_type string and strip all tags. This
|
|
||||||
also resolves known HTML4 and XHTML entities. Whitespace is
|
|
||||||
normalized to one:
|
|
||||||
|
|
||||||
>>> Markup("Main » <em>About</em>").striptags()
|
|
||||||
u'Main \xbb About'
|
|
||||||
"""
|
|
||||||
stripped = u' '.join(_striptags_re.sub('', self).split())
|
|
||||||
return Markup(stripped).unescape()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def escape(cls, s):
|
|
||||||
"""Escape the string. Works like :func:`escape` with the difference
|
|
||||||
that for subclasses of :class:`Markup` this function would return the
|
|
||||||
correct subclass.
|
|
||||||
"""
|
|
||||||
rv = escape(s)
|
|
||||||
if rv.__class__ is not cls:
|
|
||||||
return cls(rv)
|
|
||||||
return rv
|
|
||||||
|
|
||||||
def make_wrapper(name):
|
|
||||||
orig = getattr(text_type, name)
|
|
||||||
def func(self, *args, **kwargs):
|
|
||||||
args = _escape_argspec(list(args), enumerate(args), self.escape)
|
|
||||||
#_escape_argspec(kwargs, kwargs.iteritems(), None)
|
|
||||||
return self.__class__(orig(self, *args, **kwargs))
|
|
||||||
func.__name__ = orig.__name__
|
|
||||||
func.__doc__ = orig.__doc__
|
|
||||||
return func
|
|
||||||
|
|
||||||
for method in '__getitem__', 'capitalize', \
|
|
||||||
'title', 'lower', 'upper', 'replace', 'ljust', \
|
|
||||||
'rjust', 'lstrip', 'rstrip', 'center', 'strip', \
|
|
||||||
'translate', 'expandtabs', 'swapcase', 'zfill':
|
|
||||||
locals()[method] = make_wrapper(method)
|
|
||||||
|
|
||||||
# new in python 2.5
|
|
||||||
if hasattr(text_type, 'partition'):
|
|
||||||
def partition(self, sep):
|
|
||||||
return tuple(map(self.__class__,
|
|
||||||
text_type.partition(self, self.escape(sep))))
|
|
||||||
def rpartition(self, sep):
|
|
||||||
return tuple(map(self.__class__,
|
|
||||||
text_type.rpartition(self, self.escape(sep))))
|
|
||||||
|
|
||||||
# new in python 2.6
|
|
||||||
if hasattr(text_type, 'format'):
|
|
||||||
format = make_wrapper('format')
|
|
||||||
|
|
||||||
# not in python 3
|
|
||||||
if hasattr(text_type, '__getslice__'):
|
|
||||||
__getslice__ = make_wrapper('__getslice__')
|
|
||||||
|
|
||||||
del method, make_wrapper
|
|
||||||
|
|
||||||
|
|
||||||
def _escape_argspec(obj, iterable, escape):
|
|
||||||
"""Helper for various string-wrapped functions."""
|
|
||||||
for key, value in iterable:
|
|
||||||
if hasattr(value, '__html__') or isinstance(value, string_types):
|
|
||||||
obj[key] = escape(value)
|
|
||||||
return obj
|
|
||||||
|
|
||||||
|
|
||||||
class _MarkupEscapeHelper(object):
|
|
||||||
"""Helper for Markup.__mod__"""
|
|
||||||
|
|
||||||
def __init__(self, obj, escape):
|
|
||||||
self.obj = obj
|
|
||||||
self.escape = escape
|
|
||||||
|
|
||||||
__getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x], s.escape)
|
|
||||||
__unicode__ = __str__ = lambda s: text_type(s.escape(s.obj))
|
|
||||||
__repr__ = lambda s: str(s.escape(repr(s.obj)))
|
|
||||||
__int__ = lambda s: int(s.obj)
|
|
||||||
__float__ = lambda s: float(s.obj)
|
|
||||||
|
|
||||||
|
|
||||||
# we have to import it down here as the speedups and native
|
|
||||||
# modules imports the markup type which is define above.
|
|
||||||
try:
|
|
||||||
from _speedups import escape, escape_silent, soft_unicode
|
|
||||||
except ImportError:
|
|
||||||
from ._native import escape, escape_silent, soft_unicode
|
|
||||||
|
|
||||||
if not PY2:
|
|
||||||
soft_str = soft_unicode
|
|
||||||
__all__.append('soft_str')
|
|
||||||
-24
@@ -1,24 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
markupsafe._compat
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Compatibility module for different Python versions.
|
|
||||||
|
|
||||||
:copyright: (c) 2013 by Armin Ronacher.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
import sys
|
|
||||||
|
|
||||||
PY2 = sys.version_info[0] == 2
|
|
||||||
|
|
||||||
if not PY2:
|
|
||||||
text_type = str
|
|
||||||
string_types = (str,)
|
|
||||||
unichr = chr
|
|
||||||
int_types = (int,)
|
|
||||||
else:
|
|
||||||
text_type = unicode
|
|
||||||
string_types = (str, unicode)
|
|
||||||
unichr = unichr
|
|
||||||
int_types = (int, long)
|
|
||||||
-267
@@ -1,267 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
markupsafe._constants
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Highlevel implementation of the Markup string.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by Armin Ronacher.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
HTML_ENTITIES = {
|
|
||||||
'AElig': 198,
|
|
||||||
'Aacute': 193,
|
|
||||||
'Acirc': 194,
|
|
||||||
'Agrave': 192,
|
|
||||||
'Alpha': 913,
|
|
||||||
'Aring': 197,
|
|
||||||
'Atilde': 195,
|
|
||||||
'Auml': 196,
|
|
||||||
'Beta': 914,
|
|
||||||
'Ccedil': 199,
|
|
||||||
'Chi': 935,
|
|
||||||
'Dagger': 8225,
|
|
||||||
'Delta': 916,
|
|
||||||
'ETH': 208,
|
|
||||||
'Eacute': 201,
|
|
||||||
'Ecirc': 202,
|
|
||||||
'Egrave': 200,
|
|
||||||
'Epsilon': 917,
|
|
||||||
'Eta': 919,
|
|
||||||
'Euml': 203,
|
|
||||||
'Gamma': 915,
|
|
||||||
'Iacute': 205,
|
|
||||||
'Icirc': 206,
|
|
||||||
'Igrave': 204,
|
|
||||||
'Iota': 921,
|
|
||||||
'Iuml': 207,
|
|
||||||
'Kappa': 922,
|
|
||||||
'Lambda': 923,
|
|
||||||
'Mu': 924,
|
|
||||||
'Ntilde': 209,
|
|
||||||
'Nu': 925,
|
|
||||||
'OElig': 338,
|
|
||||||
'Oacute': 211,
|
|
||||||
'Ocirc': 212,
|
|
||||||
'Ograve': 210,
|
|
||||||
'Omega': 937,
|
|
||||||
'Omicron': 927,
|
|
||||||
'Oslash': 216,
|
|
||||||
'Otilde': 213,
|
|
||||||
'Ouml': 214,
|
|
||||||
'Phi': 934,
|
|
||||||
'Pi': 928,
|
|
||||||
'Prime': 8243,
|
|
||||||
'Psi': 936,
|
|
||||||
'Rho': 929,
|
|
||||||
'Scaron': 352,
|
|
||||||
'Sigma': 931,
|
|
||||||
'THORN': 222,
|
|
||||||
'Tau': 932,
|
|
||||||
'Theta': 920,
|
|
||||||
'Uacute': 218,
|
|
||||||
'Ucirc': 219,
|
|
||||||
'Ugrave': 217,
|
|
||||||
'Upsilon': 933,
|
|
||||||
'Uuml': 220,
|
|
||||||
'Xi': 926,
|
|
||||||
'Yacute': 221,
|
|
||||||
'Yuml': 376,
|
|
||||||
'Zeta': 918,
|
|
||||||
'aacute': 225,
|
|
||||||
'acirc': 226,
|
|
||||||
'acute': 180,
|
|
||||||
'aelig': 230,
|
|
||||||
'agrave': 224,
|
|
||||||
'alefsym': 8501,
|
|
||||||
'alpha': 945,
|
|
||||||
'amp': 38,
|
|
||||||
'and': 8743,
|
|
||||||
'ang': 8736,
|
|
||||||
'apos': 39,
|
|
||||||
'aring': 229,
|
|
||||||
'asymp': 8776,
|
|
||||||
'atilde': 227,
|
|
||||||
'auml': 228,
|
|
||||||
'bdquo': 8222,
|
|
||||||
'beta': 946,
|
|
||||||
'brvbar': 166,
|
|
||||||
'bull': 8226,
|
|
||||||
'cap': 8745,
|
|
||||||
'ccedil': 231,
|
|
||||||
'cedil': 184,
|
|
||||||
'cent': 162,
|
|
||||||
'chi': 967,
|
|
||||||
'circ': 710,
|
|
||||||
'clubs': 9827,
|
|
||||||
'cong': 8773,
|
|
||||||
'copy': 169,
|
|
||||||
'crarr': 8629,
|
|
||||||
'cup': 8746,
|
|
||||||
'curren': 164,
|
|
||||||
'dArr': 8659,
|
|
||||||
'dagger': 8224,
|
|
||||||
'darr': 8595,
|
|
||||||
'deg': 176,
|
|
||||||
'delta': 948,
|
|
||||||
'diams': 9830,
|
|
||||||
'divide': 247,
|
|
||||||
'eacute': 233,
|
|
||||||
'ecirc': 234,
|
|
||||||
'egrave': 232,
|
|
||||||
'empty': 8709,
|
|
||||||
'emsp': 8195,
|
|
||||||
'ensp': 8194,
|
|
||||||
'epsilon': 949,
|
|
||||||
'equiv': 8801,
|
|
||||||
'eta': 951,
|
|
||||||
'eth': 240,
|
|
||||||
'euml': 235,
|
|
||||||
'euro': 8364,
|
|
||||||
'exist': 8707,
|
|
||||||
'fnof': 402,
|
|
||||||
'forall': 8704,
|
|
||||||
'frac12': 189,
|
|
||||||
'frac14': 188,
|
|
||||||
'frac34': 190,
|
|
||||||
'frasl': 8260,
|
|
||||||
'gamma': 947,
|
|
||||||
'ge': 8805,
|
|
||||||
'gt': 62,
|
|
||||||
'hArr': 8660,
|
|
||||||
'harr': 8596,
|
|
||||||
'hearts': 9829,
|
|
||||||
'hellip': 8230,
|
|
||||||
'iacute': 237,
|
|
||||||
'icirc': 238,
|
|
||||||
'iexcl': 161,
|
|
||||||
'igrave': 236,
|
|
||||||
'image': 8465,
|
|
||||||
'infin': 8734,
|
|
||||||
'int': 8747,
|
|
||||||
'iota': 953,
|
|
||||||
'iquest': 191,
|
|
||||||
'isin': 8712,
|
|
||||||
'iuml': 239,
|
|
||||||
'kappa': 954,
|
|
||||||
'lArr': 8656,
|
|
||||||
'lambda': 955,
|
|
||||||
'lang': 9001,
|
|
||||||
'laquo': 171,
|
|
||||||
'larr': 8592,
|
|
||||||
'lceil': 8968,
|
|
||||||
'ldquo': 8220,
|
|
||||||
'le': 8804,
|
|
||||||
'lfloor': 8970,
|
|
||||||
'lowast': 8727,
|
|
||||||
'loz': 9674,
|
|
||||||
'lrm': 8206,
|
|
||||||
'lsaquo': 8249,
|
|
||||||
'lsquo': 8216,
|
|
||||||
'lt': 60,
|
|
||||||
'macr': 175,
|
|
||||||
'mdash': 8212,
|
|
||||||
'micro': 181,
|
|
||||||
'middot': 183,
|
|
||||||
'minus': 8722,
|
|
||||||
'mu': 956,
|
|
||||||
'nabla': 8711,
|
|
||||||
'nbsp': 160,
|
|
||||||
'ndash': 8211,
|
|
||||||
'ne': 8800,
|
|
||||||
'ni': 8715,
|
|
||||||
'not': 172,
|
|
||||||
'notin': 8713,
|
|
||||||
'nsub': 8836,
|
|
||||||
'ntilde': 241,
|
|
||||||
'nu': 957,
|
|
||||||
'oacute': 243,
|
|
||||||
'ocirc': 244,
|
|
||||||
'oelig': 339,
|
|
||||||
'ograve': 242,
|
|
||||||
'oline': 8254,
|
|
||||||
'omega': 969,
|
|
||||||
'omicron': 959,
|
|
||||||
'oplus': 8853,
|
|
||||||
'or': 8744,
|
|
||||||
'ordf': 170,
|
|
||||||
'ordm': 186,
|
|
||||||
'oslash': 248,
|
|
||||||
'otilde': 245,
|
|
||||||
'otimes': 8855,
|
|
||||||
'ouml': 246,
|
|
||||||
'para': 182,
|
|
||||||
'part': 8706,
|
|
||||||
'permil': 8240,
|
|
||||||
'perp': 8869,
|
|
||||||
'phi': 966,
|
|
||||||
'pi': 960,
|
|
||||||
'piv': 982,
|
|
||||||
'plusmn': 177,
|
|
||||||
'pound': 163,
|
|
||||||
'prime': 8242,
|
|
||||||
'prod': 8719,
|
|
||||||
'prop': 8733,
|
|
||||||
'psi': 968,
|
|
||||||
'quot': 34,
|
|
||||||
'rArr': 8658,
|
|
||||||
'radic': 8730,
|
|
||||||
'rang': 9002,
|
|
||||||
'raquo': 187,
|
|
||||||
'rarr': 8594,
|
|
||||||
'rceil': 8969,
|
|
||||||
'rdquo': 8221,
|
|
||||||
'real': 8476,
|
|
||||||
'reg': 174,
|
|
||||||
'rfloor': 8971,
|
|
||||||
'rho': 961,
|
|
||||||
'rlm': 8207,
|
|
||||||
'rsaquo': 8250,
|
|
||||||
'rsquo': 8217,
|
|
||||||
'sbquo': 8218,
|
|
||||||
'scaron': 353,
|
|
||||||
'sdot': 8901,
|
|
||||||
'sect': 167,
|
|
||||||
'shy': 173,
|
|
||||||
'sigma': 963,
|
|
||||||
'sigmaf': 962,
|
|
||||||
'sim': 8764,
|
|
||||||
'spades': 9824,
|
|
||||||
'sub': 8834,
|
|
||||||
'sube': 8838,
|
|
||||||
'sum': 8721,
|
|
||||||
'sup': 8835,
|
|
||||||
'sup1': 185,
|
|
||||||
'sup2': 178,
|
|
||||||
'sup3': 179,
|
|
||||||
'supe': 8839,
|
|
||||||
'szlig': 223,
|
|
||||||
'tau': 964,
|
|
||||||
'there4': 8756,
|
|
||||||
'theta': 952,
|
|
||||||
'thetasym': 977,
|
|
||||||
'thinsp': 8201,
|
|
||||||
'thorn': 254,
|
|
||||||
'tilde': 732,
|
|
||||||
'times': 215,
|
|
||||||
'trade': 8482,
|
|
||||||
'uArr': 8657,
|
|
||||||
'uacute': 250,
|
|
||||||
'uarr': 8593,
|
|
||||||
'ucirc': 251,
|
|
||||||
'ugrave': 249,
|
|
||||||
'uml': 168,
|
|
||||||
'upsih': 978,
|
|
||||||
'upsilon': 965,
|
|
||||||
'uuml': 252,
|
|
||||||
'weierp': 8472,
|
|
||||||
'xi': 958,
|
|
||||||
'yacute': 253,
|
|
||||||
'yen': 165,
|
|
||||||
'yuml': 255,
|
|
||||||
'zeta': 950,
|
|
||||||
'zwj': 8205,
|
|
||||||
'zwnj': 8204
|
|
||||||
}
|
|
||||||
-45
@@ -1,45 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
markupsafe._native
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Native Python implementation the C module is not compiled.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by Armin Ronacher.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
from ._compat import text_type
|
|
||||||
|
|
||||||
|
|
||||||
def escape(s):
|
|
||||||
"""Convert the characters &, <, >, ' and " in string s to HTML-safe
|
|
||||||
sequences. Use this if you need to display text that might contain
|
|
||||||
such characters in HTML. Marks return value as markup string.
|
|
||||||
"""
|
|
||||||
if hasattr(s, '__html__'):
|
|
||||||
return s.__html__()
|
|
||||||
return Markup(text_type(s)
|
|
||||||
.replace('&', '&')
|
|
||||||
.replace('>', '>')
|
|
||||||
.replace('<', '<')
|
|
||||||
.replace("'", ''')
|
|
||||||
.replace('"', '"')
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def escape_silent(s):
|
|
||||||
"""Like :func:`escape` but converts `None` into an empty
|
|
||||||
markup string.
|
|
||||||
"""
|
|
||||||
if s is None:
|
|
||||||
return Markup()
|
|
||||||
return escape(s)
|
|
||||||
|
|
||||||
|
|
||||||
def soft_unicode(s):
|
|
||||||
"""Make a string unicode if it isn't already. That way a markup
|
|
||||||
string is not converted back to unicode.
|
|
||||||
"""
|
|
||||||
if not isinstance(s, text_type):
|
|
||||||
s = text_type(s)
|
|
||||||
return s
|
|
||||||
Vendored
-103
@@ -1,103 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.meta
|
|
||||||
~~~~~~~~~~~
|
|
||||||
|
|
||||||
This module implements various functions that exposes information about
|
|
||||||
templates that might be interesting for various kinds of applications.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team, see AUTHORS for more details.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
from jinja2 import nodes
|
|
||||||
from jinja2.compiler import CodeGenerator
|
|
||||||
from jinja2._compat import string_types
|
|
||||||
|
|
||||||
|
|
||||||
class TrackingCodeGenerator(CodeGenerator):
|
|
||||||
"""We abuse the code generator for introspection."""
|
|
||||||
|
|
||||||
def __init__(self, environment):
|
|
||||||
CodeGenerator.__init__(self, environment, '<introspection>',
|
|
||||||
'<introspection>')
|
|
||||||
self.undeclared_identifiers = set()
|
|
||||||
|
|
||||||
def write(self, x):
|
|
||||||
"""Don't write."""
|
|
||||||
|
|
||||||
def pull_locals(self, frame):
|
|
||||||
"""Remember all undeclared identifiers."""
|
|
||||||
self.undeclared_identifiers.update(frame.identifiers.undeclared)
|
|
||||||
|
|
||||||
|
|
||||||
def find_undeclared_variables(ast):
|
|
||||||
"""Returns a set of all variables in the AST that will be looked up from
|
|
||||||
the context at runtime. Because at compile time it's not known which
|
|
||||||
variables will be used depending on the path the execution takes at
|
|
||||||
runtime, all variables are returned.
|
|
||||||
|
|
||||||
>>> from jinja2 import Environment, meta
|
|
||||||
>>> env = Environment()
|
|
||||||
>>> ast = env.parse('{% set foo = 42 %}{{ bar + foo }}')
|
|
||||||
>>> meta.find_undeclared_variables(ast)
|
|
||||||
set(['bar'])
|
|
||||||
|
|
||||||
.. admonition:: Implementation
|
|
||||||
|
|
||||||
Internally the code generator is used for finding undeclared variables.
|
|
||||||
This is good to know because the code generator might raise a
|
|
||||||
:exc:`TemplateAssertionError` during compilation and as a matter of
|
|
||||||
fact this function can currently raise that exception as well.
|
|
||||||
"""
|
|
||||||
codegen = TrackingCodeGenerator(ast.environment)
|
|
||||||
codegen.visit(ast)
|
|
||||||
return codegen.undeclared_identifiers
|
|
||||||
|
|
||||||
|
|
||||||
def find_referenced_templates(ast):
|
|
||||||
"""Finds all the referenced templates from the AST. This will return an
|
|
||||||
iterator over all the hardcoded template extensions, inclusions and
|
|
||||||
imports. If dynamic inheritance or inclusion is used, `None` will be
|
|
||||||
yielded.
|
|
||||||
|
|
||||||
>>> from jinja2 import Environment, meta
|
|
||||||
>>> env = Environment()
|
|
||||||
>>> ast = env.parse('{% extends "layout.html" %}{% include helper %}')
|
|
||||||
>>> list(meta.find_referenced_templates(ast))
|
|
||||||
['layout.html', None]
|
|
||||||
|
|
||||||
This function is useful for dependency tracking. For example if you want
|
|
||||||
to rebuild parts of the website after a layout template has changed.
|
|
||||||
"""
|
|
||||||
for node in ast.find_all((nodes.Extends, nodes.FromImport, nodes.Import,
|
|
||||||
nodes.Include)):
|
|
||||||
if not isinstance(node.template, nodes.Const):
|
|
||||||
# a tuple with some non consts in there
|
|
||||||
if isinstance(node.template, (nodes.Tuple, nodes.List)):
|
|
||||||
for template_name in node.template.items:
|
|
||||||
# something const, only yield the strings and ignore
|
|
||||||
# non-string consts that really just make no sense
|
|
||||||
if isinstance(template_name, nodes.Const):
|
|
||||||
if isinstance(template_name.value, string_types):
|
|
||||||
yield template_name.value
|
|
||||||
# something dynamic in there
|
|
||||||
else:
|
|
||||||
yield None
|
|
||||||
# something dynamic we don't know about here
|
|
||||||
else:
|
|
||||||
yield None
|
|
||||||
continue
|
|
||||||
# constant is a basestring, direct template name
|
|
||||||
if isinstance(node.template.value, string_types):
|
|
||||||
yield node.template.value
|
|
||||||
# a tuple or list (latter *should* not happen) made of consts,
|
|
||||||
# yield the consts that are strings. We could warn here for
|
|
||||||
# non string values
|
|
||||||
elif isinstance(node, nodes.Include) and \
|
|
||||||
isinstance(node.template.value, (tuple, list)):
|
|
||||||
for template_name in node.template.value:
|
|
||||||
if isinstance(template_name, string_types):
|
|
||||||
yield template_name
|
|
||||||
# something else we don't care about, we could warn here
|
|
||||||
else:
|
|
||||||
yield None
|
|
||||||
Vendored
-914
@@ -1,914 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.nodes
|
|
||||||
~~~~~~~~~~~~
|
|
||||||
|
|
||||||
This module implements additional nodes derived from the ast base node.
|
|
||||||
|
|
||||||
It also provides some node tree helper functions like `in_lineno` and
|
|
||||||
`get_nodes` used by the parser and translator in order to normalize
|
|
||||||
python and jinja nodes.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
import operator
|
|
||||||
|
|
||||||
from collections import deque
|
|
||||||
from jinja2.utils import Markup
|
|
||||||
from jinja2._compat import next, izip, with_metaclass, text_type, \
|
|
||||||
method_type, function_type
|
|
||||||
|
|
||||||
|
|
||||||
#: the types we support for context functions
|
|
||||||
_context_function_types = (function_type, method_type)
|
|
||||||
|
|
||||||
|
|
||||||
_binop_to_func = {
|
|
||||||
'*': operator.mul,
|
|
||||||
'/': operator.truediv,
|
|
||||||
'//': operator.floordiv,
|
|
||||||
'**': operator.pow,
|
|
||||||
'%': operator.mod,
|
|
||||||
'+': operator.add,
|
|
||||||
'-': operator.sub
|
|
||||||
}
|
|
||||||
|
|
||||||
_uaop_to_func = {
|
|
||||||
'not': operator.not_,
|
|
||||||
'+': operator.pos,
|
|
||||||
'-': operator.neg
|
|
||||||
}
|
|
||||||
|
|
||||||
_cmpop_to_func = {
|
|
||||||
'eq': operator.eq,
|
|
||||||
'ne': operator.ne,
|
|
||||||
'gt': operator.gt,
|
|
||||||
'gteq': operator.ge,
|
|
||||||
'lt': operator.lt,
|
|
||||||
'lteq': operator.le,
|
|
||||||
'in': lambda a, b: a in b,
|
|
||||||
'notin': lambda a, b: a not in b
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class Impossible(Exception):
|
|
||||||
"""Raised if the node could not perform a requested action."""
|
|
||||||
|
|
||||||
|
|
||||||
class NodeType(type):
|
|
||||||
"""A metaclass for nodes that handles the field and attribute
|
|
||||||
inheritance. fields and attributes from the parent class are
|
|
||||||
automatically forwarded to the child."""
|
|
||||||
|
|
||||||
def __new__(cls, name, bases, d):
|
|
||||||
for attr in 'fields', 'attributes':
|
|
||||||
storage = []
|
|
||||||
storage.extend(getattr(bases[0], attr, ()))
|
|
||||||
storage.extend(d.get(attr, ()))
|
|
||||||
assert len(bases) == 1, 'multiple inheritance not allowed'
|
|
||||||
assert len(storage) == len(set(storage)), 'layout conflict'
|
|
||||||
d[attr] = tuple(storage)
|
|
||||||
d.setdefault('abstract', False)
|
|
||||||
return type.__new__(cls, name, bases, d)
|
|
||||||
|
|
||||||
|
|
||||||
class EvalContext(object):
|
|
||||||
"""Holds evaluation time information. Custom attributes can be attached
|
|
||||||
to it in extensions.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, environment, template_name=None):
|
|
||||||
self.environment = environment
|
|
||||||
if callable(environment.autoescape):
|
|
||||||
self.autoescape = environment.autoescape(template_name)
|
|
||||||
else:
|
|
||||||
self.autoescape = environment.autoescape
|
|
||||||
self.volatile = False
|
|
||||||
|
|
||||||
def save(self):
|
|
||||||
return self.__dict__.copy()
|
|
||||||
|
|
||||||
def revert(self, old):
|
|
||||||
self.__dict__.clear()
|
|
||||||
self.__dict__.update(old)
|
|
||||||
|
|
||||||
|
|
||||||
def get_eval_context(node, ctx):
|
|
||||||
if ctx is None:
|
|
||||||
if node.environment is None:
|
|
||||||
raise RuntimeError('if no eval context is passed, the '
|
|
||||||
'node must have an attached '
|
|
||||||
'environment.')
|
|
||||||
return EvalContext(node.environment)
|
|
||||||
return ctx
|
|
||||||
|
|
||||||
|
|
||||||
class Node(with_metaclass(NodeType, object)):
|
|
||||||
"""Baseclass for all Jinja2 nodes. There are a number of nodes available
|
|
||||||
of different types. There are four major types:
|
|
||||||
|
|
||||||
- :class:`Stmt`: statements
|
|
||||||
- :class:`Expr`: expressions
|
|
||||||
- :class:`Helper`: helper nodes
|
|
||||||
- :class:`Template`: the outermost wrapper node
|
|
||||||
|
|
||||||
All nodes have fields and attributes. Fields may be other nodes, lists,
|
|
||||||
or arbitrary values. Fields are passed to the constructor as regular
|
|
||||||
positional arguments, attributes as keyword arguments. Each node has
|
|
||||||
two attributes: `lineno` (the line number of the node) and `environment`.
|
|
||||||
The `environment` attribute is set at the end of the parsing process for
|
|
||||||
all nodes automatically.
|
|
||||||
"""
|
|
||||||
fields = ()
|
|
||||||
attributes = ('lineno', 'environment')
|
|
||||||
abstract = True
|
|
||||||
|
|
||||||
def __init__(self, *fields, **attributes):
|
|
||||||
if self.abstract:
|
|
||||||
raise TypeError('abstract nodes are not instanciable')
|
|
||||||
if fields:
|
|
||||||
if len(fields) != len(self.fields):
|
|
||||||
if not self.fields:
|
|
||||||
raise TypeError('%r takes 0 arguments' %
|
|
||||||
self.__class__.__name__)
|
|
||||||
raise TypeError('%r takes 0 or %d argument%s' % (
|
|
||||||
self.__class__.__name__,
|
|
||||||
len(self.fields),
|
|
||||||
len(self.fields) != 1 and 's' or ''
|
|
||||||
))
|
|
||||||
for name, arg in izip(self.fields, fields):
|
|
||||||
setattr(self, name, arg)
|
|
||||||
for attr in self.attributes:
|
|
||||||
setattr(self, attr, attributes.pop(attr, None))
|
|
||||||
if attributes:
|
|
||||||
raise TypeError('unknown attribute %r' %
|
|
||||||
next(iter(attributes)))
|
|
||||||
|
|
||||||
def iter_fields(self, exclude=None, only=None):
|
|
||||||
"""This method iterates over all fields that are defined and yields
|
|
||||||
``(key, value)`` tuples. Per default all fields are returned, but
|
|
||||||
it's possible to limit that to some fields by providing the `only`
|
|
||||||
parameter or to exclude some using the `exclude` parameter. Both
|
|
||||||
should be sets or tuples of field names.
|
|
||||||
"""
|
|
||||||
for name in self.fields:
|
|
||||||
if (exclude is only is None) or \
|
|
||||||
(exclude is not None and name not in exclude) or \
|
|
||||||
(only is not None and name in only):
|
|
||||||
try:
|
|
||||||
yield name, getattr(self, name)
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def iter_child_nodes(self, exclude=None, only=None):
|
|
||||||
"""Iterates over all direct child nodes of the node. This iterates
|
|
||||||
over all fields and yields the values of they are nodes. If the value
|
|
||||||
of a field is a list all the nodes in that list are returned.
|
|
||||||
"""
|
|
||||||
for field, item in self.iter_fields(exclude, only):
|
|
||||||
if isinstance(item, list):
|
|
||||||
for n in item:
|
|
||||||
if isinstance(n, Node):
|
|
||||||
yield n
|
|
||||||
elif isinstance(item, Node):
|
|
||||||
yield item
|
|
||||||
|
|
||||||
def find(self, node_type):
|
|
||||||
"""Find the first node of a given type. If no such node exists the
|
|
||||||
return value is `None`.
|
|
||||||
"""
|
|
||||||
for result in self.find_all(node_type):
|
|
||||||
return result
|
|
||||||
|
|
||||||
def find_all(self, node_type):
|
|
||||||
"""Find all the nodes of a given type. If the type is a tuple,
|
|
||||||
the check is performed for any of the tuple items.
|
|
||||||
"""
|
|
||||||
for child in self.iter_child_nodes():
|
|
||||||
if isinstance(child, node_type):
|
|
||||||
yield child
|
|
||||||
for result in child.find_all(node_type):
|
|
||||||
yield result
|
|
||||||
|
|
||||||
def set_ctx(self, ctx):
|
|
||||||
"""Reset the context of a node and all child nodes. Per default the
|
|
||||||
parser will all generate nodes that have a 'load' context as it's the
|
|
||||||
most common one. This method is used in the parser to set assignment
|
|
||||||
targets and other nodes to a store context.
|
|
||||||
"""
|
|
||||||
todo = deque([self])
|
|
||||||
while todo:
|
|
||||||
node = todo.popleft()
|
|
||||||
if 'ctx' in node.fields:
|
|
||||||
node.ctx = ctx
|
|
||||||
todo.extend(node.iter_child_nodes())
|
|
||||||
return self
|
|
||||||
|
|
||||||
def set_lineno(self, lineno, override=False):
|
|
||||||
"""Set the line numbers of the node and children."""
|
|
||||||
todo = deque([self])
|
|
||||||
while todo:
|
|
||||||
node = todo.popleft()
|
|
||||||
if 'lineno' in node.attributes:
|
|
||||||
if node.lineno is None or override:
|
|
||||||
node.lineno = lineno
|
|
||||||
todo.extend(node.iter_child_nodes())
|
|
||||||
return self
|
|
||||||
|
|
||||||
def set_environment(self, environment):
|
|
||||||
"""Set the environment for all nodes."""
|
|
||||||
todo = deque([self])
|
|
||||||
while todo:
|
|
||||||
node = todo.popleft()
|
|
||||||
node.environment = environment
|
|
||||||
todo.extend(node.iter_child_nodes())
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
return type(self) is type(other) and \
|
|
||||||
tuple(self.iter_fields()) == tuple(other.iter_fields())
|
|
||||||
|
|
||||||
def __ne__(self, other):
|
|
||||||
return not self.__eq__(other)
|
|
||||||
|
|
||||||
# Restore Python 2 hashing behavior on Python 3
|
|
||||||
__hash__ = object.__hash__
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return '%s(%s)' % (
|
|
||||||
self.__class__.__name__,
|
|
||||||
', '.join('%s=%r' % (arg, getattr(self, arg, None)) for
|
|
||||||
arg in self.fields)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Stmt(Node):
|
|
||||||
"""Base node for all statements."""
|
|
||||||
abstract = True
|
|
||||||
|
|
||||||
|
|
||||||
class Helper(Node):
|
|
||||||
"""Nodes that exist in a specific context only."""
|
|
||||||
abstract = True
|
|
||||||
|
|
||||||
|
|
||||||
class Template(Node):
|
|
||||||
"""Node that represents a template. This must be the outermost node that
|
|
||||||
is passed to the compiler.
|
|
||||||
"""
|
|
||||||
fields = ('body',)
|
|
||||||
|
|
||||||
|
|
||||||
class Output(Stmt):
|
|
||||||
"""A node that holds multiple expressions which are then printed out.
|
|
||||||
This is used both for the `print` statement and the regular template data.
|
|
||||||
"""
|
|
||||||
fields = ('nodes',)
|
|
||||||
|
|
||||||
|
|
||||||
class Extends(Stmt):
|
|
||||||
"""Represents an extends statement."""
|
|
||||||
fields = ('template',)
|
|
||||||
|
|
||||||
|
|
||||||
class For(Stmt):
|
|
||||||
"""The for loop. `target` is the target for the iteration (usually a
|
|
||||||
:class:`Name` or :class:`Tuple`), `iter` the iterable. `body` is a list
|
|
||||||
of nodes that are used as loop-body, and `else_` a list of nodes for the
|
|
||||||
`else` block. If no else node exists it has to be an empty list.
|
|
||||||
|
|
||||||
For filtered nodes an expression can be stored as `test`, otherwise `None`.
|
|
||||||
"""
|
|
||||||
fields = ('target', 'iter', 'body', 'else_', 'test', 'recursive')
|
|
||||||
|
|
||||||
|
|
||||||
class If(Stmt):
|
|
||||||
"""If `test` is true, `body` is rendered, else `else_`."""
|
|
||||||
fields = ('test', 'body', 'else_')
|
|
||||||
|
|
||||||
|
|
||||||
class Macro(Stmt):
|
|
||||||
"""A macro definition. `name` is the name of the macro, `args` a list of
|
|
||||||
arguments and `defaults` a list of defaults if there are any. `body` is
|
|
||||||
a list of nodes for the macro body.
|
|
||||||
"""
|
|
||||||
fields = ('name', 'args', 'defaults', 'body')
|
|
||||||
|
|
||||||
|
|
||||||
class CallBlock(Stmt):
|
|
||||||
"""Like a macro without a name but a call instead. `call` is called with
|
|
||||||
the unnamed macro as `caller` argument this node holds.
|
|
||||||
"""
|
|
||||||
fields = ('call', 'args', 'defaults', 'body')
|
|
||||||
|
|
||||||
|
|
||||||
class FilterBlock(Stmt):
|
|
||||||
"""Node for filter sections."""
|
|
||||||
fields = ('body', 'filter')
|
|
||||||
|
|
||||||
|
|
||||||
class Block(Stmt):
|
|
||||||
"""A node that represents a block."""
|
|
||||||
fields = ('name', 'body', 'scoped')
|
|
||||||
|
|
||||||
|
|
||||||
class Include(Stmt):
|
|
||||||
"""A node that represents the include tag."""
|
|
||||||
fields = ('template', 'with_context', 'ignore_missing')
|
|
||||||
|
|
||||||
|
|
||||||
class Import(Stmt):
|
|
||||||
"""A node that represents the import tag."""
|
|
||||||
fields = ('template', 'target', 'with_context')
|
|
||||||
|
|
||||||
|
|
||||||
class FromImport(Stmt):
|
|
||||||
"""A node that represents the from import tag. It's important to not
|
|
||||||
pass unsafe names to the name attribute. The compiler translates the
|
|
||||||
attribute lookups directly into getattr calls and does *not* use the
|
|
||||||
subscript callback of the interface. As exported variables may not
|
|
||||||
start with double underscores (which the parser asserts) this is not a
|
|
||||||
problem for regular Jinja code, but if this node is used in an extension
|
|
||||||
extra care must be taken.
|
|
||||||
|
|
||||||
The list of names may contain tuples if aliases are wanted.
|
|
||||||
"""
|
|
||||||
fields = ('template', 'names', 'with_context')
|
|
||||||
|
|
||||||
|
|
||||||
class ExprStmt(Stmt):
|
|
||||||
"""A statement that evaluates an expression and discards the result."""
|
|
||||||
fields = ('node',)
|
|
||||||
|
|
||||||
|
|
||||||
class Assign(Stmt):
|
|
||||||
"""Assigns an expression to a target."""
|
|
||||||
fields = ('target', 'node')
|
|
||||||
|
|
||||||
|
|
||||||
class Expr(Node):
|
|
||||||
"""Baseclass for all expressions."""
|
|
||||||
abstract = True
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
"""Return the value of the expression as constant or raise
|
|
||||||
:exc:`Impossible` if this was not possible.
|
|
||||||
|
|
||||||
An :class:`EvalContext` can be provided, if none is given
|
|
||||||
a default context is created which requires the nodes to have
|
|
||||||
an attached environment.
|
|
||||||
|
|
||||||
.. versionchanged:: 2.4
|
|
||||||
the `eval_ctx` parameter was added.
|
|
||||||
"""
|
|
||||||
raise Impossible()
|
|
||||||
|
|
||||||
def can_assign(self):
|
|
||||||
"""Check if it's possible to assign something to this node."""
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class BinExpr(Expr):
|
|
||||||
"""Baseclass for all binary expressions."""
|
|
||||||
fields = ('left', 'right')
|
|
||||||
operator = None
|
|
||||||
abstract = True
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
# intercepted operators cannot be folded at compile time
|
|
||||||
if self.environment.sandboxed and \
|
|
||||||
self.operator in self.environment.intercepted_binops:
|
|
||||||
raise Impossible()
|
|
||||||
f = _binop_to_func[self.operator]
|
|
||||||
try:
|
|
||||||
return f(self.left.as_const(eval_ctx), self.right.as_const(eval_ctx))
|
|
||||||
except Exception:
|
|
||||||
raise Impossible()
|
|
||||||
|
|
||||||
|
|
||||||
class UnaryExpr(Expr):
|
|
||||||
"""Baseclass for all unary expressions."""
|
|
||||||
fields = ('node',)
|
|
||||||
operator = None
|
|
||||||
abstract = True
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
# intercepted operators cannot be folded at compile time
|
|
||||||
if self.environment.sandboxed and \
|
|
||||||
self.operator in self.environment.intercepted_unops:
|
|
||||||
raise Impossible()
|
|
||||||
f = _uaop_to_func[self.operator]
|
|
||||||
try:
|
|
||||||
return f(self.node.as_const(eval_ctx))
|
|
||||||
except Exception:
|
|
||||||
raise Impossible()
|
|
||||||
|
|
||||||
|
|
||||||
class Name(Expr):
|
|
||||||
"""Looks up a name or stores a value in a name.
|
|
||||||
The `ctx` of the node can be one of the following values:
|
|
||||||
|
|
||||||
- `store`: store a value in the name
|
|
||||||
- `load`: load that name
|
|
||||||
- `param`: like `store` but if the name was defined as function parameter.
|
|
||||||
"""
|
|
||||||
fields = ('name', 'ctx')
|
|
||||||
|
|
||||||
def can_assign(self):
|
|
||||||
return self.name not in ('true', 'false', 'none',
|
|
||||||
'True', 'False', 'None')
|
|
||||||
|
|
||||||
|
|
||||||
class Literal(Expr):
|
|
||||||
"""Baseclass for literals."""
|
|
||||||
abstract = True
|
|
||||||
|
|
||||||
|
|
||||||
class Const(Literal):
|
|
||||||
"""All constant values. The parser will return this node for simple
|
|
||||||
constants such as ``42`` or ``"foo"`` but it can be used to store more
|
|
||||||
complex values such as lists too. Only constants with a safe
|
|
||||||
representation (objects where ``eval(repr(x)) == x`` is true).
|
|
||||||
"""
|
|
||||||
fields = ('value',)
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
return self.value
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_untrusted(cls, value, lineno=None, environment=None):
|
|
||||||
"""Return a const object if the value is representable as
|
|
||||||
constant value in the generated code, otherwise it will raise
|
|
||||||
an `Impossible` exception.
|
|
||||||
"""
|
|
||||||
from .compiler import has_safe_repr
|
|
||||||
if not has_safe_repr(value):
|
|
||||||
raise Impossible()
|
|
||||||
return cls(value, lineno=lineno, environment=environment)
|
|
||||||
|
|
||||||
|
|
||||||
class TemplateData(Literal):
|
|
||||||
"""A constant template string."""
|
|
||||||
fields = ('data',)
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
if eval_ctx.volatile:
|
|
||||||
raise Impossible()
|
|
||||||
if eval_ctx.autoescape:
|
|
||||||
return Markup(self.data)
|
|
||||||
return self.data
|
|
||||||
|
|
||||||
|
|
||||||
class Tuple(Literal):
|
|
||||||
"""For loop unpacking and some other things like multiple arguments
|
|
||||||
for subscripts. Like for :class:`Name` `ctx` specifies if the tuple
|
|
||||||
is used for loading the names or storing.
|
|
||||||
"""
|
|
||||||
fields = ('items', 'ctx')
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
return tuple(x.as_const(eval_ctx) for x in self.items)
|
|
||||||
|
|
||||||
def can_assign(self):
|
|
||||||
for item in self.items:
|
|
||||||
if not item.can_assign():
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
class List(Literal):
|
|
||||||
"""Any list literal such as ``[1, 2, 3]``"""
|
|
||||||
fields = ('items',)
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
return [x.as_const(eval_ctx) for x in self.items]
|
|
||||||
|
|
||||||
|
|
||||||
class Dict(Literal):
|
|
||||||
"""Any dict literal such as ``{1: 2, 3: 4}``. The items must be a list of
|
|
||||||
:class:`Pair` nodes.
|
|
||||||
"""
|
|
||||||
fields = ('items',)
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
return dict(x.as_const(eval_ctx) for x in self.items)
|
|
||||||
|
|
||||||
|
|
||||||
class Pair(Helper):
|
|
||||||
"""A key, value pair for dicts."""
|
|
||||||
fields = ('key', 'value')
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
return self.key.as_const(eval_ctx), self.value.as_const(eval_ctx)
|
|
||||||
|
|
||||||
|
|
||||||
class Keyword(Helper):
|
|
||||||
"""A key, value pair for keyword arguments where key is a string."""
|
|
||||||
fields = ('key', 'value')
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
return self.key, self.value.as_const(eval_ctx)
|
|
||||||
|
|
||||||
|
|
||||||
class CondExpr(Expr):
|
|
||||||
"""A conditional expression (inline if expression). (``{{
|
|
||||||
foo if bar else baz }}``)
|
|
||||||
"""
|
|
||||||
fields = ('test', 'expr1', 'expr2')
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
if self.test.as_const(eval_ctx):
|
|
||||||
return self.expr1.as_const(eval_ctx)
|
|
||||||
|
|
||||||
# if we evaluate to an undefined object, we better do that at runtime
|
|
||||||
if self.expr2 is None:
|
|
||||||
raise Impossible()
|
|
||||||
|
|
||||||
return self.expr2.as_const(eval_ctx)
|
|
||||||
|
|
||||||
|
|
||||||
class Filter(Expr):
|
|
||||||
"""This node applies a filter on an expression. `name` is the name of
|
|
||||||
the filter, the rest of the fields are the same as for :class:`Call`.
|
|
||||||
|
|
||||||
If the `node` of a filter is `None` the contents of the last buffer are
|
|
||||||
filtered. Buffers are created by macros and filter blocks.
|
|
||||||
"""
|
|
||||||
fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
if eval_ctx.volatile or self.node is None:
|
|
||||||
raise Impossible()
|
|
||||||
# we have to be careful here because we call filter_ below.
|
|
||||||
# if this variable would be called filter, 2to3 would wrap the
|
|
||||||
# call in a list beause it is assuming we are talking about the
|
|
||||||
# builtin filter function here which no longer returns a list in
|
|
||||||
# python 3. because of that, do not rename filter_ to filter!
|
|
||||||
filter_ = self.environment.filters.get(self.name)
|
|
||||||
if filter_ is None or getattr(filter_, 'contextfilter', False):
|
|
||||||
raise Impossible()
|
|
||||||
obj = self.node.as_const(eval_ctx)
|
|
||||||
args = [x.as_const(eval_ctx) for x in self.args]
|
|
||||||
if getattr(filter_, 'evalcontextfilter', False):
|
|
||||||
args.insert(0, eval_ctx)
|
|
||||||
elif getattr(filter_, 'environmentfilter', False):
|
|
||||||
args.insert(0, self.environment)
|
|
||||||
kwargs = dict(x.as_const(eval_ctx) for x in self.kwargs)
|
|
||||||
if self.dyn_args is not None:
|
|
||||||
try:
|
|
||||||
args.extend(self.dyn_args.as_const(eval_ctx))
|
|
||||||
except Exception:
|
|
||||||
raise Impossible()
|
|
||||||
if self.dyn_kwargs is not None:
|
|
||||||
try:
|
|
||||||
kwargs.update(self.dyn_kwargs.as_const(eval_ctx))
|
|
||||||
except Exception:
|
|
||||||
raise Impossible()
|
|
||||||
try:
|
|
||||||
return filter_(obj, *args, **kwargs)
|
|
||||||
except Exception:
|
|
||||||
raise Impossible()
|
|
||||||
|
|
||||||
|
|
||||||
class Test(Expr):
|
|
||||||
"""Applies a test on an expression. `name` is the name of the test, the
|
|
||||||
rest of the fields are the same as for :class:`Call`.
|
|
||||||
"""
|
|
||||||
fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
|
|
||||||
|
|
||||||
|
|
||||||
class Call(Expr):
|
|
||||||
"""Calls an expression. `args` is a list of arguments, `kwargs` a list
|
|
||||||
of keyword arguments (list of :class:`Keyword` nodes), and `dyn_args`
|
|
||||||
and `dyn_kwargs` has to be either `None` or a node that is used as
|
|
||||||
node for dynamic positional (``*args``) or keyword (``**kwargs``)
|
|
||||||
arguments.
|
|
||||||
"""
|
|
||||||
fields = ('node', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
if eval_ctx.volatile:
|
|
||||||
raise Impossible()
|
|
||||||
obj = self.node.as_const(eval_ctx)
|
|
||||||
|
|
||||||
# don't evaluate context functions
|
|
||||||
args = [x.as_const(eval_ctx) for x in self.args]
|
|
||||||
if isinstance(obj, _context_function_types):
|
|
||||||
if getattr(obj, 'contextfunction', False):
|
|
||||||
raise Impossible()
|
|
||||||
elif getattr(obj, 'evalcontextfunction', False):
|
|
||||||
args.insert(0, eval_ctx)
|
|
||||||
elif getattr(obj, 'environmentfunction', False):
|
|
||||||
args.insert(0, self.environment)
|
|
||||||
|
|
||||||
kwargs = dict(x.as_const(eval_ctx) for x in self.kwargs)
|
|
||||||
if self.dyn_args is not None:
|
|
||||||
try:
|
|
||||||
args.extend(self.dyn_args.as_const(eval_ctx))
|
|
||||||
except Exception:
|
|
||||||
raise Impossible()
|
|
||||||
if self.dyn_kwargs is not None:
|
|
||||||
try:
|
|
||||||
kwargs.update(self.dyn_kwargs.as_const(eval_ctx))
|
|
||||||
except Exception:
|
|
||||||
raise Impossible()
|
|
||||||
try:
|
|
||||||
return obj(*args, **kwargs)
|
|
||||||
except Exception:
|
|
||||||
raise Impossible()
|
|
||||||
|
|
||||||
|
|
||||||
class Getitem(Expr):
|
|
||||||
"""Get an attribute or item from an expression and prefer the item."""
|
|
||||||
fields = ('node', 'arg', 'ctx')
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
if self.ctx != 'load':
|
|
||||||
raise Impossible()
|
|
||||||
try:
|
|
||||||
return self.environment.getitem(self.node.as_const(eval_ctx),
|
|
||||||
self.arg.as_const(eval_ctx))
|
|
||||||
except Exception:
|
|
||||||
raise Impossible()
|
|
||||||
|
|
||||||
def can_assign(self):
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class Getattr(Expr):
|
|
||||||
"""Get an attribute or item from an expression that is a ascii-only
|
|
||||||
bytestring and prefer the attribute.
|
|
||||||
"""
|
|
||||||
fields = ('node', 'attr', 'ctx')
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
if self.ctx != 'load':
|
|
||||||
raise Impossible()
|
|
||||||
try:
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
return self.environment.getattr(self.node.as_const(eval_ctx),
|
|
||||||
self.attr)
|
|
||||||
except Exception:
|
|
||||||
raise Impossible()
|
|
||||||
|
|
||||||
def can_assign(self):
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class Slice(Expr):
|
|
||||||
"""Represents a slice object. This must only be used as argument for
|
|
||||||
:class:`Subscript`.
|
|
||||||
"""
|
|
||||||
fields = ('start', 'stop', 'step')
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
def const(obj):
|
|
||||||
if obj is None:
|
|
||||||
return None
|
|
||||||
return obj.as_const(eval_ctx)
|
|
||||||
return slice(const(self.start), const(self.stop), const(self.step))
|
|
||||||
|
|
||||||
|
|
||||||
class Concat(Expr):
|
|
||||||
"""Concatenates the list of expressions provided after converting them to
|
|
||||||
unicode.
|
|
||||||
"""
|
|
||||||
fields = ('nodes',)
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
return ''.join(text_type(x.as_const(eval_ctx)) for x in self.nodes)
|
|
||||||
|
|
||||||
|
|
||||||
class Compare(Expr):
|
|
||||||
"""Compares an expression with some other expressions. `ops` must be a
|
|
||||||
list of :class:`Operand`\s.
|
|
||||||
"""
|
|
||||||
fields = ('expr', 'ops')
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
result = value = self.expr.as_const(eval_ctx)
|
|
||||||
try:
|
|
||||||
for op in self.ops:
|
|
||||||
new_value = op.expr.as_const(eval_ctx)
|
|
||||||
result = _cmpop_to_func[op.op](value, new_value)
|
|
||||||
value = new_value
|
|
||||||
except Exception:
|
|
||||||
raise Impossible()
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
class Operand(Helper):
|
|
||||||
"""Holds an operator and an expression."""
|
|
||||||
fields = ('op', 'expr')
|
|
||||||
|
|
||||||
if __debug__:
|
|
||||||
Operand.__doc__ += '\nThe following operators are available: ' + \
|
|
||||||
', '.join(sorted('``%s``' % x for x in set(_binop_to_func) |
|
|
||||||
set(_uaop_to_func) | set(_cmpop_to_func)))
|
|
||||||
|
|
||||||
|
|
||||||
class Mul(BinExpr):
|
|
||||||
"""Multiplies the left with the right node."""
|
|
||||||
operator = '*'
|
|
||||||
|
|
||||||
|
|
||||||
class Div(BinExpr):
|
|
||||||
"""Divides the left by the right node."""
|
|
||||||
operator = '/'
|
|
||||||
|
|
||||||
|
|
||||||
class FloorDiv(BinExpr):
|
|
||||||
"""Divides the left by the right node and truncates conver the
|
|
||||||
result into an integer by truncating.
|
|
||||||
"""
|
|
||||||
operator = '//'
|
|
||||||
|
|
||||||
|
|
||||||
class Add(BinExpr):
|
|
||||||
"""Add the left to the right node."""
|
|
||||||
operator = '+'
|
|
||||||
|
|
||||||
|
|
||||||
class Sub(BinExpr):
|
|
||||||
"""Substract the right from the left node."""
|
|
||||||
operator = '-'
|
|
||||||
|
|
||||||
|
|
||||||
class Mod(BinExpr):
|
|
||||||
"""Left modulo right."""
|
|
||||||
operator = '%'
|
|
||||||
|
|
||||||
|
|
||||||
class Pow(BinExpr):
|
|
||||||
"""Left to the power of right."""
|
|
||||||
operator = '**'
|
|
||||||
|
|
||||||
|
|
||||||
class And(BinExpr):
|
|
||||||
"""Short circuited AND."""
|
|
||||||
operator = 'and'
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
return self.left.as_const(eval_ctx) and self.right.as_const(eval_ctx)
|
|
||||||
|
|
||||||
|
|
||||||
class Or(BinExpr):
|
|
||||||
"""Short circuited OR."""
|
|
||||||
operator = 'or'
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
return self.left.as_const(eval_ctx) or self.right.as_const(eval_ctx)
|
|
||||||
|
|
||||||
|
|
||||||
class Not(UnaryExpr):
|
|
||||||
"""Negate the expression."""
|
|
||||||
operator = 'not'
|
|
||||||
|
|
||||||
|
|
||||||
class Neg(UnaryExpr):
|
|
||||||
"""Make the expression negative."""
|
|
||||||
operator = '-'
|
|
||||||
|
|
||||||
|
|
||||||
class Pos(UnaryExpr):
|
|
||||||
"""Make the expression positive (noop for most expressions)"""
|
|
||||||
operator = '+'
|
|
||||||
|
|
||||||
|
|
||||||
# Helpers for extensions
|
|
||||||
|
|
||||||
|
|
||||||
class EnvironmentAttribute(Expr):
|
|
||||||
"""Loads an attribute from the environment object. This is useful for
|
|
||||||
extensions that want to call a callback stored on the environment.
|
|
||||||
"""
|
|
||||||
fields = ('name',)
|
|
||||||
|
|
||||||
|
|
||||||
class ExtensionAttribute(Expr):
|
|
||||||
"""Returns the attribute of an extension bound to the environment.
|
|
||||||
The identifier is the identifier of the :class:`Extension`.
|
|
||||||
|
|
||||||
This node is usually constructed by calling the
|
|
||||||
:meth:`~jinja2.ext.Extension.attr` method on an extension.
|
|
||||||
"""
|
|
||||||
fields = ('identifier', 'name')
|
|
||||||
|
|
||||||
|
|
||||||
class ImportedName(Expr):
|
|
||||||
"""If created with an import name the import name is returned on node
|
|
||||||
access. For example ``ImportedName('cgi.escape')`` returns the `escape`
|
|
||||||
function from the cgi module on evaluation. Imports are optimized by the
|
|
||||||
compiler so there is no need to assign them to local variables.
|
|
||||||
"""
|
|
||||||
fields = ('importname',)
|
|
||||||
|
|
||||||
|
|
||||||
class InternalName(Expr):
|
|
||||||
"""An internal name in the compiler. You cannot create these nodes
|
|
||||||
yourself but the parser provides a
|
|
||||||
:meth:`~jinja2.parser.Parser.free_identifier` method that creates
|
|
||||||
a new identifier for you. This identifier is not available from the
|
|
||||||
template and is not threated specially by the compiler.
|
|
||||||
"""
|
|
||||||
fields = ('name',)
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
raise TypeError('Can\'t create internal names. Use the '
|
|
||||||
'`free_identifier` method on a parser.')
|
|
||||||
|
|
||||||
|
|
||||||
class MarkSafe(Expr):
|
|
||||||
"""Mark the wrapped expression as safe (wrap it as `Markup`)."""
|
|
||||||
fields = ('expr',)
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
return Markup(self.expr.as_const(eval_ctx))
|
|
||||||
|
|
||||||
|
|
||||||
class MarkSafeIfAutoescape(Expr):
|
|
||||||
"""Mark the wrapped expression as safe (wrap it as `Markup`) but
|
|
||||||
only if autoescaping is active.
|
|
||||||
|
|
||||||
.. versionadded:: 2.5
|
|
||||||
"""
|
|
||||||
fields = ('expr',)
|
|
||||||
|
|
||||||
def as_const(self, eval_ctx=None):
|
|
||||||
eval_ctx = get_eval_context(self, eval_ctx)
|
|
||||||
if eval_ctx.volatile:
|
|
||||||
raise Impossible()
|
|
||||||
expr = self.expr.as_const(eval_ctx)
|
|
||||||
if eval_ctx.autoescape:
|
|
||||||
return Markup(expr)
|
|
||||||
return expr
|
|
||||||
|
|
||||||
|
|
||||||
class ContextReference(Expr):
|
|
||||||
"""Returns the current template context. It can be used like a
|
|
||||||
:class:`Name` node, with a ``'load'`` ctx and will return the
|
|
||||||
current :class:`~jinja2.runtime.Context` object.
|
|
||||||
|
|
||||||
Here an example that assigns the current template name to a
|
|
||||||
variable named `foo`::
|
|
||||||
|
|
||||||
Assign(Name('foo', ctx='store'),
|
|
||||||
Getattr(ContextReference(), 'name'))
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class Continue(Stmt):
|
|
||||||
"""Continue a loop."""
|
|
||||||
|
|
||||||
|
|
||||||
class Break(Stmt):
|
|
||||||
"""Break a loop."""
|
|
||||||
|
|
||||||
|
|
||||||
class Scope(Stmt):
|
|
||||||
"""An artificial scope."""
|
|
||||||
fields = ('body',)
|
|
||||||
|
|
||||||
|
|
||||||
class EvalContextModifier(Stmt):
|
|
||||||
"""Modifies the eval context. For each option that should be modified,
|
|
||||||
a :class:`Keyword` has to be added to the :attr:`options` list.
|
|
||||||
|
|
||||||
Example to change the `autoescape` setting::
|
|
||||||
|
|
||||||
EvalContextModifier(options=[Keyword('autoescape', Const(True))])
|
|
||||||
"""
|
|
||||||
fields = ('options',)
|
|
||||||
|
|
||||||
|
|
||||||
class ScopedEvalContextModifier(EvalContextModifier):
|
|
||||||
"""Modifies the eval context and reverts it later. Works exactly like
|
|
||||||
:class:`EvalContextModifier` but will only modify the
|
|
||||||
:class:`~jinja2.nodes.EvalContext` for nodes in the :attr:`body`.
|
|
||||||
"""
|
|
||||||
fields = ('body',)
|
|
||||||
|
|
||||||
|
|
||||||
# make sure nobody creates custom nodes
|
|
||||||
def _failing_new(*args, **kwargs):
|
|
||||||
raise TypeError('can\'t create custom node types')
|
|
||||||
NodeType.__new__ = staticmethod(_failing_new); del _failing_new
|
|
||||||
Vendored
-68
@@ -1,68 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.optimizer
|
|
||||||
~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The jinja optimizer is currently trying to constant fold a few expressions
|
|
||||||
and modify the AST in place so that it should be easier to evaluate it.
|
|
||||||
|
|
||||||
Because the AST does not contain all the scoping information and the
|
|
||||||
compiler has to find that out, we cannot do all the optimizations we
|
|
||||||
want. For example loop unrolling doesn't work because unrolled loops would
|
|
||||||
have a different scoping.
|
|
||||||
|
|
||||||
The solution would be a second syntax tree that has the scoping rules stored.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD.
|
|
||||||
"""
|
|
||||||
from jinja2 import nodes
|
|
||||||
from jinja2.visitor import NodeTransformer
|
|
||||||
|
|
||||||
|
|
||||||
def optimize(node, environment):
|
|
||||||
"""The context hint can be used to perform an static optimization
|
|
||||||
based on the context given."""
|
|
||||||
optimizer = Optimizer(environment)
|
|
||||||
return optimizer.visit(node)
|
|
||||||
|
|
||||||
|
|
||||||
class Optimizer(NodeTransformer):
|
|
||||||
|
|
||||||
def __init__(self, environment):
|
|
||||||
self.environment = environment
|
|
||||||
|
|
||||||
def visit_If(self, node):
|
|
||||||
"""Eliminate dead code."""
|
|
||||||
# do not optimize ifs that have a block inside so that it doesn't
|
|
||||||
# break super().
|
|
||||||
if node.find(nodes.Block) is not None:
|
|
||||||
return self.generic_visit(node)
|
|
||||||
try:
|
|
||||||
val = self.visit(node.test).as_const()
|
|
||||||
except nodes.Impossible:
|
|
||||||
return self.generic_visit(node)
|
|
||||||
if val:
|
|
||||||
body = node.body
|
|
||||||
else:
|
|
||||||
body = node.else_
|
|
||||||
result = []
|
|
||||||
for node in body:
|
|
||||||
result.extend(self.visit_list(node))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def fold(self, node):
|
|
||||||
"""Do constant folding."""
|
|
||||||
node = self.generic_visit(node)
|
|
||||||
try:
|
|
||||||
return nodes.Const.from_untrusted(node.as_const(),
|
|
||||||
lineno=node.lineno,
|
|
||||||
environment=self.environment)
|
|
||||||
except nodes.Impossible:
|
|
||||||
return node
|
|
||||||
|
|
||||||
visit_Add = visit_Sub = visit_Mul = visit_Div = visit_FloorDiv = \
|
|
||||||
visit_Pow = visit_Mod = visit_And = visit_Or = visit_Pos = visit_Neg = \
|
|
||||||
visit_Not = visit_Compare = visit_Getitem = visit_Getattr = visit_Call = \
|
|
||||||
visit_Filter = visit_Test = visit_CondExpr = fold
|
|
||||||
del fold
|
|
||||||
Vendored
-895
@@ -1,895 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.parser
|
|
||||||
~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Implements the template parser.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
from jinja2 import nodes
|
|
||||||
from jinja2.exceptions import TemplateSyntaxError, TemplateAssertionError
|
|
||||||
from jinja2.lexer import describe_token, describe_token_expr
|
|
||||||
from jinja2._compat import next, imap
|
|
||||||
|
|
||||||
|
|
||||||
#: statements that callinto
|
|
||||||
_statement_keywords = frozenset(['for', 'if', 'block', 'extends', 'print',
|
|
||||||
'macro', 'include', 'from', 'import',
|
|
||||||
'set'])
|
|
||||||
_compare_operators = frozenset(['eq', 'ne', 'lt', 'lteq', 'gt', 'gteq'])
|
|
||||||
|
|
||||||
|
|
||||||
class Parser(object):
|
|
||||||
"""This is the central parsing class Jinja2 uses. It's passed to
|
|
||||||
extensions and can be used to parse expressions or statements.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, environment, source, name=None, filename=None,
|
|
||||||
state=None):
|
|
||||||
self.environment = environment
|
|
||||||
self.stream = environment._tokenize(source, name, filename, state)
|
|
||||||
self.name = name
|
|
||||||
self.filename = filename
|
|
||||||
self.closed = False
|
|
||||||
self.extensions = {}
|
|
||||||
for extension in environment.iter_extensions():
|
|
||||||
for tag in extension.tags:
|
|
||||||
self.extensions[tag] = extension.parse
|
|
||||||
self._last_identifier = 0
|
|
||||||
self._tag_stack = []
|
|
||||||
self._end_token_stack = []
|
|
||||||
|
|
||||||
def fail(self, msg, lineno=None, exc=TemplateSyntaxError):
|
|
||||||
"""Convenience method that raises `exc` with the message, passed
|
|
||||||
line number or last line number as well as the current name and
|
|
||||||
filename.
|
|
||||||
"""
|
|
||||||
if lineno is None:
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
raise exc(msg, lineno, self.name, self.filename)
|
|
||||||
|
|
||||||
def _fail_ut_eof(self, name, end_token_stack, lineno):
|
|
||||||
expected = []
|
|
||||||
for exprs in end_token_stack:
|
|
||||||
expected.extend(imap(describe_token_expr, exprs))
|
|
||||||
if end_token_stack:
|
|
||||||
currently_looking = ' or '.join(
|
|
||||||
"'%s'" % describe_token_expr(expr)
|
|
||||||
for expr in end_token_stack[-1])
|
|
||||||
else:
|
|
||||||
currently_looking = None
|
|
||||||
|
|
||||||
if name is None:
|
|
||||||
message = ['Unexpected end of template.']
|
|
||||||
else:
|
|
||||||
message = ['Encountered unknown tag \'%s\'.' % name]
|
|
||||||
|
|
||||||
if currently_looking:
|
|
||||||
if name is not None and name in expected:
|
|
||||||
message.append('You probably made a nesting mistake. Jinja '
|
|
||||||
'is expecting this tag, but currently looking '
|
|
||||||
'for %s.' % currently_looking)
|
|
||||||
else:
|
|
||||||
message.append('Jinja was looking for the following tags: '
|
|
||||||
'%s.' % currently_looking)
|
|
||||||
|
|
||||||
if self._tag_stack:
|
|
||||||
message.append('The innermost block that needs to be '
|
|
||||||
'closed is \'%s\'.' % self._tag_stack[-1])
|
|
||||||
|
|
||||||
self.fail(' '.join(message), lineno)
|
|
||||||
|
|
||||||
def fail_unknown_tag(self, name, lineno=None):
|
|
||||||
"""Called if the parser encounters an unknown tag. Tries to fail
|
|
||||||
with a human readable error message that could help to identify
|
|
||||||
the problem.
|
|
||||||
"""
|
|
||||||
return self._fail_ut_eof(name, self._end_token_stack, lineno)
|
|
||||||
|
|
||||||
def fail_eof(self, end_tokens=None, lineno=None):
|
|
||||||
"""Like fail_unknown_tag but for end of template situations."""
|
|
||||||
stack = list(self._end_token_stack)
|
|
||||||
if end_tokens is not None:
|
|
||||||
stack.append(end_tokens)
|
|
||||||
return self._fail_ut_eof(None, stack, lineno)
|
|
||||||
|
|
||||||
def is_tuple_end(self, extra_end_rules=None):
|
|
||||||
"""Are we at the end of a tuple?"""
|
|
||||||
if self.stream.current.type in ('variable_end', 'block_end', 'rparen'):
|
|
||||||
return True
|
|
||||||
elif extra_end_rules is not None:
|
|
||||||
return self.stream.current.test_any(extra_end_rules)
|
|
||||||
return False
|
|
||||||
|
|
||||||
def free_identifier(self, lineno=None):
|
|
||||||
"""Return a new free identifier as :class:`~jinja2.nodes.InternalName`."""
|
|
||||||
self._last_identifier += 1
|
|
||||||
rv = object.__new__(nodes.InternalName)
|
|
||||||
nodes.Node.__init__(rv, 'fi%d' % self._last_identifier, lineno=lineno)
|
|
||||||
return rv
|
|
||||||
|
|
||||||
def parse_statement(self):
|
|
||||||
"""Parse a single statement."""
|
|
||||||
token = self.stream.current
|
|
||||||
if token.type != 'name':
|
|
||||||
self.fail('tag name expected', token.lineno)
|
|
||||||
self._tag_stack.append(token.value)
|
|
||||||
pop_tag = True
|
|
||||||
try:
|
|
||||||
if token.value in _statement_keywords:
|
|
||||||
return getattr(self, 'parse_' + self.stream.current.value)()
|
|
||||||
if token.value == 'call':
|
|
||||||
return self.parse_call_block()
|
|
||||||
if token.value == 'filter':
|
|
||||||
return self.parse_filter_block()
|
|
||||||
ext = self.extensions.get(token.value)
|
|
||||||
if ext is not None:
|
|
||||||
return ext(self)
|
|
||||||
|
|
||||||
# did not work out, remove the token we pushed by accident
|
|
||||||
# from the stack so that the unknown tag fail function can
|
|
||||||
# produce a proper error message.
|
|
||||||
self._tag_stack.pop()
|
|
||||||
pop_tag = False
|
|
||||||
self.fail_unknown_tag(token.value, token.lineno)
|
|
||||||
finally:
|
|
||||||
if pop_tag:
|
|
||||||
self._tag_stack.pop()
|
|
||||||
|
|
||||||
def parse_statements(self, end_tokens, drop_needle=False):
|
|
||||||
"""Parse multiple statements into a list until one of the end tokens
|
|
||||||
is reached. This is used to parse the body of statements as it also
|
|
||||||
parses template data if appropriate. The parser checks first if the
|
|
||||||
current token is a colon and skips it if there is one. Then it checks
|
|
||||||
for the block end and parses until if one of the `end_tokens` is
|
|
||||||
reached. Per default the active token in the stream at the end of
|
|
||||||
the call is the matched end token. If this is not wanted `drop_needle`
|
|
||||||
can be set to `True` and the end token is removed.
|
|
||||||
"""
|
|
||||||
# the first token may be a colon for python compatibility
|
|
||||||
self.stream.skip_if('colon')
|
|
||||||
|
|
||||||
# in the future it would be possible to add whole code sections
|
|
||||||
# by adding some sort of end of statement token and parsing those here.
|
|
||||||
self.stream.expect('block_end')
|
|
||||||
result = self.subparse(end_tokens)
|
|
||||||
|
|
||||||
# we reached the end of the template too early, the subparser
|
|
||||||
# does not check for this, so we do that now
|
|
||||||
if self.stream.current.type == 'eof':
|
|
||||||
self.fail_eof(end_tokens)
|
|
||||||
|
|
||||||
if drop_needle:
|
|
||||||
next(self.stream)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def parse_set(self):
|
|
||||||
"""Parse an assign statement."""
|
|
||||||
lineno = next(self.stream).lineno
|
|
||||||
target = self.parse_assign_target()
|
|
||||||
self.stream.expect('assign')
|
|
||||||
expr = self.parse_tuple()
|
|
||||||
return nodes.Assign(target, expr, lineno=lineno)
|
|
||||||
|
|
||||||
def parse_for(self):
|
|
||||||
"""Parse a for loop."""
|
|
||||||
lineno = self.stream.expect('name:for').lineno
|
|
||||||
target = self.parse_assign_target(extra_end_rules=('name:in',))
|
|
||||||
self.stream.expect('name:in')
|
|
||||||
iter = self.parse_tuple(with_condexpr=False,
|
|
||||||
extra_end_rules=('name:recursive',))
|
|
||||||
test = None
|
|
||||||
if self.stream.skip_if('name:if'):
|
|
||||||
test = self.parse_expression()
|
|
||||||
recursive = self.stream.skip_if('name:recursive')
|
|
||||||
body = self.parse_statements(('name:endfor', 'name:else'))
|
|
||||||
if next(self.stream).value == 'endfor':
|
|
||||||
else_ = []
|
|
||||||
else:
|
|
||||||
else_ = self.parse_statements(('name:endfor',), drop_needle=True)
|
|
||||||
return nodes.For(target, iter, body, else_, test,
|
|
||||||
recursive, lineno=lineno)
|
|
||||||
|
|
||||||
def parse_if(self):
|
|
||||||
"""Parse an if construct."""
|
|
||||||
node = result = nodes.If(lineno=self.stream.expect('name:if').lineno)
|
|
||||||
while 1:
|
|
||||||
node.test = self.parse_tuple(with_condexpr=False)
|
|
||||||
node.body = self.parse_statements(('name:elif', 'name:else',
|
|
||||||
'name:endif'))
|
|
||||||
token = next(self.stream)
|
|
||||||
if token.test('name:elif'):
|
|
||||||
new_node = nodes.If(lineno=self.stream.current.lineno)
|
|
||||||
node.else_ = [new_node]
|
|
||||||
node = new_node
|
|
||||||
continue
|
|
||||||
elif token.test('name:else'):
|
|
||||||
node.else_ = self.parse_statements(('name:endif',),
|
|
||||||
drop_needle=True)
|
|
||||||
else:
|
|
||||||
node.else_ = []
|
|
||||||
break
|
|
||||||
return result
|
|
||||||
|
|
||||||
def parse_block(self):
|
|
||||||
node = nodes.Block(lineno=next(self.stream).lineno)
|
|
||||||
node.name = self.stream.expect('name').value
|
|
||||||
node.scoped = self.stream.skip_if('name:scoped')
|
|
||||||
|
|
||||||
# common problem people encounter when switching from django
|
|
||||||
# to jinja. we do not support hyphens in block names, so let's
|
|
||||||
# raise a nicer error message in that case.
|
|
||||||
if self.stream.current.type == 'sub':
|
|
||||||
self.fail('Block names in Jinja have to be valid Python '
|
|
||||||
'identifiers and may not contain hyphens, use an '
|
|
||||||
'underscore instead.')
|
|
||||||
|
|
||||||
node.body = self.parse_statements(('name:endblock',), drop_needle=True)
|
|
||||||
self.stream.skip_if('name:' + node.name)
|
|
||||||
return node
|
|
||||||
|
|
||||||
def parse_extends(self):
|
|
||||||
node = nodes.Extends(lineno=next(self.stream).lineno)
|
|
||||||
node.template = self.parse_expression()
|
|
||||||
return node
|
|
||||||
|
|
||||||
def parse_import_context(self, node, default):
|
|
||||||
if self.stream.current.test_any('name:with', 'name:without') and \
|
|
||||||
self.stream.look().test('name:context'):
|
|
||||||
node.with_context = next(self.stream).value == 'with'
|
|
||||||
self.stream.skip()
|
|
||||||
else:
|
|
||||||
node.with_context = default
|
|
||||||
return node
|
|
||||||
|
|
||||||
def parse_include(self):
|
|
||||||
node = nodes.Include(lineno=next(self.stream).lineno)
|
|
||||||
node.template = self.parse_expression()
|
|
||||||
if self.stream.current.test('name:ignore') and \
|
|
||||||
self.stream.look().test('name:missing'):
|
|
||||||
node.ignore_missing = True
|
|
||||||
self.stream.skip(2)
|
|
||||||
else:
|
|
||||||
node.ignore_missing = False
|
|
||||||
return self.parse_import_context(node, True)
|
|
||||||
|
|
||||||
def parse_import(self):
|
|
||||||
node = nodes.Import(lineno=next(self.stream).lineno)
|
|
||||||
node.template = self.parse_expression()
|
|
||||||
self.stream.expect('name:as')
|
|
||||||
node.target = self.parse_assign_target(name_only=True).name
|
|
||||||
return self.parse_import_context(node, False)
|
|
||||||
|
|
||||||
def parse_from(self):
|
|
||||||
node = nodes.FromImport(lineno=next(self.stream).lineno)
|
|
||||||
node.template = self.parse_expression()
|
|
||||||
self.stream.expect('name:import')
|
|
||||||
node.names = []
|
|
||||||
|
|
||||||
def parse_context():
|
|
||||||
if self.stream.current.value in ('with', 'without') and \
|
|
||||||
self.stream.look().test('name:context'):
|
|
||||||
node.with_context = next(self.stream).value == 'with'
|
|
||||||
self.stream.skip()
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
while 1:
|
|
||||||
if node.names:
|
|
||||||
self.stream.expect('comma')
|
|
||||||
if self.stream.current.type == 'name':
|
|
||||||
if parse_context():
|
|
||||||
break
|
|
||||||
target = self.parse_assign_target(name_only=True)
|
|
||||||
if target.name.startswith('_'):
|
|
||||||
self.fail('names starting with an underline can not '
|
|
||||||
'be imported', target.lineno,
|
|
||||||
exc=TemplateAssertionError)
|
|
||||||
if self.stream.skip_if('name:as'):
|
|
||||||
alias = self.parse_assign_target(name_only=True)
|
|
||||||
node.names.append((target.name, alias.name))
|
|
||||||
else:
|
|
||||||
node.names.append(target.name)
|
|
||||||
if parse_context() or self.stream.current.type != 'comma':
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
if not hasattr(node, 'with_context'):
|
|
||||||
node.with_context = False
|
|
||||||
self.stream.skip_if('comma')
|
|
||||||
return node
|
|
||||||
|
|
||||||
def parse_signature(self, node):
|
|
||||||
node.args = args = []
|
|
||||||
node.defaults = defaults = []
|
|
||||||
self.stream.expect('lparen')
|
|
||||||
while self.stream.current.type != 'rparen':
|
|
||||||
if args:
|
|
||||||
self.stream.expect('comma')
|
|
||||||
arg = self.parse_assign_target(name_only=True)
|
|
||||||
arg.set_ctx('param')
|
|
||||||
if self.stream.skip_if('assign'):
|
|
||||||
defaults.append(self.parse_expression())
|
|
||||||
args.append(arg)
|
|
||||||
self.stream.expect('rparen')
|
|
||||||
|
|
||||||
def parse_call_block(self):
|
|
||||||
node = nodes.CallBlock(lineno=next(self.stream).lineno)
|
|
||||||
if self.stream.current.type == 'lparen':
|
|
||||||
self.parse_signature(node)
|
|
||||||
else:
|
|
||||||
node.args = []
|
|
||||||
node.defaults = []
|
|
||||||
|
|
||||||
node.call = self.parse_expression()
|
|
||||||
if not isinstance(node.call, nodes.Call):
|
|
||||||
self.fail('expected call', node.lineno)
|
|
||||||
node.body = self.parse_statements(('name:endcall',), drop_needle=True)
|
|
||||||
return node
|
|
||||||
|
|
||||||
def parse_filter_block(self):
|
|
||||||
node = nodes.FilterBlock(lineno=next(self.stream).lineno)
|
|
||||||
node.filter = self.parse_filter(None, start_inline=True)
|
|
||||||
node.body = self.parse_statements(('name:endfilter',),
|
|
||||||
drop_needle=True)
|
|
||||||
return node
|
|
||||||
|
|
||||||
def parse_macro(self):
|
|
||||||
node = nodes.Macro(lineno=next(self.stream).lineno)
|
|
||||||
node.name = self.parse_assign_target(name_only=True).name
|
|
||||||
self.parse_signature(node)
|
|
||||||
node.body = self.parse_statements(('name:endmacro',),
|
|
||||||
drop_needle=True)
|
|
||||||
return node
|
|
||||||
|
|
||||||
def parse_print(self):
|
|
||||||
node = nodes.Output(lineno=next(self.stream).lineno)
|
|
||||||
node.nodes = []
|
|
||||||
while self.stream.current.type != 'block_end':
|
|
||||||
if node.nodes:
|
|
||||||
self.stream.expect('comma')
|
|
||||||
node.nodes.append(self.parse_expression())
|
|
||||||
return node
|
|
||||||
|
|
||||||
def parse_assign_target(self, with_tuple=True, name_only=False,
|
|
||||||
extra_end_rules=None):
|
|
||||||
"""Parse an assignment target. As Jinja2 allows assignments to
|
|
||||||
tuples, this function can parse all allowed assignment targets. Per
|
|
||||||
default assignments to tuples are parsed, that can be disable however
|
|
||||||
by setting `with_tuple` to `False`. If only assignments to names are
|
|
||||||
wanted `name_only` can be set to `True`. The `extra_end_rules`
|
|
||||||
parameter is forwarded to the tuple parsing function.
|
|
||||||
"""
|
|
||||||
if name_only:
|
|
||||||
token = self.stream.expect('name')
|
|
||||||
target = nodes.Name(token.value, 'store', lineno=token.lineno)
|
|
||||||
else:
|
|
||||||
if with_tuple:
|
|
||||||
target = self.parse_tuple(simplified=True,
|
|
||||||
extra_end_rules=extra_end_rules)
|
|
||||||
else:
|
|
||||||
target = self.parse_primary()
|
|
||||||
target.set_ctx('store')
|
|
||||||
if not target.can_assign():
|
|
||||||
self.fail('can\'t assign to %r' % target.__class__.
|
|
||||||
__name__.lower(), target.lineno)
|
|
||||||
return target
|
|
||||||
|
|
||||||
def parse_expression(self, with_condexpr=True):
|
|
||||||
"""Parse an expression. Per default all expressions are parsed, if
|
|
||||||
the optional `with_condexpr` parameter is set to `False` conditional
|
|
||||||
expressions are not parsed.
|
|
||||||
"""
|
|
||||||
if with_condexpr:
|
|
||||||
return self.parse_condexpr()
|
|
||||||
return self.parse_or()
|
|
||||||
|
|
||||||
def parse_condexpr(self):
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
expr1 = self.parse_or()
|
|
||||||
while self.stream.skip_if('name:if'):
|
|
||||||
expr2 = self.parse_or()
|
|
||||||
if self.stream.skip_if('name:else'):
|
|
||||||
expr3 = self.parse_condexpr()
|
|
||||||
else:
|
|
||||||
expr3 = None
|
|
||||||
expr1 = nodes.CondExpr(expr2, expr1, expr3, lineno=lineno)
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
return expr1
|
|
||||||
|
|
||||||
def parse_or(self):
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
left = self.parse_and()
|
|
||||||
while self.stream.skip_if('name:or'):
|
|
||||||
right = self.parse_and()
|
|
||||||
left = nodes.Or(left, right, lineno=lineno)
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
return left
|
|
||||||
|
|
||||||
def parse_and(self):
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
left = self.parse_not()
|
|
||||||
while self.stream.skip_if('name:and'):
|
|
||||||
right = self.parse_not()
|
|
||||||
left = nodes.And(left, right, lineno=lineno)
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
return left
|
|
||||||
|
|
||||||
def parse_not(self):
|
|
||||||
if self.stream.current.test('name:not'):
|
|
||||||
lineno = next(self.stream).lineno
|
|
||||||
return nodes.Not(self.parse_not(), lineno=lineno)
|
|
||||||
return self.parse_compare()
|
|
||||||
|
|
||||||
def parse_compare(self):
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
expr = self.parse_add()
|
|
||||||
ops = []
|
|
||||||
while 1:
|
|
||||||
token_type = self.stream.current.type
|
|
||||||
if token_type in _compare_operators:
|
|
||||||
next(self.stream)
|
|
||||||
ops.append(nodes.Operand(token_type, self.parse_add()))
|
|
||||||
elif self.stream.skip_if('name:in'):
|
|
||||||
ops.append(nodes.Operand('in', self.parse_add()))
|
|
||||||
elif self.stream.current.test('name:not') and \
|
|
||||||
self.stream.look().test('name:in'):
|
|
||||||
self.stream.skip(2)
|
|
||||||
ops.append(nodes.Operand('notin', self.parse_add()))
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
if not ops:
|
|
||||||
return expr
|
|
||||||
return nodes.Compare(expr, ops, lineno=lineno)
|
|
||||||
|
|
||||||
def parse_add(self):
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
left = self.parse_sub()
|
|
||||||
while self.stream.current.type == 'add':
|
|
||||||
next(self.stream)
|
|
||||||
right = self.parse_sub()
|
|
||||||
left = nodes.Add(left, right, lineno=lineno)
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
return left
|
|
||||||
|
|
||||||
def parse_sub(self):
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
left = self.parse_concat()
|
|
||||||
while self.stream.current.type == 'sub':
|
|
||||||
next(self.stream)
|
|
||||||
right = self.parse_concat()
|
|
||||||
left = nodes.Sub(left, right, lineno=lineno)
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
return left
|
|
||||||
|
|
||||||
def parse_concat(self):
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
args = [self.parse_mul()]
|
|
||||||
while self.stream.current.type == 'tilde':
|
|
||||||
next(self.stream)
|
|
||||||
args.append(self.parse_mul())
|
|
||||||
if len(args) == 1:
|
|
||||||
return args[0]
|
|
||||||
return nodes.Concat(args, lineno=lineno)
|
|
||||||
|
|
||||||
def parse_mul(self):
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
left = self.parse_div()
|
|
||||||
while self.stream.current.type == 'mul':
|
|
||||||
next(self.stream)
|
|
||||||
right = self.parse_div()
|
|
||||||
left = nodes.Mul(left, right, lineno=lineno)
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
return left
|
|
||||||
|
|
||||||
def parse_div(self):
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
left = self.parse_floordiv()
|
|
||||||
while self.stream.current.type == 'div':
|
|
||||||
next(self.stream)
|
|
||||||
right = self.parse_floordiv()
|
|
||||||
left = nodes.Div(left, right, lineno=lineno)
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
return left
|
|
||||||
|
|
||||||
def parse_floordiv(self):
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
left = self.parse_mod()
|
|
||||||
while self.stream.current.type == 'floordiv':
|
|
||||||
next(self.stream)
|
|
||||||
right = self.parse_mod()
|
|
||||||
left = nodes.FloorDiv(left, right, lineno=lineno)
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
return left
|
|
||||||
|
|
||||||
def parse_mod(self):
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
left = self.parse_pow()
|
|
||||||
while self.stream.current.type == 'mod':
|
|
||||||
next(self.stream)
|
|
||||||
right = self.parse_pow()
|
|
||||||
left = nodes.Mod(left, right, lineno=lineno)
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
return left
|
|
||||||
|
|
||||||
def parse_pow(self):
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
left = self.parse_unary()
|
|
||||||
while self.stream.current.type == 'pow':
|
|
||||||
next(self.stream)
|
|
||||||
right = self.parse_unary()
|
|
||||||
left = nodes.Pow(left, right, lineno=lineno)
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
return left
|
|
||||||
|
|
||||||
def parse_unary(self, with_filter=True):
|
|
||||||
token_type = self.stream.current.type
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
if token_type == 'sub':
|
|
||||||
next(self.stream)
|
|
||||||
node = nodes.Neg(self.parse_unary(False), lineno=lineno)
|
|
||||||
elif token_type == 'add':
|
|
||||||
next(self.stream)
|
|
||||||
node = nodes.Pos(self.parse_unary(False), lineno=lineno)
|
|
||||||
else:
|
|
||||||
node = self.parse_primary()
|
|
||||||
node = self.parse_postfix(node)
|
|
||||||
if with_filter:
|
|
||||||
node = self.parse_filter_expr(node)
|
|
||||||
return node
|
|
||||||
|
|
||||||
def parse_primary(self):
|
|
||||||
token = self.stream.current
|
|
||||||
if token.type == 'name':
|
|
||||||
if token.value in ('true', 'false', 'True', 'False'):
|
|
||||||
node = nodes.Const(token.value in ('true', 'True'),
|
|
||||||
lineno=token.lineno)
|
|
||||||
elif token.value in ('none', 'None'):
|
|
||||||
node = nodes.Const(None, lineno=token.lineno)
|
|
||||||
else:
|
|
||||||
node = nodes.Name(token.value, 'load', lineno=token.lineno)
|
|
||||||
next(self.stream)
|
|
||||||
elif token.type == 'string':
|
|
||||||
next(self.stream)
|
|
||||||
buf = [token.value]
|
|
||||||
lineno = token.lineno
|
|
||||||
while self.stream.current.type == 'string':
|
|
||||||
buf.append(self.stream.current.value)
|
|
||||||
next(self.stream)
|
|
||||||
node = nodes.Const(''.join(buf), lineno=lineno)
|
|
||||||
elif token.type in ('integer', 'float'):
|
|
||||||
next(self.stream)
|
|
||||||
node = nodes.Const(token.value, lineno=token.lineno)
|
|
||||||
elif token.type == 'lparen':
|
|
||||||
next(self.stream)
|
|
||||||
node = self.parse_tuple(explicit_parentheses=True)
|
|
||||||
self.stream.expect('rparen')
|
|
||||||
elif token.type == 'lbracket':
|
|
||||||
node = self.parse_list()
|
|
||||||
elif token.type == 'lbrace':
|
|
||||||
node = self.parse_dict()
|
|
||||||
else:
|
|
||||||
self.fail("unexpected '%s'" % describe_token(token), token.lineno)
|
|
||||||
return node
|
|
||||||
|
|
||||||
def parse_tuple(self, simplified=False, with_condexpr=True,
|
|
||||||
extra_end_rules=None, explicit_parentheses=False):
|
|
||||||
"""Works like `parse_expression` but if multiple expressions are
|
|
||||||
delimited by a comma a :class:`~jinja2.nodes.Tuple` node is created.
|
|
||||||
This method could also return a regular expression instead of a tuple
|
|
||||||
if no commas where found.
|
|
||||||
|
|
||||||
The default parsing mode is a full tuple. If `simplified` is `True`
|
|
||||||
only names and literals are parsed. The `no_condexpr` parameter is
|
|
||||||
forwarded to :meth:`parse_expression`.
|
|
||||||
|
|
||||||
Because tuples do not require delimiters and may end in a bogus comma
|
|
||||||
an extra hint is needed that marks the end of a tuple. For example
|
|
||||||
for loops support tuples between `for` and `in`. In that case the
|
|
||||||
`extra_end_rules` is set to ``['name:in']``.
|
|
||||||
|
|
||||||
`explicit_parentheses` is true if the parsing was triggered by an
|
|
||||||
expression in parentheses. This is used to figure out if an empty
|
|
||||||
tuple is a valid expression or not.
|
|
||||||
"""
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
if simplified:
|
|
||||||
parse = self.parse_primary
|
|
||||||
elif with_condexpr:
|
|
||||||
parse = self.parse_expression
|
|
||||||
else:
|
|
||||||
parse = lambda: self.parse_expression(with_condexpr=False)
|
|
||||||
args = []
|
|
||||||
is_tuple = False
|
|
||||||
while 1:
|
|
||||||
if args:
|
|
||||||
self.stream.expect('comma')
|
|
||||||
if self.is_tuple_end(extra_end_rules):
|
|
||||||
break
|
|
||||||
args.append(parse())
|
|
||||||
if self.stream.current.type == 'comma':
|
|
||||||
is_tuple = True
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
|
|
||||||
if not is_tuple:
|
|
||||||
if args:
|
|
||||||
return args[0]
|
|
||||||
|
|
||||||
# if we don't have explicit parentheses, an empty tuple is
|
|
||||||
# not a valid expression. This would mean nothing (literally
|
|
||||||
# nothing) in the spot of an expression would be an empty
|
|
||||||
# tuple.
|
|
||||||
if not explicit_parentheses:
|
|
||||||
self.fail('Expected an expression, got \'%s\'' %
|
|
||||||
describe_token(self.stream.current))
|
|
||||||
|
|
||||||
return nodes.Tuple(args, 'load', lineno=lineno)
|
|
||||||
|
|
||||||
def parse_list(self):
|
|
||||||
token = self.stream.expect('lbracket')
|
|
||||||
items = []
|
|
||||||
while self.stream.current.type != 'rbracket':
|
|
||||||
if items:
|
|
||||||
self.stream.expect('comma')
|
|
||||||
if self.stream.current.type == 'rbracket':
|
|
||||||
break
|
|
||||||
items.append(self.parse_expression())
|
|
||||||
self.stream.expect('rbracket')
|
|
||||||
return nodes.List(items, lineno=token.lineno)
|
|
||||||
|
|
||||||
def parse_dict(self):
|
|
||||||
token = self.stream.expect('lbrace')
|
|
||||||
items = []
|
|
||||||
while self.stream.current.type != 'rbrace':
|
|
||||||
if items:
|
|
||||||
self.stream.expect('comma')
|
|
||||||
if self.stream.current.type == 'rbrace':
|
|
||||||
break
|
|
||||||
key = self.parse_expression()
|
|
||||||
self.stream.expect('colon')
|
|
||||||
value = self.parse_expression()
|
|
||||||
items.append(nodes.Pair(key, value, lineno=key.lineno))
|
|
||||||
self.stream.expect('rbrace')
|
|
||||||
return nodes.Dict(items, lineno=token.lineno)
|
|
||||||
|
|
||||||
def parse_postfix(self, node):
|
|
||||||
while 1:
|
|
||||||
token_type = self.stream.current.type
|
|
||||||
if token_type == 'dot' or token_type == 'lbracket':
|
|
||||||
node = self.parse_subscript(node)
|
|
||||||
# calls are valid both after postfix expressions (getattr
|
|
||||||
# and getitem) as well as filters and tests
|
|
||||||
elif token_type == 'lparen':
|
|
||||||
node = self.parse_call(node)
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
return node
|
|
||||||
|
|
||||||
def parse_filter_expr(self, node):
|
|
||||||
while 1:
|
|
||||||
token_type = self.stream.current.type
|
|
||||||
if token_type == 'pipe':
|
|
||||||
node = self.parse_filter(node)
|
|
||||||
elif token_type == 'name' and self.stream.current.value == 'is':
|
|
||||||
node = self.parse_test(node)
|
|
||||||
# calls are valid both after postfix expressions (getattr
|
|
||||||
# and getitem) as well as filters and tests
|
|
||||||
elif token_type == 'lparen':
|
|
||||||
node = self.parse_call(node)
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
return node
|
|
||||||
|
|
||||||
def parse_subscript(self, node):
|
|
||||||
token = next(self.stream)
|
|
||||||
if token.type == 'dot':
|
|
||||||
attr_token = self.stream.current
|
|
||||||
next(self.stream)
|
|
||||||
if attr_token.type == 'name':
|
|
||||||
return nodes.Getattr(node, attr_token.value, 'load',
|
|
||||||
lineno=token.lineno)
|
|
||||||
elif attr_token.type != 'integer':
|
|
||||||
self.fail('expected name or number', attr_token.lineno)
|
|
||||||
arg = nodes.Const(attr_token.value, lineno=attr_token.lineno)
|
|
||||||
return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
|
|
||||||
if token.type == 'lbracket':
|
|
||||||
args = []
|
|
||||||
while self.stream.current.type != 'rbracket':
|
|
||||||
if args:
|
|
||||||
self.stream.expect('comma')
|
|
||||||
args.append(self.parse_subscribed())
|
|
||||||
self.stream.expect('rbracket')
|
|
||||||
if len(args) == 1:
|
|
||||||
arg = args[0]
|
|
||||||
else:
|
|
||||||
arg = nodes.Tuple(args, 'load', lineno=token.lineno)
|
|
||||||
return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
|
|
||||||
self.fail('expected subscript expression', self.lineno)
|
|
||||||
|
|
||||||
def parse_subscribed(self):
|
|
||||||
lineno = self.stream.current.lineno
|
|
||||||
|
|
||||||
if self.stream.current.type == 'colon':
|
|
||||||
next(self.stream)
|
|
||||||
args = [None]
|
|
||||||
else:
|
|
||||||
node = self.parse_expression()
|
|
||||||
if self.stream.current.type != 'colon':
|
|
||||||
return node
|
|
||||||
next(self.stream)
|
|
||||||
args = [node]
|
|
||||||
|
|
||||||
if self.stream.current.type == 'colon':
|
|
||||||
args.append(None)
|
|
||||||
elif self.stream.current.type not in ('rbracket', 'comma'):
|
|
||||||
args.append(self.parse_expression())
|
|
||||||
else:
|
|
||||||
args.append(None)
|
|
||||||
|
|
||||||
if self.stream.current.type == 'colon':
|
|
||||||
next(self.stream)
|
|
||||||
if self.stream.current.type not in ('rbracket', 'comma'):
|
|
||||||
args.append(self.parse_expression())
|
|
||||||
else:
|
|
||||||
args.append(None)
|
|
||||||
else:
|
|
||||||
args.append(None)
|
|
||||||
|
|
||||||
return nodes.Slice(lineno=lineno, *args)
|
|
||||||
|
|
||||||
def parse_call(self, node):
|
|
||||||
token = self.stream.expect('lparen')
|
|
||||||
args = []
|
|
||||||
kwargs = []
|
|
||||||
dyn_args = dyn_kwargs = None
|
|
||||||
require_comma = False
|
|
||||||
|
|
||||||
def ensure(expr):
|
|
||||||
if not expr:
|
|
||||||
self.fail('invalid syntax for function call expression',
|
|
||||||
token.lineno)
|
|
||||||
|
|
||||||
while self.stream.current.type != 'rparen':
|
|
||||||
if require_comma:
|
|
||||||
self.stream.expect('comma')
|
|
||||||
# support for trailing comma
|
|
||||||
if self.stream.current.type == 'rparen':
|
|
||||||
break
|
|
||||||
if self.stream.current.type == 'mul':
|
|
||||||
ensure(dyn_args is None and dyn_kwargs is None)
|
|
||||||
next(self.stream)
|
|
||||||
dyn_args = self.parse_expression()
|
|
||||||
elif self.stream.current.type == 'pow':
|
|
||||||
ensure(dyn_kwargs is None)
|
|
||||||
next(self.stream)
|
|
||||||
dyn_kwargs = self.parse_expression()
|
|
||||||
else:
|
|
||||||
ensure(dyn_args is None and dyn_kwargs is None)
|
|
||||||
if self.stream.current.type == 'name' and \
|
|
||||||
self.stream.look().type == 'assign':
|
|
||||||
key = self.stream.current.value
|
|
||||||
self.stream.skip(2)
|
|
||||||
value = self.parse_expression()
|
|
||||||
kwargs.append(nodes.Keyword(key, value,
|
|
||||||
lineno=value.lineno))
|
|
||||||
else:
|
|
||||||
ensure(not kwargs)
|
|
||||||
args.append(self.parse_expression())
|
|
||||||
|
|
||||||
require_comma = True
|
|
||||||
self.stream.expect('rparen')
|
|
||||||
|
|
||||||
if node is None:
|
|
||||||
return args, kwargs, dyn_args, dyn_kwargs
|
|
||||||
return nodes.Call(node, args, kwargs, dyn_args, dyn_kwargs,
|
|
||||||
lineno=token.lineno)
|
|
||||||
|
|
||||||
def parse_filter(self, node, start_inline=False):
|
|
||||||
while self.stream.current.type == 'pipe' or start_inline:
|
|
||||||
if not start_inline:
|
|
||||||
next(self.stream)
|
|
||||||
token = self.stream.expect('name')
|
|
||||||
name = token.value
|
|
||||||
while self.stream.current.type == 'dot':
|
|
||||||
next(self.stream)
|
|
||||||
name += '.' + self.stream.expect('name').value
|
|
||||||
if self.stream.current.type == 'lparen':
|
|
||||||
args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None)
|
|
||||||
else:
|
|
||||||
args = []
|
|
||||||
kwargs = []
|
|
||||||
dyn_args = dyn_kwargs = None
|
|
||||||
node = nodes.Filter(node, name, args, kwargs, dyn_args,
|
|
||||||
dyn_kwargs, lineno=token.lineno)
|
|
||||||
start_inline = False
|
|
||||||
return node
|
|
||||||
|
|
||||||
def parse_test(self, node):
|
|
||||||
token = next(self.stream)
|
|
||||||
if self.stream.current.test('name:not'):
|
|
||||||
next(self.stream)
|
|
||||||
negated = True
|
|
||||||
else:
|
|
||||||
negated = False
|
|
||||||
name = self.stream.expect('name').value
|
|
||||||
while self.stream.current.type == 'dot':
|
|
||||||
next(self.stream)
|
|
||||||
name += '.' + self.stream.expect('name').value
|
|
||||||
dyn_args = dyn_kwargs = None
|
|
||||||
kwargs = []
|
|
||||||
if self.stream.current.type == 'lparen':
|
|
||||||
args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None)
|
|
||||||
elif self.stream.current.type in ('name', 'string', 'integer',
|
|
||||||
'float', 'lparen', 'lbracket',
|
|
||||||
'lbrace') and not \
|
|
||||||
self.stream.current.test_any('name:else', 'name:or',
|
|
||||||
'name:and'):
|
|
||||||
if self.stream.current.test('name:is'):
|
|
||||||
self.fail('You cannot chain multiple tests with is')
|
|
||||||
args = [self.parse_expression()]
|
|
||||||
else:
|
|
||||||
args = []
|
|
||||||
node = nodes.Test(node, name, args, kwargs, dyn_args,
|
|
||||||
dyn_kwargs, lineno=token.lineno)
|
|
||||||
if negated:
|
|
||||||
node = nodes.Not(node, lineno=token.lineno)
|
|
||||||
return node
|
|
||||||
|
|
||||||
def subparse(self, end_tokens=None):
|
|
||||||
body = []
|
|
||||||
data_buffer = []
|
|
||||||
add_data = data_buffer.append
|
|
||||||
|
|
||||||
if end_tokens is not None:
|
|
||||||
self._end_token_stack.append(end_tokens)
|
|
||||||
|
|
||||||
def flush_data():
|
|
||||||
if data_buffer:
|
|
||||||
lineno = data_buffer[0].lineno
|
|
||||||
body.append(nodes.Output(data_buffer[:], lineno=lineno))
|
|
||||||
del data_buffer[:]
|
|
||||||
|
|
||||||
try:
|
|
||||||
while self.stream:
|
|
||||||
token = self.stream.current
|
|
||||||
if token.type == 'data':
|
|
||||||
if token.value:
|
|
||||||
add_data(nodes.TemplateData(token.value,
|
|
||||||
lineno=token.lineno))
|
|
||||||
next(self.stream)
|
|
||||||
elif token.type == 'variable_begin':
|
|
||||||
next(self.stream)
|
|
||||||
add_data(self.parse_tuple(with_condexpr=True))
|
|
||||||
self.stream.expect('variable_end')
|
|
||||||
elif token.type == 'block_begin':
|
|
||||||
flush_data()
|
|
||||||
next(self.stream)
|
|
||||||
if end_tokens is not None and \
|
|
||||||
self.stream.current.test_any(*end_tokens):
|
|
||||||
return body
|
|
||||||
rv = self.parse_statement()
|
|
||||||
if isinstance(rv, list):
|
|
||||||
body.extend(rv)
|
|
||||||
else:
|
|
||||||
body.append(rv)
|
|
||||||
self.stream.expect('block_end')
|
|
||||||
else:
|
|
||||||
raise AssertionError('internal parsing error')
|
|
||||||
|
|
||||||
flush_data()
|
|
||||||
finally:
|
|
||||||
if end_tokens is not None:
|
|
||||||
self._end_token_stack.pop()
|
|
||||||
|
|
||||||
return body
|
|
||||||
|
|
||||||
def parse(self):
|
|
||||||
"""Parse the whole template into a `Template` node."""
|
|
||||||
result = nodes.Template(self.subparse(), lineno=1)
|
|
||||||
result.set_environment(self.environment)
|
|
||||||
return result
|
|
||||||
Vendored
-581
@@ -1,581 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.runtime
|
|
||||||
~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Runtime helpers.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD.
|
|
||||||
"""
|
|
||||||
from itertools import chain
|
|
||||||
from jinja2.nodes import EvalContext, _context_function_types
|
|
||||||
from jinja2.utils import Markup, soft_unicode, escape, missing, concat, \
|
|
||||||
internalcode, object_type_repr
|
|
||||||
from jinja2.exceptions import UndefinedError, TemplateRuntimeError, \
|
|
||||||
TemplateNotFound
|
|
||||||
from jinja2._compat import next, imap, text_type, iteritems, \
|
|
||||||
implements_iterator, implements_to_string, string_types, PY2
|
|
||||||
|
|
||||||
|
|
||||||
# these variables are exported to the template runtime
|
|
||||||
__all__ = ['LoopContext', 'TemplateReference', 'Macro', 'Markup',
|
|
||||||
'TemplateRuntimeError', 'missing', 'concat', 'escape',
|
|
||||||
'markup_join', 'unicode_join', 'to_string', 'identity',
|
|
||||||
'TemplateNotFound']
|
|
||||||
|
|
||||||
#: the name of the function that is used to convert something into
|
|
||||||
#: a string. We can just use the text type here.
|
|
||||||
to_string = text_type
|
|
||||||
|
|
||||||
#: the identity function. Useful for certain things in the environment
|
|
||||||
identity = lambda x: x
|
|
||||||
|
|
||||||
_last_iteration = object()
|
|
||||||
|
|
||||||
|
|
||||||
def markup_join(seq):
|
|
||||||
"""Concatenation that escapes if necessary and converts to unicode."""
|
|
||||||
buf = []
|
|
||||||
iterator = imap(soft_unicode, seq)
|
|
||||||
for arg in iterator:
|
|
||||||
buf.append(arg)
|
|
||||||
if hasattr(arg, '__html__'):
|
|
||||||
return Markup(u'').join(chain(buf, iterator))
|
|
||||||
return concat(buf)
|
|
||||||
|
|
||||||
|
|
||||||
def unicode_join(seq):
|
|
||||||
"""Simple args to unicode conversion and concatenation."""
|
|
||||||
return concat(imap(text_type, seq))
|
|
||||||
|
|
||||||
|
|
||||||
def new_context(environment, template_name, blocks, vars=None,
|
|
||||||
shared=None, globals=None, locals=None):
|
|
||||||
"""Internal helper to for context creation."""
|
|
||||||
if vars is None:
|
|
||||||
vars = {}
|
|
||||||
if shared:
|
|
||||||
parent = vars
|
|
||||||
else:
|
|
||||||
parent = dict(globals or (), **vars)
|
|
||||||
if locals:
|
|
||||||
# if the parent is shared a copy should be created because
|
|
||||||
# we don't want to modify the dict passed
|
|
||||||
if shared:
|
|
||||||
parent = dict(parent)
|
|
||||||
for key, value in iteritems(locals):
|
|
||||||
if key[:2] == 'l_' and value is not missing:
|
|
||||||
parent[key[2:]] = value
|
|
||||||
return Context(environment, parent, template_name, blocks)
|
|
||||||
|
|
||||||
|
|
||||||
class TemplateReference(object):
|
|
||||||
"""The `self` in templates."""
|
|
||||||
|
|
||||||
def __init__(self, context):
|
|
||||||
self.__context = context
|
|
||||||
|
|
||||||
def __getitem__(self, name):
|
|
||||||
blocks = self.__context.blocks[name]
|
|
||||||
return BlockReference(name, self.__context, blocks, 0)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return '<%s %r>' % (
|
|
||||||
self.__class__.__name__,
|
|
||||||
self.__context.name
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Context(object):
|
|
||||||
"""The template context holds the variables of a template. It stores the
|
|
||||||
values passed to the template and also the names the template exports.
|
|
||||||
Creating instances is neither supported nor useful as it's created
|
|
||||||
automatically at various stages of the template evaluation and should not
|
|
||||||
be created by hand.
|
|
||||||
|
|
||||||
The context is immutable. Modifications on :attr:`parent` **must not**
|
|
||||||
happen and modifications on :attr:`vars` are allowed from generated
|
|
||||||
template code only. Template filters and global functions marked as
|
|
||||||
:func:`contextfunction`\s get the active context passed as first argument
|
|
||||||
and are allowed to access the context read-only.
|
|
||||||
|
|
||||||
The template context supports read only dict operations (`get`,
|
|
||||||
`keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`,
|
|
||||||
`__getitem__`, `__contains__`). Additionally there is a :meth:`resolve`
|
|
||||||
method that doesn't fail with a `KeyError` but returns an
|
|
||||||
:class:`Undefined` object for missing variables.
|
|
||||||
"""
|
|
||||||
__slots__ = ('parent', 'vars', 'environment', 'eval_ctx', 'exported_vars',
|
|
||||||
'name', 'blocks', '__weakref__')
|
|
||||||
|
|
||||||
def __init__(self, environment, parent, name, blocks):
|
|
||||||
self.parent = parent
|
|
||||||
self.vars = {}
|
|
||||||
self.environment = environment
|
|
||||||
self.eval_ctx = EvalContext(self.environment, name)
|
|
||||||
self.exported_vars = set()
|
|
||||||
self.name = name
|
|
||||||
|
|
||||||
# create the initial mapping of blocks. Whenever template inheritance
|
|
||||||
# takes place the runtime will update this mapping with the new blocks
|
|
||||||
# from the template.
|
|
||||||
self.blocks = dict((k, [v]) for k, v in iteritems(blocks))
|
|
||||||
|
|
||||||
def super(self, name, current):
|
|
||||||
"""Render a parent block."""
|
|
||||||
try:
|
|
||||||
blocks = self.blocks[name]
|
|
||||||
index = blocks.index(current) + 1
|
|
||||||
blocks[index]
|
|
||||||
except LookupError:
|
|
||||||
return self.environment.undefined('there is no parent block '
|
|
||||||
'called %r.' % name,
|
|
||||||
name='super')
|
|
||||||
return BlockReference(name, self, blocks, index)
|
|
||||||
|
|
||||||
def get(self, key, default=None):
|
|
||||||
"""Returns an item from the template context, if it doesn't exist
|
|
||||||
`default` is returned.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return self[key]
|
|
||||||
except KeyError:
|
|
||||||
return default
|
|
||||||
|
|
||||||
def resolve(self, key):
|
|
||||||
"""Looks up a variable like `__getitem__` or `get` but returns an
|
|
||||||
:class:`Undefined` object with the name of the name looked up.
|
|
||||||
"""
|
|
||||||
if key in self.vars:
|
|
||||||
return self.vars[key]
|
|
||||||
if key in self.parent:
|
|
||||||
return self.parent[key]
|
|
||||||
return self.environment.undefined(name=key)
|
|
||||||
|
|
||||||
def get_exported(self):
|
|
||||||
"""Get a new dict with the exported variables."""
|
|
||||||
return dict((k, self.vars[k]) for k in self.exported_vars)
|
|
||||||
|
|
||||||
def get_all(self):
|
|
||||||
"""Return a copy of the complete context as dict including the
|
|
||||||
exported variables.
|
|
||||||
"""
|
|
||||||
return dict(self.parent, **self.vars)
|
|
||||||
|
|
||||||
@internalcode
|
|
||||||
def call(__self, __obj, *args, **kwargs):
|
|
||||||
"""Call the callable with the arguments and keyword arguments
|
|
||||||
provided but inject the active context or environment as first
|
|
||||||
argument if the callable is a :func:`contextfunction` or
|
|
||||||
:func:`environmentfunction`.
|
|
||||||
"""
|
|
||||||
if __debug__:
|
|
||||||
__traceback_hide__ = True
|
|
||||||
|
|
||||||
# Allow callable classes to take a context
|
|
||||||
fn = __obj.__call__
|
|
||||||
for fn_type in ('contextfunction',
|
|
||||||
'evalcontextfunction',
|
|
||||||
'environmentfunction'):
|
|
||||||
if hasattr(fn, fn_type):
|
|
||||||
__obj = fn
|
|
||||||
break
|
|
||||||
|
|
||||||
if isinstance(__obj, _context_function_types):
|
|
||||||
if getattr(__obj, 'contextfunction', 0):
|
|
||||||
args = (__self,) + args
|
|
||||||
elif getattr(__obj, 'evalcontextfunction', 0):
|
|
||||||
args = (__self.eval_ctx,) + args
|
|
||||||
elif getattr(__obj, 'environmentfunction', 0):
|
|
||||||
args = (__self.environment,) + args
|
|
||||||
try:
|
|
||||||
return __obj(*args, **kwargs)
|
|
||||||
except StopIteration:
|
|
||||||
return __self.environment.undefined('value was undefined because '
|
|
||||||
'a callable raised a '
|
|
||||||
'StopIteration exception')
|
|
||||||
|
|
||||||
def derived(self, locals=None):
|
|
||||||
"""Internal helper function to create a derived context."""
|
|
||||||
context = new_context(self.environment, self.name, {},
|
|
||||||
self.parent, True, None, locals)
|
|
||||||
context.vars.update(self.vars)
|
|
||||||
context.eval_ctx = self.eval_ctx
|
|
||||||
context.blocks.update((k, list(v)) for k, v in iteritems(self.blocks))
|
|
||||||
return context
|
|
||||||
|
|
||||||
def _all(meth):
|
|
||||||
proxy = lambda self: getattr(self.get_all(), meth)()
|
|
||||||
proxy.__doc__ = getattr(dict, meth).__doc__
|
|
||||||
proxy.__name__ = meth
|
|
||||||
return proxy
|
|
||||||
|
|
||||||
keys = _all('keys')
|
|
||||||
values = _all('values')
|
|
||||||
items = _all('items')
|
|
||||||
|
|
||||||
# not available on python 3
|
|
||||||
if PY2:
|
|
||||||
iterkeys = _all('iterkeys')
|
|
||||||
itervalues = _all('itervalues')
|
|
||||||
iteritems = _all('iteritems')
|
|
||||||
del _all
|
|
||||||
|
|
||||||
def __contains__(self, name):
|
|
||||||
return name in self.vars or name in self.parent
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
"""Lookup a variable or raise `KeyError` if the variable is
|
|
||||||
undefined.
|
|
||||||
"""
|
|
||||||
item = self.resolve(key)
|
|
||||||
if isinstance(item, Undefined):
|
|
||||||
raise KeyError(key)
|
|
||||||
return item
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return '<%s %s of %r>' % (
|
|
||||||
self.__class__.__name__,
|
|
||||||
repr(self.get_all()),
|
|
||||||
self.name
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# register the context as mapping if possible
|
|
||||||
try:
|
|
||||||
from collections import Mapping
|
|
||||||
Mapping.register(Context)
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class BlockReference(object):
|
|
||||||
"""One block on a template reference."""
|
|
||||||
|
|
||||||
def __init__(self, name, context, stack, depth):
|
|
||||||
self.name = name
|
|
||||||
self._context = context
|
|
||||||
self._stack = stack
|
|
||||||
self._depth = depth
|
|
||||||
|
|
||||||
@property
|
|
||||||
def super(self):
|
|
||||||
"""Super the block."""
|
|
||||||
if self._depth + 1 >= len(self._stack):
|
|
||||||
return self._context.environment. \
|
|
||||||
undefined('there is no parent block called %r.' %
|
|
||||||
self.name, name='super')
|
|
||||||
return BlockReference(self.name, self._context, self._stack,
|
|
||||||
self._depth + 1)
|
|
||||||
|
|
||||||
@internalcode
|
|
||||||
def __call__(self):
|
|
||||||
rv = concat(self._stack[self._depth](self._context))
|
|
||||||
if self._context.eval_ctx.autoescape:
|
|
||||||
rv = Markup(rv)
|
|
||||||
return rv
|
|
||||||
|
|
||||||
|
|
||||||
class LoopContext(object):
|
|
||||||
"""A loop context for dynamic iteration."""
|
|
||||||
|
|
||||||
def __init__(self, iterable, recurse=None, depth0=0):
|
|
||||||
self._iterator = iter(iterable)
|
|
||||||
self._recurse = recurse
|
|
||||||
self._after = self._safe_next()
|
|
||||||
self.index0 = -1
|
|
||||||
self.depth0 = depth0
|
|
||||||
|
|
||||||
# try to get the length of the iterable early. This must be done
|
|
||||||
# here because there are some broken iterators around where there
|
|
||||||
# __len__ is the number of iterations left (i'm looking at your
|
|
||||||
# listreverseiterator!).
|
|
||||||
try:
|
|
||||||
self._length = len(iterable)
|
|
||||||
except (TypeError, AttributeError):
|
|
||||||
self._length = None
|
|
||||||
|
|
||||||
def cycle(self, *args):
|
|
||||||
"""Cycles among the arguments with the current loop index."""
|
|
||||||
if not args:
|
|
||||||
raise TypeError('no items for cycling given')
|
|
||||||
return args[self.index0 % len(args)]
|
|
||||||
|
|
||||||
first = property(lambda x: x.index0 == 0)
|
|
||||||
last = property(lambda x: x._after is _last_iteration)
|
|
||||||
index = property(lambda x: x.index0 + 1)
|
|
||||||
revindex = property(lambda x: x.length - x.index0)
|
|
||||||
revindex0 = property(lambda x: x.length - x.index)
|
|
||||||
depth = property(lambda x: x.depth0 + 1)
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return self.length
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
return LoopContextIterator(self)
|
|
||||||
|
|
||||||
def _safe_next(self):
|
|
||||||
try:
|
|
||||||
return next(self._iterator)
|
|
||||||
except StopIteration:
|
|
||||||
return _last_iteration
|
|
||||||
|
|
||||||
@internalcode
|
|
||||||
def loop(self, iterable):
|
|
||||||
if self._recurse is None:
|
|
||||||
raise TypeError('Tried to call non recursive loop. Maybe you '
|
|
||||||
"forgot the 'recursive' modifier.")
|
|
||||||
return self._recurse(iterable, self._recurse, self.depth0 + 1)
|
|
||||||
|
|
||||||
# a nifty trick to enhance the error message if someone tried to call
|
|
||||||
# the the loop without or with too many arguments.
|
|
||||||
__call__ = loop
|
|
||||||
del loop
|
|
||||||
|
|
||||||
@property
|
|
||||||
def length(self):
|
|
||||||
if self._length is None:
|
|
||||||
# if was not possible to get the length of the iterator when
|
|
||||||
# the loop context was created (ie: iterating over a generator)
|
|
||||||
# we have to convert the iterable into a sequence and use the
|
|
||||||
# length of that.
|
|
||||||
iterable = tuple(self._iterator)
|
|
||||||
self._iterator = iter(iterable)
|
|
||||||
self._length = len(iterable) + self.index0 + 1
|
|
||||||
return self._length
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return '<%s %r/%r>' % (
|
|
||||||
self.__class__.__name__,
|
|
||||||
self.index,
|
|
||||||
self.length
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@implements_iterator
|
|
||||||
class LoopContextIterator(object):
|
|
||||||
"""The iterator for a loop context."""
|
|
||||||
__slots__ = ('context',)
|
|
||||||
|
|
||||||
def __init__(self, context):
|
|
||||||
self.context = context
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __next__(self):
|
|
||||||
ctx = self.context
|
|
||||||
ctx.index0 += 1
|
|
||||||
if ctx._after is _last_iteration:
|
|
||||||
raise StopIteration()
|
|
||||||
next_elem = ctx._after
|
|
||||||
ctx._after = ctx._safe_next()
|
|
||||||
return next_elem, ctx
|
|
||||||
|
|
||||||
|
|
||||||
class Macro(object):
|
|
||||||
"""Wraps a macro function."""
|
|
||||||
|
|
||||||
def __init__(self, environment, func, name, arguments, defaults,
|
|
||||||
catch_kwargs, catch_varargs, caller):
|
|
||||||
self._environment = environment
|
|
||||||
self._func = func
|
|
||||||
self._argument_count = len(arguments)
|
|
||||||
self.name = name
|
|
||||||
self.arguments = arguments
|
|
||||||
self.defaults = defaults
|
|
||||||
self.catch_kwargs = catch_kwargs
|
|
||||||
self.catch_varargs = catch_varargs
|
|
||||||
self.caller = caller
|
|
||||||
|
|
||||||
@internalcode
|
|
||||||
def __call__(self, *args, **kwargs):
|
|
||||||
# try to consume the positional arguments
|
|
||||||
arguments = list(args[:self._argument_count])
|
|
||||||
off = len(arguments)
|
|
||||||
|
|
||||||
# if the number of arguments consumed is not the number of
|
|
||||||
# arguments expected we start filling in keyword arguments
|
|
||||||
# and defaults.
|
|
||||||
if off != self._argument_count:
|
|
||||||
for idx, name in enumerate(self.arguments[len(arguments):]):
|
|
||||||
try:
|
|
||||||
value = kwargs.pop(name)
|
|
||||||
except KeyError:
|
|
||||||
try:
|
|
||||||
value = self.defaults[idx - self._argument_count + off]
|
|
||||||
except IndexError:
|
|
||||||
value = self._environment.undefined(
|
|
||||||
'parameter %r was not provided' % name, name=name)
|
|
||||||
arguments.append(value)
|
|
||||||
|
|
||||||
# it's important that the order of these arguments does not change
|
|
||||||
# if not also changed in the compiler's `function_scoping` method.
|
|
||||||
# the order is caller, keyword arguments, positional arguments!
|
|
||||||
if self.caller:
|
|
||||||
caller = kwargs.pop('caller', None)
|
|
||||||
if caller is None:
|
|
||||||
caller = self._environment.undefined('No caller defined',
|
|
||||||
name='caller')
|
|
||||||
arguments.append(caller)
|
|
||||||
if self.catch_kwargs:
|
|
||||||
arguments.append(kwargs)
|
|
||||||
elif kwargs:
|
|
||||||
raise TypeError('macro %r takes no keyword argument %r' %
|
|
||||||
(self.name, next(iter(kwargs))))
|
|
||||||
if self.catch_varargs:
|
|
||||||
arguments.append(args[self._argument_count:])
|
|
||||||
elif len(args) > self._argument_count:
|
|
||||||
raise TypeError('macro %r takes not more than %d argument(s)' %
|
|
||||||
(self.name, len(self.arguments)))
|
|
||||||
return self._func(*arguments)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return '<%s %s>' % (
|
|
||||||
self.__class__.__name__,
|
|
||||||
self.name is None and 'anonymous' or repr(self.name)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@implements_to_string
|
|
||||||
class Undefined(object):
|
|
||||||
"""The default undefined type. This undefined type can be printed and
|
|
||||||
iterated over, but every other access will raise an :exc:`UndefinedError`:
|
|
||||||
|
|
||||||
>>> foo = Undefined(name='foo')
|
|
||||||
>>> str(foo)
|
|
||||||
''
|
|
||||||
>>> not foo
|
|
||||||
True
|
|
||||||
>>> foo + 42
|
|
||||||
Traceback (most recent call last):
|
|
||||||
...
|
|
||||||
UndefinedError: 'foo' is undefined
|
|
||||||
"""
|
|
||||||
__slots__ = ('_undefined_hint', '_undefined_obj', '_undefined_name',
|
|
||||||
'_undefined_exception')
|
|
||||||
|
|
||||||
def __init__(self, hint=None, obj=missing, name=None, exc=UndefinedError):
|
|
||||||
self._undefined_hint = hint
|
|
||||||
self._undefined_obj = obj
|
|
||||||
self._undefined_name = name
|
|
||||||
self._undefined_exception = exc
|
|
||||||
|
|
||||||
@internalcode
|
|
||||||
def _fail_with_undefined_error(self, *args, **kwargs):
|
|
||||||
"""Regular callback function for undefined objects that raises an
|
|
||||||
`UndefinedError` on call.
|
|
||||||
"""
|
|
||||||
if self._undefined_hint is None:
|
|
||||||
if self._undefined_obj is missing:
|
|
||||||
hint = '%r is undefined' % self._undefined_name
|
|
||||||
elif not isinstance(self._undefined_name, string_types):
|
|
||||||
hint = '%s has no element %r' % (
|
|
||||||
object_type_repr(self._undefined_obj),
|
|
||||||
self._undefined_name
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
hint = '%r has no attribute %r' % (
|
|
||||||
object_type_repr(self._undefined_obj),
|
|
||||||
self._undefined_name
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
hint = self._undefined_hint
|
|
||||||
raise self._undefined_exception(hint)
|
|
||||||
|
|
||||||
@internalcode
|
|
||||||
def __getattr__(self, name):
|
|
||||||
if name[:2] == '__':
|
|
||||||
raise AttributeError(name)
|
|
||||||
return self._fail_with_undefined_error()
|
|
||||||
|
|
||||||
__add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \
|
|
||||||
__truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \
|
|
||||||
__mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \
|
|
||||||
__getitem__ = __lt__ = __le__ = __gt__ = __ge__ = __int__ = \
|
|
||||||
__float__ = __complex__ = __pow__ = __rpow__ = \
|
|
||||||
_fail_with_undefined_error
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
return type(self) is type(other)
|
|
||||||
|
|
||||||
def __ne__(self, other):
|
|
||||||
return not self.__eq__(other)
|
|
||||||
|
|
||||||
def __hash__(self):
|
|
||||||
return id(type(self))
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return u''
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
if 0:
|
|
||||||
yield None
|
|
||||||
|
|
||||||
def __nonzero__(self):
|
|
||||||
return False
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return 'Undefined'
|
|
||||||
|
|
||||||
|
|
||||||
@implements_to_string
|
|
||||||
class DebugUndefined(Undefined):
|
|
||||||
"""An undefined that returns the debug info when printed.
|
|
||||||
|
|
||||||
>>> foo = DebugUndefined(name='foo')
|
|
||||||
>>> str(foo)
|
|
||||||
'{{ foo }}'
|
|
||||||
>>> not foo
|
|
||||||
True
|
|
||||||
>>> foo + 42
|
|
||||||
Traceback (most recent call last):
|
|
||||||
...
|
|
||||||
UndefinedError: 'foo' is undefined
|
|
||||||
"""
|
|
||||||
__slots__ = ()
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self._undefined_hint is None:
|
|
||||||
if self._undefined_obj is missing:
|
|
||||||
return u'{{ %s }}' % self._undefined_name
|
|
||||||
return '{{ no such element: %s[%r] }}' % (
|
|
||||||
object_type_repr(self._undefined_obj),
|
|
||||||
self._undefined_name
|
|
||||||
)
|
|
||||||
return u'{{ undefined value printed: %s }}' % self._undefined_hint
|
|
||||||
|
|
||||||
|
|
||||||
@implements_to_string
|
|
||||||
class StrictUndefined(Undefined):
|
|
||||||
"""An undefined that barks on print and iteration as well as boolean
|
|
||||||
tests and all kinds of comparisons. In other words: you can do nothing
|
|
||||||
with it except checking if it's defined using the `defined` test.
|
|
||||||
|
|
||||||
>>> foo = StrictUndefined(name='foo')
|
|
||||||
>>> str(foo)
|
|
||||||
Traceback (most recent call last):
|
|
||||||
...
|
|
||||||
UndefinedError: 'foo' is undefined
|
|
||||||
>>> not foo
|
|
||||||
Traceback (most recent call last):
|
|
||||||
...
|
|
||||||
UndefinedError: 'foo' is undefined
|
|
||||||
>>> foo + 42
|
|
||||||
Traceback (most recent call last):
|
|
||||||
...
|
|
||||||
UndefinedError: 'foo' is undefined
|
|
||||||
"""
|
|
||||||
__slots__ = ()
|
|
||||||
__iter__ = __str__ = __len__ = __nonzero__ = __eq__ = \
|
|
||||||
__ne__ = __bool__ = __hash__ = \
|
|
||||||
Undefined._fail_with_undefined_error
|
|
||||||
|
|
||||||
|
|
||||||
# remove remaining slots attributes, after the metaclass did the magic they
|
|
||||||
# are unneeded and irritating as they contain wrong data for the subclasses.
|
|
||||||
del Undefined.__slots__, DebugUndefined.__slots__, StrictUndefined.__slots__
|
|
||||||
Vendored
-368
@@ -1,368 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.sandbox
|
|
||||||
~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Adds a sandbox layer to Jinja as it was the default behavior in the old
|
|
||||||
Jinja 1 releases. This sandbox is slightly different from Jinja 1 as the
|
|
||||||
default behavior is easier to use.
|
|
||||||
|
|
||||||
The behavior can be changed by subclassing the environment.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD.
|
|
||||||
"""
|
|
||||||
import operator
|
|
||||||
from jinja2.environment import Environment
|
|
||||||
from jinja2.exceptions import SecurityError
|
|
||||||
from jinja2._compat import string_types, function_type, method_type, \
|
|
||||||
traceback_type, code_type, frame_type, generator_type, PY2
|
|
||||||
|
|
||||||
|
|
||||||
#: maximum number of items a range may produce
|
|
||||||
MAX_RANGE = 100000
|
|
||||||
|
|
||||||
#: attributes of function objects that are considered unsafe.
|
|
||||||
UNSAFE_FUNCTION_ATTRIBUTES = set(['func_closure', 'func_code', 'func_dict',
|
|
||||||
'func_defaults', 'func_globals'])
|
|
||||||
|
|
||||||
#: unsafe method attributes. function attributes are unsafe for methods too
|
|
||||||
UNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self'])
|
|
||||||
|
|
||||||
#: unsafe generator attirbutes.
|
|
||||||
UNSAFE_GENERATOR_ATTRIBUTES = set(['gi_frame', 'gi_code'])
|
|
||||||
|
|
||||||
# On versions > python 2 the special attributes on functions are gone,
|
|
||||||
# but they remain on methods and generators for whatever reason.
|
|
||||||
if not PY2:
|
|
||||||
UNSAFE_FUNCTION_ATTRIBUTES = set()
|
|
||||||
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
# make sure we don't warn in python 2.6 about stuff we don't care about
|
|
||||||
warnings.filterwarnings('ignore', 'the sets module', DeprecationWarning,
|
|
||||||
module='jinja2.sandbox')
|
|
||||||
|
|
||||||
from collections import deque
|
|
||||||
|
|
||||||
_mutable_set_types = (set,)
|
|
||||||
_mutable_mapping_types = (dict,)
|
|
||||||
_mutable_sequence_types = (list,)
|
|
||||||
|
|
||||||
|
|
||||||
# on python 2.x we can register the user collection types
|
|
||||||
try:
|
|
||||||
from UserDict import UserDict, DictMixin
|
|
||||||
from UserList import UserList
|
|
||||||
_mutable_mapping_types += (UserDict, DictMixin)
|
|
||||||
_mutable_set_types += (UserList,)
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# if sets is still available, register the mutable set from there as well
|
|
||||||
try:
|
|
||||||
from sets import Set
|
|
||||||
_mutable_set_types += (Set,)
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
#: register Python 2.6 abstract base classes
|
|
||||||
try:
|
|
||||||
from collections import MutableSet, MutableMapping, MutableSequence
|
|
||||||
_mutable_set_types += (MutableSet,)
|
|
||||||
_mutable_mapping_types += (MutableMapping,)
|
|
||||||
_mutable_sequence_types += (MutableSequence,)
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
_mutable_spec = (
|
|
||||||
(_mutable_set_types, frozenset([
|
|
||||||
'add', 'clear', 'difference_update', 'discard', 'pop', 'remove',
|
|
||||||
'symmetric_difference_update', 'update'
|
|
||||||
])),
|
|
||||||
(_mutable_mapping_types, frozenset([
|
|
||||||
'clear', 'pop', 'popitem', 'setdefault', 'update'
|
|
||||||
])),
|
|
||||||
(_mutable_sequence_types, frozenset([
|
|
||||||
'append', 'reverse', 'insert', 'sort', 'extend', 'remove'
|
|
||||||
])),
|
|
||||||
(deque, frozenset([
|
|
||||||
'append', 'appendleft', 'clear', 'extend', 'extendleft', 'pop',
|
|
||||||
'popleft', 'remove', 'rotate'
|
|
||||||
]))
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def safe_range(*args):
|
|
||||||
"""A range that can't generate ranges with a length of more than
|
|
||||||
MAX_RANGE items.
|
|
||||||
"""
|
|
||||||
rng = range(*args)
|
|
||||||
if len(rng) > MAX_RANGE:
|
|
||||||
raise OverflowError('range too big, maximum size for range is %d' %
|
|
||||||
MAX_RANGE)
|
|
||||||
return rng
|
|
||||||
|
|
||||||
|
|
||||||
def unsafe(f):
|
|
||||||
"""Marks a function or method as unsafe.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
@unsafe
|
|
||||||
def delete(self):
|
|
||||||
pass
|
|
||||||
"""
|
|
||||||
f.unsafe_callable = True
|
|
||||||
return f
|
|
||||||
|
|
||||||
|
|
||||||
def is_internal_attribute(obj, attr):
|
|
||||||
"""Test if the attribute given is an internal python attribute. For
|
|
||||||
example this function returns `True` for the `func_code` attribute of
|
|
||||||
python objects. This is useful if the environment method
|
|
||||||
:meth:`~SandboxedEnvironment.is_safe_attribute` is overridden.
|
|
||||||
|
|
||||||
>>> from jinja2.sandbox import is_internal_attribute
|
|
||||||
>>> is_internal_attribute(lambda: None, "func_code")
|
|
||||||
True
|
|
||||||
>>> is_internal_attribute((lambda x:x).func_code, 'co_code')
|
|
||||||
True
|
|
||||||
>>> is_internal_attribute(str, "upper")
|
|
||||||
False
|
|
||||||
"""
|
|
||||||
if isinstance(obj, function_type):
|
|
||||||
if attr in UNSAFE_FUNCTION_ATTRIBUTES:
|
|
||||||
return True
|
|
||||||
elif isinstance(obj, method_type):
|
|
||||||
if attr in UNSAFE_FUNCTION_ATTRIBUTES or \
|
|
||||||
attr in UNSAFE_METHOD_ATTRIBUTES:
|
|
||||||
return True
|
|
||||||
elif isinstance(obj, type):
|
|
||||||
if attr == 'mro':
|
|
||||||
return True
|
|
||||||
elif isinstance(obj, (code_type, traceback_type, frame_type)):
|
|
||||||
return True
|
|
||||||
elif isinstance(obj, generator_type):
|
|
||||||
if attr in UNSAFE_GENERATOR_ATTRIBUTES:
|
|
||||||
return True
|
|
||||||
return attr.startswith('__')
|
|
||||||
|
|
||||||
|
|
||||||
def modifies_known_mutable(obj, attr):
|
|
||||||
"""This function checks if an attribute on a builtin mutable object
|
|
||||||
(list, dict, set or deque) would modify it if called. It also supports
|
|
||||||
the "user"-versions of the objects (`sets.Set`, `UserDict.*` etc.) and
|
|
||||||
with Python 2.6 onwards the abstract base classes `MutableSet`,
|
|
||||||
`MutableMapping`, and `MutableSequence`.
|
|
||||||
|
|
||||||
>>> modifies_known_mutable({}, "clear")
|
|
||||||
True
|
|
||||||
>>> modifies_known_mutable({}, "keys")
|
|
||||||
False
|
|
||||||
>>> modifies_known_mutable([], "append")
|
|
||||||
True
|
|
||||||
>>> modifies_known_mutable([], "index")
|
|
||||||
False
|
|
||||||
|
|
||||||
If called with an unsupported object (such as unicode) `False` is
|
|
||||||
returned.
|
|
||||||
|
|
||||||
>>> modifies_known_mutable("foo", "upper")
|
|
||||||
False
|
|
||||||
"""
|
|
||||||
for typespec, unsafe in _mutable_spec:
|
|
||||||
if isinstance(obj, typespec):
|
|
||||||
return attr in unsafe
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class SandboxedEnvironment(Environment):
|
|
||||||
"""The sandboxed environment. It works like the regular environment but
|
|
||||||
tells the compiler to generate sandboxed code. Additionally subclasses of
|
|
||||||
this environment may override the methods that tell the runtime what
|
|
||||||
attributes or functions are safe to access.
|
|
||||||
|
|
||||||
If the template tries to access insecure code a :exc:`SecurityError` is
|
|
||||||
raised. However also other exceptions may occour during the rendering so
|
|
||||||
the caller has to ensure that all exceptions are catched.
|
|
||||||
"""
|
|
||||||
sandboxed = True
|
|
||||||
|
|
||||||
#: default callback table for the binary operators. A copy of this is
|
|
||||||
#: available on each instance of a sandboxed environment as
|
|
||||||
#: :attr:`binop_table`
|
|
||||||
default_binop_table = {
|
|
||||||
'+': operator.add,
|
|
||||||
'-': operator.sub,
|
|
||||||
'*': operator.mul,
|
|
||||||
'/': operator.truediv,
|
|
||||||
'//': operator.floordiv,
|
|
||||||
'**': operator.pow,
|
|
||||||
'%': operator.mod
|
|
||||||
}
|
|
||||||
|
|
||||||
#: default callback table for the unary operators. A copy of this is
|
|
||||||
#: available on each instance of a sandboxed environment as
|
|
||||||
#: :attr:`unop_table`
|
|
||||||
default_unop_table = {
|
|
||||||
'+': operator.pos,
|
|
||||||
'-': operator.neg
|
|
||||||
}
|
|
||||||
|
|
||||||
#: a set of binary operators that should be intercepted. Each operator
|
|
||||||
#: that is added to this set (empty by default) is delegated to the
|
|
||||||
#: :meth:`call_binop` method that will perform the operator. The default
|
|
||||||
#: operator callback is specified by :attr:`binop_table`.
|
|
||||||
#:
|
|
||||||
#: The following binary operators are interceptable:
|
|
||||||
#: ``//``, ``%``, ``+``, ``*``, ``-``, ``/``, and ``**``
|
|
||||||
#:
|
|
||||||
#: The default operation form the operator table corresponds to the
|
|
||||||
#: builtin function. Intercepted calls are always slower than the native
|
|
||||||
#: operator call, so make sure only to intercept the ones you are
|
|
||||||
#: interested in.
|
|
||||||
#:
|
|
||||||
#: .. versionadded:: 2.6
|
|
||||||
intercepted_binops = frozenset()
|
|
||||||
|
|
||||||
#: a set of unary operators that should be intercepted. Each operator
|
|
||||||
#: that is added to this set (empty by default) is delegated to the
|
|
||||||
#: :meth:`call_unop` method that will perform the operator. The default
|
|
||||||
#: operator callback is specified by :attr:`unop_table`.
|
|
||||||
#:
|
|
||||||
#: The following unary operators are interceptable: ``+``, ``-``
|
|
||||||
#:
|
|
||||||
#: The default operation form the operator table corresponds to the
|
|
||||||
#: builtin function. Intercepted calls are always slower than the native
|
|
||||||
#: operator call, so make sure only to intercept the ones you are
|
|
||||||
#: interested in.
|
|
||||||
#:
|
|
||||||
#: .. versionadded:: 2.6
|
|
||||||
intercepted_unops = frozenset()
|
|
||||||
|
|
||||||
def intercept_unop(self, operator):
|
|
||||||
"""Called during template compilation with the name of a unary
|
|
||||||
operator to check if it should be intercepted at runtime. If this
|
|
||||||
method returns `True`, :meth:`call_unop` is excuted for this unary
|
|
||||||
operator. The default implementation of :meth:`call_unop` will use
|
|
||||||
the :attr:`unop_table` dictionary to perform the operator with the
|
|
||||||
same logic as the builtin one.
|
|
||||||
|
|
||||||
The following unary operators are interceptable: ``+`` and ``-``
|
|
||||||
|
|
||||||
Intercepted calls are always slower than the native operator call,
|
|
||||||
so make sure only to intercept the ones you are interested in.
|
|
||||||
|
|
||||||
.. versionadded:: 2.6
|
|
||||||
"""
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
Environment.__init__(self, *args, **kwargs)
|
|
||||||
self.globals['range'] = safe_range
|
|
||||||
self.binop_table = self.default_binop_table.copy()
|
|
||||||
self.unop_table = self.default_unop_table.copy()
|
|
||||||
|
|
||||||
def is_safe_attribute(self, obj, attr, value):
|
|
||||||
"""The sandboxed environment will call this method to check if the
|
|
||||||
attribute of an object is safe to access. Per default all attributes
|
|
||||||
starting with an underscore are considered private as well as the
|
|
||||||
special attributes of internal python objects as returned by the
|
|
||||||
:func:`is_internal_attribute` function.
|
|
||||||
"""
|
|
||||||
return not (attr.startswith('_') or is_internal_attribute(obj, attr))
|
|
||||||
|
|
||||||
def is_safe_callable(self, obj):
|
|
||||||
"""Check if an object is safely callable. Per default a function is
|
|
||||||
considered safe unless the `unsafe_callable` attribute exists and is
|
|
||||||
True. Override this method to alter the behavior, but this won't
|
|
||||||
affect the `unsafe` decorator from this module.
|
|
||||||
"""
|
|
||||||
return not (getattr(obj, 'unsafe_callable', False) or
|
|
||||||
getattr(obj, 'alters_data', False))
|
|
||||||
|
|
||||||
def call_binop(self, context, operator, left, right):
|
|
||||||
"""For intercepted binary operator calls (:meth:`intercepted_binops`)
|
|
||||||
this function is executed instead of the builtin operator. This can
|
|
||||||
be used to fine tune the behavior of certain operators.
|
|
||||||
|
|
||||||
.. versionadded:: 2.6
|
|
||||||
"""
|
|
||||||
return self.binop_table[operator](left, right)
|
|
||||||
|
|
||||||
def call_unop(self, context, operator, arg):
|
|
||||||
"""For intercepted unary operator calls (:meth:`intercepted_unops`)
|
|
||||||
this function is executed instead of the builtin operator. This can
|
|
||||||
be used to fine tune the behavior of certain operators.
|
|
||||||
|
|
||||||
.. versionadded:: 2.6
|
|
||||||
"""
|
|
||||||
return self.unop_table[operator](arg)
|
|
||||||
|
|
||||||
def getitem(self, obj, argument):
|
|
||||||
"""Subscribe an object from sandboxed code."""
|
|
||||||
try:
|
|
||||||
return obj[argument]
|
|
||||||
except (TypeError, LookupError):
|
|
||||||
if isinstance(argument, string_types):
|
|
||||||
try:
|
|
||||||
attr = str(argument)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
value = getattr(obj, attr)
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if self.is_safe_attribute(obj, argument, value):
|
|
||||||
return value
|
|
||||||
return self.unsafe_undefined(obj, argument)
|
|
||||||
return self.undefined(obj=obj, name=argument)
|
|
||||||
|
|
||||||
def getattr(self, obj, attribute):
|
|
||||||
"""Subscribe an object from sandboxed code and prefer the
|
|
||||||
attribute. The attribute passed *must* be a bytestring.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
value = getattr(obj, attribute)
|
|
||||||
except AttributeError:
|
|
||||||
try:
|
|
||||||
return obj[attribute]
|
|
||||||
except (TypeError, LookupError):
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if self.is_safe_attribute(obj, attribute, value):
|
|
||||||
return value
|
|
||||||
return self.unsafe_undefined(obj, attribute)
|
|
||||||
return self.undefined(obj=obj, name=attribute)
|
|
||||||
|
|
||||||
def unsafe_undefined(self, obj, attribute):
|
|
||||||
"""Return an undefined object for unsafe attributes."""
|
|
||||||
return self.undefined('access to attribute %r of %r '
|
|
||||||
'object is unsafe.' % (
|
|
||||||
attribute,
|
|
||||||
obj.__class__.__name__
|
|
||||||
), name=attribute, obj=obj, exc=SecurityError)
|
|
||||||
|
|
||||||
def call(__self, __context, __obj, *args, **kwargs):
|
|
||||||
"""Call an object from sandboxed code."""
|
|
||||||
# the double prefixes are to avoid double keyword argument
|
|
||||||
# errors when proxying the call.
|
|
||||||
if not __self.is_safe_callable(__obj):
|
|
||||||
raise SecurityError('%r is not safely callable' % (__obj,))
|
|
||||||
return __context.call(__obj, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class ImmutableSandboxedEnvironment(SandboxedEnvironment):
|
|
||||||
"""Works exactly like the regular `SandboxedEnvironment` but does not
|
|
||||||
permit modifications on the builtin mutable objects `list`, `set`, and
|
|
||||||
`dict` by using the :func:`modifies_known_mutable` function.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def is_safe_attribute(self, obj, attr, value):
|
|
||||||
if not SandboxedEnvironment.is_safe_attribute(self, obj, attr, value):
|
|
||||||
return False
|
|
||||||
return not modifies_known_mutable(obj, attr)
|
|
||||||
Vendored
-149
@@ -1,149 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.tests
|
|
||||||
~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Jinja test functions. Used with the "is" operator.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
import re
|
|
||||||
from jinja2.runtime import Undefined
|
|
||||||
from jinja2._compat import text_type, string_types, mapping_types
|
|
||||||
|
|
||||||
|
|
||||||
number_re = re.compile(r'^-?\d+(\.\d+)?$')
|
|
||||||
regex_type = type(number_re)
|
|
||||||
|
|
||||||
|
|
||||||
test_callable = callable
|
|
||||||
|
|
||||||
|
|
||||||
def test_odd(value):
|
|
||||||
"""Return true if the variable is odd."""
|
|
||||||
return value % 2 == 1
|
|
||||||
|
|
||||||
|
|
||||||
def test_even(value):
|
|
||||||
"""Return true if the variable is even."""
|
|
||||||
return value % 2 == 0
|
|
||||||
|
|
||||||
|
|
||||||
def test_divisibleby(value, num):
|
|
||||||
"""Check if a variable is divisible by a number."""
|
|
||||||
return value % num == 0
|
|
||||||
|
|
||||||
|
|
||||||
def test_defined(value):
|
|
||||||
"""Return true if the variable is defined:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{% if variable is defined %}
|
|
||||||
value of variable: {{ variable }}
|
|
||||||
{% else %}
|
|
||||||
variable is not defined
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
See the :func:`default` filter for a simple way to set undefined
|
|
||||||
variables.
|
|
||||||
"""
|
|
||||||
return not isinstance(value, Undefined)
|
|
||||||
|
|
||||||
|
|
||||||
def test_undefined(value):
|
|
||||||
"""Like :func:`defined` but the other way round."""
|
|
||||||
return isinstance(value, Undefined)
|
|
||||||
|
|
||||||
|
|
||||||
def test_none(value):
|
|
||||||
"""Return true if the variable is none."""
|
|
||||||
return value is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_lower(value):
|
|
||||||
"""Return true if the variable is lowercased."""
|
|
||||||
return text_type(value).islower()
|
|
||||||
|
|
||||||
|
|
||||||
def test_upper(value):
|
|
||||||
"""Return true if the variable is uppercased."""
|
|
||||||
return text_type(value).isupper()
|
|
||||||
|
|
||||||
|
|
||||||
def test_string(value):
|
|
||||||
"""Return true if the object is a string."""
|
|
||||||
return isinstance(value, string_types)
|
|
||||||
|
|
||||||
|
|
||||||
def test_mapping(value):
|
|
||||||
"""Return true if the object is a mapping (dict etc.).
|
|
||||||
|
|
||||||
.. versionadded:: 2.6
|
|
||||||
"""
|
|
||||||
return isinstance(value, mapping_types)
|
|
||||||
|
|
||||||
|
|
||||||
def test_number(value):
|
|
||||||
"""Return true if the variable is a number."""
|
|
||||||
return isinstance(value, (int, float, complex))
|
|
||||||
|
|
||||||
|
|
||||||
def test_sequence(value):
|
|
||||||
"""Return true if the variable is a sequence. Sequences are variables
|
|
||||||
that are iterable.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
len(value)
|
|
||||||
value.__getitem__
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def test_sameas(value, other):
|
|
||||||
"""Check if an object points to the same memory address than another
|
|
||||||
object:
|
|
||||||
|
|
||||||
.. sourcecode:: jinja
|
|
||||||
|
|
||||||
{% if foo.attribute is sameas false %}
|
|
||||||
the foo attribute really is the `False` singleton
|
|
||||||
{% endif %}
|
|
||||||
"""
|
|
||||||
return value is other
|
|
||||||
|
|
||||||
|
|
||||||
def test_iterable(value):
|
|
||||||
"""Check if it's possible to iterate over an object."""
|
|
||||||
try:
|
|
||||||
iter(value)
|
|
||||||
except TypeError:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def test_escaped(value):
|
|
||||||
"""Check if the value is escaped."""
|
|
||||||
return hasattr(value, '__html__')
|
|
||||||
|
|
||||||
|
|
||||||
TESTS = {
|
|
||||||
'odd': test_odd,
|
|
||||||
'even': test_even,
|
|
||||||
'divisibleby': test_divisibleby,
|
|
||||||
'defined': test_defined,
|
|
||||||
'undefined': test_undefined,
|
|
||||||
'none': test_none,
|
|
||||||
'lower': test_lower,
|
|
||||||
'upper': test_upper,
|
|
||||||
'string': test_string,
|
|
||||||
'mapping': test_mapping,
|
|
||||||
'number': test_number,
|
|
||||||
'sequence': test_sequence,
|
|
||||||
'iterable': test_iterable,
|
|
||||||
'callable': test_callable,
|
|
||||||
'sameas': test_sameas,
|
|
||||||
'escaped': test_escaped
|
|
||||||
}
|
|
||||||
Vendored
-520
@@ -1,520 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.utils
|
|
||||||
~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Utility functions.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
import re
|
|
||||||
import errno
|
|
||||||
from collections import deque
|
|
||||||
from jinja2._compat import text_type, string_types, implements_iterator, \
|
|
||||||
allocate_lock, url_quote
|
|
||||||
|
|
||||||
|
|
||||||
_word_split_re = re.compile(r'(\s+)')
|
|
||||||
_punctuation_re = re.compile(
|
|
||||||
'^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % (
|
|
||||||
'|'.join(map(re.escape, ('(', '<', '<'))),
|
|
||||||
'|'.join(map(re.escape, ('.', ',', ')', '>', '\n', '>')))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
_simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$')
|
|
||||||
_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
|
|
||||||
_entity_re = re.compile(r'&([^;]+);')
|
|
||||||
_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
|
||||||
_digits = '0123456789'
|
|
||||||
|
|
||||||
# special singleton representing missing values for the runtime
|
|
||||||
missing = type('MissingType', (), {'__repr__': lambda x: 'missing'})()
|
|
||||||
|
|
||||||
# internal code
|
|
||||||
internal_code = set()
|
|
||||||
|
|
||||||
concat = u''.join
|
|
||||||
|
|
||||||
|
|
||||||
def contextfunction(f):
|
|
||||||
"""This decorator can be used to mark a function or method context callable.
|
|
||||||
A context callable is passed the active :class:`Context` as first argument when
|
|
||||||
called from the template. This is useful if a function wants to get access
|
|
||||||
to the context or functions provided on the context object. For example
|
|
||||||
a function that returns a sorted list of template variables the current
|
|
||||||
template exports could look like this::
|
|
||||||
|
|
||||||
@contextfunction
|
|
||||||
def get_exported_names(context):
|
|
||||||
return sorted(context.exported_vars)
|
|
||||||
"""
|
|
||||||
f.contextfunction = True
|
|
||||||
return f
|
|
||||||
|
|
||||||
|
|
||||||
def evalcontextfunction(f):
|
|
||||||
"""This decorator can be used to mark a function or method as an eval
|
|
||||||
context callable. This is similar to the :func:`contextfunction`
|
|
||||||
but instead of passing the context, an evaluation context object is
|
|
||||||
passed. For more information about the eval context, see
|
|
||||||
:ref:`eval-context`.
|
|
||||||
|
|
||||||
.. versionadded:: 2.4
|
|
||||||
"""
|
|
||||||
f.evalcontextfunction = True
|
|
||||||
return f
|
|
||||||
|
|
||||||
|
|
||||||
def environmentfunction(f):
|
|
||||||
"""This decorator can be used to mark a function or method as environment
|
|
||||||
callable. This decorator works exactly like the :func:`contextfunction`
|
|
||||||
decorator just that the first argument is the active :class:`Environment`
|
|
||||||
and not context.
|
|
||||||
"""
|
|
||||||
f.environmentfunction = True
|
|
||||||
return f
|
|
||||||
|
|
||||||
|
|
||||||
def internalcode(f):
|
|
||||||
"""Marks the function as internally used"""
|
|
||||||
internal_code.add(f.__code__)
|
|
||||||
return f
|
|
||||||
|
|
||||||
|
|
||||||
def is_undefined(obj):
|
|
||||||
"""Check if the object passed is undefined. This does nothing more than
|
|
||||||
performing an instance check against :class:`Undefined` but looks nicer.
|
|
||||||
This can be used for custom filters or tests that want to react to
|
|
||||||
undefined variables. For example a custom default filter can look like
|
|
||||||
this::
|
|
||||||
|
|
||||||
def default(var, default=''):
|
|
||||||
if is_undefined(var):
|
|
||||||
return default
|
|
||||||
return var
|
|
||||||
"""
|
|
||||||
from jinja2.runtime import Undefined
|
|
||||||
return isinstance(obj, Undefined)
|
|
||||||
|
|
||||||
|
|
||||||
def consume(iterable):
|
|
||||||
"""Consumes an iterable without doing anything with it."""
|
|
||||||
for event in iterable:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def clear_caches():
|
|
||||||
"""Jinja2 keeps internal caches for environments and lexers. These are
|
|
||||||
used so that Jinja2 doesn't have to recreate environments and lexers all
|
|
||||||
the time. Normally you don't have to care about that but if you are
|
|
||||||
messuring memory consumption you may want to clean the caches.
|
|
||||||
"""
|
|
||||||
from jinja2.environment import _spontaneous_environments
|
|
||||||
from jinja2.lexer import _lexer_cache
|
|
||||||
_spontaneous_environments.clear()
|
|
||||||
_lexer_cache.clear()
|
|
||||||
|
|
||||||
|
|
||||||
def import_string(import_name, silent=False):
|
|
||||||
"""Imports an object based on a string. This is useful if you want to
|
|
||||||
use import paths as endpoints or something similar. An import path can
|
|
||||||
be specified either in dotted notation (``xml.sax.saxutils.escape``)
|
|
||||||
or with a colon as object delimiter (``xml.sax.saxutils:escape``).
|
|
||||||
|
|
||||||
If the `silent` is True the return value will be `None` if the import
|
|
||||||
fails.
|
|
||||||
|
|
||||||
:return: imported object
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
if ':' in import_name:
|
|
||||||
module, obj = import_name.split(':', 1)
|
|
||||||
elif '.' in import_name:
|
|
||||||
items = import_name.split('.')
|
|
||||||
module = '.'.join(items[:-1])
|
|
||||||
obj = items[-1]
|
|
||||||
else:
|
|
||||||
return __import__(import_name)
|
|
||||||
return getattr(__import__(module, None, None, [obj]), obj)
|
|
||||||
except (ImportError, AttributeError):
|
|
||||||
if not silent:
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
def open_if_exists(filename, mode='rb'):
|
|
||||||
"""Returns a file descriptor for the filename if that file exists,
|
|
||||||
otherwise `None`.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return open(filename, mode)
|
|
||||||
except IOError as e:
|
|
||||||
if e.errno not in (errno.ENOENT, errno.EISDIR):
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
def object_type_repr(obj):
|
|
||||||
"""Returns the name of the object's type. For some recognized
|
|
||||||
singletons the name of the object is returned instead. (For
|
|
||||||
example for `None` and `Ellipsis`).
|
|
||||||
"""
|
|
||||||
if obj is None:
|
|
||||||
return 'None'
|
|
||||||
elif obj is Ellipsis:
|
|
||||||
return 'Ellipsis'
|
|
||||||
# __builtin__ in 2.x, builtins in 3.x
|
|
||||||
if obj.__class__.__module__ in ('__builtin__', 'builtins'):
|
|
||||||
name = obj.__class__.__name__
|
|
||||||
else:
|
|
||||||
name = obj.__class__.__module__ + '.' + obj.__class__.__name__
|
|
||||||
return '%s object' % name
|
|
||||||
|
|
||||||
|
|
||||||
def pformat(obj, verbose=False):
|
|
||||||
"""Prettyprint an object. Either use the `pretty` library or the
|
|
||||||
builtin `pprint`.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
from pretty import pretty
|
|
||||||
return pretty(obj, verbose=verbose)
|
|
||||||
except ImportError:
|
|
||||||
from pprint import pformat
|
|
||||||
return pformat(obj)
|
|
||||||
|
|
||||||
|
|
||||||
def urlize(text, trim_url_limit=None, nofollow=False):
|
|
||||||
"""Converts any URLs in text into clickable links. Works on http://,
|
|
||||||
https:// and www. links. Links can have trailing punctuation (periods,
|
|
||||||
commas, close-parens) and leading punctuation (opening parens) and
|
|
||||||
it'll still do the right thing.
|
|
||||||
|
|
||||||
If trim_url_limit is not None, the URLs in link text will be limited
|
|
||||||
to trim_url_limit characters.
|
|
||||||
|
|
||||||
If nofollow is True, the URLs in link text will get a rel="nofollow"
|
|
||||||
attribute.
|
|
||||||
"""
|
|
||||||
trim_url = lambda x, limit=trim_url_limit: limit is not None \
|
|
||||||
and (x[:limit] + (len(x) >=limit and '...'
|
|
||||||
or '')) or x
|
|
||||||
words = _word_split_re.split(text_type(escape(text)))
|
|
||||||
nofollow_attr = nofollow and ' rel="nofollow"' or ''
|
|
||||||
for i, word in enumerate(words):
|
|
||||||
match = _punctuation_re.match(word)
|
|
||||||
if match:
|
|
||||||
lead, middle, trail = match.groups()
|
|
||||||
if middle.startswith('www.') or (
|
|
||||||
'@' not in middle and
|
|
||||||
not middle.startswith('http://') and
|
|
||||||
not middle.startswith('https://') and
|
|
||||||
len(middle) > 0 and
|
|
||||||
middle[0] in _letters + _digits and (
|
|
||||||
middle.endswith('.org') or
|
|
||||||
middle.endswith('.net') or
|
|
||||||
middle.endswith('.com')
|
|
||||||
)):
|
|
||||||
middle = '<a href="http://%s"%s>%s</a>' % (middle,
|
|
||||||
nofollow_attr, trim_url(middle))
|
|
||||||
if middle.startswith('http://') or \
|
|
||||||
middle.startswith('https://'):
|
|
||||||
middle = '<a href="%s"%s>%s</a>' % (middle,
|
|
||||||
nofollow_attr, trim_url(middle))
|
|
||||||
if '@' in middle and not middle.startswith('www.') and \
|
|
||||||
not ':' in middle and _simple_email_re.match(middle):
|
|
||||||
middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
|
|
||||||
if lead + middle + trail != word:
|
|
||||||
words[i] = lead + middle + trail
|
|
||||||
return u''.join(words)
|
|
||||||
|
|
||||||
|
|
||||||
def generate_lorem_ipsum(n=5, html=True, min=20, max=100):
|
|
||||||
"""Generate some lorem impsum for the template."""
|
|
||||||
from jinja2.constants import LOREM_IPSUM_WORDS
|
|
||||||
from random import choice, randrange
|
|
||||||
words = LOREM_IPSUM_WORDS.split()
|
|
||||||
result = []
|
|
||||||
|
|
||||||
for _ in range(n):
|
|
||||||
next_capitalized = True
|
|
||||||
last_comma = last_fullstop = 0
|
|
||||||
word = None
|
|
||||||
last = None
|
|
||||||
p = []
|
|
||||||
|
|
||||||
# each paragraph contains out of 20 to 100 words.
|
|
||||||
for idx, _ in enumerate(range(randrange(min, max))):
|
|
||||||
while True:
|
|
||||||
word = choice(words)
|
|
||||||
if word != last:
|
|
||||||
last = word
|
|
||||||
break
|
|
||||||
if next_capitalized:
|
|
||||||
word = word.capitalize()
|
|
||||||
next_capitalized = False
|
|
||||||
# add commas
|
|
||||||
if idx - randrange(3, 8) > last_comma:
|
|
||||||
last_comma = idx
|
|
||||||
last_fullstop += 2
|
|
||||||
word += ','
|
|
||||||
# add end of sentences
|
|
||||||
if idx - randrange(10, 20) > last_fullstop:
|
|
||||||
last_comma = last_fullstop = idx
|
|
||||||
word += '.'
|
|
||||||
next_capitalized = True
|
|
||||||
p.append(word)
|
|
||||||
|
|
||||||
# ensure that the paragraph ends with a dot.
|
|
||||||
p = u' '.join(p)
|
|
||||||
if p.endswith(','):
|
|
||||||
p = p[:-1] + '.'
|
|
||||||
elif not p.endswith('.'):
|
|
||||||
p += '.'
|
|
||||||
result.append(p)
|
|
||||||
|
|
||||||
if not html:
|
|
||||||
return u'\n\n'.join(result)
|
|
||||||
return Markup(u'\n'.join(u'<p>%s</p>' % escape(x) for x in result))
|
|
||||||
|
|
||||||
|
|
||||||
def unicode_urlencode(obj, charset='utf-8'):
|
|
||||||
"""URL escapes a single bytestring or unicode string with the
|
|
||||||
given charset if applicable to URL safe quoting under all rules
|
|
||||||
that need to be considered under all supported Python versions.
|
|
||||||
|
|
||||||
If non strings are provided they are converted to their unicode
|
|
||||||
representation first.
|
|
||||||
"""
|
|
||||||
if not isinstance(obj, string_types):
|
|
||||||
obj = text_type(obj)
|
|
||||||
if isinstance(obj, text_type):
|
|
||||||
obj = obj.encode(charset)
|
|
||||||
return text_type(url_quote(obj))
|
|
||||||
|
|
||||||
|
|
||||||
class LRUCache(object):
|
|
||||||
"""A simple LRU Cache implementation."""
|
|
||||||
|
|
||||||
# this is fast for small capacities (something below 1000) but doesn't
|
|
||||||
# scale. But as long as it's only used as storage for templates this
|
|
||||||
# won't do any harm.
|
|
||||||
|
|
||||||
def __init__(self, capacity):
|
|
||||||
self.capacity = capacity
|
|
||||||
self._mapping = {}
|
|
||||||
self._queue = deque()
|
|
||||||
self._postinit()
|
|
||||||
|
|
||||||
def _postinit(self):
|
|
||||||
# alias all queue methods for faster lookup
|
|
||||||
self._popleft = self._queue.popleft
|
|
||||||
self._pop = self._queue.pop
|
|
||||||
self._remove = self._queue.remove
|
|
||||||
self._wlock = allocate_lock()
|
|
||||||
self._append = self._queue.append
|
|
||||||
|
|
||||||
def __getstate__(self):
|
|
||||||
return {
|
|
||||||
'capacity': self.capacity,
|
|
||||||
'_mapping': self._mapping,
|
|
||||||
'_queue': self._queue
|
|
||||||
}
|
|
||||||
|
|
||||||
def __setstate__(self, d):
|
|
||||||
self.__dict__.update(d)
|
|
||||||
self._postinit()
|
|
||||||
|
|
||||||
def __getnewargs__(self):
|
|
||||||
return (self.capacity,)
|
|
||||||
|
|
||||||
def copy(self):
|
|
||||||
"""Return a shallow copy of the instance."""
|
|
||||||
rv = self.__class__(self.capacity)
|
|
||||||
rv._mapping.update(self._mapping)
|
|
||||||
rv._queue = deque(self._queue)
|
|
||||||
return rv
|
|
||||||
|
|
||||||
def get(self, key, default=None):
|
|
||||||
"""Return an item from the cache dict or `default`"""
|
|
||||||
try:
|
|
||||||
return self[key]
|
|
||||||
except KeyError:
|
|
||||||
return default
|
|
||||||
|
|
||||||
def setdefault(self, key, default=None):
|
|
||||||
"""Set `default` if the key is not in the cache otherwise
|
|
||||||
leave unchanged. Return the value of this key.
|
|
||||||
"""
|
|
||||||
self._wlock.acquire()
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
return self[key]
|
|
||||||
except KeyError:
|
|
||||||
self[key] = default
|
|
||||||
return default
|
|
||||||
finally:
|
|
||||||
self._wlock.release()
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
"""Clear the cache."""
|
|
||||||
self._wlock.acquire()
|
|
||||||
try:
|
|
||||||
self._mapping.clear()
|
|
||||||
self._queue.clear()
|
|
||||||
finally:
|
|
||||||
self._wlock.release()
|
|
||||||
|
|
||||||
def __contains__(self, key):
|
|
||||||
"""Check if a key exists in this cache."""
|
|
||||||
return key in self._mapping
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
"""Return the current size of the cache."""
|
|
||||||
return len(self._mapping)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return '<%s %r>' % (
|
|
||||||
self.__class__.__name__,
|
|
||||||
self._mapping
|
|
||||||
)
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
"""Get an item from the cache. Moves the item up so that it has the
|
|
||||||
highest priority then.
|
|
||||||
|
|
||||||
Raise a `KeyError` if it does not exist.
|
|
||||||
"""
|
|
||||||
self._wlock.acquire()
|
|
||||||
try:
|
|
||||||
rv = self._mapping[key]
|
|
||||||
if self._queue[-1] != key:
|
|
||||||
try:
|
|
||||||
self._remove(key)
|
|
||||||
except ValueError:
|
|
||||||
# if something removed the key from the container
|
|
||||||
# when we read, ignore the ValueError that we would
|
|
||||||
# get otherwise.
|
|
||||||
pass
|
|
||||||
self._append(key)
|
|
||||||
return rv
|
|
||||||
finally:
|
|
||||||
self._wlock.release()
|
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
|
||||||
"""Sets the value for an item. Moves the item up so that it
|
|
||||||
has the highest priority then.
|
|
||||||
"""
|
|
||||||
self._wlock.acquire()
|
|
||||||
try:
|
|
||||||
if key in self._mapping:
|
|
||||||
self._remove(key)
|
|
||||||
elif len(self._mapping) == self.capacity:
|
|
||||||
del self._mapping[self._popleft()]
|
|
||||||
self._append(key)
|
|
||||||
self._mapping[key] = value
|
|
||||||
finally:
|
|
||||||
self._wlock.release()
|
|
||||||
|
|
||||||
def __delitem__(self, key):
|
|
||||||
"""Remove an item from the cache dict.
|
|
||||||
Raise a `KeyError` if it does not exist.
|
|
||||||
"""
|
|
||||||
self._wlock.acquire()
|
|
||||||
try:
|
|
||||||
del self._mapping[key]
|
|
||||||
try:
|
|
||||||
self._remove(key)
|
|
||||||
except ValueError:
|
|
||||||
# __getitem__ is not locked, it might happen
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
self._wlock.release()
|
|
||||||
|
|
||||||
def items(self):
|
|
||||||
"""Return a list of items."""
|
|
||||||
result = [(key, self._mapping[key]) for key in list(self._queue)]
|
|
||||||
result.reverse()
|
|
||||||
return result
|
|
||||||
|
|
||||||
def iteritems(self):
|
|
||||||
"""Iterate over all items."""
|
|
||||||
return iter(self.items())
|
|
||||||
|
|
||||||
def values(self):
|
|
||||||
"""Return a list of all values."""
|
|
||||||
return [x[1] for x in self.items()]
|
|
||||||
|
|
||||||
def itervalue(self):
|
|
||||||
"""Iterate over all values."""
|
|
||||||
return iter(self.values())
|
|
||||||
|
|
||||||
def keys(self):
|
|
||||||
"""Return a list of all keys ordered by most recent usage."""
|
|
||||||
return list(self)
|
|
||||||
|
|
||||||
def iterkeys(self):
|
|
||||||
"""Iterate over all keys in the cache dict, ordered by
|
|
||||||
the most recent usage.
|
|
||||||
"""
|
|
||||||
return reversed(tuple(self._queue))
|
|
||||||
|
|
||||||
__iter__ = iterkeys
|
|
||||||
|
|
||||||
def __reversed__(self):
|
|
||||||
"""Iterate over the values in the cache dict, oldest items
|
|
||||||
coming first.
|
|
||||||
"""
|
|
||||||
return iter(tuple(self._queue))
|
|
||||||
|
|
||||||
__copy__ = copy
|
|
||||||
|
|
||||||
|
|
||||||
# register the LRU cache as mutable mapping if possible
|
|
||||||
try:
|
|
||||||
from collections import MutableMapping
|
|
||||||
MutableMapping.register(LRUCache)
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@implements_iterator
|
|
||||||
class Cycler(object):
|
|
||||||
"""A cycle helper for templates."""
|
|
||||||
|
|
||||||
def __init__(self, *items):
|
|
||||||
if not items:
|
|
||||||
raise RuntimeError('at least one item has to be provided')
|
|
||||||
self.items = items
|
|
||||||
self.reset()
|
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
"""Resets the cycle."""
|
|
||||||
self.pos = 0
|
|
||||||
|
|
||||||
@property
|
|
||||||
def current(self):
|
|
||||||
"""Returns the current item."""
|
|
||||||
return self.items[self.pos]
|
|
||||||
|
|
||||||
def __next__(self):
|
|
||||||
"""Goes one item ahead and returns it."""
|
|
||||||
rv = self.current
|
|
||||||
self.pos = (self.pos + 1) % len(self.items)
|
|
||||||
return rv
|
|
||||||
|
|
||||||
|
|
||||||
class Joiner(object):
|
|
||||||
"""A joining helper for templates."""
|
|
||||||
|
|
||||||
def __init__(self, sep=u', '):
|
|
||||||
self.sep = sep
|
|
||||||
self.used = False
|
|
||||||
|
|
||||||
def __call__(self):
|
|
||||||
if not self.used:
|
|
||||||
self.used = True
|
|
||||||
return u''
|
|
||||||
return self.sep
|
|
||||||
|
|
||||||
|
|
||||||
# Imported here because that's where it was in the past
|
|
||||||
from .markupsafe import Markup, escape, soft_unicode
|
|
||||||
Vendored
-87
@@ -1,87 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
jinja2.visitor
|
|
||||||
~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
This module implements a visitor for the nodes.
|
|
||||||
|
|
||||||
:copyright: (c) 2010 by the Jinja Team.
|
|
||||||
:license: BSD.
|
|
||||||
"""
|
|
||||||
from jinja2.nodes import Node
|
|
||||||
|
|
||||||
|
|
||||||
class NodeVisitor(object):
|
|
||||||
"""Walks the abstract syntax tree and call visitor functions for every
|
|
||||||
node found. The visitor functions may return values which will be
|
|
||||||
forwarded by the `visit` method.
|
|
||||||
|
|
||||||
Per default the visitor functions for the nodes are ``'visit_'`` +
|
|
||||||
class name of the node. So a `TryFinally` node visit function would
|
|
||||||
be `visit_TryFinally`. This behavior can be changed by overriding
|
|
||||||
the `get_visitor` function. If no visitor function exists for a node
|
|
||||||
(return value `None`) the `generic_visit` visitor is used instead.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def get_visitor(self, node):
|
|
||||||
"""Return the visitor function for this node or `None` if no visitor
|
|
||||||
exists for this node. In that case the generic visit function is
|
|
||||||
used instead.
|
|
||||||
"""
|
|
||||||
method = 'visit_' + node.__class__.__name__
|
|
||||||
return getattr(self, method, None)
|
|
||||||
|
|
||||||
def visit(self, node, *args, **kwargs):
|
|
||||||
"""Visit a node."""
|
|
||||||
f = self.get_visitor(node)
|
|
||||||
if f is not None:
|
|
||||||
return f(node, *args, **kwargs)
|
|
||||||
return self.generic_visit(node, *args, **kwargs)
|
|
||||||
|
|
||||||
def generic_visit(self, node, *args, **kwargs):
|
|
||||||
"""Called if no explicit visitor function exists for a node."""
|
|
||||||
for node in node.iter_child_nodes():
|
|
||||||
self.visit(node, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class NodeTransformer(NodeVisitor):
|
|
||||||
"""Walks the abstract syntax tree and allows modifications of nodes.
|
|
||||||
|
|
||||||
The `NodeTransformer` will walk the AST and use the return value of the
|
|
||||||
visitor functions to replace or remove the old node. If the return
|
|
||||||
value of the visitor function is `None` the node will be removed
|
|
||||||
from the previous location otherwise it's replaced with the return
|
|
||||||
value. The return value may be the original node in which case no
|
|
||||||
replacement takes place.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def generic_visit(self, node, *args, **kwargs):
|
|
||||||
for field, old_value in node.iter_fields():
|
|
||||||
if isinstance(old_value, list):
|
|
||||||
new_values = []
|
|
||||||
for value in old_value:
|
|
||||||
if isinstance(value, Node):
|
|
||||||
value = self.visit(value, *args, **kwargs)
|
|
||||||
if value is None:
|
|
||||||
continue
|
|
||||||
elif not isinstance(value, Node):
|
|
||||||
new_values.extend(value)
|
|
||||||
continue
|
|
||||||
new_values.append(value)
|
|
||||||
old_value[:] = new_values
|
|
||||||
elif isinstance(old_value, Node):
|
|
||||||
new_node = self.visit(old_value, *args, **kwargs)
|
|
||||||
if new_node is None:
|
|
||||||
delattr(node, field)
|
|
||||||
else:
|
|
||||||
setattr(node, field, new_node)
|
|
||||||
return node
|
|
||||||
|
|
||||||
def visit_list(self, node, *args, **kwargs):
|
|
||||||
"""As transformers may return lists in some places this method
|
|
||||||
can be used to enforce a list as return value.
|
|
||||||
"""
|
|
||||||
rv = self.visit(node, *args, **kwargs)
|
|
||||||
if not isinstance(rv, list):
|
|
||||||
rv = [rv]
|
|
||||||
return rv
|
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user