mirror of
https://gitlab.freedesktop.org/pkg-config/pkg-config.git
synced 2026-05-09 12:58:03 +02:00
glib: Bundle snapshot of glib-2.0
Add a snapshot of the current stable version of glib, glib-2.32.0. Since we only need the glib library, a lot of files are removed. See the README and update-glib.sh files in glib-patches for details.
This commit is contained in:
parent
9961b85d2a
commit
c23f6a6ef3
255 changed files with 207331 additions and 0 deletions
43
glib/.gitignore
vendored
Normal file
43
glib/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# for all subdirectories
|
||||
Makefile.in
|
||||
Makefile
|
||||
TAGS
|
||||
.libs
|
||||
.deps
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
*.pc
|
||||
.*.swp
|
||||
.sw?
|
||||
*.rc
|
||||
*.gcno
|
||||
*.gcda
|
||||
*.gcov
|
||||
*.sourcefiles
|
||||
*.stp
|
||||
*.exe
|
||||
|
||||
# autofoo stuff here
|
||||
compile
|
||||
config.*
|
||||
configure
|
||||
depcomp
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
stamp-*
|
||||
libtool
|
||||
ltmain.sh
|
||||
mingw32-config.cache
|
||||
missing
|
||||
install-sh
|
||||
glib-gettextize
|
||||
glib-zip
|
||||
gtk-doc.make
|
||||
py-compile
|
||||
|
||||
INSTALL
|
||||
README
|
||||
ChangeLog
|
||||
/glib-lcov.info
|
||||
/glib-lcov/
|
||||
40
glib/AUTHORS
Normal file
40
glib/AUTHORS
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
Below are just a few of the people who have contributed
|
||||
to GLib. Please don't mail these people about problems you
|
||||
have with GTK+; see the README file for information about
|
||||
filing bugs and submitting patches.
|
||||
|
||||
GLib-2.0 Team
|
||||
-------------
|
||||
Hans Breuer <hans@breuer.org>
|
||||
Matthias Clasen <mclasen@redhat.com>
|
||||
Tor Lillqvist <tml@iki.fi>
|
||||
Tim Janik <timj@gtk.org>
|
||||
Havoc Pennington <hp@redhat.com>
|
||||
Ron Steinke <rsteinke@w-link.net>
|
||||
Owen Taylor <otaylor@redhat.com>
|
||||
Sebastian Wilhelmi <seppi@seppi.de>
|
||||
|
||||
GLib-1.2 Team
|
||||
-------------
|
||||
Shawn T. Amundson <amundson@gimp.org>
|
||||
Jeff Garzik <jgarzik@pobox.com>
|
||||
Raja R Harinath <harinath@cs.umn.edu>
|
||||
Tim Janik <timj@gtk.org>
|
||||
Elliot Lee <sopwith@redhat.com>
|
||||
Tor Lillqvist <tml@iki.fi>
|
||||
Paolo Molaro <lupus@debian.org>
|
||||
Havoc Pennington <hp@pobox.com>
|
||||
Manish Singh <yosh@gimp.org>
|
||||
Owen Taylor <otaylor@gtk.org>
|
||||
Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
The random number generator "Mersenne Twister", which is used by GLib,
|
||||
was developed and originally coded by:
|
||||
Makoto Matsumoto <matumoto@math.keio.ac.jp>
|
||||
Takuji Nishimura <nisimura@math.keio.ac.jp>
|
||||
|
||||
Original Authors
|
||||
----------------
|
||||
Peter Mattis <petm@xcf.berkeley.edu>
|
||||
Spencer Kimball <spencer@xcf.berkeley.edu>
|
||||
Josh MacDonald <jmacd@xcf.berkeley.edu>
|
||||
482
glib/COPYING
Normal file
482
glib/COPYING
Normal file
|
|
@ -0,0 +1,482 @@
|
|||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 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 library GPL. It is
|
||||
numbered 2 because it goes with version 2 of the ordinary GPL.]
|
||||
|
||||
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 Library General Public License, applies to some
|
||||
specially designated Free Software Foundation software, and to any
|
||||
other libraries whose authors decide to use it. You can use it for
|
||||
your libraries, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, 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 or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the 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 a program 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.
|
||||
|
||||
Our method of protecting your rights has two steps: (1) copyright
|
||||
the library, and (2) offer you this license which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
Also, for each distributor's protection, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
library. If the library is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original
|
||||
version, so that any problems introduced by others will not reflect on
|
||||
the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that companies distributing free
|
||||
software will individually obtain patent licenses, thus in effect
|
||||
transforming the program into proprietary software. To prevent this,
|
||||
we have made it clear that any patent must be licensed for everyone's
|
||||
free use or not licensed at all.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the ordinary
|
||||
GNU General Public License, which was designed for utility programs. This
|
||||
license, the GNU Library General Public License, applies to certain
|
||||
designated libraries. This license is quite different from the ordinary
|
||||
one; be sure to read it in full, and don't assume that anything in it is
|
||||
the same as in the ordinary license.
|
||||
|
||||
The reason we have a separate public license for some libraries is that
|
||||
they blur the distinction we usually make between modifying or adding to a
|
||||
program and simply using it. Linking a program with a library, without
|
||||
changing the library, is in some sense simply using the library, and is
|
||||
analogous to running a utility program or application program. However, in
|
||||
a textual and legal sense, the linked executable is a combined work, a
|
||||
derivative of the original library, and the ordinary General Public License
|
||||
treats it as such.
|
||||
|
||||
Because of this blurred distinction, using the ordinary General
|
||||
Public License for libraries did not effectively promote software
|
||||
sharing, because most developers did not use the libraries. We
|
||||
concluded that weaker conditions might promote sharing better.
|
||||
|
||||
However, unrestricted linking of non-free programs would deprive the
|
||||
users of those programs of all benefit from the free status of the
|
||||
libraries themselves. This Library General Public License is intended to
|
||||
permit developers of non-free programs to use free libraries, while
|
||||
preserving your freedom as a user of such programs to change the free
|
||||
libraries that are incorporated in them. (We have not seen how to achieve
|
||||
this as regards changes in header files, but we have achieved it as regards
|
||||
changes in the actual functions of the Library.) The hope is that this
|
||||
will lead to faster development of free libraries.
|
||||
|
||||
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, while the latter only
|
||||
works together with the library.
|
||||
|
||||
Note that it is possible for a library to be covered by the ordinary
|
||||
General Public License rather than by this special one.
|
||||
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library which
|
||||
contains a notice placed by the copyright holder or other authorized
|
||||
party saying it may be distributed under the terms of this Library
|
||||
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 compile 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) 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.
|
||||
|
||||
c) 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.
|
||||
|
||||
d) 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 source code 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 to
|
||||
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 Library 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 Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307 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!
|
||||
135
glib/Makefile.am
Normal file
135
glib/Makefile.am
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
include $(top_srcdir)/Makefile.decl
|
||||
|
||||
# http://people.gnome.org/~walters/docs/build-api.txt
|
||||
.buildapi-allow-builddir:
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4macros ${ACLOCAL_FLAGS}
|
||||
|
||||
SUBDIRS = . m4macros glib gmodule gthread gobject gio tests po docs
|
||||
DIST_SUBDIRS = $(SUBDIRS) build
|
||||
|
||||
bin_SCRIPTS = glib-gettextize
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-DG_LOG_DOMAIN=g_log_domain_glib \
|
||||
@GLIB_DEBUG_FLAGS@ \
|
||||
-DG_DISABLE_DEPRECATED \
|
||||
-DGLIB_COMPILATION
|
||||
|
||||
EXTRA_DIST += \
|
||||
ChangeLog.pre-2-20 \
|
||||
ChangeLog.pre-2-18 \
|
||||
ChangeLog.pre-2-16 \
|
||||
ChangeLog.pre-2-14 \
|
||||
ChangeLog.pre-2-12 \
|
||||
ChangeLog.pre-2-10 \
|
||||
ChangeLog.pre-2-8 \
|
||||
ChangeLog.pre-2-6 \
|
||||
ChangeLog.pre-2-4 \
|
||||
ChangeLog.pre-2-2 \
|
||||
ChangeLog.pre-2-0 \
|
||||
ChangeLog.pre-1-2 \
|
||||
glib-zip.in \
|
||||
NEWS.pre-1-3 \
|
||||
acglib.m4 \
|
||||
sanity_check \
|
||||
README.commits \
|
||||
README.in \
|
||||
INSTALL.in \
|
||||
README.win32 \
|
||||
HACKING \
|
||||
autogen.sh \
|
||||
Makefile.decl \
|
||||
mkinstalldirs \
|
||||
makefile.msc \
|
||||
msvc_recommended_pragmas.h \
|
||||
config.h.win32.in \
|
||||
po/po2tbl.sed.in \
|
||||
glib-2.0.pc.in \
|
||||
gobject-2.0.pc.in \
|
||||
gmodule-2.0.pc.in \
|
||||
gmodule-export-2.0.pc.in \
|
||||
gmodule-no-export-2.0.pc.in \
|
||||
gthread-2.0.pc.in \
|
||||
gio-2.0.pc.in \
|
||||
gio-unix-2.0.pc.in \
|
||||
gio-windows-2.0.pc.in
|
||||
|
||||
|
||||
# These may be in the builddir too
|
||||
BUILT_EXTRA_DIST = \
|
||||
README \
|
||||
INSTALL \
|
||||
ChangeLog \
|
||||
config.h.win32 \
|
||||
gtk-doc.make
|
||||
|
||||
CONFIGURE_DEPENDENCIES = acglib.m4
|
||||
|
||||
ChangeLog:
|
||||
$(AM_V_GEN) if test -d "$(srcdir)/.git"; then \
|
||||
(GIT_DIR=$(top_srcdir)/.git ./missing --run git log GLIB_2_20_0^^.. --stat) | fmt --split-only > $@.tmp \
|
||||
&& mv -f $@.tmp $@ \
|
||||
|| ($(RM) $@.tmp; \
|
||||
echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \
|
||||
(test -f $@ || echo git-log is required to generate this file >> $@)); \
|
||||
else \
|
||||
test -f $@ || \
|
||||
(echo A git checkout and git-log is required to generate ChangeLog >&2 && \
|
||||
echo A git checkout and git-log is required to generate this file >> $@); \
|
||||
fi
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = glib-2.0.pc gobject-2.0.pc gmodule-2.0.pc gmodule-export-2.0.pc gmodule-no-export-2.0.pc gthread-2.0.pc gio-2.0.pc
|
||||
|
||||
if OS_UNIX
|
||||
pkgconfig_DATA += gio-unix-2.0.pc
|
||||
endif
|
||||
|
||||
if OS_WIN32
|
||||
pkgconfig_DATA += gio-windows-2.0.pc
|
||||
endif
|
||||
|
||||
$(pkgconfig_DATA): config.status
|
||||
|
||||
# install mkinstalldirs for glib-gettextize's benefit
|
||||
gettextdir = $(datadir)/glib-2.0/gettext
|
||||
gettext_SCRIPTS = mkinstalldirs
|
||||
|
||||
# build documentation when doing distcheck
|
||||
DISTCHECK_CONFIGURE_FLAGS = --enable-debug --enable-gtk-doc --enable-man --disable-maintainer-mode
|
||||
|
||||
DISTCLEANFILES = config.lt
|
||||
|
||||
distclean-local: lcov-clean
|
||||
if test $(srcdir) = .; then :; else \
|
||||
rm -f $(BUILT_EXTRA_DIST); \
|
||||
fi
|
||||
|
||||
.PHONY: files release sanity snapshot ChangeLog
|
||||
|
||||
files:
|
||||
@files=`ls $(DISTFILES) 2> /dev/null `; for p in $$files; do \
|
||||
echo $$p; \
|
||||
done
|
||||
|
||||
release:
|
||||
rm -rf .deps */.deps
|
||||
cd docs && make glib.html
|
||||
$(MAKE) distcheck
|
||||
|
||||
sanity:
|
||||
./sanity_check $(VERSION)
|
||||
|
||||
snapshot:
|
||||
$(MAKE) dist distdir=$(PACKAGE)-snap`date +"%Y%m%d"`
|
||||
|
||||
snapcheck:
|
||||
$(MAKE) distcheck distdir=$(PACKAGE)-snap`date +"%Y%m%d"`
|
||||
|
||||
dist-hook: $(BUILT_EXTRA_DIST)
|
||||
files='$(BUILT_EXTRA_DIST)'; \
|
||||
for f in $$files; do \
|
||||
if test -f $$f; then d=.; else d=$(srcdir); fi; \
|
||||
rm -f $(distdir)/$$f && cp $$d/$$f $(distdir) || exit 1; done
|
||||
97
glib/Makefile.decl
Normal file
97
glib/Makefile.decl
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
# GLIB - Library of useful C routines
|
||||
|
||||
#GTESTER = gtester # for non-GLIB packages
|
||||
GTESTER = $(top_builddir)/glib/gtester # for the GLIB package
|
||||
GTESTER_REPORT = $(top_builddir)/glib/gtester-report # for the GLIB package
|
||||
|
||||
# initialize variables for unconditional += appending
|
||||
EXTRA_DIST =
|
||||
TEST_PROGS =
|
||||
|
||||
### testing rules
|
||||
|
||||
# test: run all tests in cwd and subdirs
|
||||
test: test-nonrecursive
|
||||
if OS_UNIX
|
||||
@ for subdir in $(SUBDIRS) . ; do \
|
||||
test "$$subdir" = "." -o "$$subdir" = "po" || \
|
||||
( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $? ; \
|
||||
done
|
||||
|
||||
# test-nonrecursive: run tests only in cwd
|
||||
test-nonrecursive: ${TEST_PROGS}
|
||||
@test -z "${TEST_PROGS}" || G_DEBUG=gc-friendly MALLOC_CHECK_=2 MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256)) ${GTESTER} --verbose ${TEST_PROGS}
|
||||
else
|
||||
test-nonrecursive:
|
||||
endif
|
||||
|
||||
# test-report: run tests in subdirs and generate report
|
||||
# perf-report: run tests in subdirs with -m perf and generate report
|
||||
# full-report: like test-report: with -m perf and -m slow
|
||||
test-report perf-report full-report: ${TEST_PROGS}
|
||||
@test -z "${TEST_PROGS}" || { \
|
||||
case $@ in \
|
||||
test-report) test_options="-k";; \
|
||||
perf-report) test_options="-k -m=perf";; \
|
||||
full-report) test_options="-k -m=perf -m=slow";; \
|
||||
esac ; \
|
||||
if test -z "$$GTESTER_LOGDIR" ; then \
|
||||
${GTESTER} --verbose $$test_options -o test-report.xml ${TEST_PROGS} ; \
|
||||
elif test -n "${TEST_PROGS}" ; then \
|
||||
${GTESTER} --verbose $$test_options -o `mktemp "$$GTESTER_LOGDIR/log-XXXXXX"` ${TEST_PROGS} ; \
|
||||
fi ; \
|
||||
}
|
||||
@ ignore_logdir=true ; \
|
||||
if test -z "$$GTESTER_LOGDIR" ; then \
|
||||
GTESTER_LOGDIR=`mktemp -d "\`pwd\`/.testlogs-XXXXXX"`; export GTESTER_LOGDIR ; \
|
||||
ignore_logdir=false ; \
|
||||
fi ; \
|
||||
if test -d "$(top_srcdir)/.git" ; then \
|
||||
REVISION=`git describe` ; \
|
||||
else \
|
||||
REVISION=$(VERSION) ; \
|
||||
fi ; \
|
||||
for subdir in $(SUBDIRS) . ; do \
|
||||
test "$$subdir" = "." -o "$$subdir" = "po" || \
|
||||
( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $? ; \
|
||||
done ; \
|
||||
$$ignore_logdir || { \
|
||||
echo '<?xml version="1.0"?>' > $@.xml ; \
|
||||
echo '<report-collection>' >> $@.xml ; \
|
||||
echo '<info>' >> $@.xml ; \
|
||||
echo ' <package>$(PACKAGE)</package>' >> $@.xml ; \
|
||||
echo ' <version>$(VERSION)</version>' >> $@.xml ; \
|
||||
echo " <revision>$$REVISION</revision>" >> $@.xml ; \
|
||||
echo '</info>' >> $@.xml ; \
|
||||
for lf in `ls -L "$$GTESTER_LOGDIR"/.` ; do \
|
||||
sed '1,1s/^<?xml\b[^>?]*?>//' <"$$GTESTER_LOGDIR"/"$$lf" >> $@.xml ; \
|
||||
done ; \
|
||||
echo >> $@.xml ; \
|
||||
echo '</report-collection>' >> $@.xml ; \
|
||||
rm -rf "$$GTESTER_LOGDIR"/ ; \
|
||||
${GTESTER_REPORT} --version 2>/dev/null 1>&2 ; test "$$?" != 0 || ${GTESTER_REPORT} $@.xml >$@.html ; \
|
||||
}
|
||||
.PHONY: test test-report perf-report full-report test-nonrecursive
|
||||
|
||||
.PHONY: lcov genlcov lcov-clean
|
||||
# use recursive makes in order to ignore errors during check
|
||||
lcov:
|
||||
-$(MAKE) $(AM_MAKEFLAGS) -k check
|
||||
$(MAKE) $(AM_MAKEFLAGS) genlcov
|
||||
|
||||
# we have to massage the lcov.info file slightly to hide the effect of libtool
|
||||
# placing the objects files in the .libs/ directory separate from the *.c
|
||||
# we also have to delete tests/.libs/libmoduletestplugin_*.gcda
|
||||
genlcov:
|
||||
rm -f $(top_builddir)/tests/.libs/libmoduletestplugin_*.gcda
|
||||
$(LTP) --directory $(top_builddir) --capture --output-file glib-lcov.info --test-name GLIB_PERF --no-checksum --compat-libtool
|
||||
LANG=C $(LTP_GENHTML) --prefix $(top_builddir) --output-directory glib-lcov --title "GLib Code Coverage" --legend --show-details glib-lcov.info
|
||||
@echo "file://$(abs_top_builddir)/glib-lcov/index.html"
|
||||
|
||||
lcov-clean:
|
||||
-$(LTP) --directory $(top_builddir) -z
|
||||
-rm -rf glib-lcov.info glib-lcov
|
||||
-find -name '*.gcda' -print | xargs rm
|
||||
|
||||
# run tests in cwd as part of make check
|
||||
check-local: test-nonrecursive
|
||||
288
glib/README.in
Normal file
288
glib/README.in
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
General Information
|
||||
===================
|
||||
|
||||
This is GLib version @GLIB_VERSION@. GLib is the low-level core
|
||||
library that forms the basis for projects such as GTK+ and GNOME. It
|
||||
provides data structure handling for C, portability wrappers, and
|
||||
interfaces for such runtime functionality as an event loop, threads,
|
||||
dynamic loading, and an object system.
|
||||
|
||||
The official download locations are:
|
||||
ftp://ftp.gtk.org/pub/glib
|
||||
http://download.gnome.org/sources/glib
|
||||
|
||||
The official web site is:
|
||||
http://www.gtk.org/
|
||||
|
||||
Information about mailing lists can be found at
|
||||
http://www.gtk.org/mailing-lists.html
|
||||
|
||||
To subscribe, send mail to gtk-list-request@gnome.org
|
||||
with the subject "subscribe".
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
See the file 'INSTALL'
|
||||
|
||||
How to report bugs
|
||||
==================
|
||||
|
||||
Bugs should be reported to the GNOME bug tracking system.
|
||||
(http://bugzilla.gnome.org, product glib.) You will need
|
||||
to create an account for yourself.
|
||||
|
||||
In the bug report please include:
|
||||
|
||||
* Information about your system. For instance:
|
||||
|
||||
- What operating system and version
|
||||
- For Linux, what version of the C library
|
||||
|
||||
And anything else you think is relevant.
|
||||
|
||||
* How to reproduce the bug.
|
||||
|
||||
If you can reproduce it with one of the test programs that are built
|
||||
in the tests/ subdirectory, that will be most convenient. Otherwise,
|
||||
please include a short test program that exhibits the behavior.
|
||||
As a last resort, you can also provide a pointer to a larger piece
|
||||
of software that can be downloaded.
|
||||
|
||||
* If the bug was a crash, the exact text that was printed out
|
||||
when the crash occured.
|
||||
|
||||
* Further information such as stack traces may be useful, but
|
||||
is not necessary.
|
||||
|
||||
Patches
|
||||
=======
|
||||
|
||||
Patches should also be submitted to bugzilla.gnome.org. If the
|
||||
patch fixes an existing bug, add the patch as an attachment
|
||||
to that bug report.
|
||||
|
||||
Otherwise, enter a new bug report that describes the patch,
|
||||
and attach the patch to that bug report.
|
||||
|
||||
Patches should be in unified diff form. (The -up option to GNU diff.)
|
||||
|
||||
Notes about GLib 2.32
|
||||
=====================
|
||||
|
||||
* It is no longer necessary to use g_thread_init() or to link against
|
||||
libgthread. libglib is now always thread-enabled. Custom thread
|
||||
system implementations are no longer supported (including errorcheck
|
||||
mutexes).
|
||||
|
||||
* The thread and synchronisation APIs have been updated.
|
||||
GMutex and GCond can be statically allocated without explicit
|
||||
initialisation, as can new types GRWLock and GRecMutex. The
|
||||
GStatic_______ variants of these types have been deprecated. GPrivate
|
||||
can also be statically allocated and has a nicer API (deprecating
|
||||
GStaticPrivate). Finally, g_thread_create() has been replaced with a
|
||||
substantially simplified g_thread_new().
|
||||
|
||||
* The g_once_init_enter()/_leave() functions have been replaced with
|
||||
macros that allow for a pointer to any gsize-sized object, not just a
|
||||
gsize*. The assertions to ensure that a pointer to a correctly-sized
|
||||
object is being used will not work with generic pointers (ie: (void*)
|
||||
and (gpointer) casts) which would have worked with the old version.
|
||||
|
||||
* It is now mandatory to include glib.h instead of individual headers.
|
||||
|
||||
* The -uninstalled variants of the pkg-config files have been dropped.
|
||||
|
||||
* For a long time, gobject-2.0.pc mistakenly declared a public
|
||||
dependency on gthread-2.0.pc (when the dependency should have been
|
||||
private). This means that programs got away with calling
|
||||
g_thread_init() without explicitly listing gthread-2.0.pc among their
|
||||
dependencies.
|
||||
|
||||
gthread has now been removed as a gobject dependency, which will cause
|
||||
such programs to break.
|
||||
|
||||
The fix for this problem is either to declare an explicit dependency
|
||||
on gthread-2.0.pc (if you care about compatibility with older GLib
|
||||
versions) or to stop calling g_thread_init().
|
||||
|
||||
* g_debug() output is no longer enabled by default. It can be enabled
|
||||
on a per-domain basis with the G_MESSAGES_DEBUG environment variable
|
||||
like
|
||||
G_MESSAGES_DEBUG=domain1,domain2
|
||||
or
|
||||
G_MESSAGES_DEBUG=all
|
||||
|
||||
Notes about GLib 2.30
|
||||
=====================
|
||||
|
||||
* GObject includes a generic marshaller, g_cclosure_marshal_generic.
|
||||
To use it, simply specify NULL as the marshaller in g_signal_new().
|
||||
The generic marshaller is implemented with libffi, and consequently
|
||||
GObject depends on libffi now.
|
||||
|
||||
Notes about GLib 2.28
|
||||
=====================
|
||||
|
||||
* The GApplication API has changed compared to the version that was
|
||||
included in the 2.25 development snapshots. Existing users will need
|
||||
adjustments.
|
||||
|
||||
Notes about GLib 2.26
|
||||
=====================
|
||||
|
||||
* Nothing noteworthy.
|
||||
|
||||
Notes about GLib 2.24
|
||||
=====================
|
||||
|
||||
* It is now allowed to call g_thread_init(NULL) multiple times, and
|
||||
to call glib functions before g_thread_init(NULL) is called
|
||||
(although the later is mainly a change in docs as this worked before
|
||||
too). See the GThread reference documentation for the details.
|
||||
|
||||
* GObject now links to GThread and threads are enabled automatically
|
||||
when g_type_init() is called.
|
||||
|
||||
* GObject no longer allows to call g_object_set() on construct-only properties
|
||||
while an object is being initialized. If this behavior is needed, setting a
|
||||
custom constructor that just chains up will re-enable this functionality.
|
||||
|
||||
* GMappedFile on an empty file now returns NULL for the contents instead of
|
||||
returning an empty string. The documentation specifically states that code
|
||||
may not rely on nul-termination here so any breakage caused by this change
|
||||
is a bug in application code.
|
||||
|
||||
Notes about GLib 2.22
|
||||
=====================
|
||||
|
||||
* Repeated calls to g_simple_async_result_set_op_res_gpointer used
|
||||
to leak the data. This has been fixed to always call the provided
|
||||
destroy notify.
|
||||
|
||||
Notes about GLib 2.20
|
||||
=====================
|
||||
|
||||
* The functions for launching applications (e.g. g_app_info_launch() +
|
||||
friends) now passes a FUSE file:// URI if possible (requires gvfs
|
||||
with the FUSE daemon to be running and operational). With gvfs 2.26,
|
||||
FUSE file:// URIs will be mapped back to gio URIs in the GFile
|
||||
constructors. The intent of this change is to better integrate
|
||||
POSIX-only applications, see bug #528670 for the rationale. The
|
||||
only user-visible change is when an application needs to examine an
|
||||
URI passed to it (e.g. as a positional parameter). Instead of
|
||||
looking at the given URI, the application will now need to look at
|
||||
the result of g_file_get_uri() after having constructed a GFile
|
||||
object with the given URI.
|
||||
|
||||
Notes about GLib 2.18
|
||||
=====================
|
||||
|
||||
* The recommended way of using GLib has always been to only include the
|
||||
toplevel headers glib.h, glib-object.h and gio.h. GLib enforces this by
|
||||
generating an error when individual headers are directly included.
|
||||
To help with the transition, the enforcement is not turned on by
|
||||
default for GLib headers (it is turned on for GObject and GIO).
|
||||
To turn it on, define the preprocessor symbol G_DISABLE_SINGLE_INCLUDES.
|
||||
|
||||
Notes about GLib 2.16
|
||||
=====================
|
||||
|
||||
* GLib now includes GIO, which adds optional dependencies against libattr
|
||||
and libselinux for extended attribute and SELinux support. Use
|
||||
--disable-xattr and --disable-selinux to build without these.
|
||||
|
||||
Notes about GLib 2.10
|
||||
=====================
|
||||
|
||||
* The functions g_snprintf() and g_vsnprintf() have been removed from
|
||||
the gprintf.h header, since they are already declared in glib.h. This
|
||||
doesn't break documented use of gprintf.h, but people have been known
|
||||
to include gprintf.h without including glib.h.
|
||||
|
||||
* The Unicode support has been updated to Unicode 4.1. This adds several
|
||||
new members to the GUnicodeBreakType enumeration.
|
||||
|
||||
* The support for Solaris threads has been retired. Solaris has provided
|
||||
POSIX threads for long enough now to have them available on every
|
||||
Solaris platform.
|
||||
|
||||
* 'make check' has been changed to validate translations by calling
|
||||
msgfmt with the -c option. As a result, it may fail on systems with
|
||||
older gettext implementations (GNU gettext < 0.14.1, or Solaris gettext).
|
||||
'make check' will also fail on systems where the C compiler does not
|
||||
support ELF visibility attributes.
|
||||
|
||||
* The GMemChunk API has been deprecated in favour of a new 'slice
|
||||
allocator'. See the g_slice documentation for more details.
|
||||
|
||||
* A new type, GInitiallyUnowned, has been introduced, which is
|
||||
intended to serve as a common implementation of the 'floating reference'
|
||||
concept that is e.g. used by GtkObject. Note that changing the
|
||||
inheritance hierarchy of a type can cause problems for language
|
||||
bindings and other code which needs to work closely with the type
|
||||
system. Therefore, switching to GInitiallyUnowned should be done
|
||||
carefully. g_object_compat_control() has been added to GLib 2.8.5
|
||||
to help with the transition.
|
||||
|
||||
Notes about GLib 2.6.0
|
||||
======================
|
||||
|
||||
* GLib 2.6 introduces the concept of 'GLib filename encoding', which is the
|
||||
on-disk encoding on Unix, but UTF-8 on Windows. All GLib functions
|
||||
returning or accepting pathnames have been changed to expect
|
||||
filenames in this encoding, and the common POSIX functions dealing
|
||||
with pathnames have been wrapped. These wrappers are declared in the
|
||||
header <glib/gstdio.h> which must be included explicitly; it is not
|
||||
included through <glib.h>.
|
||||
|
||||
On current (NT-based) Windows versions, where the on-disk file names
|
||||
are Unicode, these wrappers use the wide-character API in the C
|
||||
library. Thus applications can handle file names containing any
|
||||
Unicode characters through GLib's own API and its POSIX wrappers,
|
||||
not just file names restricted to characters in the system codepage.
|
||||
|
||||
To keep binary compatibility with applications compiled against
|
||||
older versions of GLib, the Windows DLL still provides entry points
|
||||
with the old semantics using the old names, and applications
|
||||
compiled against GLib 2.6 will actually use new names for the
|
||||
functions. This is transparent to the programmer.
|
||||
|
||||
When compiling against GLib 2.6, applications intended to be
|
||||
portable to Windows must take the UTF-8 file name encoding into
|
||||
consideration, and use the gstdio wrappers to access files whose
|
||||
names have been constructed from strings returned from GLib.
|
||||
|
||||
* Likewise, g_get_user_name() and g_get_real_name() have been changed
|
||||
to return UTF-8 on Windows, while keeping the old semantics for
|
||||
applications compiled against older versions of GLib.
|
||||
|
||||
* The GLib uses an '_' prefix to indicate private symbols that
|
||||
must not be used by applications. On some platforms, symbols beginning
|
||||
with prefixes such as _g will be exported from the library, on others not.
|
||||
In no case can applications use these private symbols. In addition to that,
|
||||
GLib+ 2.6 makes several symbols private which were not in any installed
|
||||
header files and were never intended to be exported.
|
||||
|
||||
* To reduce code size and improve efficiency, GLib, when compiled
|
||||
with the GNU toolchain, has separate internal and external entry
|
||||
points for exported functions. The internal names, which begin with
|
||||
IA__, may be seen when debugging a GLib program.
|
||||
|
||||
* On Windows, GLib no longer opens a console window when printing
|
||||
warning messages if stdout or stderr are invalid, as they are in
|
||||
"Windows subsystem" (GUI) applications. Simply redirect stdout or
|
||||
stderr if you need to see them.
|
||||
|
||||
* The child watch functionality tends to reveal a bug in many
|
||||
thread implementations (in particular the older LinuxThreads
|
||||
implementation on Linux) where it's not possible to call waitpid()
|
||||
for a child created in a different thread. For this reason, for
|
||||
maximum portability, you should structure your code to fork all
|
||||
child processes that you want to wait for from the main thread.
|
||||
|
||||
* A problem was recently discovered with g_signal_connect_object();
|
||||
it doesn't actually disconnect the signal handler once the object being
|
||||
connected to dies, just disables it. See the API docs for the function
|
||||
for further details and the correct workaround that will continue to
|
||||
work with future versions of GLib.
|
||||
131
glib/acglib.m4
Normal file
131
glib/acglib.m4
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
## Portability defines that help interoperate with classic and modern autoconfs
|
||||
ifdef([AC_TR_SH],[
|
||||
define([GLIB_TR_SH],[AC_TR_SH([$1])])
|
||||
define([GLIB_TR_CPP],[AC_TR_CPP([$1])])
|
||||
], [
|
||||
define([GLIB_TR_SH],
|
||||
[patsubst(translit([[$1]], [*+], [pp]), [[^a-zA-Z0-9_]], [_])])
|
||||
define([GLIB_TR_CPP],
|
||||
[patsubst(translit([[$1]],
|
||||
[*abcdefghijklmnopqrstuvwxyz],
|
||||
[PABCDEFGHIJKLMNOPQRSTUVWXYZ]),
|
||||
[[^A-Z0-9_]], [_])])
|
||||
])
|
||||
|
||||
# GLIB_AC_DIVERT_BEFORE_HELP(STUFF)
|
||||
# ---------------------------------
|
||||
# Put STUFF early enough so that they are available for $ac_help expansion.
|
||||
# Handle both classic (<= v2.13) and modern autoconf
|
||||
AC_DEFUN([GLIB_AC_DIVERT_BEFORE_HELP],
|
||||
[ifdef([m4_divert_text], [m4_divert_text([NOTICE],[$1])],
|
||||
[ifdef([AC_DIVERT], [AC_DIVERT([NOTICE],[$1])],
|
||||
[AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)dnl
|
||||
$1
|
||||
AC_DIVERT_POP()])])])
|
||||
|
||||
dnl GLIB_IF_VAR_EQ (ENV_VAR, VALUE [, EQUALS_ACTION] [, ELSE_ACTION])
|
||||
AC_DEFUN([GLIB_IF_VAR_EQ],[
|
||||
case "$[$1]" in
|
||||
"[$2]"[)]
|
||||
[$3]
|
||||
;;
|
||||
*[)]
|
||||
[$4]
|
||||
;;
|
||||
esac
|
||||
])
|
||||
dnl GLIB_STR_CONTAINS (SRC_STRING, SUB_STRING [, CONTAINS_ACTION] [, ELSE_ACTION])
|
||||
AC_DEFUN([GLIB_STR_CONTAINS],[
|
||||
case "[$1]" in
|
||||
*"[$2]"*[)]
|
||||
[$3]
|
||||
;;
|
||||
*[)]
|
||||
[$4]
|
||||
;;
|
||||
esac
|
||||
])
|
||||
dnl GLIB_ADD_TO_VAR (ENV_VARIABLE, CHECK_STRING, ADD_STRING)
|
||||
AC_DEFUN([GLIB_ADD_TO_VAR],[
|
||||
GLIB_STR_CONTAINS($[$1], [$2], [$1]="$[$1]", [$1]="$[$1] [$3]")
|
||||
])
|
||||
|
||||
# GLIB_SIZEOF (INCLUDES, TYPE, ALIAS)
|
||||
# ---------------------------------------------------------------
|
||||
# The definition here is based of that of AC_CHECK_SIZEOF
|
||||
AC_DEFUN([GLIB_SIZEOF],
|
||||
[AS_LITERAL_IF([$3], [],
|
||||
[AC_FATAL([$0: requires literal arguments])])dnl
|
||||
AC_CACHE_CHECK([size of $2], AS_TR_SH([glib_cv_sizeof_$3]),
|
||||
[ # The cast to unsigned long works around a bug in the HP C Compiler
|
||||
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
|
||||
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
|
||||
# This bug is HP SR number 8606223364.
|
||||
_AC_COMPUTE_INT([(long) (sizeof ($2))],
|
||||
[AS_TR_SH([glib_cv_sizeof_$3])],
|
||||
[AC_INCLUDES_DEFAULT([$1])],
|
||||
[AC_MSG_ERROR([cannot compute sizeof ($2), 77])])
|
||||
])dnl
|
||||
AC_DEFINE_UNQUOTED(GLIB_TR_CPP(glib_sizeof_$3), $AS_TR_SH([glib_cv_sizeof_$3]),
|
||||
[The size of $3, as computed by sizeof.])
|
||||
])# GLIB_SIZEOF
|
||||
|
||||
dnl GLIB_BYTE_CONTENTS (INCLUDES, TYPE, ALIAS, N_BYTES, INITIALIZER)
|
||||
AC_DEFUN([GLIB_BYTE_CONTENTS],
|
||||
[pushdef([glib_ByteContents], GLIB_TR_SH([glib_cv_byte_contents_$3]))dnl
|
||||
AC_CACHE_CHECK([byte contents of $5], glib_ByteContents,
|
||||
[AC_TRY_RUN([#include <stdio.h>
|
||||
$1
|
||||
main()
|
||||
{
|
||||
static $2 tv = $5;
|
||||
char *p = (char*) &tv;
|
||||
int i;
|
||||
FILE *f=fopen("conftestval", "w");
|
||||
if (!f) exit(1);
|
||||
for (i = 0; i < $4; i++)
|
||||
fprintf(f, "%s%d", i?",":"", *(p++));
|
||||
fprintf(f, "\n");
|
||||
exit(0);
|
||||
}],
|
||||
[glib_ByteContents=`cat conftestval` dnl''
|
||||
],
|
||||
[glib_ByteContents=no],
|
||||
[glib_ByteContents=no])])
|
||||
AC_DEFINE_UNQUOTED(GLIB_TR_CPP(glib_byte_contents_$3), [$[]glib_ByteContents],
|
||||
[Byte contents of $3])
|
||||
popdef([glib_ByteContents])dnl
|
||||
])
|
||||
|
||||
# GLIB_CHECK_VALUE(SYMBOL, INCLUDES, ACTION-IF-FAIL)
|
||||
# ---------------------------------------------------------------
|
||||
AC_DEFUN([GLIB_CHECK_VALUE],
|
||||
[AC_CACHE_CHECK([value of $1], AS_TR_SH([glib_cv_value_$1]),
|
||||
[_AC_COMPUTE_INT([$1], AS_TR_SH([glib_cv_value_$1]), [$2], [$3])])
|
||||
])dnl
|
||||
|
||||
# GLIB_CHECK_COMPILE_WARNINGS(PROGRAM, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
# ---------------------------------------------------------------------
|
||||
# Try to compile PROGRAM, check for warnings
|
||||
m4_define([GLIB_CHECK_COMPILE_WARNINGS],
|
||||
[m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl
|
||||
rm -f conftest.$ac_objext
|
||||
glib_ac_compile_save="$ac_compile"
|
||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext'
|
||||
AS_IF([_AC_EVAL_STDERR($ac_compile) &&
|
||||
AC_TRY_COMMAND([(if test -s conftest.err; then false ; else true; fi)])],
|
||||
[$2],
|
||||
[echo "$as_me: failed program was:" >&AS_MESSAGE_LOG_FD
|
||||
cat conftest.$ac_ext >&AS_MESSAGE_LOG_FD
|
||||
m4_ifvaln([$3],[$3])dnl])
|
||||
ac_compile="$glib_ac_compile_save"
|
||||
rm -f conftest.$ac_objext conftest.err m4_ifval([$1], [conftest.$ac_ext])[]dnl
|
||||
])# GLIB_CHECK_COMPILE_WARNINGS
|
||||
|
||||
# GLIB_ASSERT_SET(VARIABLE)
|
||||
# -------------------------
|
||||
AC_DEFUN([GLIB_ASSERT_SET],
|
||||
[if test "x${$1+set}" != "xset" ; then
|
||||
AC_MSG_ERROR($1 [must be set in cache file when cross-compiling.])
|
||||
fi
|
||||
])dnl
|
||||
452
glib/acinclude.m4
Normal file
452
glib/acinclude.m4
Normal file
|
|
@ -0,0 +1,452 @@
|
|||
dnl @synopsis AC_FUNC_VSNPRINTF_C99
|
||||
dnl
|
||||
dnl Check whether there is a vsnprintf() function with C99 semantics installed.
|
||||
dnl
|
||||
AC_DEFUN([AC_FUNC_VSNPRINTF_C99],
|
||||
[AC_CACHE_CHECK(for C99 vsnprintf,
|
||||
ac_cv_func_vsnprintf_c99,
|
||||
[AC_TRY_RUN(
|
||||
[#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int
|
||||
doit(char * s, ...)
|
||||
{
|
||||
char buffer[32];
|
||||
va_list args;
|
||||
int r;
|
||||
|
||||
va_start(args, s);
|
||||
r = vsnprintf(buffer, 5, s, args);
|
||||
va_end(args);
|
||||
|
||||
if (r != 7)
|
||||
exit(1);
|
||||
|
||||
/* AIX 5.1 and Solaris seems to have a half-baked vsnprintf()
|
||||
implementation. The above will return 7 but if you replace
|
||||
the size of the buffer with 0, it borks! */
|
||||
va_start(args, s);
|
||||
r = vsnprintf(buffer, 0, s, args);
|
||||
va_end(args);
|
||||
|
||||
if (r != 7)
|
||||
exit(1);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
doit("1234567");
|
||||
exit(1);
|
||||
}], ac_cv_func_vsnprintf_c99=yes, ac_cv_func_vsnprintf_c99=no, ac_cv_func_vsnprintf_c99=no)])
|
||||
dnl Note that the default is to be pessimistic in the case of cross compilation.
|
||||
dnl If you know that the target has a C99 vsnprintf(), you can get around this
|
||||
dnl by setting ac_func_vsnprintf_c99 to yes, as described in the Autoconf manual.
|
||||
if test $ac_cv_func_vsnprintf_c99 = yes; then
|
||||
AC_DEFINE(HAVE_C99_VSNPRINTF, 1,
|
||||
[Define if you have a version of the vsnprintf function
|
||||
with semantics as specified by the ISO C99 standard.])
|
||||
fi
|
||||
])# AC_FUNC_VSNPRINTF_C99
|
||||
|
||||
|
||||
dnl @synopsis AC_FUNC_SNPRINTF_C99
|
||||
dnl
|
||||
dnl Check whether there is a snprintf() function with C99 semantics installed.
|
||||
dnl
|
||||
AC_DEFUN([AC_FUNC_SNPRINTF_C99],
|
||||
[AC_CACHE_CHECK(for C99 snprintf,
|
||||
ac_cv_func_snprintf_c99,
|
||||
[AC_TRY_RUN(
|
||||
[#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int
|
||||
doit()
|
||||
{
|
||||
char buffer[32];
|
||||
va_list args;
|
||||
int r;
|
||||
|
||||
r = snprintf(buffer, 5, "1234567");
|
||||
|
||||
if (r != 7)
|
||||
exit(1);
|
||||
|
||||
r = snprintf(buffer, 0, "1234567");
|
||||
|
||||
if (r != 7)
|
||||
exit(1);
|
||||
|
||||
r = snprintf(NULL, 0, "1234567");
|
||||
|
||||
if (r != 7)
|
||||
exit(1);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
doit();
|
||||
exit(1);
|
||||
}], ac_cv_func_snprintf_c99=yes, ac_cv_func_snprintf_c99=no, ac_cv_func_snprintf_c99=no)])
|
||||
dnl Note that the default is to be pessimistic in the case of cross compilation.
|
||||
dnl If you know that the target has a C99 snprintf(), you can get around this
|
||||
dnl by setting ac_func_snprintf_c99 to yes, as described in the Autoconf manual.
|
||||
if test $ac_cv_func_snprintf_c99 = yes; then
|
||||
AC_DEFINE(HAVE_C99_SNPRINTF, 1,
|
||||
[Define if you have a version of the snprintf function
|
||||
with semantics as specified by the ISO C99 standard.])
|
||||
fi
|
||||
])# AC_FUNC_SNPRINTF_C99
|
||||
|
||||
|
||||
dnl @synopsis AC_FUNC_PRINTF_UNIX98
|
||||
dnl
|
||||
dnl Check whether the printf() family supports Unix98 %n$ positional parameters
|
||||
dnl
|
||||
AC_DEFUN([AC_FUNC_PRINTF_UNIX98],
|
||||
[AC_CACHE_CHECK(whether printf supports positional parameters,
|
||||
ac_cv_func_printf_unix98,
|
||||
[AC_TRY_RUN(
|
||||
[#include <stdio.h>
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
char buffer[128];
|
||||
|
||||
sprintf (buffer, "%2\$d %3\$d %1\$d", 1, 2, 3);
|
||||
if (strcmp ("2 3 1", buffer) == 0)
|
||||
exit (0);
|
||||
exit (1);
|
||||
}], ac_cv_func_printf_unix98=yes, ac_cv_func_printf_unix98=no, ac_cv_func_printf_unix98=no)])
|
||||
dnl Note that the default is to be pessimistic in the case of cross compilation.
|
||||
dnl If you know that the target printf() supports positional parameters, you can get around
|
||||
dnl this by setting ac_func_printf_unix98 to yes, as described in the Autoconf manual.
|
||||
if test $ac_cv_func_printf_unix98 = yes; then
|
||||
AC_DEFINE(HAVE_UNIX98_PRINTF, 1,
|
||||
[Define if your printf function family supports positional parameters
|
||||
as specified by Unix98.])
|
||||
fi
|
||||
])# AC_FUNC_PRINTF_UNIX98
|
||||
|
||||
# Checks the location of the XML Catalog
|
||||
# Usage:
|
||||
# JH_PATH_XML_CATALOG([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
# Defines XMLCATALOG and XML_CATALOG_FILE substitutions
|
||||
AC_DEFUN([JH_PATH_XML_CATALOG],
|
||||
[
|
||||
# check for the presence of the XML catalog
|
||||
AC_ARG_WITH([xml-catalog],
|
||||
AC_HELP_STRING([--with-xml-catalog=CATALOG],
|
||||
[path to xml catalog to use]),,
|
||||
[with_xml_catalog=/etc/xml/catalog])
|
||||
jh_found_xmlcatalog=true
|
||||
XML_CATALOG_FILE="$with_xml_catalog"
|
||||
AC_SUBST([XML_CATALOG_FILE])
|
||||
AC_MSG_CHECKING([for XML catalog ($XML_CATALOG_FILE)])
|
||||
if test -f "$XML_CATALOG_FILE"; then
|
||||
AC_MSG_RESULT([found])
|
||||
else
|
||||
jh_found_xmlcatalog=false
|
||||
AC_MSG_RESULT([not found])
|
||||
fi
|
||||
|
||||
# check for the xmlcatalog program
|
||||
AC_PATH_PROG(XMLCATALOG, xmlcatalog, no)
|
||||
if test "x$XMLCATALOG" = xno; then
|
||||
jh_found_xmlcatalog=false
|
||||
fi
|
||||
|
||||
if $jh_found_xmlcatalog; then
|
||||
ifelse([$1],,[:],[$1])
|
||||
else
|
||||
ifelse([$2],,[AC_MSG_ERROR([could not find XML catalog])],[$2])
|
||||
fi
|
||||
])
|
||||
|
||||
# Checks if a particular URI appears in the XML catalog
|
||||
# Usage:
|
||||
# JH_CHECK_XML_CATALOG(URI, [FRIENDLY-NAME], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
AC_DEFUN([JH_CHECK_XML_CATALOG],
|
||||
[
|
||||
AC_REQUIRE([JH_PATH_XML_CATALOG],[JH_PATH_XML_CATALOG(,[:])])dnl
|
||||
AC_MSG_CHECKING([for ifelse([$2],,[$1],[$2]) in XML catalog])
|
||||
if $jh_found_xmlcatalog && \
|
||||
AC_RUN_LOG([$XMLCATALOG --noout "$XML_CATALOG_FILE" "$1" >&2]); then
|
||||
AC_MSG_RESULT([found])
|
||||
ifelse([$3],,,[$3
|
||||
])dnl
|
||||
else
|
||||
AC_MSG_RESULT([not found])
|
||||
ifelse([$4],,
|
||||
[AC_MSG_ERROR([could not find ifelse([$2],,[$1],[$2]) in XML catalog])],
|
||||
[$4])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
# signed.m4 serial 1 (gettext-0.10.40)
|
||||
dnl Copyright (C) 2001-2002 Free Software Foundation, Inc.
|
||||
dnl This file is free software, distributed under the terms of the GNU
|
||||
dnl General Public License. As a special exception to the GNU General
|
||||
dnl Public License, this file may be distributed as part of a program
|
||||
dnl that contains a configuration script generated by Autoconf, under
|
||||
dnl the same distribution terms as the rest of that program.
|
||||
|
||||
dnl From Bruno Haible.
|
||||
|
||||
AC_DEFUN([bh_C_SIGNED],
|
||||
[
|
||||
AC_CACHE_CHECK([for signed], bh_cv_c_signed,
|
||||
[AC_TRY_COMPILE(, [signed char x;], bh_cv_c_signed=yes, bh_cv_c_signed=no)])
|
||||
if test $bh_cv_c_signed = no; then
|
||||
AC_DEFINE(signed, ,
|
||||
[Define to empty if the C compiler doesn't support this keyword.])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
# longlong.m4 serial 4
|
||||
dnl Copyright (C) 1999-2003 Free Software Foundation, Inc.
|
||||
dnl This file is free software, distributed under the terms of the GNU
|
||||
dnl General Public License. As a special exception to the GNU General
|
||||
dnl Public License, this file may be distributed as part of a program
|
||||
dnl that contains a configuration script generated by Autoconf, under
|
||||
dnl the same distribution terms as the rest of that program.
|
||||
|
||||
dnl From Paul Eggert.
|
||||
|
||||
# Define HAVE_LONG_LONG if 'long long' works.
|
||||
|
||||
AC_DEFUN([jm_AC_TYPE_LONG_LONG],
|
||||
[
|
||||
AC_CACHE_CHECK([for long long], ac_cv_type_long_long,
|
||||
[AC_TRY_LINK([long long ll = 1LL; int i = 63;],
|
||||
[long long llmax = (long long) -1;
|
||||
return ll << i | ll >> i | llmax / ll | llmax % ll;],
|
||||
ac_cv_type_long_long=yes,
|
||||
ac_cv_type_long_long=no)])
|
||||
if test $ac_cv_type_long_long = yes; then
|
||||
AC_DEFINE(HAVE_LONG_LONG, 1,
|
||||
[Define if you have the 'long long' type.])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
# longdouble.m4 serial 1 (gettext-0.11.6)
|
||||
dnl Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
dnl This file is free software, distributed under the terms of the GNU
|
||||
dnl General Public License. As a special exception to the GNU General
|
||||
dnl Public License, this file may be distributed as part of a program
|
||||
dnl that contains a configuration script generated by Autoconf, under
|
||||
dnl the same distribution terms as the rest of that program.
|
||||
|
||||
dnl From Bruno Haible.
|
||||
dnl Test whether the compiler supports the 'long double' type.
|
||||
dnl Prerequisite: AC_PROG_CC
|
||||
|
||||
AC_DEFUN([gt_TYPE_LONGDOUBLE],
|
||||
[
|
||||
AC_CACHE_CHECK([for long double], gt_cv_c_long_double,
|
||||
[if test "$GCC" = yes; then
|
||||
gt_cv_c_long_double=yes
|
||||
else
|
||||
AC_TRY_COMPILE([
|
||||
/* The Stardent Vistra knows sizeof(long double), but does not support it. */
|
||||
long double foo = 0.0;
|
||||
/* On Ultrix 4.3 cc, long double is 4 and double is 8. */
|
||||
int array [2*(sizeof(long double) >= sizeof(double)) - 1];
|
||||
], ,
|
||||
gt_cv_c_long_double=yes, gt_cv_c_long_double=no)
|
||||
fi])
|
||||
if test $gt_cv_c_long_double = yes; then
|
||||
AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the 'long double' type.])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
|
||||
# wchar_t.m4 serial 1 (gettext-0.11.6)
|
||||
dnl Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
dnl This file is free software, distributed under the terms of the GNU
|
||||
dnl General Public License. As a special exception to the GNU General
|
||||
dnl Public License, this file may be distributed as part of a program
|
||||
dnl that contains a configuration script generated by Autoconf, under
|
||||
dnl the same distribution terms as the rest of that program.
|
||||
|
||||
dnl From Bruno Haible.
|
||||
dnl Test whether <stddef.h> has the 'wchar_t' type.
|
||||
dnl Prerequisite: AC_PROG_CC
|
||||
|
||||
AC_DEFUN([gt_TYPE_WCHAR_T],
|
||||
[
|
||||
AC_CACHE_CHECK([for wchar_t], gt_cv_c_wchar_t,
|
||||
[AC_TRY_COMPILE([#include <stddef.h>
|
||||
wchar_t foo = (wchar_t)'\0';], ,
|
||||
gt_cv_c_wchar_t=yes, gt_cv_c_wchar_t=no)])
|
||||
if test $gt_cv_c_wchar_t = yes; then
|
||||
AC_DEFINE(HAVE_WCHAR_T, 1, [Define if you have the 'wchar_t' type.])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
# wint_t.m4 serial 1
|
||||
dnl Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
dnl This file is free software, distributed under the terms of the GNU
|
||||
dnl General Public License. As a special exception to the GNU General
|
||||
dnl Public License, this file may be distributed as part of a program
|
||||
dnl that contains a configuration script generated by Autoconf, under
|
||||
dnl the same distribution terms as the rest of that program.
|
||||
|
||||
dnl From Bruno Haible.
|
||||
dnl Test whether <wchar.h> has the 'wint_t' type.
|
||||
dnl Prerequisite: AC_PROG_CC
|
||||
|
||||
AC_DEFUN([gt_TYPE_WINT_T],
|
||||
[
|
||||
AC_CACHE_CHECK([for wint_t], gt_cv_c_wint_t,
|
||||
[AC_TRY_COMPILE([#include <wchar.h>
|
||||
wint_t foo = (wchar_t)'\0';], ,
|
||||
gt_cv_c_wint_t=yes, gt_cv_c_wint_t=no)])
|
||||
if test $gt_cv_c_wint_t = yes; then
|
||||
AC_DEFINE(HAVE_WINT_T, 1, [Define if you have the 'wint_t' type.])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
# intmax_t.m4 serial 1
|
||||
dnl Copyright (C) 1997-2002 Free Software Foundation, Inc.
|
||||
dnl This file is free software, distributed under the terms of the GNU
|
||||
dnl General Public License. As a special exception to the GNU General
|
||||
dnl Public License, this file may be distributed as part of a program
|
||||
dnl that contains a configuration script generated by Autoconf, under
|
||||
dnl the same distribution terms as the rest of that program.
|
||||
|
||||
dnl From Paul Eggert.
|
||||
|
||||
AC_PREREQ(2.13)
|
||||
|
||||
# Define intmax_t to 'long' or 'long long'
|
||||
# if it is not already defined in <stdint.h> or <inttypes.h>.
|
||||
|
||||
AC_DEFUN([jm_AC_TYPE_INTMAX_T],
|
||||
[
|
||||
dnl For simplicity, we assume that a header file defines 'intmax_t' if and
|
||||
dnl only if it defines 'uintmax_t'.
|
||||
AC_REQUIRE([jm_AC_HEADER_INTTYPES_H])
|
||||
AC_REQUIRE([jm_AC_HEADER_STDINT_H])
|
||||
if test $jm_ac_cv_header_inttypes_h = no && test $jm_ac_cv_header_stdint_h = no; then
|
||||
AC_REQUIRE([jm_AC_TYPE_LONG_LONG])
|
||||
test $ac_cv_type_long_long = yes \
|
||||
&& ac_type='long long' \
|
||||
|| ac_type='long'
|
||||
AC_DEFINE_UNQUOTED(intmax_t, $ac_type,
|
||||
[Define to long or long long if <inttypes.h> and <stdint.h> don't define.])
|
||||
else
|
||||
AC_DEFINE(HAVE_INTMAX_T, 1,
|
||||
[Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl An alternative would be to explicitly test for 'intmax_t'.
|
||||
|
||||
AC_DEFUN([gt_AC_TYPE_INTMAX_T],
|
||||
[
|
||||
AC_REQUIRE([jm_AC_HEADER_INTTYPES_H])
|
||||
AC_REQUIRE([jm_AC_HEADER_STDINT_H])
|
||||
AC_CACHE_CHECK(for intmax_t, gt_cv_c_intmax_t,
|
||||
[AC_TRY_COMPILE([
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#if HAVE_STDINT_H_WITH_UINTMAX
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#if HAVE_INTTYPES_H_WITH_UINTMAX
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
], [intmax_t x = -1;], gt_cv_c_intmax_t=yes, gt_cv_c_intmax_t=no)])
|
||||
if test $gt_cv_c_intmax_t = yes; then
|
||||
AC_DEFINE(HAVE_INTMAX_T, 1,
|
||||
[Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.])
|
||||
else
|
||||
AC_REQUIRE([jm_AC_TYPE_LONG_LONG])
|
||||
test $ac_cv_type_long_long = yes \
|
||||
&& ac_type='long long' \
|
||||
|| ac_type='long'
|
||||
AC_DEFINE_UNQUOTED(intmax_t, $ac_type,
|
||||
[Define to long or long long if <stdint.h> and <inttypes.h> don't define.])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
# stdint_h.m4 serial 3 (gettext-0.11.6)
|
||||
dnl Copyright (C) 1997-2002 Free Software Foundation, Inc.
|
||||
dnl This file is free software, distributed under the terms of the GNU
|
||||
dnl General Public License. As a special exception to the GNU General
|
||||
dnl Public License, this file may be distributed as part of a program
|
||||
dnl that contains a configuration script generated by Autoconf, under
|
||||
dnl the same distribution terms as the rest of that program.
|
||||
|
||||
dnl From Paul Eggert.
|
||||
|
||||
# Define HAVE_STDINT_H_WITH_UINTMAX if <stdint.h> exists,
|
||||
# doesn't clash with <sys/types.h>, and declares uintmax_t.
|
||||
|
||||
AC_DEFUN([jm_AC_HEADER_STDINT_H],
|
||||
[
|
||||
AC_CACHE_CHECK([for stdint.h], jm_ac_cv_header_stdint_h,
|
||||
[AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>
|
||||
#include <stdint.h>],
|
||||
[uintmax_t i = (uintmax_t) -1;],
|
||||
jm_ac_cv_header_stdint_h=yes,
|
||||
jm_ac_cv_header_stdint_h=no)])
|
||||
if test $jm_ac_cv_header_stdint_h = yes; then
|
||||
AC_DEFINE_UNQUOTED(HAVE_STDINT_H_WITH_UINTMAX, 1,
|
||||
[Define if <stdint.h> exists, doesn't clash with <sys/types.h>,
|
||||
and declares uintmax_t. ])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
# inttypes_h.m4 serial 5 (gettext-0.11.6)
|
||||
dnl Copyright (C) 1997-2002 Free Software Foundation, Inc.
|
||||
dnl This file is free software, distributed under the terms of the GNU
|
||||
dnl General Public License. As a special exception to the GNU General
|
||||
dnl Public License, this file may be distributed as part of a program
|
||||
dnl that contains a configuration script generated by Autoconf, under
|
||||
dnl the same distribution terms as the rest of that program.
|
||||
|
||||
dnl From Paul Eggert.
|
||||
|
||||
# Define HAVE_INTTYPES_H_WITH_UINTMAX if <inttypes.h> exists,
|
||||
# doesn't clash with <sys/types.h>, and declares uintmax_t.
|
||||
|
||||
AC_DEFUN([jm_AC_HEADER_INTTYPES_H],
|
||||
[
|
||||
AC_CACHE_CHECK([for inttypes.h], jm_ac_cv_header_inttypes_h,
|
||||
[AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>
|
||||
#include <inttypes.h>],
|
||||
[uintmax_t i = (uintmax_t) -1;],
|
||||
jm_ac_cv_header_inttypes_h=yes,
|
||||
jm_ac_cv_header_inttypes_h=no)])
|
||||
if test $jm_ac_cv_header_inttypes_h = yes; then
|
||||
AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H_WITH_UINTMAX, 1,
|
||||
[Define if <inttypes.h> exists, doesn't clash with <sys/types.h>,
|
||||
and declares uintmax_t. ])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
m4_include(acglib.m4)dnl
|
||||
m4_include(glib/libcharset/codeset.m4)dnl
|
||||
m4_include(glib/libcharset/glibc21.m4)dnl
|
||||
m4_include(m4macros/glib-gettext.m4)dnl
|
||||
3571
glib/configure.ac
Normal file
3571
glib/configure.ac
Normal file
File diff suppressed because it is too large
Load diff
188
glib/glib-gettextize.in
Normal file
188
glib/glib-gettextize.in
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
#! /bin/sh
|
||||
#
|
||||
# Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
|
||||
# - Modified in October 2001 by jacob berkman <jacob@ximian.com> to
|
||||
# work with glib's Makefile.in.in and po2tbl.sed.in, to not copy in
|
||||
# intl/, and to not add ChangeLog entries to po/ChangeLog
|
||||
|
||||
# This file is meant for authors or maintainers which want to
|
||||
# internationalize their package with the help of GNU gettext. For
|
||||
# further information how to use it consult the GNU gettext manual.
|
||||
|
||||
echo=echo
|
||||
progname=$0
|
||||
force=0
|
||||
configstatus=0
|
||||
origdir=`pwd`
|
||||
usage="\
|
||||
Usage: glib-gettextize [OPTION]... [package-dir]
|
||||
--help print this help and exit
|
||||
--version print version information and exit
|
||||
-c, --copy copy files instead of making symlinks
|
||||
-f, --force force writing of new files even if old exist
|
||||
Report bugs to http://bugzilla.gnome.org/."
|
||||
package=@PACKAGE@
|
||||
version=@VERSION@
|
||||
try_ln_s=:
|
||||
|
||||
# Directory where the sources are stored.
|
||||
prefix=@prefix@
|
||||
case `uname` in
|
||||
MINGW32*)
|
||||
prefix="`dirname $0`/.."
|
||||
;;
|
||||
esac
|
||||
|
||||
datadir=@datadir@
|
||||
datarootdir=@datarootdir@
|
||||
|
||||
gettext_dir=$prefix/share/glib-2.0/gettext
|
||||
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
-c | --copy | --c* )
|
||||
shift
|
||||
try_ln_s=false ;;
|
||||
-f | --force | --f* )
|
||||
shift
|
||||
force=1 ;;
|
||||
-r | --run | --r* )
|
||||
shift
|
||||
configstatus=1 ;;
|
||||
--help | --h* )
|
||||
$echo "$usage"; exit 0 ;;
|
||||
--version | --v* )
|
||||
echo "$progname (GNU $package) $version"
|
||||
$echo "Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
$echo "Written by" "Ulrich Drepper"
|
||||
exit 0 ;;
|
||||
-- ) # Stop option prcessing
|
||||
shift; break ;;
|
||||
-* )
|
||||
$echo "glib-gettextize: unknown option $1"
|
||||
$echo "Try \`glib-gettextize --help' for more information."; exit 1 ;;
|
||||
* )
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if test $# -gt 1; then
|
||||
$echo "$usage"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Fill in the command line options value.
|
||||
if test $# -eq 1; then
|
||||
srcdir=$1
|
||||
if cd "$srcdir"; then
|
||||
srcdir=`pwd`
|
||||
else
|
||||
$echo "Cannot change directory to \`$srcdir'"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
srcdir=$origdir
|
||||
fi
|
||||
|
||||
test -f configure.in || test -f configure.ac || {
|
||||
$echo "Missing configure.in or configure.ac, please cd to your package first."
|
||||
exit 1
|
||||
}
|
||||
|
||||
configure_in=NONE
|
||||
if test -f configure.in; then
|
||||
configure_in=configure.in
|
||||
else
|
||||
if test -f configure.ac; then
|
||||
configure_in=configure.ac
|
||||
fi
|
||||
fi
|
||||
# Check in which directory config.rpath, mkinstalldirs etc. belong.
|
||||
auxdir=`cat "$configure_in" | grep '^AC_CONFIG_AUX_DIR' | sed -n -e 's/AC_CONFIG_AUX_DIR(\([^()]*\))/\1/p' | sed -e 's/^\[\(.*\)\]$/\1/' | sed -e 1q`
|
||||
if test -n "$auxdir"; then
|
||||
auxdir="$auxdir/"
|
||||
fi
|
||||
|
||||
if test -f po/Makefile.in.in && test $force -eq 0; then
|
||||
$echo "\
|
||||
po/Makefile.in.in exists: use option -f if you really want to delete it."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test -d po || {
|
||||
$echo "Creating po/ subdirectory"
|
||||
mkdir po || {
|
||||
$echo "failed to create po/ subdirectory"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# For simplicity we changed to the gettext source directory.
|
||||
cd $gettext_dir || {
|
||||
$echo "gettext source directory '${gettext_dir}' doesn't exist"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Now copy all files. Take care for the destination directories.
|
||||
for file in *; do
|
||||
case $file in
|
||||
intl | po)
|
||||
;;
|
||||
mkinstalldirs)
|
||||
rm -f "$srcdir/$auxdir$file"
|
||||
($try_ln_s && ln -s $gettext_dir/$file "$srcdir/$auxdir$file" && $echo "Symlinking file $file") 2>/dev/null ||
|
||||
{ $echo "Copying file $file"; cp $file "$srcdir/$auxdir$file"; }
|
||||
;;
|
||||
*)
|
||||
rm -f "$srcdir/$file"
|
||||
($try_ln_s && ln -s $gettext_dir/$file "$srcdir/$file" && $echo "Symlinking file $file") 2>/dev/null ||
|
||||
{ $echo "Copying file $file"; cp $file "$srcdir/$file"; }
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Copy files to po/ subdirectory.
|
||||
cd po
|
||||
for file in *; do
|
||||
rm -f "$srcdir/po/$file"
|
||||
($try_ln_s && ln -s $gettext_dir/po/$file "$srcdir/po/$file" && $echo "Symlinking file po/$file") 2>/dev/null ||
|
||||
{ $echo "Copying file po/$file"; cp $file "$srcdir/po/$file"; }
|
||||
done
|
||||
if test -f "$srcdir/po/cat-id-tbl.c"; then
|
||||
$echo "Removing po/cat-id-tbl.c"
|
||||
rm -f "$srcdir/po/cat-id-tbl.c"
|
||||
fi
|
||||
if test -f "$srcdir/po/stamp-cat-id"; then
|
||||
$echo "Removing po/stamp-cat-id"
|
||||
rm -f "$srcdir/po/stamp-cat-id"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Please add the files"
|
||||
echo " codeset.m4 gettext.m4 glibc21.m4 iconv.m4 isc-posix.m4 lcmessage.m4"
|
||||
echo " progtest.m4"
|
||||
echo "from the $datadir/aclocal directory to your autoconf macro directory"
|
||||
echo "or directly to your aclocal.m4 file."
|
||||
echo "You will also need config.guess and config.sub, which you can get from"
|
||||
echo "ftp://ftp.gnu.org/pub/gnu/config/."
|
||||
echo
|
||||
|
||||
exit 0
|
||||
47
glib/glib.doap
Normal file
47
glib/glib.doap
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
|
||||
xmlns:foaf="http://xmlns.com/foaf/0.1/"
|
||||
xmlns:gnome="http://api.gnome.org/doap-extensions#"
|
||||
xmlns="http://usefulinc.com/ns/doap#">
|
||||
|
||||
<name>GLib</name>
|
||||
<shortname>glib</shortname>
|
||||
|
||||
<shortdesc xml:lang="en">Low level core library</shortdesc>
|
||||
|
||||
<description xml:lang="en">GLib is the low-level core library that forms the basis for projects such as GTK+ and GNOME. It provides data structure handling for C, portability wrappers, and interfaces for such runtime functionality as an event loop, threads, dynamic loading, and an object system.</description>
|
||||
|
||||
<homepage rdf:resource="http://www.gtk.org" />
|
||||
<license rdf:resource="http://usefulinc.com/doap/licenses/lgpl" />
|
||||
<bug-database rdf:resource="http://bugzilla.gnome.org/enter_bug.cgi?product=glib"/>
|
||||
<download-page rdf:resource="http://download.gnome.org/sources/glib/" />
|
||||
<mailing-list rdf:resource="mailto:gtk-devel-list@gnome.org" />
|
||||
<category rdf:resource="http://api.gnome.org/doap-extensions#platform" />
|
||||
|
||||
<programming-language>C</programming-language>
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Matthias Clasen</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:mclasen@redhat.com"/>
|
||||
<gnome:userid>matthiasc</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Ryan Lortie</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:desrt@desrt.ca"/>
|
||||
<gnome:userid>ryanl</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<repository>
|
||||
<GitRepository>
|
||||
<browse rdf:resource="http://git.gnome.org/browse/glib/"/>
|
||||
<location rdf:resource="git://git.gnome.org/glib"/>
|
||||
</GitRepository>
|
||||
</repository>
|
||||
|
||||
</Project>
|
||||
12
glib/glib/.gitignore
vendored
Normal file
12
glib/glib/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
glibconfig.h
|
||||
glibconfig.h.win32
|
||||
glibconfig-stamp
|
||||
|
||||
gtester
|
||||
libglib-gdb.py
|
||||
makefile.msc
|
||||
gspawn-win32-helper-console.c
|
||||
gspawn-win64-helper-console.c
|
||||
gspawn-win64-helper.c
|
||||
glib_probes.h
|
||||
glib-public-headers.txt
|
||||
526
glib/glib/Makefile.am
Normal file
526
glib/glib/Makefile.am
Normal file
|
|
@ -0,0 +1,526 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
include $(top_srcdir)/Makefile.decl
|
||||
|
||||
BUILT_SOURCES =
|
||||
DISTCLEANFILES =
|
||||
CLEANFILES =
|
||||
|
||||
#
|
||||
# Generate glibconfig.h
|
||||
#
|
||||
# The timestamp of the stamp file is used to indicate if glibconfig.h is
|
||||
# up to date with respect to config.status. In the usual case, changes
|
||||
# to config.status will not result in changes to glibconfig.h so we
|
||||
# avoid touching its timestamp (in order not to rebuild the whole tree).
|
||||
#
|
||||
DISTCLEANFILES += glibconfig-stamp glibconfig.h
|
||||
BUILT_SOURCES += glibconfig-stamp
|
||||
configexecincludedir = $(libdir)/glib-2.0/include
|
||||
nodist_configexecinclude_HEADERS = glibconfig.h
|
||||
glibconfig-stamp: ../config.status
|
||||
$(AM_V_GEN) cd $(top_builddir) && \
|
||||
$(SHELL) ./config.status glib/glibconfig.h
|
||||
@touch glibconfig-stamp
|
||||
|
||||
|
||||
|
||||
if HAVE_GOOD_PRINTF
|
||||
else
|
||||
PRINTF_SUBDIR = gnulib
|
||||
printf_la = gnulib/libgnulib.la
|
||||
endif
|
||||
|
||||
if USE_SYSTEM_PCRE
|
||||
else
|
||||
MAYBE_PCRE = pcre
|
||||
endif
|
||||
|
||||
SUBDIRS = libcharset $(PRINTF_SUBDIR) $(MAYBE_PCRE) update-pcre . tests
|
||||
|
||||
DIST_SUBDIRS = libcharset gnulib pcre update-pcre tests
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
$(glib_INCLUDES) \
|
||||
$(pcre_inc) \
|
||||
-DG_LOG_DOMAIN=\"GLib\" \
|
||||
$(GLIB_DEBUG_FLAGS) \
|
||||
-DGLIB_COMPILATION \
|
||||
-DPCRE_STATIC
|
||||
|
||||
glib.def: glib.symbols
|
||||
$(AM_V_GEN) (echo EXPORTS; $(CPP) -P -DG_OS_WIN32 - <$(srcdir)/glib.symbols | sed -e '/^$$/d' -e 's/^/ /') > $(builddir)/glib.def
|
||||
|
||||
if OS_LINUX
|
||||
if HAVE_GNUC_VISIBILITY
|
||||
TESTS_ENVIRONMENT = GLIB_DEBUG_FLAGS="$(GLIB_DEBUG_FLAGS)"
|
||||
TESTS = abicheck.sh
|
||||
endif
|
||||
endif
|
||||
|
||||
MIRRORING_TAB_SOURCE = \
|
||||
glib-mirroring-tab/Makefile \
|
||||
glib-mirroring-tab/gen-mirroring-tab.c \
|
||||
glib-mirroring-tab/packtab.h \
|
||||
glib-mirroring-tab/packtab.c
|
||||
|
||||
# The compilation of GRegex can be disabled, but the source files must
|
||||
# be distributed.
|
||||
EXTRA_DIST += \
|
||||
makefile.msc.in \
|
||||
glib.rc.in \
|
||||
gen-iswide-table.py \
|
||||
gen-unicode-tables.pl \
|
||||
gen-script-table.pl \
|
||||
glibconfig.h.win32.in \
|
||||
abicheck.sh \
|
||||
glib.symbols \
|
||||
gregex.c \
|
||||
gregex.h \
|
||||
win_iconv.c \
|
||||
libglib-gdb.py.in \
|
||||
docs.c \
|
||||
gconstructor.h \
|
||||
$(MIRRORING_TAB_SOURCE)
|
||||
|
||||
CLEANFILES= libglib-gdb.py
|
||||
|
||||
# These may be in the builddir too
|
||||
BUILT_EXTRA_DIST = \
|
||||
makefile.msc \
|
||||
glibconfig.h.win32 \
|
||||
glib.rc
|
||||
|
||||
lib_LTLIBRARIES = libglib-2.0.la
|
||||
|
||||
if OS_WIN32_AND_DLL_COMPILATION
|
||||
if MS_LIB_AVAILABLE
|
||||
noinst_DATA = glib-2.0.lib
|
||||
|
||||
install_ms_lib_cmd = $(INSTALL) glib-2.0.lib $(DESTDIR)$(libdir)
|
||||
uninstall_ms_lib_cmd = -rm $(DESTDIR)$(libdir)/glib-2.0.lib
|
||||
endif
|
||||
endif
|
||||
|
||||
install-ms-lib:
|
||||
$(install_ms_lib_cmd)
|
||||
|
||||
uninstall-ms-lib:
|
||||
$(uninstall_ms_lib_cmd)
|
||||
|
||||
deprecated_sources = \
|
||||
deprecated/gallocator.c \
|
||||
deprecated/gcache.c \
|
||||
deprecated/gcompletion.c \
|
||||
deprecated/grel.c \
|
||||
deprecated/gthread-deprecated.c
|
||||
|
||||
libglib_2_0_la_SOURCES = \
|
||||
$(deprecated_sources) \
|
||||
glib_probes.d \
|
||||
garray.c \
|
||||
gasyncqueue.c \
|
||||
gasyncqueueprivate.h \
|
||||
gatomic.c \
|
||||
gbacktrace.c \
|
||||
gbase64.c \
|
||||
gbitlock.c \
|
||||
gbookmarkfile.c \
|
||||
gbsearcharray.h \
|
||||
gbytes.c \
|
||||
gbytes.h \
|
||||
gcharset.c \
|
||||
gchecksum.c \
|
||||
gconvert.c \
|
||||
gdataset.c \
|
||||
gdatasetprivate.h \
|
||||
gdate.c \
|
||||
gdatetime.c \
|
||||
gdir.c \
|
||||
genviron.c \
|
||||
gerror.c \
|
||||
gfileutils.c \
|
||||
ggettext.c \
|
||||
ghash.c \
|
||||
ghmac.c \
|
||||
ghook.c \
|
||||
ghostutils.c \
|
||||
giochannel.c \
|
||||
gkeyfile.c \
|
||||
glibintl.h \
|
||||
glib_trace.h \
|
||||
glib-init.h \
|
||||
glib-init.c \
|
||||
glib-private.h \
|
||||
glib-private.c \
|
||||
glist.c \
|
||||
gmain-internal.h \
|
||||
gmain.c \
|
||||
gmappedfile.c \
|
||||
gmarkup.c \
|
||||
gmem.c \
|
||||
gmessages.c \
|
||||
gmirroringtable.h \
|
||||
gnode.c \
|
||||
goption.c \
|
||||
gpattern.c \
|
||||
gpoll.c \
|
||||
gprimes.c \
|
||||
gqsort.c \
|
||||
gqueue.c \
|
||||
grand.c \
|
||||
gregex.c \
|
||||
gscanner.c \
|
||||
gscripttable.h \
|
||||
gsequence.c \
|
||||
gshell.c \
|
||||
gslice.c \
|
||||
gslist.c \
|
||||
gstdio.c \
|
||||
gstrfuncs.c \
|
||||
gstring.c \
|
||||
gstringchunk.c \
|
||||
gtestutils.c \
|
||||
gthread.c \
|
||||
gthreadprivate.h \
|
||||
gthreadpool.c \
|
||||
gtimer.c \
|
||||
gtimezone.c \
|
||||
gtrashstack.c \
|
||||
gtree.c \
|
||||
guniprop.c \
|
||||
gutf8.c \
|
||||
gunibreak.h \
|
||||
gunibreak.c \
|
||||
gunichartables.h \
|
||||
gunicollate.c \
|
||||
gunicomp.h \
|
||||
gunidecomp.h \
|
||||
gunidecomp.c \
|
||||
gunicodeprivate.h \
|
||||
gurifuncs.c \
|
||||
gutils.c \
|
||||
gvariant.h \
|
||||
gvariant.c \
|
||||
gvariant-core.h \
|
||||
gvariant-core.c \
|
||||
gvariant-internal.h \
|
||||
gvariant-parser.c \
|
||||
gvariant-serialiser.h \
|
||||
gvariant-serialiser.c \
|
||||
gvarianttypeinfo.h \
|
||||
gvarianttypeinfo.c \
|
||||
gvarianttype.c \
|
||||
gversion.c \
|
||||
gwakeup.h \
|
||||
gwakeup.c \
|
||||
gprintf.c \
|
||||
gprintfint.h
|
||||
|
||||
if OS_UNIX
|
||||
libglib_2_0_la_SOURCES += glib-unix.c
|
||||
endif
|
||||
|
||||
if OS_WIN32
|
||||
libglib_2_0_la_SOURCES += gthread-win32.c
|
||||
else
|
||||
libglib_2_0_la_SOURCES += gthread-posix.c
|
||||
endif
|
||||
|
||||
EXTRA_libglib_2_0_la_SOURCES = \
|
||||
giounix.c \
|
||||
giowin32.c \
|
||||
gspawn.c \
|
||||
gspawn-win32.c \
|
||||
gwin32.c
|
||||
|
||||
glibincludedir=$(includedir)/glib-2.0
|
||||
glibinclude_HEADERS = \
|
||||
glib-unix.h \
|
||||
glib-object.h \
|
||||
glib.h
|
||||
|
||||
deprecatedincludedir=$(includedir)/glib-2.0/glib/deprecated
|
||||
deprecatedinclude_HEADERS = \
|
||||
deprecated/gallocator.h \
|
||||
deprecated/gcache.h \
|
||||
deprecated/gcompletion.h \
|
||||
deprecated/gmain.h \
|
||||
deprecated/grel.h \
|
||||
deprecated/gthread.h
|
||||
|
||||
glibsubincludedir=$(includedir)/glib-2.0/glib
|
||||
glibsubinclude_HEADERS = \
|
||||
galloca.h \
|
||||
garray.h \
|
||||
gasyncqueue.h \
|
||||
gatomic.h \
|
||||
gbacktrace.h \
|
||||
gbase64.h \
|
||||
gbitlock.h \
|
||||
gbookmarkfile.h \
|
||||
gbytes.h \
|
||||
gcharset.h \
|
||||
gchecksum.h \
|
||||
gconvert.h \
|
||||
gdataset.h \
|
||||
gdate.h \
|
||||
gdatetime.h \
|
||||
gdir.h \
|
||||
genviron.h \
|
||||
gerror.h \
|
||||
gfileutils.h \
|
||||
ggettext.h \
|
||||
ghash.h \
|
||||
ghmac.h \
|
||||
ghook.h \
|
||||
ghostutils.h \
|
||||
gi18n.h \
|
||||
gi18n-lib.h \
|
||||
giochannel.h \
|
||||
gkeyfile.h \
|
||||
glist.h \
|
||||
gmacros.h \
|
||||
gmain.h \
|
||||
gmappedfile.h \
|
||||
gmarkup.h \
|
||||
gmem.h \
|
||||
gmessages.h \
|
||||
gnode.h \
|
||||
goption.h \
|
||||
gpattern.h \
|
||||
gpoll.h \
|
||||
gprimes.h \
|
||||
gqsort.h \
|
||||
gquark.h \
|
||||
gqueue.h \
|
||||
grand.h \
|
||||
gregex.h \
|
||||
gscanner.h \
|
||||
gsequence.h \
|
||||
gshell.h \
|
||||
gslice.h \
|
||||
gslist.h \
|
||||
gspawn.h \
|
||||
gstdio.h \
|
||||
gstrfuncs.h \
|
||||
gtestutils.h \
|
||||
gstring.h \
|
||||
gstringchunk.h \
|
||||
gthread.h \
|
||||
gthreadpool.h \
|
||||
gtimer.h \
|
||||
gtimezone.h \
|
||||
gtrashstack.h \
|
||||
gtree.h \
|
||||
gtypes.h \
|
||||
gunicode.h \
|
||||
gurifuncs.h \
|
||||
gutils.h \
|
||||
gvarianttype.h \
|
||||
gvariant.h \
|
||||
gversion.h \
|
||||
gversionmacros.h \
|
||||
gwin32.h \
|
||||
gprintf.h
|
||||
|
||||
# This is read by gobject-introspection/misc/ and gtk-doc
|
||||
glib-public-headers.txt: Makefile
|
||||
echo $(glibinclude_HEADERS) $(glibsubinclude_HEADERS) > $@.tmp && mv $@.tmp $@
|
||||
|
||||
CLEANFILES += glib-public-headers.txt
|
||||
|
||||
all-local: glib-public-headers.txt
|
||||
|
||||
install-data-local: install-ms-lib install-def-file
|
||||
@if test -f $(glibincludedir)/glist.h ; then \
|
||||
echo "*** Old headers found in $(glibincludedir). You should remove the" ; \
|
||||
echo "*** contents of this directory and type 'make install' again." ; \
|
||||
false ; \
|
||||
fi
|
||||
|
||||
uninstall-local: uninstall-ms-lib uninstall-def-file uninstall-gdb
|
||||
|
||||
if PLATFORM_WIN32
|
||||
no_undefined = -no-undefined
|
||||
endif
|
||||
|
||||
if OS_WIN32_AND_DLL_COMPILATION
|
||||
export_symbols = -export-symbols $(builddir)/glib.def
|
||||
|
||||
glib_win32_res = glib-win32-res.o
|
||||
glib_win32_res_ldflag = -Wl,$(glib_win32_res)
|
||||
|
||||
glib_def = glib.def
|
||||
|
||||
install-def-file:
|
||||
$(INSTALL) $(builddir)/glib.def $(DESTDIR)$(libdir)/glib-2.0.def
|
||||
|
||||
uninstall-def-file:
|
||||
-rm $(DESTDIR)$(libdir)/glib-2.0.def
|
||||
else
|
||||
install-def-file:
|
||||
uninstall-def-file:
|
||||
|
||||
export_symbols = $(LIBTOOL_EXPORT_OPTIONS)
|
||||
endif
|
||||
|
||||
if USE_SYSTEM_PCRE
|
||||
pcre_lib = $(PCRE_LIBS)
|
||||
pcre_inc = $(PCRE_CFLAGS)
|
||||
else
|
||||
pcre_lib = pcre/libpcre.la
|
||||
pcre_inc =
|
||||
endif
|
||||
|
||||
libglib_2_0_la_LIBADD = libcharset/libcharset.la $(printf_la) @GIO@ @GSPAWN@ @PLATFORMDEP@ @ICONV_LIBS@ @G_LIBS_EXTRA@ $(pcre_lib) $(G_THREAD_LIBS_EXTRA) $(G_THREAD_LIBS_FOR_GTHREAD)
|
||||
libglib_2_0_la_DEPENDENCIES = libcharset/libcharset.la $(printf_la) @GIO@ @GSPAWN@ @PLATFORMDEP@ $(glib_win32_res) $(glib_def)
|
||||
|
||||
libglib_2_0_la_LDFLAGS = $(GLIB_LINK_FLAGS) \
|
||||
$(glib_win32_res_ldflag) \
|
||||
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
|
||||
-export-dynamic $(no_undefined) $(export_symbols)
|
||||
|
||||
INSTALL_PROGS=
|
||||
|
||||
if ENABLE_DTRACE
|
||||
glib_probes.h: glib_probes.d Makefile
|
||||
$(AM_V_GEN) $(DTRACE) -C -h -s $< -o $@.tmp
|
||||
@$(SED) -e "s,define STAP_HAS_SEMAPHORES 1,undef STAP_HAS_SEMAPHORES," < $@.tmp > $@ && rm -f $@.tmp
|
||||
glib_probes.o: glib_probes.d Makefile
|
||||
$(AM_V_GEN) $(DTRACE) -G -s $< -o $@
|
||||
BUILT_SOURCES += glib_probes.h glib_probes.o
|
||||
CLEANFILES += glib_probes.h glib_probes.h.tmp
|
||||
libglib_2_0_la_LIBADD += glib_probes.o
|
||||
endif
|
||||
|
||||
if ENABLE_SYSTEMTAP
|
||||
tapset_in_files = glib.stp.in
|
||||
tapsetdir = @ABS_TAPSET_DIR@
|
||||
tapset_DATA = $(tapset_in_files:.stp.in=.stp)
|
||||
EXTRA_DIST += $(tapset_in_files)
|
||||
endif
|
||||
|
||||
gspawn-win32-helper-console.c:
|
||||
echo '#define HELPER_CONSOLE' >$@
|
||||
echo '#include "gspawn-win32-helper.c"' >>$@
|
||||
|
||||
gspawn-win64-helper.c:
|
||||
echo '#include "gspawn-win32-helper.c"' >$@
|
||||
|
||||
gspawn-win64-helper-console.c:
|
||||
echo '#define HELPER_CONSOLE' >$@
|
||||
echo '#include "gspawn-win32-helper.c"' >>$@
|
||||
|
||||
|
||||
if OS_WIN32
|
||||
if OS_WIN32_X64
|
||||
INSTALL_PROGS += gspawn-win64-helper gspawn-win64-helper-console
|
||||
gspawn_win64_helper_LDADD = libglib-2.0.la
|
||||
gspawn_win64_helper_LDFLAGS = -mwindows
|
||||
gspawn_win64_helper_console_LDADD = libglib-2.0.la
|
||||
else
|
||||
INSTALL_PROGS += gspawn-win32-helper gspawn-win32-helper-console
|
||||
gspawn_win32_helper_LDADD = libglib-2.0.la
|
||||
gspawn_win32_helper_LDFLAGS = -mwindows
|
||||
gspawn_win32_helper_console_LDADD = libglib-2.0.la
|
||||
endif
|
||||
endif
|
||||
|
||||
glib-win32-res.o: glib.rc
|
||||
$(WINDRES) glib.rc $@
|
||||
|
||||
bin_PROGRAMS = ${INSTALL_PROGS}
|
||||
|
||||
if OS_UNIX
|
||||
|
||||
INSTALL_PROGS += gtester
|
||||
gtester_SOURCES = gtester.c
|
||||
gtester_LDADD = libglib-2.0.la
|
||||
|
||||
auto_config_binscripts = gtester-report
|
||||
bin_SCRIPTS = ${auto_config_binscripts}
|
||||
EXTRA_DIST += ${auto_config_binscripts}
|
||||
|
||||
CONFIGVARS = \
|
||||
"bindir" : "${bindir}", \
|
||||
"glib-version" : "${GLIB_VERSION}"
|
||||
|
||||
install-exec-hook:
|
||||
for sf in ${auto_config_binscripts} ; do \
|
||||
mv -f "$(DESTDIR)$(bindir)/$$sf" "$(DESTDIR)$(bindir)/$$sf".tmp \
|
||||
&& sed < "$(DESTDIR)$(bindir)/$$sf".tmp > "$(DESTDIR)$(bindir)/$$sf" \
|
||||
-e '1,24s|^ *#@PKGINSTALL_CONFIGVARS_IN24LINES@| ${CONFIGVARS}|' \
|
||||
-e '1,1s|#! /usr/bin/env python\([0-9]\+\(\.[0-9]\+\)\?\)\?|#!${PYTHON}|' \
|
||||
|| exit $$? ; \
|
||||
chmod a+x $(DESTDIR)$(bindir)/$$sf ; \
|
||||
rm -f "$(DESTDIR)$(bindir)/$$sf".tmp ; \
|
||||
done
|
||||
|
||||
endif
|
||||
|
||||
glib-2.0.lib: libglib-2.0.la glib.def
|
||||
lib -machine:@LIB_EXE_MACHINE_FLAG@ -name:libglib-2.0-$(LT_CURRENT_MINUS_AGE).dll -def:$(builddir)/glib.def -out:$@
|
||||
|
||||
dist-hook: $(BUILT_EXTRA_DIST) ../build/win32/vs9/glib.vcproj ../build/win32/vs10/glib.vcxproj ../build/win32/vs10/glib.vcxproj.filters
|
||||
files='$(BUILT_EXTRA_DIST)'; \
|
||||
for f in $$files; do \
|
||||
if test -f $$f; then d=.; else d=$(srcdir); fi; \
|
||||
cp $$d/$$f $(distdir) || exit 1; done
|
||||
|
||||
../build/win32/vs9/glib.vcproj: $(top_srcdir)/build/win32/vs9/glib.vcprojin
|
||||
for F in `echo $(libglib_2_0_la_SOURCES) | tr '/' '\\'`; do \
|
||||
case $$F in \
|
||||
*-unix.c|gthread-*.c) \
|
||||
;; \
|
||||
*.c) echo ' <File RelativePath="..\..\..\glib\'$$F'" />' \
|
||||
;; \
|
||||
esac; \
|
||||
done >libglib.sourcefiles
|
||||
$(CPP) -P - <$(top_srcdir)/build/win32/vs9/glib.vcprojin >$@
|
||||
rm libglib.sourcefiles
|
||||
|
||||
../build/win32/vs10/glib.vcxproj: $(top_srcdir)/build/win32/vs10/glib.vcxprojin
|
||||
for F in `echo $(libglib_2_0_la_SOURCES) | tr '/' '\\'`; do \
|
||||
case $$F in \
|
||||
*-unix.c|gthread-*.c) \
|
||||
;; \
|
||||
*.c) echo ' <ClCompile Include="..\..\..\glib\'$$F'" />' \
|
||||
;; \
|
||||
esac; \
|
||||
done >libglib.vs10.sourcefiles
|
||||
$(CPP) -P - <$(top_srcdir)/build/win32/vs10/glib.vcxprojin >$@
|
||||
rm libglib.vs10.sourcefiles
|
||||
|
||||
../build/win32/vs10/glib.vcxproj.filters: $(top_srcdir)/build/win32/vs10/glib.vcxproj.filtersin
|
||||
for F in `echo $(libglib_2_0_la_SOURCES) | tr '/' '\\'`; do \
|
||||
case $$F in \
|
||||
*-unix.c|gthread-*.c) \
|
||||
;; \
|
||||
*.c) echo ' <ClCompile Include="..\..\..\glib\'$$F'"><Filter>Source Files</Filter></ClCompile>' \
|
||||
;; \
|
||||
esac; \
|
||||
done >libglib.vs10.sourcefiles.filters
|
||||
$(CPP) -P - <$(top_srcdir)/build/win32/vs10/glib.vcxproj.filtersin >$@
|
||||
rm libglib.vs10.sourcefiles.filters
|
||||
|
||||
# install gdb scripts
|
||||
gdbdir = $(datadir)/glib-2.0/gdb
|
||||
dist_gdb_SCRIPTS = glib.py
|
||||
|
||||
libglib-gdb.py: libglib-gdb.py.in
|
||||
$(AM_V_GEN) $(SED) -e "s|\@datadir\@|$(datadir)|" $(srcdir)/libglib-gdb.py.in > $(builddir)/libglib-gdb.py
|
||||
|
||||
|
||||
install-data-hook: libglib-gdb.py
|
||||
mkdir -p $(DESTDIR)$(datadir)/gdb/auto-load$(ABS_GLIB_RUNTIME_LIBDIR)
|
||||
$(INSTALL) $(builddir)/libglib-gdb.py $(DESTDIR)$(datadir)/gdb/auto-load$(ABS_GLIB_RUNTIME_LIBDIR)/libglib-2.0.so.0.$(LT_CURRENT).$(LT_REVISION)-gdb.py
|
||||
if HAVE_GLIB_RUNTIME_LIBDIR
|
||||
mkdir -p $(DESTDIR)$(libdir)/$(GLIB_RUNTIME_LIBDIR)
|
||||
mv $(DESTDIR)$(libdir)/libglib-2.0.so.0 $(DESTDIR)$(libdir)/$(GLIB_RUNTIME_LIBDIR)
|
||||
mv $(DESTDIR)$(libdir)/libglib-2.0.so.0.$(LT_CURRENT).$(LT_REVISION) $(DESTDIR)$(libdir)/$(GLIB_RUNTIME_LIBDIR)
|
||||
rm -f $(DESTDIR)$(libdir)/libglib-2.0.so
|
||||
ln -s $(GLIB_RUNTIME_LIBDIR)/libglib-2.0.so.0.$(LT_CURRENT).$(LT_REVISION) $(DESTDIR)$(libdir)/libglib-2.0.so
|
||||
endif
|
||||
|
||||
uninstall-gdb:
|
||||
-rm -r $(DESTDIR)$(datadir)/gdb
|
||||
13
glib/glib/abicheck.sh
Executable file
13
glib/glib/abicheck.sh
Executable file
|
|
@ -0,0 +1,13 @@
|
|||
#! /bin/sh
|
||||
|
||||
egrep '^#([^i]|if).*[^\]$' "${builddir:-.}/glibconfig.h" > glibconfig.cpp
|
||||
|
||||
INCLUDES="-include ${top_builddir:-..}/config.h"
|
||||
INCLUDES="$INCLUDES -include glibconfig.cpp $GLIB_DEBUG_FLAGS"
|
||||
|
||||
cpp -P -DG_STDIO_NO_WRAP_ON_UNIX $INCLUDES "${srcdir:-.}/glib.symbols" | sed -e '/^$/d' -e 's/ PRIVATE$//' | sort > expected-abi
|
||||
rm -f glibconfig.cpp
|
||||
|
||||
nm -D -g --defined-only .libs/libglib-2.0.so | cut -d ' ' -f 3 | egrep -v '^(__bss_start|_edata|_end)' | sort > actual-abi
|
||||
|
||||
diff -u expected-abi actual-abi && rm -f expected-abi actual-abi
|
||||
104
glib/glib/deprecated/gallocator.c
Normal file
104
glib/glib/deprecated/gallocator.c
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* 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 of the licence, 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* we know we are deprecated here, no need for warnings */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include "gallocator.h"
|
||||
|
||||
#include <glib/gmessages.h>
|
||||
#include <glib/gslice.h>
|
||||
|
||||
struct _GMemChunk {
|
||||
guint alloc_size; /* the size of an atom */
|
||||
};
|
||||
|
||||
GMemChunk*
|
||||
g_mem_chunk_new (const gchar *name,
|
||||
gint atom_size,
|
||||
gsize area_size,
|
||||
gint type)
|
||||
{
|
||||
GMemChunk *mem_chunk;
|
||||
|
||||
g_return_val_if_fail (atom_size > 0, NULL);
|
||||
|
||||
mem_chunk = g_slice_new (GMemChunk);
|
||||
mem_chunk->alloc_size = atom_size;
|
||||
|
||||
return mem_chunk;
|
||||
}
|
||||
|
||||
void
|
||||
g_mem_chunk_destroy (GMemChunk *mem_chunk)
|
||||
{
|
||||
g_return_if_fail (mem_chunk != NULL);
|
||||
|
||||
g_slice_free (GMemChunk, mem_chunk);
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_mem_chunk_alloc (GMemChunk *mem_chunk)
|
||||
{
|
||||
g_return_val_if_fail (mem_chunk != NULL, NULL);
|
||||
|
||||
return g_slice_alloc (mem_chunk->alloc_size);
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_mem_chunk_alloc0 (GMemChunk *mem_chunk)
|
||||
{
|
||||
g_return_val_if_fail (mem_chunk != NULL, NULL);
|
||||
|
||||
return g_slice_alloc0 (mem_chunk->alloc_size);
|
||||
}
|
||||
|
||||
void
|
||||
g_mem_chunk_free (GMemChunk *mem_chunk,
|
||||
gpointer mem)
|
||||
{
|
||||
g_return_if_fail (mem_chunk != NULL);
|
||||
|
||||
g_slice_free1 (mem_chunk->alloc_size, mem);
|
||||
}
|
||||
|
||||
GAllocator*
|
||||
g_allocator_new (const gchar *name,
|
||||
guint n_preallocs)
|
||||
{
|
||||
/* some (broken) GAllocator uses depend on non-NULL allocators */
|
||||
return (void *) 1;
|
||||
}
|
||||
|
||||
void g_allocator_free (GAllocator *allocator) { }
|
||||
|
||||
void g_mem_chunk_clean (GMemChunk *mem_chunk) { }
|
||||
void g_mem_chunk_reset (GMemChunk *mem_chunk) { }
|
||||
void g_mem_chunk_print (GMemChunk *mem_chunk) { }
|
||||
void g_mem_chunk_info (void) { }
|
||||
void g_blow_chunks (void) { }
|
||||
|
||||
void g_list_push_allocator (GAllocator *allocator) { }
|
||||
void g_list_pop_allocator (void) { }
|
||||
|
||||
void g_slist_push_allocator (GAllocator *allocator) { }
|
||||
void g_slist_pop_allocator (void) { }
|
||||
|
||||
void g_node_push_allocator (GAllocator *allocator) { }
|
||||
void g_node_pop_allocator (void) { }
|
||||
90
glib/glib/deprecated/gallocator.h
Normal file
90
glib/glib/deprecated/gallocator.h
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* 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 of the licence, 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_ALLOCATOR_H__
|
||||
#define __G_ALLOCATOR_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GAllocator GAllocator;
|
||||
typedef struct _GMemChunk GMemChunk;
|
||||
|
||||
#define G_ALLOC_ONLY 1
|
||||
#define G_ALLOC_AND_FREE 2
|
||||
#define G_ALLOCATOR_LIST 1
|
||||
#define G_ALLOCATOR_SLIST 2
|
||||
#define G_ALLOCATOR_NODE 3
|
||||
|
||||
#define g_chunk_new(type, chunk) ((type *) g_mem_chunk_alloc (chunk))
|
||||
#define g_chunk_new0(type, chunk) ((type *) g_mem_chunk_alloc0 (chunk))
|
||||
#define g_chunk_free(mem, mem_chunk) (g_mem_chunk_free (mem_chunk, mem))
|
||||
#define g_mem_chunk_create(type, x, y) (g_mem_chunk_new (NULL, sizeof (type), 0, 0))
|
||||
|
||||
|
||||
GLIB_DEPRECATED
|
||||
GMemChunk * g_mem_chunk_new (const gchar *name,
|
||||
gint atom_size,
|
||||
gsize area_size,
|
||||
gint type);
|
||||
GLIB_DEPRECATED
|
||||
void g_mem_chunk_destroy (GMemChunk *mem_chunk);
|
||||
GLIB_DEPRECATED
|
||||
gpointer g_mem_chunk_alloc (GMemChunk *mem_chunk);
|
||||
GLIB_DEPRECATED
|
||||
gpointer g_mem_chunk_alloc0 (GMemChunk *mem_chunk);
|
||||
GLIB_DEPRECATED
|
||||
void g_mem_chunk_free (GMemChunk *mem_chunk,
|
||||
gpointer mem);
|
||||
GLIB_DEPRECATED
|
||||
void g_mem_chunk_clean (GMemChunk *mem_chunk);
|
||||
GLIB_DEPRECATED
|
||||
void g_mem_chunk_reset (GMemChunk *mem_chunk);
|
||||
GLIB_DEPRECATED
|
||||
void g_mem_chunk_print (GMemChunk *mem_chunk);
|
||||
GLIB_DEPRECATED
|
||||
void g_mem_chunk_info (void);
|
||||
GLIB_DEPRECATED
|
||||
void g_blow_chunks (void);
|
||||
|
||||
|
||||
GLIB_DEPRECATED
|
||||
GAllocator * g_allocator_new (const gchar *name,
|
||||
guint n_preallocs);
|
||||
GLIB_DEPRECATED
|
||||
void g_allocator_free (GAllocator *allocator);
|
||||
GLIB_DEPRECATED
|
||||
void g_list_push_allocator (GAllocator *allocator);
|
||||
GLIB_DEPRECATED
|
||||
void g_list_pop_allocator (void);
|
||||
GLIB_DEPRECATED
|
||||
void g_slist_push_allocator (GAllocator *allocator);
|
||||
GLIB_DEPRECATED
|
||||
void g_slist_pop_allocator (void);
|
||||
GLIB_DEPRECATED
|
||||
void g_node_push_allocator (GAllocator *allocator);
|
||||
GLIB_DEPRECATED
|
||||
void g_node_pop_allocator (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_ALLOCATOR_H__ */
|
||||
345
glib/glib/deprecated/gcache.c
Normal file
345
glib/glib/deprecated/gcache.c
Normal file
|
|
@ -0,0 +1,345 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gcache.h"
|
||||
|
||||
#include "gslice.h"
|
||||
#include "ghash.h"
|
||||
#include "gtestutils.h"
|
||||
|
||||
/**
|
||||
* SECTION:caches
|
||||
* @title: Caches
|
||||
* @short_description: caches allow sharing of complex data structures
|
||||
* to save resources
|
||||
*
|
||||
* A #GCache allows sharing of complex data structures, in order to
|
||||
* save system resources.
|
||||
*
|
||||
* GCache uses keys and values. A GCache key describes the properties
|
||||
* of a particular resource. A GCache value is the actual resource.
|
||||
*
|
||||
* GCache has been marked as deprecated, since this API is rarely
|
||||
* used and not very actively maintained.
|
||||
*/
|
||||
|
||||
typedef struct _GCacheNode GCacheNode;
|
||||
|
||||
struct _GCacheNode
|
||||
{
|
||||
/* A reference counted node */
|
||||
gpointer value;
|
||||
gint ref_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* GCache:
|
||||
*
|
||||
* The #GCache struct is an opaque data structure containing
|
||||
* information about a #GCache. It should only be accessed via the
|
||||
* following functions.
|
||||
*
|
||||
* Deprecated:2.32: Use a #GHashTable instead
|
||||
*/
|
||||
struct _GCache
|
||||
{
|
||||
/* Called to create a value from a key */
|
||||
GCacheNewFunc value_new_func;
|
||||
|
||||
/* Called to destroy a value */
|
||||
GCacheDestroyFunc value_destroy_func;
|
||||
|
||||
/* Called to duplicate a key */
|
||||
GCacheDupFunc key_dup_func;
|
||||
|
||||
/* Called to destroy a key */
|
||||
GCacheDestroyFunc key_destroy_func;
|
||||
|
||||
/* Associates keys with nodes */
|
||||
GHashTable *key_table;
|
||||
|
||||
/* Associates nodes with keys */
|
||||
GHashTable *value_table;
|
||||
};
|
||||
|
||||
static inline GCacheNode*
|
||||
g_cache_node_new (gpointer value)
|
||||
{
|
||||
GCacheNode *node = g_slice_new (GCacheNode);
|
||||
node->value = value;
|
||||
node->ref_count = 1;
|
||||
return node;
|
||||
}
|
||||
|
||||
static inline void
|
||||
g_cache_node_destroy (GCacheNode *node)
|
||||
{
|
||||
g_slice_free (GCacheNode, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_cache_new:
|
||||
* @value_new_func: a function to create a new object given a key.
|
||||
* This is called by g_cache_insert() if an object
|
||||
* with the given key does not already exist
|
||||
* @value_destroy_func: a function to destroy an object. It is called
|
||||
* by g_cache_remove() when the object is no
|
||||
* longer needed (i.e. its reference count drops
|
||||
* to 0)
|
||||
* @key_dup_func: a function to copy a key. It is called by
|
||||
* g_cache_insert() if the key does not already exist in
|
||||
* the #GCache
|
||||
* @key_destroy_func: a function to destroy a key. It is called by
|
||||
* g_cache_remove() when the object is no longer
|
||||
* needed (i.e. its reference count drops to 0)
|
||||
* @hash_key_func: a function to create a hash value from a key
|
||||
* @hash_value_func: a function to create a hash value from a value
|
||||
* @key_equal_func: a function to compare two keys. It should return
|
||||
* %TRUE if the two keys are equivalent
|
||||
*
|
||||
* Creates a new #GCache.
|
||||
*
|
||||
* Returns: a new #GCache
|
||||
*
|
||||
* Deprecated:2.32: Use a #GHashTable instead
|
||||
*/
|
||||
|
||||
/**
|
||||
* GCacheNewFunc:
|
||||
* @key: a #GCache key
|
||||
* @Returns: a new #GCache value corresponding to the key.
|
||||
*
|
||||
* Specifies the type of the @value_new_func function passed to
|
||||
* g_cache_new(). It is passed a #GCache key and should create the
|
||||
* value corresponding to the key.
|
||||
*/
|
||||
|
||||
/**
|
||||
* GCacheDestroyFunc:
|
||||
* @value: the #GCache value to destroy
|
||||
*
|
||||
* Specifies the type of the @value_destroy_func and @key_destroy_func
|
||||
* functions passed to g_cache_new(). The functions are passed a
|
||||
* pointer to the #GCache key or #GCache value and should free any
|
||||
* memory and other resources associated with it.
|
||||
*/
|
||||
|
||||
/**
|
||||
* GCacheDupFunc:
|
||||
* @value: the #GCache key to destroy (<emphasis>not</emphasis> a
|
||||
* #GCache value as it seems)
|
||||
* @Returns: a copy of the #GCache key
|
||||
*
|
||||
* Specifies the type of the @key_dup_func function passed to
|
||||
* g_cache_new(). The function is passed a key
|
||||
* (<emphasis>not</emphasis> a value as the prototype implies) and
|
||||
* should return a duplicate of the key.
|
||||
*/
|
||||
GCache*
|
||||
g_cache_new (GCacheNewFunc value_new_func,
|
||||
GCacheDestroyFunc value_destroy_func,
|
||||
GCacheDupFunc key_dup_func,
|
||||
GCacheDestroyFunc key_destroy_func,
|
||||
GHashFunc hash_key_func,
|
||||
GHashFunc hash_value_func,
|
||||
GEqualFunc key_equal_func)
|
||||
{
|
||||
GCache *cache;
|
||||
|
||||
g_return_val_if_fail (value_new_func != NULL, NULL);
|
||||
g_return_val_if_fail (value_destroy_func != NULL, NULL);
|
||||
g_return_val_if_fail (key_dup_func != NULL, NULL);
|
||||
g_return_val_if_fail (key_destroy_func != NULL, NULL);
|
||||
g_return_val_if_fail (hash_key_func != NULL, NULL);
|
||||
g_return_val_if_fail (hash_value_func != NULL, NULL);
|
||||
g_return_val_if_fail (key_equal_func != NULL, NULL);
|
||||
|
||||
cache = g_slice_new (GCache);
|
||||
cache->value_new_func = value_new_func;
|
||||
cache->value_destroy_func = value_destroy_func;
|
||||
cache->key_dup_func = key_dup_func;
|
||||
cache->key_destroy_func = key_destroy_func;
|
||||
cache->key_table = g_hash_table_new (hash_key_func, key_equal_func);
|
||||
cache->value_table = g_hash_table_new (hash_value_func, NULL);
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_cache_destroy:
|
||||
* @cache: a #GCache
|
||||
*
|
||||
* Frees the memory allocated for the #GCache.
|
||||
*
|
||||
* Note that it does not destroy the keys and values which were
|
||||
* contained in the #GCache.
|
||||
*
|
||||
* Deprecated:2.32: Use a #GHashTable instead
|
||||
*/
|
||||
void
|
||||
g_cache_destroy (GCache *cache)
|
||||
{
|
||||
g_return_if_fail (cache != NULL);
|
||||
|
||||
g_hash_table_destroy (cache->key_table);
|
||||
g_hash_table_destroy (cache->value_table);
|
||||
g_slice_free (GCache, cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_cache_insert:
|
||||
* @cache: a #GCache
|
||||
* @key: a key describing a #GCache object
|
||||
*
|
||||
* Gets the value corresponding to the given key, creating it if
|
||||
* necessary. It first checks if the value already exists in the
|
||||
* #GCache, by using the @key_equal_func function passed to
|
||||
* g_cache_new(). If it does already exist it is returned, and its
|
||||
* reference count is increased by one. If the value does not currently
|
||||
* exist, if is created by calling the @value_new_func. The key is
|
||||
* duplicated by calling @key_dup_func and the duplicated key and value
|
||||
* are inserted into the #GCache.
|
||||
*
|
||||
* Returns: a pointer to a #GCache value
|
||||
*
|
||||
* Deprecated:2.32: Use a #GHashTable instead
|
||||
*/
|
||||
gpointer
|
||||
g_cache_insert (GCache *cache,
|
||||
gpointer key)
|
||||
{
|
||||
GCacheNode *node;
|
||||
gpointer value;
|
||||
|
||||
g_return_val_if_fail (cache != NULL, NULL);
|
||||
|
||||
node = g_hash_table_lookup (cache->key_table, key);
|
||||
if (node)
|
||||
{
|
||||
node->ref_count += 1;
|
||||
return node->value;
|
||||
}
|
||||
|
||||
key = (* cache->key_dup_func) (key);
|
||||
value = (* cache->value_new_func) (key);
|
||||
node = g_cache_node_new (value);
|
||||
|
||||
g_hash_table_insert (cache->key_table, key, node);
|
||||
g_hash_table_insert (cache->value_table, value, key);
|
||||
|
||||
return node->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_cache_remove:
|
||||
* @cache: a #GCache
|
||||
* @value: the value to remove
|
||||
*
|
||||
* Decreases the reference count of the given value. If it drops to 0
|
||||
* then the value and its corresponding key are destroyed, using the
|
||||
* @value_destroy_func and @key_destroy_func passed to g_cache_new().
|
||||
*
|
||||
* Deprecated:2.32: Use a #GHashTable instead
|
||||
*/
|
||||
void
|
||||
g_cache_remove (GCache *cache,
|
||||
gconstpointer value)
|
||||
{
|
||||
GCacheNode *node;
|
||||
gpointer key;
|
||||
|
||||
g_return_if_fail (cache != NULL);
|
||||
|
||||
key = g_hash_table_lookup (cache->value_table, value);
|
||||
node = g_hash_table_lookup (cache->key_table, key);
|
||||
|
||||
g_return_if_fail (node != NULL);
|
||||
|
||||
node->ref_count -= 1;
|
||||
if (node->ref_count == 0)
|
||||
{
|
||||
g_hash_table_remove (cache->value_table, value);
|
||||
g_hash_table_remove (cache->key_table, key);
|
||||
|
||||
(* cache->key_destroy_func) (key);
|
||||
(* cache->value_destroy_func) (node->value);
|
||||
g_cache_node_destroy (node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_cache_key_foreach:
|
||||
* @cache: a #GCache
|
||||
* @func: the function to call with each #GCache key
|
||||
* @user_data: user data to pass to the function
|
||||
*
|
||||
* Calls the given function for each of the keys in the #GCache.
|
||||
*
|
||||
* NOTE @func is passed three parameters, the value and key of a cache
|
||||
* entry and the @user_data. The order of value and key is different
|
||||
* from the order in which g_hash_table_foreach() passes key-value
|
||||
* pairs to its callback function !
|
||||
*
|
||||
* Deprecated:2.32: Use a #GHashTable instead
|
||||
*/
|
||||
void
|
||||
g_cache_key_foreach (GCache *cache,
|
||||
GHFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (cache != NULL);
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
g_hash_table_foreach (cache->value_table, func, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_cache_value_foreach:
|
||||
* @cache: a #GCache
|
||||
* @func: the function to call with each #GCache value
|
||||
* @user_data: user data to pass to the function
|
||||
*
|
||||
* Calls the given function for each of the values in the #GCache.
|
||||
*
|
||||
* Deprecated:2.10: The reason is that it passes pointers to internal
|
||||
* data structures to @func; use g_cache_key_foreach() instead
|
||||
*/
|
||||
void
|
||||
g_cache_value_foreach (GCache *cache,
|
||||
GHFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (cache != NULL);
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
g_hash_table_foreach (cache->key_table, func, user_data);
|
||||
}
|
||||
73
glib/glib/deprecated/gcache.h
Normal file
73
glib/glib/deprecated/gcache.h
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_CACHE_H__
|
||||
#define __G_CACHE_H__
|
||||
|
||||
#include <glib/glist.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GCache GCache;
|
||||
|
||||
typedef gpointer (*GCacheNewFunc) (gpointer key);
|
||||
typedef gpointer (*GCacheDupFunc) (gpointer value);
|
||||
typedef void (*GCacheDestroyFunc) (gpointer value);
|
||||
|
||||
/* Caches
|
||||
*/
|
||||
GLIB_DEPRECATED
|
||||
GCache* g_cache_new (GCacheNewFunc value_new_func,
|
||||
GCacheDestroyFunc value_destroy_func,
|
||||
GCacheDupFunc key_dup_func,
|
||||
GCacheDestroyFunc key_destroy_func,
|
||||
GHashFunc hash_key_func,
|
||||
GHashFunc hash_value_func,
|
||||
GEqualFunc key_equal_func);
|
||||
GLIB_DEPRECATED
|
||||
void g_cache_destroy (GCache *cache);
|
||||
GLIB_DEPRECATED
|
||||
gpointer g_cache_insert (GCache *cache,
|
||||
gpointer key);
|
||||
GLIB_DEPRECATED
|
||||
void g_cache_remove (GCache *cache,
|
||||
gconstpointer value);
|
||||
GLIB_DEPRECATED
|
||||
void g_cache_key_foreach (GCache *cache,
|
||||
GHFunc func,
|
||||
gpointer user_data);
|
||||
GLIB_DEPRECATED
|
||||
void g_cache_value_foreach (GCache *cache,
|
||||
GHFunc func,
|
||||
gpointer user_data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_CACHE_H__ */
|
||||
492
glib/glib/deprecated/gcompletion.c
Normal file
492
glib/glib/deprecated/gcompletion.c
Normal file
|
|
@ -0,0 +1,492 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* we know we are deprecated here, no need for warnings */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include "gcompletion.h"
|
||||
|
||||
#include <glib/gstrfuncs.h>
|
||||
#include <glib/gmessages.h>
|
||||
#include <glib/gunicode.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* SECTION:completion
|
||||
* @title: Automatic String Completion
|
||||
* @short_description: support for automatic completion using a group
|
||||
* of target strings
|
||||
*
|
||||
* #GCompletion provides support for automatic completion of a string
|
||||
* using any group of target strings. It is typically used for file
|
||||
* name completion as is common in many UNIX shells.
|
||||
*
|
||||
* A #GCompletion is created using g_completion_new(). Target items are
|
||||
* added and removed with g_completion_add_items(),
|
||||
* g_completion_remove_items() and g_completion_clear_items(). A
|
||||
* completion attempt is requested with g_completion_complete() or
|
||||
* g_completion_complete_utf8(). When no longer needed, the
|
||||
* #GCompletion is freed with g_completion_free().
|
||||
*
|
||||
* Items in the completion can be simple strings (e.g. filenames), or
|
||||
* pointers to arbitrary data structures. If data structures are used
|
||||
* you must provide a #GCompletionFunc in g_completion_new(), which
|
||||
* retrieves the item's string from the data structure. You can change
|
||||
* the way in which strings are compared by setting a different
|
||||
* #GCompletionStrncmpFunc in g_completion_set_compare().
|
||||
*
|
||||
* GCompletion has been marked as deprecated, since this API is rarely
|
||||
* used and not very actively maintained.
|
||||
**/
|
||||
|
||||
/**
|
||||
* GCompletion:
|
||||
* @items: list of target items (strings or data structures).
|
||||
* @func: function which is called to get the string associated with a
|
||||
* target item. It is %NULL if the target items are strings.
|
||||
* @prefix: the last prefix passed to g_completion_complete() or
|
||||
* g_completion_complete_utf8().
|
||||
* @cache: the list of items which begin with @prefix.
|
||||
* @strncmp_func: The function to use when comparing strings. Use
|
||||
* g_completion_set_compare() to modify this function.
|
||||
*
|
||||
* The data structure used for automatic completion.
|
||||
**/
|
||||
|
||||
/**
|
||||
* GCompletionFunc:
|
||||
* @Param1: the completion item.
|
||||
* @Returns: the string corresponding to the item.
|
||||
*
|
||||
* Specifies the type of the function passed to g_completion_new(). It
|
||||
* should return the string corresponding to the given target item.
|
||||
* This is used when you use data structures as #GCompletion items.
|
||||
**/
|
||||
|
||||
/**
|
||||
* GCompletionStrncmpFunc:
|
||||
* @s1: string to compare with @s2.
|
||||
* @s2: string to compare with @s1.
|
||||
* @n: maximal number of bytes to compare.
|
||||
* @Returns: an integer less than, equal to, or greater than zero if
|
||||
* the first @n bytes of @s1 is found, respectively, to be
|
||||
* less than, to match, or to be greater than the first @n
|
||||
* bytes of @s2.
|
||||
*
|
||||
* Specifies the type of the function passed to
|
||||
* g_completion_set_compare(). This is used when you use strings as
|
||||
* #GCompletion items.
|
||||
**/
|
||||
|
||||
static void completion_check_cache (GCompletion* cmp,
|
||||
gchar** new_prefix);
|
||||
|
||||
/**
|
||||
* g_completion_new:
|
||||
* @func: the function to be called to return the string representing
|
||||
* an item in the #GCompletion, or %NULL if strings are going to
|
||||
* be used as the #GCompletion items.
|
||||
* @Returns: the new #GCompletion.
|
||||
*
|
||||
* Creates a new #GCompletion.
|
||||
**/
|
||||
GCompletion*
|
||||
g_completion_new (GCompletionFunc func)
|
||||
{
|
||||
GCompletion* gcomp;
|
||||
|
||||
gcomp = g_new (GCompletion, 1);
|
||||
gcomp->items = NULL;
|
||||
gcomp->cache = NULL;
|
||||
gcomp->prefix = NULL;
|
||||
gcomp->func = func;
|
||||
gcomp->strncmp_func = strncmp;
|
||||
|
||||
return gcomp;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_completion_add_items:
|
||||
* @cmp: the #GCompletion.
|
||||
* @items: the list of items to add.
|
||||
*
|
||||
* Adds items to the #GCompletion.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
void
|
||||
g_completion_add_items (GCompletion* cmp,
|
||||
GList* items)
|
||||
{
|
||||
GList* it;
|
||||
|
||||
g_return_if_fail (cmp != NULL);
|
||||
|
||||
/* optimize adding to cache? */
|
||||
if (cmp->cache)
|
||||
{
|
||||
g_list_free (cmp->cache);
|
||||
cmp->cache = NULL;
|
||||
}
|
||||
|
||||
if (cmp->prefix)
|
||||
{
|
||||
g_free (cmp->prefix);
|
||||
cmp->prefix = NULL;
|
||||
}
|
||||
|
||||
it = items;
|
||||
while (it)
|
||||
{
|
||||
cmp->items = g_list_prepend (cmp->items, it->data);
|
||||
it = it->next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_completion_remove_items:
|
||||
* @cmp: the #GCompletion.
|
||||
* @items: the items to remove.
|
||||
*
|
||||
* Removes items from a #GCompletion.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
void
|
||||
g_completion_remove_items (GCompletion* cmp,
|
||||
GList* items)
|
||||
{
|
||||
GList* it;
|
||||
|
||||
g_return_if_fail (cmp != NULL);
|
||||
|
||||
it = items;
|
||||
while (cmp->items && it)
|
||||
{
|
||||
cmp->items = g_list_remove (cmp->items, it->data);
|
||||
it = it->next;
|
||||
}
|
||||
|
||||
it = items;
|
||||
while (cmp->cache && it)
|
||||
{
|
||||
cmp->cache = g_list_remove(cmp->cache, it->data);
|
||||
it = it->next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_completion_clear_items:
|
||||
* @cmp: the #GCompletion.
|
||||
*
|
||||
* Removes all items from the #GCompletion.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
void
|
||||
g_completion_clear_items (GCompletion* cmp)
|
||||
{
|
||||
g_return_if_fail (cmp != NULL);
|
||||
|
||||
g_list_free (cmp->items);
|
||||
cmp->items = NULL;
|
||||
g_list_free (cmp->cache);
|
||||
cmp->cache = NULL;
|
||||
g_free (cmp->prefix);
|
||||
cmp->prefix = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
completion_check_cache (GCompletion* cmp,
|
||||
gchar** new_prefix)
|
||||
{
|
||||
register GList* list;
|
||||
register gsize len;
|
||||
register gsize i;
|
||||
register gsize plen;
|
||||
gchar* postfix;
|
||||
gchar* s;
|
||||
|
||||
if (!new_prefix)
|
||||
return;
|
||||
if (!cmp->cache)
|
||||
{
|
||||
*new_prefix = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
len = strlen(cmp->prefix);
|
||||
list = cmp->cache;
|
||||
s = cmp->func ? cmp->func (list->data) : (gchar*) list->data;
|
||||
postfix = s + len;
|
||||
plen = strlen (postfix);
|
||||
list = list->next;
|
||||
|
||||
while (list && plen)
|
||||
{
|
||||
s = cmp->func ? cmp->func (list->data) : (gchar*) list->data;
|
||||
s += len;
|
||||
for (i = 0; i < plen; ++i)
|
||||
{
|
||||
if (postfix[i] != s[i])
|
||||
break;
|
||||
}
|
||||
plen = i;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
*new_prefix = g_new0 (gchar, len + plen + 1);
|
||||
strncpy (*new_prefix, cmp->prefix, len);
|
||||
strncpy (*new_prefix + len, postfix, plen);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_completion_complete_utf8:
|
||||
* @cmp: the #GCompletion
|
||||
* @prefix: the prefix string, typically used by the user, which is compared
|
||||
* with each of the items
|
||||
* @new_prefix: if non-%NULL, returns the longest prefix which is common to all
|
||||
* items that matched @prefix, or %NULL if no items matched @prefix.
|
||||
* This string should be freed when no longer needed.
|
||||
*
|
||||
* Attempts to complete the string @prefix using the #GCompletion target items.
|
||||
* In contrast to g_completion_complete(), this function returns the largest common
|
||||
* prefix that is a valid UTF-8 string, omitting a possible common partial
|
||||
* character.
|
||||
*
|
||||
* You should use this function instead of g_completion_complete() if your
|
||||
* items are UTF-8 strings.
|
||||
*
|
||||
* Return value: (element-type utf8) (transfer none): the list of items whose strings begin with @prefix. This should
|
||||
* not be changed.
|
||||
*
|
||||
* Since: 2.4
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
GList*
|
||||
g_completion_complete_utf8 (GCompletion *cmp,
|
||||
const gchar *prefix,
|
||||
gchar **new_prefix)
|
||||
{
|
||||
GList *list;
|
||||
gchar *p, *q;
|
||||
|
||||
list = g_completion_complete (cmp, prefix, new_prefix);
|
||||
|
||||
if (new_prefix && *new_prefix)
|
||||
{
|
||||
p = *new_prefix + strlen (*new_prefix);
|
||||
q = g_utf8_find_prev_char (*new_prefix, p);
|
||||
|
||||
switch (g_utf8_get_char_validated (q, p - q))
|
||||
{
|
||||
case (gunichar)-2:
|
||||
case (gunichar)-1:
|
||||
*q = 0;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_completion_complete:
|
||||
* @cmp: the #GCompletion.
|
||||
* @prefix: the prefix string, typically typed by the user, which is
|
||||
* compared with each of the items.
|
||||
* @new_prefix: if non-%NULL, returns the longest prefix which is
|
||||
* common to all items that matched @prefix, or %NULL if
|
||||
* no items matched @prefix. This string should be freed
|
||||
* when no longer needed.
|
||||
* @Returns: the list of items whose strings begin with @prefix. This
|
||||
* should not be changed.
|
||||
*
|
||||
* Attempts to complete the string @prefix using the #GCompletion
|
||||
* target items.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
GList*
|
||||
g_completion_complete (GCompletion* cmp,
|
||||
const gchar* prefix,
|
||||
gchar** new_prefix)
|
||||
{
|
||||
gsize plen, len;
|
||||
gboolean done = FALSE;
|
||||
GList* list;
|
||||
|
||||
g_return_val_if_fail (cmp != NULL, NULL);
|
||||
g_return_val_if_fail (prefix != NULL, NULL);
|
||||
|
||||
len = strlen (prefix);
|
||||
if (cmp->prefix && cmp->cache)
|
||||
{
|
||||
plen = strlen (cmp->prefix);
|
||||
if (plen <= len && ! cmp->strncmp_func (prefix, cmp->prefix, plen))
|
||||
{
|
||||
/* use the cache */
|
||||
list = cmp->cache;
|
||||
while (list)
|
||||
{
|
||||
GList *next = list->next;
|
||||
|
||||
if (cmp->strncmp_func (prefix,
|
||||
cmp->func ? cmp->func (list->data) : (gchar*) list->data,
|
||||
len))
|
||||
cmp->cache = g_list_delete_link (cmp->cache, list);
|
||||
|
||||
list = next;
|
||||
}
|
||||
done = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!done)
|
||||
{
|
||||
/* normal code */
|
||||
g_list_free (cmp->cache);
|
||||
cmp->cache = NULL;
|
||||
list = cmp->items;
|
||||
while (*prefix && list)
|
||||
{
|
||||
if (!cmp->strncmp_func (prefix,
|
||||
cmp->func ? cmp->func (list->data) : (gchar*) list->data,
|
||||
len))
|
||||
cmp->cache = g_list_prepend (cmp->cache, list->data);
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
if (cmp->prefix)
|
||||
{
|
||||
g_free (cmp->prefix);
|
||||
cmp->prefix = NULL;
|
||||
}
|
||||
if (cmp->cache)
|
||||
cmp->prefix = g_strdup (prefix);
|
||||
completion_check_cache (cmp, new_prefix);
|
||||
|
||||
return *prefix ? cmp->cache : cmp->items;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_completion_free:
|
||||
* @cmp: the #GCompletion.
|
||||
*
|
||||
* Frees all memory used by the #GCompletion.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
void
|
||||
g_completion_free (GCompletion* cmp)
|
||||
{
|
||||
g_return_if_fail (cmp != NULL);
|
||||
|
||||
g_completion_clear_items (cmp);
|
||||
g_free (cmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_completion_set_compare:
|
||||
* @cmp: a #GCompletion.
|
||||
* @strncmp_func: the string comparison function.
|
||||
*
|
||||
* Sets the function to use for string comparisons. The default string
|
||||
* comparison function is strncmp().
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
void
|
||||
g_completion_set_compare(GCompletion *cmp,
|
||||
GCompletionStrncmpFunc strncmp_func)
|
||||
{
|
||||
cmp->strncmp_func = strncmp_func;
|
||||
}
|
||||
|
||||
#ifdef TEST_COMPLETION
|
||||
#include <stdio.h>
|
||||
int
|
||||
main (int argc,
|
||||
char* argv[])
|
||||
{
|
||||
FILE *file;
|
||||
gchar buf[1024];
|
||||
GList *list;
|
||||
GList *result;
|
||||
GList *tmp;
|
||||
GCompletion *cmp;
|
||||
gint i;
|
||||
gchar *longp = NULL;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
g_warning ("Usage: %s filename prefix1 [prefix2 ...]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
file = fopen (argv[1], "r");
|
||||
if (!file)
|
||||
{
|
||||
g_warning ("Cannot open %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
cmp = g_completion_new (NULL);
|
||||
list = g_list_alloc ();
|
||||
while (fgets (buf, 1024, file))
|
||||
{
|
||||
list->data = g_strdup (buf);
|
||||
g_completion_add_items (cmp, list);
|
||||
}
|
||||
fclose (file);
|
||||
|
||||
for (i = 2; i < argc; ++i)
|
||||
{
|
||||
printf ("COMPLETING: %s\n", argv[i]);
|
||||
result = g_completion_complete (cmp, argv[i], &longp);
|
||||
g_list_foreach (result, (GFunc) printf, NULL);
|
||||
printf ("LONG MATCH: %s\n", longp);
|
||||
g_free (longp);
|
||||
longp = NULL;
|
||||
}
|
||||
|
||||
g_list_foreach (cmp->items, (GFunc) g_free, NULL);
|
||||
g_completion_free (cmp);
|
||||
g_list_free (list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
85
glib/glib/deprecated/gcompletion.h
Normal file
85
glib/glib/deprecated/gcompletion.h
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_COMPLETION_H__
|
||||
#define __G_COMPLETION_H__
|
||||
|
||||
#include <glib/glist.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GCompletion GCompletion;
|
||||
|
||||
typedef gchar* (*GCompletionFunc) (gpointer);
|
||||
|
||||
/* GCompletion
|
||||
*/
|
||||
|
||||
typedef gint (*GCompletionStrncmpFunc) (const gchar *s1,
|
||||
const gchar *s2,
|
||||
gsize n);
|
||||
|
||||
struct _GCompletion
|
||||
{
|
||||
GList* items;
|
||||
GCompletionFunc func;
|
||||
|
||||
gchar* prefix;
|
||||
GList* cache;
|
||||
GCompletionStrncmpFunc strncmp_func;
|
||||
};
|
||||
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
GCompletion* g_completion_new (GCompletionFunc func);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
void g_completion_add_items (GCompletion* cmp,
|
||||
GList* items);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
void g_completion_remove_items (GCompletion* cmp,
|
||||
GList* items);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
void g_completion_clear_items (GCompletion* cmp);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
GList* g_completion_complete (GCompletion* cmp,
|
||||
const gchar* prefix,
|
||||
gchar** new_prefix);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
GList* g_completion_complete_utf8 (GCompletion *cmp,
|
||||
const gchar* prefix,
|
||||
gchar** new_prefix);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
void g_completion_set_compare (GCompletion *cmp,
|
||||
GCompletionStrncmpFunc strncmp_func);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
void g_completion_free (GCompletion* cmp);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_COMPLETION_H__ */
|
||||
138
glib/glib/deprecated/gmain.h
Normal file
138
glib/glib/deprecated/gmain.h
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_DEPRECATED_MAIN_H__
|
||||
#define __G_DEPRECATED_MAIN_H__
|
||||
|
||||
#include <glib/gmain.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* ============== Compat main loop stuff ================== */
|
||||
|
||||
/**
|
||||
* g_main_new:
|
||||
* @is_running: set to %TRUE to indicate that the loop is running. This
|
||||
* is not very important since calling g_main_run() will set this
|
||||
* to %TRUE anyway.
|
||||
*
|
||||
* Creates a new #GMainLoop for th default main context.
|
||||
*
|
||||
* Returns: a new #GMainLoop
|
||||
*
|
||||
* Deprecated: 2.2: Use g_main_loop_new() instead
|
||||
*/
|
||||
#define g_main_new(is_running) g_main_loop_new (NULL, is_running)
|
||||
|
||||
/**
|
||||
* g_main_run:
|
||||
* @loop: a #GMainLoop
|
||||
*
|
||||
* Runs a main loop until it stops running.
|
||||
*
|
||||
* Deprecated: 2.2: Use g_main_loop_run() instead
|
||||
*/
|
||||
#define g_main_run(loop) g_main_loop_run(loop)
|
||||
|
||||
/**
|
||||
* g_main_quit:
|
||||
* @loop: a #GMainLoop
|
||||
*
|
||||
* Stops the #GMainLoop.
|
||||
* If g_main_run() was called to run the #GMainLoop, it will now return.
|
||||
*
|
||||
* Deprecated: 2.2: Use g_main_loop_quit() instead
|
||||
*/
|
||||
#define g_main_quit(loop) g_main_loop_quit(loop)
|
||||
|
||||
/**
|
||||
* g_main_destroy:
|
||||
* @loop: a #GMainLoop
|
||||
*
|
||||
* Frees the memory allocated for the #GMainLoop.
|
||||
*
|
||||
* Deprecated: 2.2: Use g_main_loop_unref() instead
|
||||
*/
|
||||
#define g_main_destroy(loop) g_main_loop_unref(loop)
|
||||
|
||||
/**
|
||||
* g_main_is_running:
|
||||
* @loop: a #GMainLoop
|
||||
*
|
||||
* Checks if the main loop is running.
|
||||
*
|
||||
* Returns: %TRUE if the main loop is running
|
||||
*
|
||||
* Deprecated: 2.2: Use g_main_loop_is_running() instead
|
||||
*/
|
||||
#define g_main_is_running(loop) g_main_loop_is_running(loop)
|
||||
|
||||
/**
|
||||
* g_main_iteration:
|
||||
* @may_block: set to %TRUE if it should block (i.e. wait) until an event
|
||||
* source becomes ready. It will return after an event source has been
|
||||
* processed. If set to %FALSE it will return immediately if no event
|
||||
* source is ready to be processed.
|
||||
*
|
||||
* Runs a single iteration for the default #GMainContext.
|
||||
*
|
||||
* Returns: %TRUE if more events are pending.
|
||||
*
|
||||
* Deprecated: 2.2: Use g_main_context_iteration() instead.
|
||||
*/
|
||||
#define g_main_iteration(may_block) g_main_context_iteration (NULL, may_block)
|
||||
|
||||
/**
|
||||
* g_main_pending:
|
||||
*
|
||||
* Checks if any events are pending for the default #GMainContext
|
||||
* (i.e. ready to be processed).
|
||||
*
|
||||
* Returns: %TRUE if any events are pending.
|
||||
*
|
||||
* Deprected: 2.2: Use g_main_context_pending() instead.
|
||||
*/
|
||||
#define g_main_pending() g_main_context_pending (NULL)
|
||||
|
||||
/**
|
||||
* g_main_set_poll_func:
|
||||
* @func: the function to call to poll all file descriptors
|
||||
*
|
||||
* Sets the function to use for the handle polling of file descriptors
|
||||
* for the default main context.
|
||||
*
|
||||
* Deprecated: 2.2: Use g_main_context_set_poll_func() again
|
||||
*/
|
||||
#define g_main_set_poll_func(func) g_main_context_set_poll_func (NULL, func)
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_DEPRECATED_MAIN_H__ */
|
||||
677
glib/glib/deprecated/grel.c
Normal file
677
glib/glib/deprecated/grel.c
Normal file
|
|
@ -0,0 +1,677 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* we know we are deprecated here, no need for warnings */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include "grel.h"
|
||||
|
||||
#include <glib/gmessages.h>
|
||||
#include <glib/gtestutils.h>
|
||||
#include <glib/gstring.h>
|
||||
#include <glib/gslice.h>
|
||||
#include <glib/ghash.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* SECTION:relations
|
||||
* @title: Relations and Tuples
|
||||
* @short_description: tables of data which can be indexed on any
|
||||
* number of fields
|
||||
*
|
||||
* A #GRelation is a table of data which can be indexed on any number
|
||||
* of fields, rather like simple database tables. A #GRelation contains
|
||||
* a number of records, called tuples. Each record contains a number of
|
||||
* fields. Records are not ordered, so it is not possible to find the
|
||||
* record at a particular index.
|
||||
*
|
||||
* Note that #GRelation tables are currently limited to 2 fields.
|
||||
*
|
||||
* To create a GRelation, use g_relation_new().
|
||||
*
|
||||
* To specify which fields should be indexed, use g_relation_index().
|
||||
* Note that this must be called before any tuples are added to the
|
||||
* #GRelation.
|
||||
*
|
||||
* To add records to a #GRelation use g_relation_insert().
|
||||
*
|
||||
* To determine if a given record appears in a #GRelation, use
|
||||
* g_relation_exists(). Note that fields are compared directly, so
|
||||
* pointers must point to the exact same position (i.e. different
|
||||
* copies of the same string will not match.)
|
||||
*
|
||||
* To count the number of records which have a particular value in a
|
||||
* given field, use g_relation_count().
|
||||
*
|
||||
* To get all the records which have a particular value in a given
|
||||
* field, use g_relation_select(). To access fields of the resulting
|
||||
* records, use g_tuples_index(). To free the resulting records use
|
||||
* g_tuples_destroy().
|
||||
*
|
||||
* To delete all records which have a particular value in a given
|
||||
* field, use g_relation_delete().
|
||||
*
|
||||
* To destroy the #GRelation, use g_relation_destroy().
|
||||
*
|
||||
* To help debug #GRelation objects, use g_relation_print().
|
||||
*
|
||||
* GRelation has been marked as deprecated, since this API has never
|
||||
* been fully implemented, is not very actively maintained and rarely
|
||||
* used.
|
||||
**/
|
||||
|
||||
typedef struct _GRealTuples GRealTuples;
|
||||
|
||||
/**
|
||||
* GRelation:
|
||||
*
|
||||
* The #GRelation struct is an opaque data structure to represent a
|
||||
* <link linkend="glib-Relations-and-Tuples">Relation</link>. It should
|
||||
* only be accessed via the following functions.
|
||||
**/
|
||||
struct _GRelation
|
||||
{
|
||||
gint fields;
|
||||
gint current_field;
|
||||
|
||||
GHashTable *all_tuples;
|
||||
GHashTable **hashed_tuple_tables;
|
||||
|
||||
gint count;
|
||||
};
|
||||
|
||||
/**
|
||||
* GTuples:
|
||||
* @len: the number of records that matched.
|
||||
*
|
||||
* The #GTuples struct is used to return records (or tuples) from the
|
||||
* #GRelation by g_relation_select(). It only contains one public
|
||||
* member - the number of records that matched. To access the matched
|
||||
* records, you must use g_tuples_index().
|
||||
**/
|
||||
struct _GRealTuples
|
||||
{
|
||||
gint len;
|
||||
gint width;
|
||||
gpointer *data;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
tuple_equal_2 (gconstpointer v_a,
|
||||
gconstpointer v_b)
|
||||
{
|
||||
gpointer* a = (gpointer*) v_a;
|
||||
gpointer* b = (gpointer*) v_b;
|
||||
|
||||
return a[0] == b[0] && a[1] == b[1];
|
||||
}
|
||||
|
||||
static guint
|
||||
tuple_hash_2 (gconstpointer v_a)
|
||||
{
|
||||
#if GLIB_SIZEOF_VOID_P > GLIB_SIZEOF_LONG
|
||||
/* In practise this snippet has been written for 64-bit Windows
|
||||
* where ints are 32 bits, pointers 64 bits. More exotic platforms
|
||||
* need more tweaks.
|
||||
*/
|
||||
guint* a = (guint*) v_a;
|
||||
|
||||
return (a[0] ^ a[1] ^ a[2] ^ a[3]);
|
||||
#else
|
||||
gpointer* a = (gpointer*) v_a;
|
||||
|
||||
return (gulong)a[0] ^ (gulong)a[1];
|
||||
#endif
|
||||
}
|
||||
|
||||
static GHashFunc
|
||||
tuple_hash (gint fields)
|
||||
{
|
||||
switch (fields)
|
||||
{
|
||||
case 2:
|
||||
return tuple_hash_2;
|
||||
default:
|
||||
g_error ("no tuple hash for %d", fields);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GEqualFunc
|
||||
tuple_equal (gint fields)
|
||||
{
|
||||
switch (fields)
|
||||
{
|
||||
case 2:
|
||||
return tuple_equal_2;
|
||||
default:
|
||||
g_error ("no tuple equal for %d", fields);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_relation_new:
|
||||
* @fields: the number of fields.
|
||||
* @Returns: a new #GRelation.
|
||||
*
|
||||
* Creates a new #GRelation with the given number of fields. Note that
|
||||
* currently the number of fields must be 2.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
GRelation*
|
||||
g_relation_new (gint fields)
|
||||
{
|
||||
GRelation* rel = g_new0 (GRelation, 1);
|
||||
|
||||
rel->fields = fields;
|
||||
rel->all_tuples = g_hash_table_new (tuple_hash (fields), tuple_equal (fields));
|
||||
rel->hashed_tuple_tables = g_new0 (GHashTable*, fields);
|
||||
|
||||
return rel;
|
||||
}
|
||||
|
||||
static void
|
||||
relation_delete_value_tuple (gpointer tuple_key,
|
||||
gpointer tuple_value,
|
||||
gpointer user_data)
|
||||
{
|
||||
GRelation *relation = user_data;
|
||||
gpointer *tuple = tuple_value;
|
||||
g_slice_free1 (relation->fields * sizeof (gpointer), tuple);
|
||||
}
|
||||
|
||||
static void
|
||||
g_relation_free_array (gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
g_hash_table_destroy ((GHashTable*) value);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_relation_destroy:
|
||||
* @relation: a #GRelation.
|
||||
*
|
||||
* Destroys the #GRelation, freeing all memory allocated. However, it
|
||||
* does not free memory allocated for the tuple data, so you should
|
||||
* free that first if appropriate.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
void
|
||||
g_relation_destroy (GRelation *relation)
|
||||
{
|
||||
gint i;
|
||||
|
||||
if (relation)
|
||||
{
|
||||
for (i = 0; i < relation->fields; i += 1)
|
||||
{
|
||||
if (relation->hashed_tuple_tables[i])
|
||||
{
|
||||
g_hash_table_foreach (relation->hashed_tuple_tables[i], g_relation_free_array, NULL);
|
||||
g_hash_table_destroy (relation->hashed_tuple_tables[i]);
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_foreach (relation->all_tuples, relation_delete_value_tuple, relation);
|
||||
g_hash_table_destroy (relation->all_tuples);
|
||||
|
||||
g_free (relation->hashed_tuple_tables);
|
||||
g_free (relation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_relation_index:
|
||||
* @relation: a #GRelation.
|
||||
* @field: the field to index, counting from 0.
|
||||
* @hash_func: a function to produce a hash value from the field data.
|
||||
* @key_equal_func: a function to compare two values of the given field.
|
||||
*
|
||||
* Creates an index on the given field. Note that this must be called
|
||||
* before any records are added to the #GRelation.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
void
|
||||
g_relation_index (GRelation *relation,
|
||||
gint field,
|
||||
GHashFunc hash_func,
|
||||
GEqualFunc key_equal_func)
|
||||
{
|
||||
g_return_if_fail (relation != NULL);
|
||||
|
||||
g_return_if_fail (relation->count == 0 && relation->hashed_tuple_tables[field] == NULL);
|
||||
|
||||
relation->hashed_tuple_tables[field] = g_hash_table_new (hash_func, key_equal_func);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_relation_insert:
|
||||
* @relation: a #GRelation.
|
||||
* @...: the fields of the record to add. These must match the
|
||||
* number of fields in the #GRelation, and of type #gpointer
|
||||
* or #gconstpointer.
|
||||
*
|
||||
* Inserts a record into a #GRelation.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
void
|
||||
g_relation_insert (GRelation *relation,
|
||||
...)
|
||||
{
|
||||
gpointer* tuple = g_slice_alloc (relation->fields * sizeof (gpointer));
|
||||
va_list args;
|
||||
gint i;
|
||||
|
||||
va_start (args, relation);
|
||||
|
||||
for (i = 0; i < relation->fields; i += 1)
|
||||
tuple[i] = va_arg (args, gpointer);
|
||||
|
||||
va_end (args);
|
||||
|
||||
g_hash_table_insert (relation->all_tuples, tuple, tuple);
|
||||
|
||||
relation->count += 1;
|
||||
|
||||
for (i = 0; i < relation->fields; i += 1)
|
||||
{
|
||||
GHashTable *table;
|
||||
gpointer key;
|
||||
GHashTable *per_key_table;
|
||||
|
||||
table = relation->hashed_tuple_tables[i];
|
||||
|
||||
if (table == NULL)
|
||||
continue;
|
||||
|
||||
key = tuple[i];
|
||||
per_key_table = g_hash_table_lookup (table, key);
|
||||
|
||||
if (per_key_table == NULL)
|
||||
{
|
||||
per_key_table = g_hash_table_new (tuple_hash (relation->fields), tuple_equal (relation->fields));
|
||||
g_hash_table_insert (table, key, per_key_table);
|
||||
}
|
||||
|
||||
g_hash_table_insert (per_key_table, tuple, tuple);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
g_relation_delete_tuple (gpointer tuple_key,
|
||||
gpointer tuple_value,
|
||||
gpointer user_data)
|
||||
{
|
||||
gpointer *tuple = (gpointer*) tuple_value;
|
||||
GRelation *relation = (GRelation *) user_data;
|
||||
gint j;
|
||||
|
||||
g_assert (tuple_key == tuple_value);
|
||||
|
||||
for (j = 0; j < relation->fields; j += 1)
|
||||
{
|
||||
GHashTable *one_table = relation->hashed_tuple_tables[j];
|
||||
gpointer one_key;
|
||||
GHashTable *per_key_table;
|
||||
|
||||
if (one_table == NULL)
|
||||
continue;
|
||||
|
||||
if (j == relation->current_field)
|
||||
/* can't delete from the table we're foreaching in */
|
||||
continue;
|
||||
|
||||
one_key = tuple[j];
|
||||
|
||||
per_key_table = g_hash_table_lookup (one_table, one_key);
|
||||
|
||||
g_hash_table_remove (per_key_table, tuple);
|
||||
}
|
||||
|
||||
if (g_hash_table_remove (relation->all_tuples, tuple))
|
||||
g_slice_free1 (relation->fields * sizeof (gpointer), tuple);
|
||||
|
||||
relation->count -= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_relation_delete:
|
||||
* @relation: a #GRelation.
|
||||
* @key: the value to compare with.
|
||||
* @field: the field of each record to match.
|
||||
* @Returns: the number of records deleted.
|
||||
*
|
||||
* Deletes any records from a #GRelation that have the given key value
|
||||
* in the given field.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
gint
|
||||
g_relation_delete (GRelation *relation,
|
||||
gconstpointer key,
|
||||
gint field)
|
||||
{
|
||||
GHashTable *table;
|
||||
GHashTable *key_table;
|
||||
gint count;
|
||||
|
||||
g_return_val_if_fail (relation != NULL, 0);
|
||||
|
||||
table = relation->hashed_tuple_tables[field];
|
||||
count = relation->count;
|
||||
|
||||
g_return_val_if_fail (table != NULL, 0);
|
||||
|
||||
key_table = g_hash_table_lookup (table, key);
|
||||
|
||||
if (!key_table)
|
||||
return 0;
|
||||
|
||||
relation->current_field = field;
|
||||
|
||||
g_hash_table_foreach (key_table, g_relation_delete_tuple, relation);
|
||||
|
||||
g_hash_table_remove (table, key);
|
||||
|
||||
g_hash_table_destroy (key_table);
|
||||
|
||||
/* @@@ FIXME: Remove empty hash tables. */
|
||||
|
||||
return count - relation->count;
|
||||
}
|
||||
|
||||
static void
|
||||
g_relation_select_tuple (gpointer tuple_key,
|
||||
gpointer tuple_value,
|
||||
gpointer user_data)
|
||||
{
|
||||
gpointer *tuple = (gpointer*) tuple_value;
|
||||
GRealTuples *tuples = (GRealTuples*) user_data;
|
||||
gint stride = sizeof (gpointer) * tuples->width;
|
||||
|
||||
g_assert (tuple_key == tuple_value);
|
||||
|
||||
memcpy (tuples->data + (tuples->len * tuples->width),
|
||||
tuple,
|
||||
stride);
|
||||
|
||||
tuples->len += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_relation_select:
|
||||
* @relation: a #GRelation.
|
||||
* @key: the value to compare with.
|
||||
* @field: the field of each record to match.
|
||||
* @Returns: the records (tuples) that matched.
|
||||
*
|
||||
* Returns all of the tuples which have the given key in the given
|
||||
* field. Use g_tuples_index() to access the returned records. The
|
||||
* returned records should be freed with g_tuples_destroy().
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
GTuples*
|
||||
g_relation_select (GRelation *relation,
|
||||
gconstpointer key,
|
||||
gint field)
|
||||
{
|
||||
GHashTable *table;
|
||||
GHashTable *key_table;
|
||||
GRealTuples *tuples;
|
||||
gint count;
|
||||
|
||||
g_return_val_if_fail (relation != NULL, NULL);
|
||||
|
||||
table = relation->hashed_tuple_tables[field];
|
||||
|
||||
g_return_val_if_fail (table != NULL, NULL);
|
||||
|
||||
tuples = g_new0 (GRealTuples, 1);
|
||||
key_table = g_hash_table_lookup (table, key);
|
||||
|
||||
if (!key_table)
|
||||
return (GTuples*)tuples;
|
||||
|
||||
count = g_relation_count (relation, key, field);
|
||||
|
||||
tuples->data = g_malloc (sizeof (gpointer) * relation->fields * count);
|
||||
tuples->width = relation->fields;
|
||||
|
||||
g_hash_table_foreach (key_table, g_relation_select_tuple, tuples);
|
||||
|
||||
g_assert (count == tuples->len);
|
||||
|
||||
return (GTuples*)tuples;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_relation_count:
|
||||
* @relation: a #GRelation.
|
||||
* @key: the value to compare with.
|
||||
* @field: the field of each record to match.
|
||||
* @Returns: the number of matches.
|
||||
*
|
||||
* Returns the number of tuples in a #GRelation that have the given
|
||||
* value in the given field.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
gint
|
||||
g_relation_count (GRelation *relation,
|
||||
gconstpointer key,
|
||||
gint field)
|
||||
{
|
||||
GHashTable *table;
|
||||
GHashTable *key_table;
|
||||
|
||||
g_return_val_if_fail (relation != NULL, 0);
|
||||
|
||||
table = relation->hashed_tuple_tables[field];
|
||||
|
||||
g_return_val_if_fail (table != NULL, 0);
|
||||
|
||||
key_table = g_hash_table_lookup (table, key);
|
||||
|
||||
if (!key_table)
|
||||
return 0;
|
||||
|
||||
return g_hash_table_size (key_table);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_relation_exists:
|
||||
* @relation: a #GRelation.
|
||||
* @...: the fields of the record to compare. The number must match
|
||||
* the number of fields in the #GRelation.
|
||||
* @Returns: %TRUE if a record matches.
|
||||
*
|
||||
* Returns %TRUE if a record with the given values exists in a
|
||||
* #GRelation. Note that the values are compared directly, so that, for
|
||||
* example, two copies of the same string will not match.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
gboolean
|
||||
g_relation_exists (GRelation *relation, ...)
|
||||
{
|
||||
gpointer *tuple = g_slice_alloc (relation->fields * sizeof (gpointer));
|
||||
va_list args;
|
||||
gint i;
|
||||
gboolean result;
|
||||
|
||||
va_start(args, relation);
|
||||
|
||||
for (i = 0; i < relation->fields; i += 1)
|
||||
tuple[i] = va_arg(args, gpointer);
|
||||
|
||||
va_end(args);
|
||||
|
||||
result = g_hash_table_lookup (relation->all_tuples, tuple) != NULL;
|
||||
|
||||
g_slice_free1 (relation->fields * sizeof (gpointer), tuple);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_tuples_destroy:
|
||||
* @tuples: the tuple data to free.
|
||||
*
|
||||
* Frees the records which were returned by g_relation_select(). This
|
||||
* should always be called after g_relation_select() when you are
|
||||
* finished with the records. The records are not removed from the
|
||||
* #GRelation.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
void
|
||||
g_tuples_destroy (GTuples *tuples0)
|
||||
{
|
||||
GRealTuples *tuples = (GRealTuples*) tuples0;
|
||||
|
||||
if (tuples)
|
||||
{
|
||||
g_free (tuples->data);
|
||||
g_free (tuples);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_tuples_index:
|
||||
* @tuples: the tuple data, returned by g_relation_select().
|
||||
* @index_: the index of the record.
|
||||
* @field: the field to return.
|
||||
* @Returns: the field of the record.
|
||||
*
|
||||
* Gets a field from the records returned by g_relation_select(). It
|
||||
* returns the given field of the record at the given index. The
|
||||
* returned value should not be changed.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
gpointer
|
||||
g_tuples_index (GTuples *tuples0,
|
||||
gint index,
|
||||
gint field)
|
||||
{
|
||||
GRealTuples *tuples = (GRealTuples*) tuples0;
|
||||
|
||||
g_return_val_if_fail (tuples0 != NULL, NULL);
|
||||
g_return_val_if_fail (field < tuples->width, NULL);
|
||||
|
||||
return tuples->data[index * tuples->width + field];
|
||||
}
|
||||
|
||||
/* Print
|
||||
*/
|
||||
|
||||
static void
|
||||
g_relation_print_one (gpointer tuple_key,
|
||||
gpointer tuple_value,
|
||||
gpointer user_data)
|
||||
{
|
||||
gint i;
|
||||
GString *gstring;
|
||||
GRelation* rel = (GRelation*) user_data;
|
||||
gpointer* tuples = (gpointer*) tuple_value;
|
||||
|
||||
gstring = g_string_new ("[");
|
||||
|
||||
for (i = 0; i < rel->fields; i += 1)
|
||||
{
|
||||
g_string_append_printf (gstring, "%p", tuples[i]);
|
||||
|
||||
if (i < (rel->fields - 1))
|
||||
g_string_append (gstring, ",");
|
||||
}
|
||||
|
||||
g_string_append (gstring, "]");
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "%s", gstring->str);
|
||||
g_string_free (gstring, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
g_relation_print_index (gpointer tuple_key,
|
||||
gpointer tuple_value,
|
||||
gpointer user_data)
|
||||
{
|
||||
GRelation* rel = (GRelation*) user_data;
|
||||
GHashTable* table = (GHashTable*) tuple_value;
|
||||
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "*** key %p", tuple_key);
|
||||
|
||||
g_hash_table_foreach (table,
|
||||
g_relation_print_one,
|
||||
rel);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_relation_print:
|
||||
* @relation: a #GRelation.
|
||||
*
|
||||
* Outputs information about all records in a #GRelation, as well as
|
||||
* the indexes. It is for debugging.
|
||||
*
|
||||
* Deprecated: 2.26: Rarely used API
|
||||
**/
|
||||
void
|
||||
g_relation_print (GRelation *relation)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "*** all tuples (%d)", relation->count);
|
||||
|
||||
g_hash_table_foreach (relation->all_tuples,
|
||||
g_relation_print_one,
|
||||
relation);
|
||||
|
||||
for (i = 0; i < relation->fields; i += 1)
|
||||
{
|
||||
if (relation->hashed_tuple_tables[i] == NULL)
|
||||
continue;
|
||||
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "*** index %d", i);
|
||||
|
||||
g_hash_table_foreach (relation->hashed_tuple_tables[i],
|
||||
g_relation_print_index,
|
||||
relation);
|
||||
}
|
||||
|
||||
}
|
||||
107
glib/glib/deprecated/grel.h
Normal file
107
glib/glib/deprecated/grel.h
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_REL_H__
|
||||
#define __G_REL_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GRelation GRelation;
|
||||
typedef struct _GTuples GTuples;
|
||||
|
||||
struct _GTuples
|
||||
{
|
||||
guint len;
|
||||
};
|
||||
|
||||
/* GRelation
|
||||
*
|
||||
* Indexed Relations. Imagine a really simple table in a
|
||||
* database. Relations are not ordered. This data type is meant for
|
||||
* maintaining a N-way mapping.
|
||||
*
|
||||
* g_relation_new() creates a relation with FIELDS fields
|
||||
*
|
||||
* g_relation_destroy() frees all resources
|
||||
* g_tuples_destroy() frees the result of g_relation_select()
|
||||
*
|
||||
* g_relation_index() indexes relation FIELD with the provided
|
||||
* equality and hash functions. this must be done before any
|
||||
* calls to insert are made.
|
||||
*
|
||||
* g_relation_insert() inserts a new tuple. you are expected to
|
||||
* provide the right number of fields.
|
||||
*
|
||||
* g_relation_delete() deletes all relations with KEY in FIELD
|
||||
* g_relation_select() returns ...
|
||||
* g_relation_count() counts ...
|
||||
*/
|
||||
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
GRelation* g_relation_new (gint fields);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
void g_relation_destroy (GRelation *relation);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
void g_relation_index (GRelation *relation,
|
||||
gint field,
|
||||
GHashFunc hash_func,
|
||||
GEqualFunc key_equal_func);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
void g_relation_insert (GRelation *relation,
|
||||
...);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
gint g_relation_delete (GRelation *relation,
|
||||
gconstpointer key,
|
||||
gint field);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
GTuples* g_relation_select (GRelation *relation,
|
||||
gconstpointer key,
|
||||
gint field);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
gint g_relation_count (GRelation *relation,
|
||||
gconstpointer key,
|
||||
gint field);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
gboolean g_relation_exists (GRelation *relation,
|
||||
...);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
void g_relation_print (GRelation *relation);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
void g_tuples_destroy (GTuples *tuples);
|
||||
GLIB_DEPRECATED_IN_2_26
|
||||
gpointer g_tuples_index (GTuples *tuples,
|
||||
gint index_,
|
||||
gint field);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_REL_H__ */
|
||||
1592
glib/glib/deprecated/gthread-deprecated.c
Normal file
1592
glib/glib/deprecated/gthread-deprecated.c
Normal file
File diff suppressed because it is too large
Load diff
285
glib/glib/deprecated/gthread.h
Normal file
285
glib/glib/deprecated/gthread.h
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_DEPRECATED_THREAD_H__
|
||||
#define __G_DEPRECATED_THREAD_H__
|
||||
|
||||
#include <glib/gthread.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum
|
||||
{
|
||||
G_THREAD_PRIORITY_LOW,
|
||||
G_THREAD_PRIORITY_NORMAL,
|
||||
G_THREAD_PRIORITY_HIGH,
|
||||
G_THREAD_PRIORITY_URGENT
|
||||
} GThreadPriority;
|
||||
|
||||
struct _GThread
|
||||
{
|
||||
/*< private >*/
|
||||
GThreadFunc func;
|
||||
gpointer data;
|
||||
gboolean joinable;
|
||||
GThreadPriority priority;
|
||||
};
|
||||
|
||||
typedef struct _GThreadFunctions GThreadFunctions;
|
||||
struct _GThreadFunctions
|
||||
{
|
||||
GMutex* (*mutex_new) (void);
|
||||
void (*mutex_lock) (GMutex *mutex);
|
||||
gboolean (*mutex_trylock) (GMutex *mutex);
|
||||
void (*mutex_unlock) (GMutex *mutex);
|
||||
void (*mutex_free) (GMutex *mutex);
|
||||
GCond* (*cond_new) (void);
|
||||
void (*cond_signal) (GCond *cond);
|
||||
void (*cond_broadcast) (GCond *cond);
|
||||
void (*cond_wait) (GCond *cond,
|
||||
GMutex *mutex);
|
||||
gboolean (*cond_timed_wait) (GCond *cond,
|
||||
GMutex *mutex,
|
||||
GTimeVal *end_time);
|
||||
void (*cond_free) (GCond *cond);
|
||||
GPrivate* (*private_new) (GDestroyNotify destructor);
|
||||
gpointer (*private_get) (GPrivate *private_key);
|
||||
void (*private_set) (GPrivate *private_key,
|
||||
gpointer data);
|
||||
void (*thread_create) (GThreadFunc func,
|
||||
gpointer data,
|
||||
gulong stack_size,
|
||||
gboolean joinable,
|
||||
gboolean bound,
|
||||
GThreadPriority priority,
|
||||
gpointer thread,
|
||||
GError **error);
|
||||
void (*thread_yield) (void);
|
||||
void (*thread_join) (gpointer thread);
|
||||
void (*thread_exit) (void);
|
||||
void (*thread_set_priority)(gpointer thread,
|
||||
GThreadPriority priority);
|
||||
void (*thread_self) (gpointer thread);
|
||||
gboolean (*thread_equal) (gpointer thread1,
|
||||
gpointer thread2);
|
||||
};
|
||||
|
||||
GLIB_VAR GThreadFunctions g_thread_functions_for_glib_use;
|
||||
GLIB_VAR gboolean g_thread_use_default_impl;
|
||||
|
||||
GLIB_VAR guint64 (*g_thread_gettime) (void);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_thread_new)
|
||||
GThread *g_thread_create (GThreadFunc func,
|
||||
gpointer data,
|
||||
gboolean joinable,
|
||||
GError **error);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_thread_new)
|
||||
GThread *g_thread_create_full (GThreadFunc func,
|
||||
gpointer data,
|
||||
gulong stack_size,
|
||||
gboolean joinable,
|
||||
gboolean bound,
|
||||
GThreadPriority priority,
|
||||
GError **error);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32
|
||||
void g_thread_set_priority (GThread *thread,
|
||||
GThreadPriority priority);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32
|
||||
void g_thread_foreach (GFunc thread_func,
|
||||
gpointer user_data);
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define g_static_mutex_get_mutex g_static_mutex_get_mutex_impl
|
||||
#define G_STATIC_MUTEX_INIT { NULL }
|
||||
typedef struct
|
||||
{
|
||||
GMutex *mutex;
|
||||
#ifndef G_OS_WIN32
|
||||
/* only for ABI compatibility reasons */
|
||||
pthread_mutex_t unused;
|
||||
#endif
|
||||
} GStaticMutex;
|
||||
|
||||
#define g_static_mutex_lock(mutex) \
|
||||
g_mutex_lock (g_static_mutex_get_mutex (mutex))
|
||||
#define g_static_mutex_trylock(mutex) \
|
||||
g_mutex_trylock (g_static_mutex_get_mutex (mutex))
|
||||
#define g_static_mutex_unlock(mutex) \
|
||||
g_mutex_unlock (g_static_mutex_get_mutex (mutex))
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_mutex_init)
|
||||
void g_static_mutex_init (GStaticMutex *mutex);
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_mutex_free)
|
||||
void g_static_mutex_free (GStaticMutex *mutex);
|
||||
GMutex *g_static_mutex_get_mutex_impl (GStaticMutex *mutex);
|
||||
|
||||
typedef struct _GStaticRecMutex GStaticRecMutex;
|
||||
struct _GStaticRecMutex
|
||||
{
|
||||
/*< private >*/
|
||||
GStaticMutex mutex;
|
||||
guint depth;
|
||||
|
||||
/* ABI compat only */
|
||||
union {
|
||||
#ifdef G_OS_WIN32
|
||||
void *owner;
|
||||
#else
|
||||
pthread_t owner;
|
||||
#endif
|
||||
gdouble dummy;
|
||||
} unused;
|
||||
};
|
||||
|
||||
#define G_STATIC_REC_MUTEX_INIT { G_STATIC_MUTEX_INIT }
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_rec_mutex_init)
|
||||
void g_static_rec_mutex_init (GStaticRecMutex *mutex);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_rec_mutex_lock)
|
||||
void g_static_rec_mutex_lock (GStaticRecMutex *mutex);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_rec_mutex_try_lock)
|
||||
gboolean g_static_rec_mutex_trylock (GStaticRecMutex *mutex);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_rec_mutex_unlock)
|
||||
void g_static_rec_mutex_unlock (GStaticRecMutex *mutex);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32
|
||||
void g_static_rec_mutex_lock_full (GStaticRecMutex *mutex,
|
||||
guint depth);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32
|
||||
guint g_static_rec_mutex_unlock_full (GStaticRecMutex *mutex);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_rec_mutex_free)
|
||||
void g_static_rec_mutex_free (GStaticRecMutex *mutex);
|
||||
|
||||
typedef struct _GStaticRWLock GStaticRWLock;
|
||||
struct _GStaticRWLock
|
||||
{
|
||||
/*< private >*/
|
||||
GStaticMutex mutex;
|
||||
GCond *read_cond;
|
||||
GCond *write_cond;
|
||||
guint read_counter;
|
||||
gboolean have_writer;
|
||||
guint want_to_read;
|
||||
guint want_to_write;
|
||||
};
|
||||
|
||||
#define G_STATIC_RW_LOCK_INIT { G_STATIC_MUTEX_INIT, NULL, NULL, 0, FALSE, 0, 0 }
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_rw_lock_init)
|
||||
void g_static_rw_lock_init (GStaticRWLock *lock);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_rw_lock_reader_lock)
|
||||
void g_static_rw_lock_reader_lock (GStaticRWLock *lock);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_rw_lock_reader_trylock)
|
||||
gboolean g_static_rw_lock_reader_trylock (GStaticRWLock *lock);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_rw_lock_reader_unlock)
|
||||
void g_static_rw_lock_reader_unlock (GStaticRWLock *lock);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_rw_lock_writer_lock)
|
||||
void g_static_rw_lock_writer_lock (GStaticRWLock *lock);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_rw_lock_writer_trylock)
|
||||
gboolean g_static_rw_lock_writer_trylock (GStaticRWLock *lock);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_rw_lock_writer_unlock)
|
||||
void g_static_rw_lock_writer_unlock (GStaticRWLock *lock);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_rw_lock_free)
|
||||
void g_static_rw_lock_free (GStaticRWLock *lock);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32
|
||||
GPrivate * g_private_new (GDestroyNotify notify);
|
||||
|
||||
typedef struct _GStaticPrivate GStaticPrivate;
|
||||
struct _GStaticPrivate
|
||||
{
|
||||
/*< private >*/
|
||||
guint index;
|
||||
};
|
||||
|
||||
#define G_STATIC_PRIVATE_INIT { 0 }
|
||||
GLIB_DEPRECATED_IN_2_32
|
||||
void g_static_private_init (GStaticPrivate *private_key);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_private_get)
|
||||
gpointer g_static_private_get (GStaticPrivate *private_key);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32_FOR(g_private_set)
|
||||
void g_static_private_set (GStaticPrivate *private_key,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32
|
||||
void g_static_private_free (GStaticPrivate *private_key);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32
|
||||
gboolean g_once_init_enter_impl (volatile gsize *location);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32
|
||||
void g_thread_init (gpointer vtable);
|
||||
GLIB_DEPRECATED_IN_2_32
|
||||
void g_thread_init_with_errorcheck_mutexes (gpointer vtable);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32
|
||||
gboolean g_thread_get_initialized (void);
|
||||
|
||||
GLIB_VAR gboolean g_threads_got_initialized;
|
||||
|
||||
#define g_thread_supported() (1)
|
||||
|
||||
GLIB_DEPRECATED_IN_2_32
|
||||
GMutex * g_mutex_new (void);
|
||||
GLIB_DEPRECATED_IN_2_32
|
||||
void g_mutex_free (GMutex *mutex);
|
||||
GLIB_DEPRECATED_IN_2_32
|
||||
GCond * g_cond_new (void);
|
||||
GLIB_DEPRECATED_IN_2_32
|
||||
void g_cond_free (GCond *cond);
|
||||
GLIB_DEPRECATED_IN_2_32
|
||||
gboolean g_cond_timed_wait (GCond *cond,
|
||||
GMutex *mutex,
|
||||
GTimeVal *timeval);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_DEPRECATED_THREAD_H__ */
|
||||
2334
glib/glib/docs.c
Normal file
2334
glib/glib/docs.c
Normal file
File diff suppressed because it is too large
Load diff
110
glib/glib/galloca.h
Normal file
110
glib/glib/galloca.h
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_ALLOCA_H__
|
||||
#define __G_ALLOCA_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
/* GCC does the right thing */
|
||||
# undef alloca
|
||||
# define alloca(size) __builtin_alloca (size)
|
||||
#elif defined (GLIB_HAVE_ALLOCA_H)
|
||||
/* a native and working alloca.h is there */
|
||||
# include <alloca.h>
|
||||
#else /* !__GNUC__ && !GLIB_HAVE_ALLOCA_H */
|
||||
# if defined(_MSC_VER) || defined(__DMC__)
|
||||
# include <malloc.h>
|
||||
# define alloca _alloca
|
||||
# else /* !_MSC_VER && !__DMC__ */
|
||||
# ifdef _AIX
|
||||
# pragma alloca
|
||||
# else /* !_AIX */
|
||||
# ifndef alloca /* predefined by HP cc +Olibcalls */
|
||||
G_BEGIN_DECLS
|
||||
char *alloca ();
|
||||
G_END_DECLS
|
||||
# endif /* !alloca */
|
||||
# endif /* !_AIX */
|
||||
# endif /* !_MSC_VER && !__DMC__ */
|
||||
#endif /* !__GNUC__ && !GLIB_HAVE_ALLOCA_H */
|
||||
|
||||
/**
|
||||
* g_alloca:
|
||||
* @size: number of bytes to allocate.
|
||||
*
|
||||
* Allocates @size bytes on the stack; these bytes will be freed when the current
|
||||
* stack frame is cleaned up. This macro essentially just wraps the alloca()
|
||||
* function present on most UNIX variants.
|
||||
* Thus it provides the same advantages and pitfalls as alloca():
|
||||
* <variablelist>
|
||||
* <varlistentry><term></term><listitem><para>
|
||||
* + alloca() is very fast, as on most systems it's implemented by just adjusting
|
||||
* the stack pointer register.
|
||||
* </para></listitem></varlistentry>
|
||||
* <varlistentry><term></term><listitem><para>
|
||||
* + It doesn't cause any memory fragmentation, within its scope, separate alloca()
|
||||
* blocks just build up and are released together at function end.
|
||||
* </para></listitem></varlistentry>
|
||||
* <varlistentry><term></term><listitem><para>
|
||||
* - Allocation sizes have to fit into the current stack frame. For instance in a
|
||||
* threaded environment on Linux, the per-thread stack size is limited to 2 Megabytes,
|
||||
* so be sparse with alloca() uses.
|
||||
* </para></listitem></varlistentry>
|
||||
* <varlistentry><term></term><listitem><para>
|
||||
* - Allocation failure due to insufficient stack space is not indicated with a %NULL
|
||||
* return like e.g. with malloc(). Instead, most systems probably handle it the same
|
||||
* way as out of stack space situations from infinite function recursion, i.e.
|
||||
* with a segmentation fault.
|
||||
* </para></listitem></varlistentry>
|
||||
* <varlistentry><term></term><listitem><para>
|
||||
* - Special care has to be taken when mixing alloca() with GNU C variable sized arrays.
|
||||
* Stack space allocated with alloca() in the same scope as a variable sized array
|
||||
* will be freed together with the variable sized array upon exit of that scope, and
|
||||
* not upon exit of the enclosing function scope.
|
||||
* </para></listitem></varlistentry>
|
||||
* </variablelist>
|
||||
*
|
||||
* Returns: space for @size bytes, allocated on the stack
|
||||
*/
|
||||
#define g_alloca(size) alloca (size)
|
||||
/**
|
||||
* g_newa:
|
||||
* @struct_type: Type of memory chunks to be allocated
|
||||
* @n_structs: Number of chunks to be allocated
|
||||
*
|
||||
* Wraps g_alloca() in a more typesafe manner.
|
||||
*
|
||||
* Returns: Pointer to stack space for @n_structs chunks of type @struct_type
|
||||
*/
|
||||
#define g_newa(struct_type, n_structs) ((struct_type*) g_alloca (sizeof (struct_type) * (gsize) (n_structs)))
|
||||
|
||||
#endif /* __G_ALLOCA_H__ */
|
||||
1777
glib/glib/garray.c
Normal file
1777
glib/glib/garray.c
Normal file
File diff suppressed because it is too large
Load diff
187
glib/glib/garray.h
Normal file
187
glib/glib/garray.h
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_ARRAY_H__
|
||||
#define __G_ARRAY_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GBytes GBytes;
|
||||
typedef struct _GArray GArray;
|
||||
typedef struct _GByteArray GByteArray;
|
||||
typedef struct _GPtrArray GPtrArray;
|
||||
|
||||
struct _GArray
|
||||
{
|
||||
gchar *data;
|
||||
guint len;
|
||||
};
|
||||
|
||||
struct _GByteArray
|
||||
{
|
||||
guint8 *data;
|
||||
guint len;
|
||||
};
|
||||
|
||||
struct _GPtrArray
|
||||
{
|
||||
gpointer *pdata;
|
||||
guint len;
|
||||
};
|
||||
|
||||
/* Resizable arrays. remove fills any cleared spot and shortens the
|
||||
* array, while preserving the order. remove_fast will distort the
|
||||
* order by moving the last element to the position of the removed.
|
||||
*/
|
||||
|
||||
#define g_array_append_val(a,v) g_array_append_vals (a, &(v), 1)
|
||||
#define g_array_prepend_val(a,v) g_array_prepend_vals (a, &(v), 1)
|
||||
#define g_array_insert_val(a,i,v) g_array_insert_vals (a, i, &(v), 1)
|
||||
#define g_array_index(a,t,i) (((t*) (void *) (a)->data) [(i)])
|
||||
|
||||
GArray* g_array_new (gboolean zero_terminated,
|
||||
gboolean clear_,
|
||||
guint element_size);
|
||||
GArray* g_array_sized_new (gboolean zero_terminated,
|
||||
gboolean clear_,
|
||||
guint element_size,
|
||||
guint reserved_size);
|
||||
gchar* g_array_free (GArray *array,
|
||||
gboolean free_segment);
|
||||
GArray *g_array_ref (GArray *array);
|
||||
void g_array_unref (GArray *array);
|
||||
guint g_array_get_element_size (GArray *array);
|
||||
GArray* g_array_append_vals (GArray *array,
|
||||
gconstpointer data,
|
||||
guint len);
|
||||
GArray* g_array_prepend_vals (GArray *array,
|
||||
gconstpointer data,
|
||||
guint len);
|
||||
GArray* g_array_insert_vals (GArray *array,
|
||||
guint index_,
|
||||
gconstpointer data,
|
||||
guint len);
|
||||
GArray* g_array_set_size (GArray *array,
|
||||
guint length);
|
||||
GArray* g_array_remove_index (GArray *array,
|
||||
guint index_);
|
||||
GArray* g_array_remove_index_fast (GArray *array,
|
||||
guint index_);
|
||||
GArray* g_array_remove_range (GArray *array,
|
||||
guint index_,
|
||||
guint length);
|
||||
void g_array_sort (GArray *array,
|
||||
GCompareFunc compare_func);
|
||||
void g_array_sort_with_data (GArray *array,
|
||||
GCompareDataFunc compare_func,
|
||||
gpointer user_data);
|
||||
void g_array_set_clear_func (GArray *array,
|
||||
GDestroyNotify clear_func);
|
||||
|
||||
/* Resizable pointer array. This interface is much less complicated
|
||||
* than the above. Add appends a pointer. Remove fills any cleared
|
||||
* spot and shortens the array. remove_fast will again distort order.
|
||||
*/
|
||||
#define g_ptr_array_index(array,index_) ((array)->pdata)[index_]
|
||||
GPtrArray* g_ptr_array_new (void);
|
||||
GPtrArray* g_ptr_array_new_with_free_func (GDestroyNotify element_free_func);
|
||||
GPtrArray* g_ptr_array_sized_new (guint reserved_size);
|
||||
GPtrArray* g_ptr_array_new_full (guint reserved_size,
|
||||
GDestroyNotify element_free_func);
|
||||
gpointer* g_ptr_array_free (GPtrArray *array,
|
||||
gboolean free_seg);
|
||||
GPtrArray* g_ptr_array_ref (GPtrArray *array);
|
||||
void g_ptr_array_unref (GPtrArray *array);
|
||||
void g_ptr_array_set_free_func (GPtrArray *array,
|
||||
GDestroyNotify element_free_func);
|
||||
void g_ptr_array_set_size (GPtrArray *array,
|
||||
gint length);
|
||||
gpointer g_ptr_array_remove_index (GPtrArray *array,
|
||||
guint index_);
|
||||
gpointer g_ptr_array_remove_index_fast (GPtrArray *array,
|
||||
guint index_);
|
||||
gboolean g_ptr_array_remove (GPtrArray *array,
|
||||
gpointer data);
|
||||
gboolean g_ptr_array_remove_fast (GPtrArray *array,
|
||||
gpointer data);
|
||||
void g_ptr_array_remove_range (GPtrArray *array,
|
||||
guint index_,
|
||||
guint length);
|
||||
void g_ptr_array_add (GPtrArray *array,
|
||||
gpointer data);
|
||||
void g_ptr_array_sort (GPtrArray *array,
|
||||
GCompareFunc compare_func);
|
||||
void g_ptr_array_sort_with_data (GPtrArray *array,
|
||||
GCompareDataFunc compare_func,
|
||||
gpointer user_data);
|
||||
void g_ptr_array_foreach (GPtrArray *array,
|
||||
GFunc func,
|
||||
gpointer user_data);
|
||||
|
||||
|
||||
/* Byte arrays, an array of guint8. Implemented as a GArray,
|
||||
* but type-safe.
|
||||
*/
|
||||
|
||||
GByteArray* g_byte_array_new (void);
|
||||
GByteArray* g_byte_array_new_take (guint8 *data,
|
||||
gsize len);
|
||||
GByteArray* g_byte_array_sized_new (guint reserved_size);
|
||||
guint8* g_byte_array_free (GByteArray *array,
|
||||
gboolean free_segment);
|
||||
GBytes* g_byte_array_free_to_bytes (GByteArray *array);
|
||||
GByteArray *g_byte_array_ref (GByteArray *array);
|
||||
void g_byte_array_unref (GByteArray *array);
|
||||
GByteArray* g_byte_array_append (GByteArray *array,
|
||||
const guint8 *data,
|
||||
guint len);
|
||||
GByteArray* g_byte_array_prepend (GByteArray *array,
|
||||
const guint8 *data,
|
||||
guint len);
|
||||
GByteArray* g_byte_array_set_size (GByteArray *array,
|
||||
guint length);
|
||||
GByteArray* g_byte_array_remove_index (GByteArray *array,
|
||||
guint index_);
|
||||
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
|
||||
guint index_);
|
||||
GByteArray* g_byte_array_remove_range (GByteArray *array,
|
||||
guint index_,
|
||||
guint length);
|
||||
void g_byte_array_sort (GByteArray *array,
|
||||
GCompareFunc compare_func);
|
||||
void g_byte_array_sort_with_data (GByteArray *array,
|
||||
GCompareDataFunc compare_func,
|
||||
gpointer user_data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_ARRAY_H__ */
|
||||
802
glib/glib/gasyncqueue.c
Normal file
802
glib/glib/gasyncqueue.c
Normal file
|
|
@ -0,0 +1,802 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* GAsyncQueue: asynchronous queue implementation, based on GQueue.
|
||||
* Copyright (C) 2000 Sebastian Wilhelmi; University of Karlsruhe
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gasyncqueue.h"
|
||||
#include "gasyncqueueprivate.h"
|
||||
|
||||
#include "gmain.h"
|
||||
#include "gmem.h"
|
||||
#include "gqueue.h"
|
||||
#include "gtestutils.h"
|
||||
#include "gtimer.h"
|
||||
#include "gthread.h"
|
||||
#include "deprecated/gthread.h"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:async_queues
|
||||
* @title: Asynchronous Queues
|
||||
* @short_description: asynchronous communication between threads
|
||||
* @see_also: #GThreadPool
|
||||
*
|
||||
* Often you need to communicate between different threads. In general
|
||||
* it's safer not to do this by shared memory, but by explicit message
|
||||
* passing. These messages only make sense asynchronously for
|
||||
* multi-threaded applications though, as a synchronous operation could
|
||||
* as well be done in the same thread.
|
||||
*
|
||||
* Asynchronous queues are an exception from most other GLib data
|
||||
* structures, as they can be used simultaneously from multiple threads
|
||||
* without explicit locking and they bring their own builtin reference
|
||||
* counting. This is because the nature of an asynchronous queue is that
|
||||
* it will always be used by at least 2 concurrent threads.
|
||||
*
|
||||
* For using an asynchronous queue you first have to create one with
|
||||
* g_async_queue_new(). #GAsyncQueue structs are reference counted,
|
||||
* use g_async_queue_ref() and g_async_queue_unref() to manage your
|
||||
* references.
|
||||
*
|
||||
* A thread which wants to send a message to that queue simply calls
|
||||
* g_async_queue_push() to push the message to the queue.
|
||||
*
|
||||
* A thread which is expecting messages from an asynchronous queue
|
||||
* simply calls g_async_queue_pop() for that queue. If no message is
|
||||
* available in the queue at that point, the thread is now put to sleep
|
||||
* until a message arrives. The message will be removed from the queue
|
||||
* and returned. The functions g_async_queue_try_pop() and
|
||||
* g_async_queue_timeout_pop() can be used to only check for the presence
|
||||
* of messages or to only wait a certain time for messages respectively.
|
||||
*
|
||||
* For almost every function there exist two variants, one that locks
|
||||
* the queue and one that doesn't. That way you can hold the queue lock
|
||||
* (acquire it with g_async_queue_lock() and release it with
|
||||
* g_async_queue_unlock()) over multiple queue accessing instructions.
|
||||
* This can be necessary to ensure the integrity of the queue, but should
|
||||
* only be used when really necessary, as it can make your life harder
|
||||
* if used unwisely. Normally you should only use the locking function
|
||||
* variants (those without the _unlocked suffix).
|
||||
*
|
||||
* In many cases, it may be more convenient to use #GThreadPool when
|
||||
* you need to distribute work to a set of worker threads instead of
|
||||
* using #GAsyncQueue manually. #GThreadPool uses a GAsyncQueue
|
||||
* internally.
|
||||
*/
|
||||
|
||||
/**
|
||||
* GAsyncQueue:
|
||||
*
|
||||
* The GAsyncQueue struct is an opaque data structure which represents
|
||||
* an asynchronous queue. It should only be accessed through the
|
||||
* <function>g_async_queue_*</function> functions.
|
||||
*/
|
||||
struct _GAsyncQueue
|
||||
{
|
||||
GMutex mutex;
|
||||
GCond cond;
|
||||
GQueue queue;
|
||||
GDestroyNotify item_free_func;
|
||||
guint waiting_threads;
|
||||
gint ref_count;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GCompareDataFunc func;
|
||||
gpointer user_data;
|
||||
} SortData;
|
||||
|
||||
/**
|
||||
* g_async_queue_new:
|
||||
*
|
||||
* Creates a new asynchronous queue.
|
||||
*
|
||||
* Return value: a new #GAsyncQueue. Free with g_async_queue_unref()
|
||||
*/
|
||||
GAsyncQueue *
|
||||
g_async_queue_new (void)
|
||||
{
|
||||
return g_async_queue_new_full (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_new_full:
|
||||
* @item_free_func: function to free queue elements
|
||||
*
|
||||
* Creates a new asynchronous queue and sets up a destroy notify
|
||||
* function that is used to free any remaining queue items when
|
||||
* the queue is destroyed after the final unref.
|
||||
*
|
||||
* Return value: a new #GAsyncQueue. Free with g_async_queue_unref()
|
||||
*
|
||||
* Since: 2.16
|
||||
*/
|
||||
GAsyncQueue *
|
||||
g_async_queue_new_full (GDestroyNotify item_free_func)
|
||||
{
|
||||
GAsyncQueue *queue;
|
||||
|
||||
queue = g_new (GAsyncQueue, 1);
|
||||
g_mutex_init (&queue->mutex);
|
||||
g_cond_init (&queue->cond);
|
||||
g_queue_init (&queue->queue);
|
||||
queue->waiting_threads = 0;
|
||||
queue->ref_count = 1;
|
||||
queue->item_free_func = item_free_func;
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_ref:
|
||||
* @queue: a #GAsyncQueue
|
||||
*
|
||||
* Increases the reference count of the asynchronous @queue by 1.
|
||||
* You do not need to hold the lock to call this function.
|
||||
*
|
||||
* Returns: the @queue that was passed in (since 2.6)
|
||||
*/
|
||||
GAsyncQueue *
|
||||
g_async_queue_ref (GAsyncQueue *queue)
|
||||
{
|
||||
g_return_val_if_fail (queue, NULL);
|
||||
|
||||
g_atomic_int_inc (&queue->ref_count);
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_ref_unlocked:
|
||||
* @queue: a #GAsyncQueue
|
||||
*
|
||||
* Increases the reference count of the asynchronous @queue by 1.
|
||||
*
|
||||
* @Deprecated: Since 2.8, reference counting is done atomically
|
||||
* so g_async_queue_ref() can be used regardless of the @queue's
|
||||
* lock.
|
||||
*/
|
||||
void
|
||||
g_async_queue_ref_unlocked (GAsyncQueue *queue)
|
||||
{
|
||||
g_return_if_fail (queue);
|
||||
|
||||
g_atomic_int_inc (&queue->ref_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_unref_and_unlock:
|
||||
* @queue: a #GAsyncQueue
|
||||
*
|
||||
* Decreases the reference count of the asynchronous @queue by 1
|
||||
* and releases the lock. This function must be called while holding
|
||||
* the @queue's lock. If the reference count went to 0, the @queue
|
||||
* will be destroyed and the memory allocated will be freed.
|
||||
*
|
||||
* @Deprecated: Since 2.8, reference counting is done atomically
|
||||
* so g_async_queue_unref() can be used regardless of the @queue's
|
||||
* lock.
|
||||
*/
|
||||
void
|
||||
g_async_queue_unref_and_unlock (GAsyncQueue *queue)
|
||||
{
|
||||
g_return_if_fail (queue);
|
||||
|
||||
g_mutex_unlock (&queue->mutex);
|
||||
g_async_queue_unref (queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_unref:
|
||||
* @queue: a #GAsyncQueue.
|
||||
*
|
||||
* Decreases the reference count of the asynchronous @queue by 1.
|
||||
*
|
||||
* If the reference count went to 0, the @queue will be destroyed
|
||||
* and the memory allocated will be freed. So you are not allowed
|
||||
* to use the @queue afterwards, as it might have disappeared.
|
||||
* You do not need to hold the lock to call this function.
|
||||
*/
|
||||
void
|
||||
g_async_queue_unref (GAsyncQueue *queue)
|
||||
{
|
||||
g_return_if_fail (queue);
|
||||
|
||||
if (g_atomic_int_dec_and_test (&queue->ref_count))
|
||||
{
|
||||
g_return_if_fail (queue->waiting_threads == 0);
|
||||
g_mutex_clear (&queue->mutex);
|
||||
g_cond_clear (&queue->cond);
|
||||
if (queue->item_free_func)
|
||||
g_queue_foreach (&queue->queue, (GFunc) queue->item_free_func, NULL);
|
||||
g_queue_clear (&queue->queue);
|
||||
g_free (queue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_lock:
|
||||
* @queue: a #GAsyncQueue
|
||||
*
|
||||
* Acquires the @queue's lock. If another thread is already
|
||||
* holding the lock, this call will block until the lock
|
||||
* becomes available.
|
||||
*
|
||||
* Call g_async_queue_unlock() to drop the lock again.
|
||||
*
|
||||
* While holding the lock, you can only call the
|
||||
* <function>g_async_queue_*_unlocked()</function> functions
|
||||
* on @queue. Otherwise, deadlock may occur.
|
||||
*/
|
||||
void
|
||||
g_async_queue_lock (GAsyncQueue *queue)
|
||||
{
|
||||
g_return_if_fail (queue);
|
||||
|
||||
g_mutex_lock (&queue->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_unlock:
|
||||
* @queue: a #GAsyncQueue
|
||||
*
|
||||
* Releases the queue's lock.
|
||||
*
|
||||
* Calling this function when you have not acquired
|
||||
* the with g_async_queue_lock() leads to undefined
|
||||
* behaviour.
|
||||
*/
|
||||
void
|
||||
g_async_queue_unlock (GAsyncQueue *queue)
|
||||
{
|
||||
g_return_if_fail (queue);
|
||||
|
||||
g_mutex_unlock (&queue->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_push:
|
||||
* @queue: a #GAsyncQueue
|
||||
* @data: @data to push into the @queue
|
||||
*
|
||||
* Pushes the @data into the @queue. @data must not be %NULL.
|
||||
*/
|
||||
void
|
||||
g_async_queue_push (GAsyncQueue *queue,
|
||||
gpointer data)
|
||||
{
|
||||
g_return_if_fail (queue);
|
||||
g_return_if_fail (data);
|
||||
|
||||
g_mutex_lock (&queue->mutex);
|
||||
g_async_queue_push_unlocked (queue, data);
|
||||
g_mutex_unlock (&queue->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_push_unlocked:
|
||||
* @queue: a #GAsyncQueue
|
||||
* @data: @data to push into the @queue
|
||||
*
|
||||
* Pushes the @data into the @queue. @data must not be %NULL.
|
||||
*
|
||||
* This function must be called while holding the @queue's lock.
|
||||
*/
|
||||
void
|
||||
g_async_queue_push_unlocked (GAsyncQueue *queue,
|
||||
gpointer data)
|
||||
{
|
||||
g_return_if_fail (queue);
|
||||
g_return_if_fail (data);
|
||||
|
||||
g_queue_push_head (&queue->queue, data);
|
||||
if (queue->waiting_threads > 0)
|
||||
g_cond_signal (&queue->cond);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_push_sorted:
|
||||
* @queue: a #GAsyncQueue
|
||||
* @data: the @data to push into the @queue
|
||||
* @func: the #GCompareDataFunc is used to sort @queue
|
||||
* @user_data: user data passed to @func.
|
||||
*
|
||||
* Inserts @data into @queue using @func to determine the new
|
||||
* position.
|
||||
*
|
||||
* This function requires that the @queue is sorted before pushing on
|
||||
* new elements, see g_async_queue_sort().
|
||||
*
|
||||
* This function will lock @queue before it sorts the queue and unlock
|
||||
* it when it is finished.
|
||||
*
|
||||
* For an example of @func see g_async_queue_sort().
|
||||
*
|
||||
* Since: 2.10
|
||||
*/
|
||||
void
|
||||
g_async_queue_push_sorted (GAsyncQueue *queue,
|
||||
gpointer data,
|
||||
GCompareDataFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (queue != NULL);
|
||||
|
||||
g_mutex_lock (&queue->mutex);
|
||||
g_async_queue_push_sorted_unlocked (queue, data, func, user_data);
|
||||
g_mutex_unlock (&queue->mutex);
|
||||
}
|
||||
|
||||
static gint
|
||||
g_async_queue_invert_compare (gpointer v1,
|
||||
gpointer v2,
|
||||
SortData *sd)
|
||||
{
|
||||
return -sd->func (v1, v2, sd->user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_push_sorted_unlocked:
|
||||
* @queue: a #GAsyncQueue
|
||||
* @data: the @data to push into the @queue
|
||||
* @func: the #GCompareDataFunc is used to sort @queue
|
||||
* @user_data: user data passed to @func.
|
||||
*
|
||||
* Inserts @data into @queue using @func to determine the new
|
||||
* position.
|
||||
*
|
||||
* The sort function @func is passed two elements of the @queue.
|
||||
* It should return 0 if they are equal, a negative value if the
|
||||
* first element should be higher in the @queue or a positive value
|
||||
* if the first element should be lower in the @queue than the second
|
||||
* element.
|
||||
*
|
||||
* This function requires that the @queue is sorted before pushing on
|
||||
* new elements, see g_async_queue_sort().
|
||||
*
|
||||
* This function must be called while holding the @queue's lock.
|
||||
*
|
||||
* For an example of @func see g_async_queue_sort().
|
||||
*
|
||||
* Since: 2.10
|
||||
*/
|
||||
void
|
||||
g_async_queue_push_sorted_unlocked (GAsyncQueue *queue,
|
||||
gpointer data,
|
||||
GCompareDataFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
SortData sd;
|
||||
|
||||
g_return_if_fail (queue != NULL);
|
||||
|
||||
sd.func = func;
|
||||
sd.user_data = user_data;
|
||||
|
||||
g_queue_insert_sorted (&queue->queue,
|
||||
data,
|
||||
(GCompareDataFunc)g_async_queue_invert_compare,
|
||||
&sd);
|
||||
if (queue->waiting_threads > 0)
|
||||
g_cond_signal (&queue->cond);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
g_async_queue_pop_intern_unlocked (GAsyncQueue *queue,
|
||||
gboolean wait,
|
||||
gint64 end_time)
|
||||
{
|
||||
gpointer retval;
|
||||
|
||||
if (!g_queue_peek_tail_link (&queue->queue) && wait)
|
||||
{
|
||||
queue->waiting_threads++;
|
||||
while (!g_queue_peek_tail_link (&queue->queue))
|
||||
{
|
||||
if (end_time == -1)
|
||||
g_cond_wait (&queue->cond, &queue->mutex);
|
||||
else
|
||||
{
|
||||
if (!g_cond_wait_until (&queue->cond, &queue->mutex, end_time))
|
||||
break;
|
||||
}
|
||||
}
|
||||
queue->waiting_threads--;
|
||||
}
|
||||
|
||||
retval = g_queue_pop_tail (&queue->queue);
|
||||
|
||||
g_assert (retval || !wait || end_time > 0);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_pop:
|
||||
* @queue: a #GAsyncQueue
|
||||
*
|
||||
* Pops data from the @queue. If @queue is empty, this function
|
||||
* blocks until data becomes available.
|
||||
*
|
||||
* Return value: data from the queue
|
||||
*/
|
||||
gpointer
|
||||
g_async_queue_pop (GAsyncQueue *queue)
|
||||
{
|
||||
gpointer retval;
|
||||
|
||||
g_return_val_if_fail (queue, NULL);
|
||||
|
||||
g_mutex_lock (&queue->mutex);
|
||||
retval = g_async_queue_pop_intern_unlocked (queue, TRUE, -1);
|
||||
g_mutex_unlock (&queue->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_pop_unlocked:
|
||||
* @queue: a #GAsyncQueue
|
||||
*
|
||||
* Pops data from the @queue. If @queue is empty, this function
|
||||
* blocks until data becomes available.
|
||||
*
|
||||
* This function must be called while holding the @queue's lock.
|
||||
*
|
||||
* Return value: data from the queue.
|
||||
*/
|
||||
gpointer
|
||||
g_async_queue_pop_unlocked (GAsyncQueue *queue)
|
||||
{
|
||||
g_return_val_if_fail (queue, NULL);
|
||||
|
||||
return g_async_queue_pop_intern_unlocked (queue, TRUE, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_try_pop:
|
||||
* @queue: a #GAsyncQueue
|
||||
*
|
||||
* Tries to pop data from the @queue. If no data is available,
|
||||
* %NULL is returned.
|
||||
*
|
||||
* Return value: data from the queue or %NULL, when no data is
|
||||
* available immediately.
|
||||
*/
|
||||
gpointer
|
||||
g_async_queue_try_pop (GAsyncQueue *queue)
|
||||
{
|
||||
gpointer retval;
|
||||
|
||||
g_return_val_if_fail (queue, NULL);
|
||||
|
||||
g_mutex_lock (&queue->mutex);
|
||||
retval = g_async_queue_pop_intern_unlocked (queue, FALSE, -1);
|
||||
g_mutex_unlock (&queue->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_try_pop_unlocked:
|
||||
* @queue: a #GAsyncQueue
|
||||
*
|
||||
* Tries to pop data from the @queue. If no data is available,
|
||||
* %NULL is returned.
|
||||
*
|
||||
* This function must be called while holding the @queue's lock.
|
||||
*
|
||||
* Return value: data from the queue or %NULL, when no data is
|
||||
* available immediately.
|
||||
*/
|
||||
gpointer
|
||||
g_async_queue_try_pop_unlocked (GAsyncQueue *queue)
|
||||
{
|
||||
g_return_val_if_fail (queue, NULL);
|
||||
|
||||
return g_async_queue_pop_intern_unlocked (queue, FALSE, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_timeout_pop:
|
||||
* @queue: a #GAsyncQueue
|
||||
* @timeout: the number of microseconds to wait
|
||||
*
|
||||
* Pops data from the @queue. If the queue is empty, blocks for
|
||||
* @timeout microseconds, or until data becomes available.
|
||||
*
|
||||
* If no data is received before the timeout, %NULL is returned.
|
||||
*
|
||||
* Return value: data from the queue or %NULL, when no data is
|
||||
* received before the timeout.
|
||||
*/
|
||||
gpointer
|
||||
g_async_queue_timeout_pop (GAsyncQueue *queue,
|
||||
guint64 timeout)
|
||||
{
|
||||
gint64 end_time = g_get_monotonic_time () + timeout;
|
||||
gpointer retval;
|
||||
|
||||
g_mutex_lock (&queue->mutex);
|
||||
retval = g_async_queue_pop_intern_unlocked (queue, TRUE, end_time);
|
||||
g_mutex_unlock (&queue->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_timeout_pop_unlocked:
|
||||
* @queue: a #GAsyncQueue
|
||||
* @timeout: the number of microseconds to wait
|
||||
*
|
||||
* Pops data from the @queue. If the queue is empty, blocks for
|
||||
* @timeout microseconds, or until data becomes available.
|
||||
*
|
||||
* If no data is received before the timeout, %NULL is returned.
|
||||
*
|
||||
* This function must be called while holding the @queue's lock.
|
||||
*
|
||||
* Return value: data from the queue or %NULL, when no data is
|
||||
* received before the timeout.
|
||||
*/
|
||||
gpointer
|
||||
g_async_queue_timeout_pop_unlocked (GAsyncQueue *queue,
|
||||
guint64 timeout)
|
||||
{
|
||||
gint64 end_time = g_get_monotonic_time () + timeout;
|
||||
|
||||
return g_async_queue_pop_intern_unlocked (queue, TRUE, end_time);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_timed_pop:
|
||||
* @queue: a #GAsyncQueue
|
||||
* @end_time: a #GTimeVal, determining the final time
|
||||
*
|
||||
* Pops data from the @queue. If the queue is empty, blocks until
|
||||
* @end_time or until data becomes available.
|
||||
*
|
||||
* If no data is received before @end_time, %NULL is returned.
|
||||
*
|
||||
* To easily calculate @end_time, a combination of g_get_current_time()
|
||||
* and g_time_val_add() can be used.
|
||||
*
|
||||
* Return value: data from the queue or %NULL, when no data is
|
||||
* received before @end_time.
|
||||
*
|
||||
* Deprecated: use g_async_queue_timeout_pop().
|
||||
*/
|
||||
gpointer
|
||||
g_async_queue_timed_pop (GAsyncQueue *queue,
|
||||
GTimeVal *end_time)
|
||||
{
|
||||
gint64 m_end_time;
|
||||
gpointer retval;
|
||||
|
||||
g_return_val_if_fail (queue, NULL);
|
||||
|
||||
if (end_time != NULL)
|
||||
{
|
||||
m_end_time = g_get_monotonic_time () +
|
||||
((gint64)end_time->tv_sec * G_USEC_PER_SEC + end_time->tv_usec -
|
||||
g_get_real_time ());
|
||||
}
|
||||
else
|
||||
m_end_time = -1;
|
||||
|
||||
g_mutex_lock (&queue->mutex);
|
||||
retval = g_async_queue_pop_intern_unlocked (queue, TRUE, m_end_time);
|
||||
g_mutex_unlock (&queue->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_timed_pop_unlocked:
|
||||
* @queue: a #GAsyncQueue
|
||||
* @end_time: a #GTimeVal, determining the final time
|
||||
*
|
||||
* Pops data from the @queue. If the queue is empty, blocks until
|
||||
* @end_time or until data becomes available.
|
||||
*
|
||||
* If no data is received before @end_time, %NULL is returned.
|
||||
*
|
||||
* To easily calculate @end_time, a combination of g_get_current_time()
|
||||
* and g_time_val_add() can be used.
|
||||
*
|
||||
* This function must be called while holding the @queue's lock.
|
||||
*
|
||||
* Return value: data from the queue or %NULL, when no data is
|
||||
* received before @end_time.
|
||||
*
|
||||
* Deprecated: use g_async_queue_timeout_pop_unlocked().
|
||||
*/
|
||||
gpointer
|
||||
g_async_queue_timed_pop_unlocked (GAsyncQueue *queue,
|
||||
GTimeVal *end_time)
|
||||
{
|
||||
gint64 m_end_time;
|
||||
|
||||
g_return_val_if_fail (queue, NULL);
|
||||
|
||||
if (end_time != NULL)
|
||||
{
|
||||
m_end_time = g_get_monotonic_time () +
|
||||
(end_time->tv_sec * G_USEC_PER_SEC + end_time->tv_usec -
|
||||
g_get_real_time ());
|
||||
}
|
||||
else
|
||||
m_end_time = -1;
|
||||
|
||||
return g_async_queue_pop_intern_unlocked (queue, TRUE, m_end_time);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_length:
|
||||
* @queue: a #GAsyncQueue.
|
||||
*
|
||||
* Returns the length of the queue.
|
||||
*
|
||||
* Actually this function returns the number of data items in
|
||||
* the queue minus the number of waiting threads, so a negative
|
||||
* value means waiting threads, and a positive value means available
|
||||
* entries in the @queue. A return value of 0 could mean n entries
|
||||
* in the queue and n threads waiting. This can happen due to locking
|
||||
* of the queue or due to scheduling.
|
||||
*
|
||||
* Return value: the length of the @queue
|
||||
*/
|
||||
gint
|
||||
g_async_queue_length (GAsyncQueue *queue)
|
||||
{
|
||||
gint retval;
|
||||
|
||||
g_return_val_if_fail (queue, 0);
|
||||
|
||||
g_mutex_lock (&queue->mutex);
|
||||
retval = queue->queue.length - queue->waiting_threads;
|
||||
g_mutex_unlock (&queue->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_length_unlocked:
|
||||
* @queue: a #GAsyncQueue
|
||||
*
|
||||
* Returns the length of the queue.
|
||||
*
|
||||
* Actually this function returns the number of data items in
|
||||
* the queue minus the number of waiting threads, so a negative
|
||||
* value means waiting threads, and a positive value means available
|
||||
* entries in the @queue. A return value of 0 could mean n entries
|
||||
* in the queue and n threads waiting. This can happen due to locking
|
||||
* of the queue or due to scheduling.
|
||||
*
|
||||
* This function must be called while holding the @queue's lock.
|
||||
*
|
||||
* Return value: the length of the @queue.
|
||||
*/
|
||||
gint
|
||||
g_async_queue_length_unlocked (GAsyncQueue *queue)
|
||||
{
|
||||
g_return_val_if_fail (queue, 0);
|
||||
|
||||
return queue->queue.length - queue->waiting_threads;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_sort:
|
||||
* @queue: a #GAsyncQueue
|
||||
* @func: the #GCompareDataFunc is used to sort @queue
|
||||
* @user_data: user data passed to @func
|
||||
*
|
||||
* Sorts @queue using @func.
|
||||
*
|
||||
* The sort function @func is passed two elements of the @queue.
|
||||
* It should return 0 if they are equal, a negative value if the
|
||||
* first element should be higher in the @queue or a positive value
|
||||
* if the first element should be lower in the @queue than the second
|
||||
* element.
|
||||
*
|
||||
* This function will lock @queue before it sorts the queue and unlock
|
||||
* it when it is finished.
|
||||
*
|
||||
* If you were sorting a list of priority numbers to make sure the
|
||||
* lowest priority would be at the top of the queue, you could use:
|
||||
* |[
|
||||
* gint32 id1;
|
||||
* gint32 id2;
|
||||
*
|
||||
* id1 = GPOINTER_TO_INT (element1);
|
||||
* id2 = GPOINTER_TO_INT (element2);
|
||||
*
|
||||
* return (id1 > id2 ? +1 : id1 == id2 ? 0 : -1);
|
||||
* ]|
|
||||
*
|
||||
* Since: 2.10
|
||||
*/
|
||||
void
|
||||
g_async_queue_sort (GAsyncQueue *queue,
|
||||
GCompareDataFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (queue != NULL);
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
g_mutex_lock (&queue->mutex);
|
||||
g_async_queue_sort_unlocked (queue, func, user_data);
|
||||
g_mutex_unlock (&queue->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_async_queue_sort_unlocked:
|
||||
* @queue: a #GAsyncQueue
|
||||
* @func: the #GCompareDataFunc is used to sort @queue
|
||||
* @user_data: user data passed to @func
|
||||
*
|
||||
* Sorts @queue using @func.
|
||||
*
|
||||
* The sort function @func is passed two elements of the @queue.
|
||||
* It should return 0 if they are equal, a negative value if the
|
||||
* first element should be higher in the @queue or a positive value
|
||||
* if the first element should be lower in the @queue than the second
|
||||
* element.
|
||||
*
|
||||
* This function must be called while holding the @queue's lock.
|
||||
*
|
||||
* Since: 2.10
|
||||
*/
|
||||
void
|
||||
g_async_queue_sort_unlocked (GAsyncQueue *queue,
|
||||
GCompareDataFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
SortData sd;
|
||||
|
||||
g_return_if_fail (queue != NULL);
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
sd.func = func;
|
||||
sd.user_data = user_data;
|
||||
|
||||
g_queue_sort (&queue->queue,
|
||||
(GCompareDataFunc)g_async_queue_invert_compare,
|
||||
&sd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Private API
|
||||
*/
|
||||
|
||||
GMutex *
|
||||
_g_async_queue_get_mutex (GAsyncQueue *queue)
|
||||
{
|
||||
g_return_val_if_fail (queue, NULL);
|
||||
|
||||
return &queue->mutex;
|
||||
}
|
||||
91
glib/glib/gasyncqueue.h
Normal file
91
glib/glib/gasyncqueue.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_ASYNCQUEUE_H__
|
||||
#define __G_ASYNCQUEUE_H__
|
||||
|
||||
#include <glib/gthread.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GAsyncQueue GAsyncQueue;
|
||||
|
||||
GAsyncQueue *g_async_queue_new (void);
|
||||
GAsyncQueue *g_async_queue_new_full (GDestroyNotify item_free_func);
|
||||
void g_async_queue_lock (GAsyncQueue *queue);
|
||||
void g_async_queue_unlock (GAsyncQueue *queue);
|
||||
GAsyncQueue *g_async_queue_ref (GAsyncQueue *queue);
|
||||
void g_async_queue_unref (GAsyncQueue *queue);
|
||||
|
||||
GLIB_DEPRECATED_FOR(g_async_queue_ref)
|
||||
void g_async_queue_ref_unlocked (GAsyncQueue *queue);
|
||||
|
||||
GLIB_DEPRECATED_FOR(g_async_queue_unref)
|
||||
void g_async_queue_unref_and_unlock (GAsyncQueue *queue);
|
||||
|
||||
void g_async_queue_push (GAsyncQueue *queue,
|
||||
gpointer data);
|
||||
void g_async_queue_push_unlocked (GAsyncQueue *queue,
|
||||
gpointer data);
|
||||
void g_async_queue_push_sorted (GAsyncQueue *queue,
|
||||
gpointer data,
|
||||
GCompareDataFunc func,
|
||||
gpointer user_data);
|
||||
void g_async_queue_push_sorted_unlocked (GAsyncQueue *queue,
|
||||
gpointer data,
|
||||
GCompareDataFunc func,
|
||||
gpointer user_data);
|
||||
gpointer g_async_queue_pop (GAsyncQueue *queue);
|
||||
gpointer g_async_queue_pop_unlocked (GAsyncQueue *queue);
|
||||
gpointer g_async_queue_try_pop (GAsyncQueue *queue);
|
||||
gpointer g_async_queue_try_pop_unlocked (GAsyncQueue *queue);
|
||||
gpointer g_async_queue_timeout_pop (GAsyncQueue *queue,
|
||||
guint64 timeout);
|
||||
gpointer g_async_queue_timeout_pop_unlocked (GAsyncQueue *queue,
|
||||
guint64 timeout);
|
||||
gint g_async_queue_length (GAsyncQueue *queue);
|
||||
gint g_async_queue_length_unlocked (GAsyncQueue *queue);
|
||||
void g_async_queue_sort (GAsyncQueue *queue,
|
||||
GCompareDataFunc func,
|
||||
gpointer user_data);
|
||||
void g_async_queue_sort_unlocked (GAsyncQueue *queue,
|
||||
GCompareDataFunc func,
|
||||
gpointer user_data);
|
||||
|
||||
GLIB_DEPRECATED_FOR(g_async_queue_timeout_pop)
|
||||
gpointer g_async_queue_timed_pop (GAsyncQueue *queue,
|
||||
GTimeVal *end_time);
|
||||
GLIB_DEPRECATED_FOR(g_async_queue_timeout_pop_unlocked)
|
||||
gpointer g_async_queue_timed_pop_unlocked (GAsyncQueue *queue,
|
||||
GTimeVal *end_time);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_ASYNCQUEUE_H__ */
|
||||
31
glib/glib/gasyncqueueprivate.h
Normal file
31
glib/glib/gasyncqueueprivate.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __G_ASYNCQUEUEPRIVATE_H__
|
||||
#define __G_ASYNCQUEUEPRIVATE_H__
|
||||
|
||||
#include "gasyncqueue.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GMutex *_g_async_queue_get_mutex (GAsyncQueue *queue);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_ASYNCQUEUEPRIVATE_H__ */
|
||||
871
glib/glib/gatomic.c
Normal file
871
glib/glib/gatomic.c
Normal file
|
|
@ -0,0 +1,871 @@
|
|||
/*
|
||||
* Copyright © 2011 Ryan Lortie
|
||||
*
|
||||
* 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 of the
|
||||
* licence, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*
|
||||
* Author: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gatomic.h"
|
||||
|
||||
/**
|
||||
* SECTION:atomic_operations
|
||||
* @title: Atomic Operations
|
||||
* @short_description: basic atomic integer and pointer operations
|
||||
* @see_also: #GMutex
|
||||
*
|
||||
* The following is a collection of compiler macros to provide atomic
|
||||
* access to integer and pointer-sized values.
|
||||
*
|
||||
* The macros that have 'int' in the name will operate on pointers to
|
||||
* #gint and #guint. The macros with 'pointer' in the name will operate
|
||||
* on pointers to any pointer-sized value, including #gsize. There is
|
||||
* no support for 64bit operations on platforms with 32bit pointers
|
||||
* because it is not generally possible to perform these operations
|
||||
* atomically.
|
||||
*
|
||||
* The get, set and exchange operations for integers and pointers
|
||||
* nominally operate on #gint and #gpointer, respectively. Of the
|
||||
* arithmetic operations, the 'add' operation operates on (and returns)
|
||||
* signed integer values (#gint and #gssize) and the 'and', 'or', and
|
||||
* 'xor' operations operate on (and return) unsigned integer values
|
||||
* (#guint and #gsize).
|
||||
*
|
||||
* All of the operations act as a full compiler and (where appropriate)
|
||||
* hardware memory barrier. Acquire and release or producer and
|
||||
* consumer barrier semantics are not available through this API.
|
||||
*
|
||||
* It is very important that all accesses to a particular integer or
|
||||
* pointer be performed using only this API and that different sizes of
|
||||
* operation are not mixed or used on overlapping memory regions. Never
|
||||
* read or assign directly from or to a value -- always use this API.
|
||||
*
|
||||
* For simple reference counting purposes you should use
|
||||
* g_atomic_int_inc() and g_atomic_int_dec_and_test(). Other uses that
|
||||
* fall outside of simple reference counting patterns are prone to
|
||||
* subtle bugs and occasionally undefined behaviour. It is also worth
|
||||
* noting that since all of these operations require global
|
||||
* synchronisation of the entire machine, they can be quite slow. In
|
||||
* the case of performing multiple atomic operations it can often be
|
||||
* faster to simply acquire a mutex lock around the critical area,
|
||||
* perform the operations normally and then release the lock.
|
||||
**/
|
||||
|
||||
/**
|
||||
* G_ATOMIC_LOCK_FREE:
|
||||
*
|
||||
* This macro is defined if the atomic operations of GLib are
|
||||
* implemented using real hardware atomic operations. This means that
|
||||
* the GLib atomic API can be used between processes and safely mixed
|
||||
* with other (hardware) atomic APIs.
|
||||
*
|
||||
* If this macro is not defined, the atomic operations may be
|
||||
* emulated using a mutex. In that case, the GLib atomic operations are
|
||||
* only atomic relative to themselves and within a single process.
|
||||
**/
|
||||
|
||||
/* NOTE CAREFULLY:
|
||||
*
|
||||
* This file is the lowest-level part of GLib.
|
||||
*
|
||||
* Other lowlevel parts of GLib (threads, slice allocator, g_malloc,
|
||||
* messages, etc) call into these functions and macros to get work done.
|
||||
*
|
||||
* As such, these functions can not call back into any part of GLib
|
||||
* without risking recursion.
|
||||
*/
|
||||
|
||||
#ifdef G_ATOMIC_LOCK_FREE
|
||||
|
||||
/* if G_ATOMIC_LOCK_FREE was defined by ./configure then we MUST
|
||||
* implement the atomic operations in a lock-free manner.
|
||||
*/
|
||||
|
||||
#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
|
||||
/**
|
||||
* g_atomic_int_get:
|
||||
* @atomic: a pointer to a #gint or #guint
|
||||
*
|
||||
* Gets the current value of @atomic.
|
||||
*
|
||||
* This call acts as a full compiler and hardware
|
||||
* memory barrier (before the get).
|
||||
*
|
||||
* Returns: the value of the integer
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
gint
|
||||
(g_atomic_int_get) (volatile gint *atomic)
|
||||
{
|
||||
return g_atomic_int_get (atomic);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_int_set:
|
||||
* @atomic: a pointer to a #gint or #guint
|
||||
* @newval: a new value to store
|
||||
*
|
||||
* Sets the value of @atomic to @newval.
|
||||
*
|
||||
* This call acts as a full compiler and hardware
|
||||
* memory barrier (after the set).
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
void
|
||||
(g_atomic_int_set) (volatile gint *atomic,
|
||||
gint newval)
|
||||
{
|
||||
g_atomic_int_set (atomic, newval);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_int_inc:
|
||||
* @atomic: a pointer to a #gint or #guint
|
||||
*
|
||||
* Increments the value of @atomic by 1.
|
||||
*
|
||||
* Think of this operation as an atomic version of
|
||||
* <literal>{ *@atomic += 1; }</literal>
|
||||
*
|
||||
* This call acts as a full compiler and hardware memory barrier.
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
void
|
||||
(g_atomic_int_inc) (volatile gint *atomic)
|
||||
{
|
||||
g_atomic_int_inc (atomic);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_int_dec_and_test:
|
||||
* @atomic: a pointer to a #gint or #guint
|
||||
*
|
||||
* Decrements the value of @atomic by 1.
|
||||
*
|
||||
* Think of this operation as an atomic version of
|
||||
* <literal>{ *@atomic -= 1; return (*@atomic == 0); }</literal>
|
||||
*
|
||||
* This call acts as a full compiler and hardware memory barrier.
|
||||
*
|
||||
* Returns: %TRUE if the resultant value is zero
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
gboolean
|
||||
(g_atomic_int_dec_and_test) (volatile gint *atomic)
|
||||
{
|
||||
return g_atomic_int_dec_and_test (atomic);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_int_compare_and_exchange:
|
||||
* @atomic: a pointer to a #gint or #guint
|
||||
* @oldval: the value to compare with
|
||||
* @newval: the value to conditionally replace with
|
||||
*
|
||||
* Compares @atomic to @oldval and, if equal, sets it to @newval.
|
||||
* If @atomic was not equal to @oldval then no change occurs.
|
||||
*
|
||||
* This compare and exchange is done atomically.
|
||||
*
|
||||
* Think of this operation as an atomic version of
|
||||
* <literal>{ if (*@atomic == @oldval) { *@atomic = @newval; return TRUE; } else return FALSE; }</literal>
|
||||
*
|
||||
* This call acts as a full compiler and hardware memory barrier.
|
||||
*
|
||||
* Returns: %TRUE if the exchange took place
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
gboolean
|
||||
(g_atomic_int_compare_and_exchange) (volatile gint *atomic,
|
||||
gint oldval,
|
||||
gint newval)
|
||||
{
|
||||
return g_atomic_int_compare_and_exchange (atomic, oldval, newval);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_int_add:
|
||||
* @atomic: a pointer to a #gint or #guint
|
||||
* @val: the value to add
|
||||
*
|
||||
* Atomically adds @val to the value of @atomic.
|
||||
*
|
||||
* Think of this operation as an atomic version of
|
||||
* <literal>{ tmp = *atomic; *@atomic += @val; return tmp; }</literal>
|
||||
*
|
||||
* This call acts as a full compiler and hardware memory barrier.
|
||||
*
|
||||
* Before version 2.30, this function did not return a value
|
||||
* (but g_atomic_int_exchange_and_add() did, and had the same meaning).
|
||||
*
|
||||
* Returns: the value of @atomic before the add, signed
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
gint
|
||||
(g_atomic_int_add) (volatile gint *atomic,
|
||||
gint val)
|
||||
{
|
||||
return g_atomic_int_add (atomic, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_int_and:
|
||||
* @atomic: a pointer to a #gint or #guint
|
||||
* @val: the value to 'and'
|
||||
*
|
||||
* Performs an atomic bitwise 'and' of the value of @atomic and @val,
|
||||
* storing the result back in @atomic.
|
||||
*
|
||||
* This call acts as a full compiler and hardware memory barrier.
|
||||
*
|
||||
* Think of this operation as an atomic version of
|
||||
* <literal>{ tmp = *atomic; *@atomic &= @val; return tmp; }</literal>
|
||||
*
|
||||
* Returns: the value of @atomic before the operation, unsigned
|
||||
*
|
||||
* Since: 2.30
|
||||
**/
|
||||
guint
|
||||
(g_atomic_int_and) (volatile guint *atomic,
|
||||
guint val)
|
||||
{
|
||||
return g_atomic_int_and (atomic, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_int_or:
|
||||
* @atomic: a pointer to a #gint or #guint
|
||||
* @val: the value to 'or'
|
||||
*
|
||||
* Performs an atomic bitwise 'or' of the value of @atomic and @val,
|
||||
* storing the result back in @atomic.
|
||||
*
|
||||
* Think of this operation as an atomic version of
|
||||
* <literal>{ tmp = *atomic; *@atomic |= @val; return tmp; }</literal>
|
||||
*
|
||||
* This call acts as a full compiler and hardware memory barrier.
|
||||
*
|
||||
* Returns: the value of @atomic before the operation, unsigned
|
||||
*
|
||||
* Since: 2.30
|
||||
**/
|
||||
guint
|
||||
(g_atomic_int_or) (volatile guint *atomic,
|
||||
guint val)
|
||||
{
|
||||
return g_atomic_int_or (atomic, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_int_xor:
|
||||
* @atomic: a pointer to a #gint or #guint
|
||||
* @val: the value to 'xor'
|
||||
*
|
||||
* Performs an atomic bitwise 'xor' of the value of @atomic and @val,
|
||||
* storing the result back in @atomic.
|
||||
*
|
||||
* Think of this operation as an atomic version of
|
||||
* <literal>{ tmp = *atomic; *@atomic ^= @val; return tmp; }</literal>
|
||||
*
|
||||
* This call acts as a full compiler and hardware memory barrier.
|
||||
*
|
||||
* Returns: the value of @atomic before the operation, unsigned
|
||||
*
|
||||
* Since: 2.30
|
||||
**/
|
||||
guint
|
||||
(g_atomic_int_xor) (volatile guint *atomic,
|
||||
guint val)
|
||||
{
|
||||
return g_atomic_int_xor (atomic, val);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* g_atomic_pointer_get:
|
||||
* @atomic: a pointer to a #gpointer-sized value
|
||||
*
|
||||
* Gets the current value of @atomic.
|
||||
*
|
||||
* This call acts as a full compiler and hardware
|
||||
* memory barrier (before the get).
|
||||
*
|
||||
* Returns: the value of the pointer
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
gpointer
|
||||
(g_atomic_pointer_get) (volatile void *atomic)
|
||||
{
|
||||
return g_atomic_pointer_get ((volatile gpointer *) atomic);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_pointer_set:
|
||||
* @atomic: a pointer to a #gpointer-sized value
|
||||
* @newval: a new value to store
|
||||
*
|
||||
* Sets the value of @atomic to @newval.
|
||||
*
|
||||
* This call acts as a full compiler and hardware
|
||||
* memory barrier (after the set).
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
void
|
||||
(g_atomic_pointer_set) (volatile void *atomic,
|
||||
gpointer newval)
|
||||
{
|
||||
g_atomic_pointer_set ((volatile gpointer *) atomic, newval);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_pointer_compare_and_exchange:
|
||||
* @atomic: a pointer to a #gpointer-sized value
|
||||
* @oldval: the value to compare with
|
||||
* @newval: the value to conditionally replace with
|
||||
*
|
||||
* Compares @atomic to @oldval and, if equal, sets it to @newval.
|
||||
* If @atomic was not equal to @oldval then no change occurs.
|
||||
*
|
||||
* This compare and exchange is done atomically.
|
||||
*
|
||||
* Think of this operation as an atomic version of
|
||||
* <literal>{ if (*@atomic == @oldval) { *@atomic = @newval; return TRUE; } else return FALSE; }</literal>
|
||||
*
|
||||
* This call acts as a full compiler and hardware memory barrier.
|
||||
*
|
||||
* Returns: %TRUE if the exchange took place
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
gboolean
|
||||
(g_atomic_pointer_compare_and_exchange) (volatile void *atomic,
|
||||
gpointer oldval,
|
||||
gpointer newval)
|
||||
{
|
||||
return g_atomic_pointer_compare_and_exchange ((volatile gpointer *) atomic,
|
||||
oldval, newval);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_pointer_add:
|
||||
* @atomic: a pointer to a #gpointer-sized value
|
||||
* @val: the value to add
|
||||
*
|
||||
* Atomically adds @val to the value of @atomic.
|
||||
*
|
||||
* Think of this operation as an atomic version of
|
||||
* <literal>{ tmp = *atomic; *@atomic += @val; return tmp; }</literal>
|
||||
*
|
||||
* This call acts as a full compiler and hardware memory barrier.
|
||||
*
|
||||
* Returns: the value of @atomic before the add, signed
|
||||
*
|
||||
* Since: 2.30
|
||||
**/
|
||||
gssize
|
||||
(g_atomic_pointer_add) (volatile void *atomic,
|
||||
gssize val)
|
||||
{
|
||||
return g_atomic_pointer_add ((volatile gpointer *) atomic, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_pointer_and:
|
||||
* @atomic: a pointer to a #gpointer-sized value
|
||||
* @val: the value to 'and'
|
||||
*
|
||||
* Performs an atomic bitwise 'and' of the value of @atomic and @val,
|
||||
* storing the result back in @atomic.
|
||||
*
|
||||
* Think of this operation as an atomic version of
|
||||
* <literal>{ tmp = *atomic; *@atomic &= @val; return tmp; }</literal>
|
||||
*
|
||||
* This call acts as a full compiler and hardware memory barrier.
|
||||
*
|
||||
* Returns: the value of @atomic before the operation, unsigned
|
||||
*
|
||||
* Since: 2.30
|
||||
**/
|
||||
gsize
|
||||
(g_atomic_pointer_and) (volatile void *atomic,
|
||||
gsize val)
|
||||
{
|
||||
return g_atomic_pointer_and ((volatile gpointer *) atomic, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_pointer_or:
|
||||
* @atomic: a pointer to a #gpointer-sized value
|
||||
* @val: the value to 'or'
|
||||
*
|
||||
* Performs an atomic bitwise 'or' of the value of @atomic and @val,
|
||||
* storing the result back in @atomic.
|
||||
*
|
||||
* Think of this operation as an atomic version of
|
||||
* <literal>{ tmp = *atomic; *@atomic |= @val; return tmp; }</literal>
|
||||
*
|
||||
* This call acts as a full compiler and hardware memory barrier.
|
||||
*
|
||||
* Returns: the value of @atomic before the operation, unsigned
|
||||
*
|
||||
* Since: 2.30
|
||||
**/
|
||||
gsize
|
||||
(g_atomic_pointer_or) (volatile void *atomic,
|
||||
gsize val)
|
||||
{
|
||||
return g_atomic_pointer_or ((volatile gpointer *) atomic, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_atomic_pointer_xor:
|
||||
* @atomic: a pointer to a #gpointer-sized value
|
||||
* @val: the value to 'xor'
|
||||
*
|
||||
* Performs an atomic bitwise 'xor' of the value of @atomic and @val,
|
||||
* storing the result back in @atomic.
|
||||
*
|
||||
* Think of this operation as an atomic version of
|
||||
* <literal>{ tmp = *atomic; *@atomic ^= @val; return tmp; }</literal>
|
||||
*
|
||||
* This call acts as a full compiler and hardware memory barrier.
|
||||
*
|
||||
* Returns: the value of @atomic before the operation, unsigned
|
||||
*
|
||||
* Since: 2.30
|
||||
**/
|
||||
gsize
|
||||
(g_atomic_pointer_xor) (volatile void *atomic,
|
||||
gsize val)
|
||||
{
|
||||
return g_atomic_pointer_xor ((volatile gpointer *) atomic, val);
|
||||
}
|
||||
|
||||
#elif defined (G_PLATFORM_WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
#if !defined(_M_AMD64) && !defined (_M_IA64) && !defined(_M_X64)
|
||||
#define InterlockedAnd _InterlockedAnd
|
||||
#define InterlockedOr _InterlockedOr
|
||||
#define InterlockedXor _InterlockedXor
|
||||
#endif
|
||||
|
||||
/*
|
||||
* http://msdn.microsoft.com/en-us/library/ms684122(v=vs.85).aspx
|
||||
*/
|
||||
gint
|
||||
(g_atomic_int_get) (volatile gint *atomic)
|
||||
{
|
||||
MemoryBarrier ();
|
||||
return *atomic;
|
||||
}
|
||||
|
||||
void
|
||||
(g_atomic_int_set) (volatile gint *atomic,
|
||||
gint newval)
|
||||
{
|
||||
*atomic = newval;
|
||||
MemoryBarrier ();
|
||||
}
|
||||
|
||||
void
|
||||
(g_atomic_int_inc) (volatile gint *atomic)
|
||||
{
|
||||
InterlockedIncrement (atomic);
|
||||
}
|
||||
|
||||
gboolean
|
||||
(g_atomic_int_dec_and_test) (volatile gint *atomic)
|
||||
{
|
||||
return InterlockedDecrement (atomic) == 0;
|
||||
}
|
||||
|
||||
gboolean
|
||||
(g_atomic_int_compare_and_exchange) (volatile gint *atomic,
|
||||
gint oldval,
|
||||
gint newval)
|
||||
{
|
||||
return InterlockedCompareExchange (atomic, newval, oldval) == oldval;
|
||||
}
|
||||
|
||||
gint
|
||||
(g_atomic_int_add) (volatile gint *atomic,
|
||||
gint val)
|
||||
{
|
||||
return InterlockedExchangeAdd (atomic, val);
|
||||
}
|
||||
|
||||
guint
|
||||
(g_atomic_int_and) (volatile guint *atomic,
|
||||
guint val)
|
||||
{
|
||||
return InterlockedAnd (atomic, val);
|
||||
}
|
||||
|
||||
guint
|
||||
(g_atomic_int_or) (volatile guint *atomic,
|
||||
guint val)
|
||||
{
|
||||
return InterlockedOr (atomic, val);
|
||||
}
|
||||
|
||||
guint
|
||||
(g_atomic_int_xor) (volatile guint *atomic,
|
||||
guint val)
|
||||
{
|
||||
return InterlockedXor (atomic, val);
|
||||
}
|
||||
|
||||
|
||||
gpointer
|
||||
(g_atomic_pointer_get) (volatile void *atomic)
|
||||
{
|
||||
volatile gpointer *ptr = atomic;
|
||||
|
||||
MemoryBarrier ();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
void
|
||||
(g_atomic_pointer_set) (volatile void *atomic,
|
||||
gpointer newval)
|
||||
{
|
||||
volatile gpointer *ptr = atomic;
|
||||
|
||||
*ptr = newval;
|
||||
MemoryBarrier ();
|
||||
}
|
||||
|
||||
gboolean
|
||||
(g_atomic_pointer_compare_and_exchange) (volatile void *atomic,
|
||||
gpointer oldval,
|
||||
gpointer newval)
|
||||
{
|
||||
return InterlockedCompareExchangePointer (atomic, newval, oldval) == oldval;
|
||||
}
|
||||
|
||||
gssize
|
||||
(g_atomic_pointer_add) (volatile void *atomic,
|
||||
gssize val)
|
||||
{
|
||||
#if GLIB_SIZEOF_VOID_P == 8
|
||||
return InterlockedExchangeAdd64 (atomic, val);
|
||||
#else
|
||||
return InterlockedExchangeAdd (atomic, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
gsize
|
||||
(g_atomic_pointer_and) (volatile void *atomic,
|
||||
gsize val)
|
||||
{
|
||||
#if GLIB_SIZEOF_VOID_P == 8
|
||||
return InterlockedAnd64 (atomic, val);
|
||||
#else
|
||||
return InterlockedAnd (atomic, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
gsize
|
||||
(g_atomic_pointer_or) (volatile void *atomic,
|
||||
gsize val)
|
||||
{
|
||||
#if GLIB_SIZEOF_VOID_P == 8
|
||||
return InterlockedOr64 (atomic, val);
|
||||
#else
|
||||
return InterlockedOr (atomic, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
gsize
|
||||
(g_atomic_pointer_xor) (volatile void *atomic,
|
||||
gsize val)
|
||||
{
|
||||
#if GLIB_SIZEOF_VOID_P == 8
|
||||
return InterlockedXor64 (atomic, val);
|
||||
#else
|
||||
return InterlockedXor (atomic, val);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
|
||||
/* This error occurs when ./configure decided that we should be capable
|
||||
* of lock-free atomics but we find at compile-time that we are not.
|
||||
*/
|
||||
#error G_ATOMIC_LOCK_FREE defined, but incapable of lock-free atomics.
|
||||
|
||||
#endif /* defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) */
|
||||
|
||||
#else /* G_ATOMIC_LOCK_FREE */
|
||||
|
||||
/* We are not permitted to call into any GLib functions from here, so we
|
||||
* can not use GMutex.
|
||||
*
|
||||
* Fortunately, we already take care of the Windows case above, and all
|
||||
* non-Windows platforms on which glib runs have pthreads. Use those.
|
||||
*/
|
||||
#include <pthread.h>
|
||||
|
||||
static pthread_mutex_t g_atomic_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
gint
|
||||
(g_atomic_int_get) (volatile gint *atomic)
|
||||
{
|
||||
gint value;
|
||||
|
||||
pthread_mutex_lock (&g_atomic_lock);
|
||||
value = *atomic;
|
||||
pthread_mutex_unlock (&g_atomic_lock);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void
|
||||
(g_atomic_int_set) (volatile gint *atomic,
|
||||
gint value)
|
||||
{
|
||||
pthread_mutex_lock (&g_atomic_lock);
|
||||
*atomic = value;
|
||||
pthread_mutex_unlock (&g_atomic_lock);
|
||||
}
|
||||
|
||||
void
|
||||
(g_atomic_int_inc) (volatile gint *atomic)
|
||||
{
|
||||
pthread_mutex_lock (&g_atomic_lock);
|
||||
(*atomic)++;
|
||||
pthread_mutex_unlock (&g_atomic_lock);
|
||||
}
|
||||
|
||||
gboolean
|
||||
(g_atomic_int_dec_and_test) (volatile gint *atomic)
|
||||
{
|
||||
gboolean is_zero;
|
||||
|
||||
pthread_mutex_lock (&g_atomic_lock);
|
||||
is_zero = --(*atomic) == 0;
|
||||
pthread_mutex_unlock (&g_atomic_lock);
|
||||
|
||||
return is_zero;
|
||||
}
|
||||
|
||||
gboolean
|
||||
(g_atomic_int_compare_and_exchange) (volatile gint *atomic,
|
||||
gint oldval,
|
||||
gint newval)
|
||||
{
|
||||
gboolean success;
|
||||
|
||||
pthread_mutex_lock (&g_atomic_lock);
|
||||
|
||||
if ((success = (*atomic == oldval)))
|
||||
*atomic = newval;
|
||||
|
||||
pthread_mutex_unlock (&g_atomic_lock);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
gint
|
||||
(g_atomic_int_add) (volatile gint *atomic,
|
||||
gint val)
|
||||
{
|
||||
gint oldval;
|
||||
|
||||
pthread_mutex_lock (&g_atomic_lock);
|
||||
oldval = *atomic;
|
||||
*atomic = oldval + val;
|
||||
pthread_mutex_unlock (&g_atomic_lock);
|
||||
|
||||
return oldval;
|
||||
}
|
||||
|
||||
guint
|
||||
(g_atomic_int_and) (volatile guint *atomic,
|
||||
guint val)
|
||||
{
|
||||
guint oldval;
|
||||
|
||||
pthread_mutex_lock (&g_atomic_lock);
|
||||
oldval = *atomic;
|
||||
*atomic = oldval & val;
|
||||
pthread_mutex_unlock (&g_atomic_lock);
|
||||
|
||||
return oldval;
|
||||
}
|
||||
|
||||
guint
|
||||
(g_atomic_int_or) (volatile guint *atomic,
|
||||
guint val)
|
||||
{
|
||||
guint oldval;
|
||||
|
||||
pthread_mutex_lock (&g_atomic_lock);
|
||||
oldval = *atomic;
|
||||
*atomic = oldval | val;
|
||||
pthread_mutex_unlock (&g_atomic_lock);
|
||||
|
||||
return oldval;
|
||||
}
|
||||
|
||||
guint
|
||||
(g_atomic_int_xor) (volatile guint *atomic,
|
||||
guint val)
|
||||
{
|
||||
guint oldval;
|
||||
|
||||
pthread_mutex_lock (&g_atomic_lock);
|
||||
oldval = *atomic;
|
||||
*atomic = oldval ^ val;
|
||||
pthread_mutex_unlock (&g_atomic_lock);
|
||||
|
||||
return oldval;
|
||||
}
|
||||
|
||||
|
||||
gpointer
|
||||
(g_atomic_pointer_get) (volatile void *atomic)
|
||||
{
|
||||
volatile gpointer *ptr = atomic;
|
||||
gpointer value;
|
||||
|
||||
pthread_mutex_lock (&g_atomic_lock);
|
||||
value = *ptr;
|
||||
pthread_mutex_unlock (&g_atomic_lock);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void
|
||||
(g_atomic_pointer_set) (volatile void *atomic,
|
||||
gpointer newval)
|
||||
{
|
||||
volatile gpointer *ptr = atomic;
|
||||
|
||||
pthread_mutex_lock (&g_atomic_lock);
|
||||
*ptr = newval;
|
||||
pthread_mutex_unlock (&g_atomic_lock);
|
||||
}
|
||||
|
||||
gboolean
|
||||
(g_atomic_pointer_compare_and_exchange) (volatile void *atomic,
|
||||
gpointer oldval,
|
||||
gpointer newval)
|
||||
{
|
||||
volatile gpointer *ptr = atomic;
|
||||
gboolean success;
|
||||
|
||||
pthread_mutex_lock (&g_atomic_lock);
|
||||
|
||||
if ((success = (*ptr == oldval)))
|
||||
*ptr = newval;
|
||||
|
||||
pthread_mutex_unlock (&g_atomic_lock);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
gssize
|
||||
(g_atomic_pointer_add) (volatile void *atomic,
|
||||
gssize val)
|
||||
{
|
||||
volatile gssize *ptr = atomic;
|
||||
gssize oldval;
|
||||
|
||||
pthread_mutex_lock (&g_atomic_lock);
|
||||
oldval = *ptr;
|
||||
*ptr = oldval + val;
|
||||
pthread_mutex_unlock (&g_atomic_lock);
|
||||
|
||||
return oldval;
|
||||
}
|
||||
|
||||
gsize
|
||||
(g_atomic_pointer_and) (volatile void *atomic,
|
||||
gsize val)
|
||||
{
|
||||
volatile gsize *ptr = atomic;
|
||||
gsize oldval;
|
||||
|
||||
pthread_mutex_lock (&g_atomic_lock);
|
||||
oldval = *ptr;
|
||||
*ptr = oldval & val;
|
||||
pthread_mutex_unlock (&g_atomic_lock);
|
||||
|
||||
return oldval;
|
||||
}
|
||||
|
||||
gsize
|
||||
(g_atomic_pointer_or) (volatile void *atomic,
|
||||
gsize val)
|
||||
{
|
||||
volatile gsize *ptr = atomic;
|
||||
gsize oldval;
|
||||
|
||||
pthread_mutex_lock (&g_atomic_lock);
|
||||
oldval = *ptr;
|
||||
*ptr = oldval | val;
|
||||
pthread_mutex_unlock (&g_atomic_lock);
|
||||
|
||||
return oldval;
|
||||
}
|
||||
|
||||
gsize
|
||||
(g_atomic_pointer_xor) (volatile void *atomic,
|
||||
gsize val)
|
||||
{
|
||||
volatile gsize *ptr = atomic;
|
||||
gsize oldval;
|
||||
|
||||
pthread_mutex_lock (&g_atomic_lock);
|
||||
oldval = *ptr;
|
||||
*ptr = oldval ^ val;
|
||||
pthread_mutex_unlock (&g_atomic_lock);
|
||||
|
||||
return oldval;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* g_atomic_int_exchange_and_add:
|
||||
* @atomic: a pointer to a #gint
|
||||
* @val: the value to add
|
||||
*
|
||||
* This function existed before g_atomic_int_add() returned the prior
|
||||
* value of the integer (which it now does). It is retained only for
|
||||
* compatibility reasons. Don't use this function in new code.
|
||||
*
|
||||
* Returns: the value of @atomic before the add, signed
|
||||
* Since: 2.4
|
||||
* Deprecated: 2.30: Use g_atomic_int_add() instead.
|
||||
**/
|
||||
gint
|
||||
g_atomic_int_exchange_and_add (volatile gint *atomic,
|
||||
gint val)
|
||||
{
|
||||
return (g_atomic_int_add) (atomic, val);
|
||||
}
|
||||
216
glib/glib/gatomic.h
Normal file
216
glib/glib/gatomic.h
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* Copyright © 2011 Ryan Lortie
|
||||
*
|
||||
* 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 of the
|
||||
* licence, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*
|
||||
* Author: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_ATOMIC_H__
|
||||
#define __G_ATOMIC_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gint g_atomic_int_get (volatile gint *atomic);
|
||||
void g_atomic_int_set (volatile gint *atomic,
|
||||
gint newval);
|
||||
void g_atomic_int_inc (volatile gint *atomic);
|
||||
gboolean g_atomic_int_dec_and_test (volatile gint *atomic);
|
||||
gboolean g_atomic_int_compare_and_exchange (volatile gint *atomic,
|
||||
gint oldval,
|
||||
gint newval);
|
||||
gint g_atomic_int_add (volatile gint *atomic,
|
||||
gint val);
|
||||
guint g_atomic_int_and (volatile guint *atomic,
|
||||
guint val);
|
||||
guint g_atomic_int_or (volatile guint *atomic,
|
||||
guint val);
|
||||
guint g_atomic_int_xor (volatile guint *atomic,
|
||||
guint val);
|
||||
|
||||
gpointer g_atomic_pointer_get (volatile void *atomic);
|
||||
void g_atomic_pointer_set (volatile void *atomic,
|
||||
gpointer newval);
|
||||
gboolean g_atomic_pointer_compare_and_exchange (volatile void *atomic,
|
||||
gpointer oldval,
|
||||
gpointer newval);
|
||||
gssize g_atomic_pointer_add (volatile void *atomic,
|
||||
gssize val);
|
||||
gsize g_atomic_pointer_and (volatile void *atomic,
|
||||
gsize val);
|
||||
gsize g_atomic_pointer_or (volatile void *atomic,
|
||||
gsize val);
|
||||
gsize g_atomic_pointer_xor (volatile void *atomic,
|
||||
gsize val);
|
||||
|
||||
GLIB_DEPRECATED_IN_2_30_FOR(g_atomic_add)
|
||||
gint g_atomic_int_exchange_and_add (volatile gint *atomic,
|
||||
gint val);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#if defined(G_ATOMIC_LOCK_FREE) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
|
||||
|
||||
#define g_atomic_int_get(atomic) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
|
||||
(void) (0 ? *(atomic) ^ *(atomic) : 0); \
|
||||
__sync_synchronize (); \
|
||||
(gint) *(atomic); \
|
||||
}))
|
||||
#define g_atomic_int_set(atomic, newval) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
|
||||
(void) (0 ? *(atomic) ^ (newval) : 0); \
|
||||
*(atomic) = (newval); \
|
||||
__sync_synchronize (); \
|
||||
}))
|
||||
#define g_atomic_int_inc(atomic) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
|
||||
(void) (0 ? *(atomic) ^ *(atomic) : 0); \
|
||||
(void) __sync_fetch_and_add ((atomic), 1); \
|
||||
}))
|
||||
#define g_atomic_int_dec_and_test(atomic) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
|
||||
(void) (0 ? *(atomic) ^ *(atomic) : 0); \
|
||||
__sync_fetch_and_sub ((atomic), 1) == 1; \
|
||||
}))
|
||||
#define g_atomic_int_compare_and_exchange(atomic, oldval, newval) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
|
||||
(void) (0 ? *(atomic) ^ (newval) ^ (oldval) : 0); \
|
||||
(gboolean) __sync_bool_compare_and_swap ((atomic), (oldval), (newval)); \
|
||||
}))
|
||||
#define g_atomic_int_add(atomic, val) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
|
||||
(void) (0 ? *(atomic) ^ (val) : 0); \
|
||||
(gint) __sync_fetch_and_add ((atomic), (val)); \
|
||||
}))
|
||||
#define g_atomic_int_and(atomic, val) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
|
||||
(void) (0 ? *(atomic) ^ (val) : 0); \
|
||||
(guint) __sync_fetch_and_and ((atomic), (val)); \
|
||||
}))
|
||||
#define g_atomic_int_or(atomic, val) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
|
||||
(void) (0 ? *(atomic) ^ (val) : 0); \
|
||||
(guint) __sync_fetch_and_or ((atomic), (val)); \
|
||||
}))
|
||||
#define g_atomic_int_xor(atomic, val) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
|
||||
(void) (0 ? *(atomic) ^ (val) : 0); \
|
||||
(guint) __sync_fetch_and_xor ((atomic), (val)); \
|
||||
}))
|
||||
|
||||
#define g_atomic_pointer_get(atomic) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
||||
__sync_synchronize (); \
|
||||
(gpointer) *(atomic); \
|
||||
}))
|
||||
#define g_atomic_pointer_set(atomic, newval) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
||||
(void) (0 ? (gpointer) *(atomic) : 0); \
|
||||
*(atomic) = (__typeof__ (*(atomic))) (gsize) (newval); \
|
||||
__sync_synchronize (); \
|
||||
}))
|
||||
#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
||||
(void) (0 ? (gpointer) *(atomic) : 0); \
|
||||
(gboolean) __sync_bool_compare_and_swap ((atomic), (oldval), (newval)); \
|
||||
}))
|
||||
#define g_atomic_pointer_add(atomic, val) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
||||
(void) (0 ? (gpointer) *(atomic) : 0); \
|
||||
(void) (0 ? (val) ^ (val) : 0); \
|
||||
(gssize) __sync_fetch_and_add ((atomic), (val)); \
|
||||
}))
|
||||
#define g_atomic_pointer_and(atomic, val) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
||||
(void) (0 ? (gpointer) *(atomic) : 0); \
|
||||
(void) (0 ? (val) ^ (val) : 0); \
|
||||
(gsize) __sync_fetch_and_and ((atomic), (val)); \
|
||||
}))
|
||||
#define g_atomic_pointer_or(atomic, val) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
||||
(void) (0 ? (gpointer) *(atomic) : 0); \
|
||||
(void) (0 ? (val) ^ (val) : 0); \
|
||||
(gsize) __sync_fetch_and_or ((atomic), (val)); \
|
||||
}))
|
||||
#define g_atomic_pointer_xor(atomic, val) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
|
||||
(void) (0 ? (gpointer) *(atomic) : 0); \
|
||||
(void) (0 ? (val) ^ (val) : 0); \
|
||||
(gsize) __sync_fetch_and_xor ((atomic), (val)); \
|
||||
}))
|
||||
|
||||
#else /* defined(G_ATOMIC_LOCK_FREE) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) */
|
||||
|
||||
#define g_atomic_int_get(atomic) \
|
||||
(g_atomic_int_get ((gint *) (atomic)))
|
||||
#define g_atomic_int_set(atomic, newval) \
|
||||
(g_atomic_int_set ((gint *) (atomic), (gint) (newval)))
|
||||
#define g_atomic_int_compare_and_exchange(atomic, oldval, newval) \
|
||||
(g_atomic_int_compare_and_exchange ((gint *) (atomic), (oldval), (newval)))
|
||||
#define g_atomic_int_add(atomic, val) \
|
||||
(g_atomic_int_add ((gint *) (atomic), (val)))
|
||||
#define g_atomic_int_and(atomic, val) \
|
||||
(g_atomic_int_and ((guint *) (atomic), (val)))
|
||||
#define g_atomic_int_or(atomic, val) \
|
||||
(g_atomic_int_or ((guint *) (atomic), (val)))
|
||||
#define g_atomic_int_xor(atomic, val) \
|
||||
(g_atomic_int_xor ((guint *) (atomic), (val)))
|
||||
#define g_atomic_int_inc(atomic) \
|
||||
(g_atomic_int_inc ((gint *) (atomic)))
|
||||
#define g_atomic_int_dec_and_test(atomic) \
|
||||
(g_atomic_int_dec_and_test ((gint *) (atomic)))
|
||||
|
||||
#define g_atomic_pointer_get(atomic) \
|
||||
(g_atomic_pointer_get (atomic))
|
||||
#define g_atomic_pointer_set(atomic, newval) \
|
||||
(g_atomic_pointer_set ((atomic), (gpointer) (newval)))
|
||||
#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
|
||||
(g_atomic_pointer_compare_and_exchange ((atomic), (gpointer) (oldval), (gpointer) (newval)))
|
||||
#define g_atomic_pointer_add(atomic, val) \
|
||||
(g_atomic_pointer_add ((atomic), (gssize) (val)))
|
||||
#define g_atomic_pointer_and(atomic, val) \
|
||||
(g_atomic_pointer_and ((atomic), (gsize) (val)))
|
||||
#define g_atomic_pointer_or(atomic, val) \
|
||||
(g_atomic_pointer_or ((atomic), (gsize) (val)))
|
||||
#define g_atomic_pointer_xor(atomic, val) \
|
||||
(g_atomic_pointer_xor ((atomic), (gsize) (val)))
|
||||
|
||||
#endif /* defined(__GNUC__) && defined(G_ATOMIC_OP_USE_GCC_BUILTINS) */
|
||||
|
||||
#endif /* __G_ATOMIC_H__ */
|
||||
374
glib/glib/gbacktrace.c
Normal file
374
glib/glib/gbacktrace.c
Normal file
|
|
@ -0,0 +1,374 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe ; except for g_on_error_stack_trace, but who wants thread safety
|
||||
* then
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "glibconfig.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIMES_H
|
||||
#include <sys/times.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif /* HAVE_SYS_SELECT_H */
|
||||
|
||||
#include <string.h> /* for bzero on BSD systems */
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
# define STRICT /* Strict typing, please */
|
||||
# define _WIN32_WINDOWS 0x0401 /* to get IsDebuggerPresent */
|
||||
# include <windows.h>
|
||||
# undef STRICT
|
||||
#endif
|
||||
|
||||
#include "gbacktrace.h"
|
||||
|
||||
#include "gtypes.h"
|
||||
#include "gmain.h"
|
||||
#include "gprintfint.h"
|
||||
#include "gutils.h"
|
||||
|
||||
|
||||
#ifndef NO_FD_SET
|
||||
# define SELECT_MASK fd_set
|
||||
#else
|
||||
# if defined(_IBMR2)
|
||||
# define SELECT_MASK void
|
||||
# else
|
||||
# define SELECT_MASK int
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
static void stack_trace (char **args);
|
||||
#endif
|
||||
|
||||
extern volatile gboolean glib_on_error_halt;
|
||||
volatile gboolean glib_on_error_halt = TRUE;
|
||||
|
||||
/**
|
||||
* g_on_error_query:
|
||||
* @prg_name: the program name, needed by <command>gdb</command>
|
||||
* for the [S]tack trace option. If @prg_name is %NULL, g_get_prgname()
|
||||
* is called to get the program name (which will work correctly if
|
||||
* gdk_init() or gtk_init() has been called)
|
||||
*
|
||||
* Prompts the user with
|
||||
* <computeroutput>[E]xit, [H]alt, show [S]tack trace or [P]roceed</computeroutput>.
|
||||
* This function is intended to be used for debugging use only.
|
||||
* The following example shows how it can be used together with
|
||||
* the g_log() functions.
|
||||
*
|
||||
* |[
|
||||
* #include <glib.h>
|
||||
*
|
||||
* static void
|
||||
* log_handler (const gchar *log_domain,
|
||||
* GLogLevelFlags log_level,
|
||||
* const gchar *message,
|
||||
* gpointer user_data)
|
||||
* {
|
||||
* g_log_default_handler (log_domain, log_level, message, user_data);
|
||||
*
|
||||
* g_on_error_query (MY_PROGRAM_NAME);
|
||||
* }
|
||||
*
|
||||
* int
|
||||
* main (int argc, char *argv[])
|
||||
* {
|
||||
* g_log_set_handler (MY_LOG_DOMAIN,
|
||||
* G_LOG_LEVEL_WARNING |
|
||||
* G_LOG_LEVEL_ERROR |
|
||||
* G_LOG_LEVEL_CRITICAL,
|
||||
* log_handler,
|
||||
* NULL);
|
||||
* /* ... */
|
||||
* ]|
|
||||
*
|
||||
* If [E]xit is selected, the application terminates with a call
|
||||
* to <literal>_exit(0)</literal>.
|
||||
*
|
||||
* If [S]tack trace is selected, g_on_error_stack_trace() is called.
|
||||
* This invokes <command>gdb</command>, which attaches to the current
|
||||
* process and shows a stack trace. The prompt is then shown again.
|
||||
*
|
||||
* If [P]roceed is selected, the function returns.
|
||||
*
|
||||
* This function may cause different actions on non-UNIX platforms.
|
||||
*/
|
||||
void
|
||||
g_on_error_query (const gchar *prg_name)
|
||||
{
|
||||
#ifndef G_OS_WIN32
|
||||
static const gchar * const query1 = "[E]xit, [H]alt";
|
||||
static const gchar * const query2 = ", show [S]tack trace";
|
||||
static const gchar * const query3 = " or [P]roceed";
|
||||
gchar buf[16];
|
||||
|
||||
if (!prg_name)
|
||||
prg_name = g_get_prgname ();
|
||||
|
||||
retry:
|
||||
|
||||
if (prg_name)
|
||||
_g_fprintf (stdout,
|
||||
"%s (pid:%u): %s%s%s: ",
|
||||
prg_name,
|
||||
(guint) getpid (),
|
||||
query1,
|
||||
query2,
|
||||
query3);
|
||||
else
|
||||
_g_fprintf (stdout,
|
||||
"(process:%u): %s%s: ",
|
||||
(guint) getpid (),
|
||||
query1,
|
||||
query3);
|
||||
fflush (stdout);
|
||||
|
||||
if (isatty(0) && isatty(1))
|
||||
fgets (buf, 8, stdin);
|
||||
else
|
||||
strcpy (buf, "E\n");
|
||||
|
||||
if ((buf[0] == 'E' || buf[0] == 'e')
|
||||
&& buf[1] == '\n')
|
||||
_exit (0);
|
||||
else if ((buf[0] == 'P' || buf[0] == 'p')
|
||||
&& buf[1] == '\n')
|
||||
return;
|
||||
else if (prg_name
|
||||
&& (buf[0] == 'S' || buf[0] == 's')
|
||||
&& buf[1] == '\n')
|
||||
{
|
||||
g_on_error_stack_trace (prg_name);
|
||||
goto retry;
|
||||
}
|
||||
else if ((buf[0] == 'H' || buf[0] == 'h')
|
||||
&& buf[1] == '\n')
|
||||
{
|
||||
while (glib_on_error_halt)
|
||||
;
|
||||
glib_on_error_halt = TRUE;
|
||||
return;
|
||||
}
|
||||
else
|
||||
goto retry;
|
||||
#else
|
||||
if (!prg_name)
|
||||
prg_name = g_get_prgname ();
|
||||
|
||||
MessageBox (NULL, "g_on_error_query called, program terminating",
|
||||
(prg_name && *prg_name) ? prg_name : NULL,
|
||||
MB_OK|MB_ICONERROR);
|
||||
_exit(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* g_on_error_stack_trace:
|
||||
* @prg_name: the program name, needed by <command>gdb</command>
|
||||
* for the [S]tack trace option.
|
||||
*
|
||||
* Invokes <command>gdb</command>, which attaches to the current
|
||||
* process and shows a stack trace. Called by g_on_error_query()
|
||||
* when the [S]tack trace option is selected. You can get the current
|
||||
* process's "program name" with g_get_prgname(), assuming that you
|
||||
* have called gtk_init() or gdk_init().
|
||||
*
|
||||
* This function may cause different actions on non-UNIX platforms.
|
||||
*/
|
||||
void
|
||||
g_on_error_stack_trace (const gchar *prg_name)
|
||||
{
|
||||
#if defined(G_OS_UNIX) || defined(G_OS_BEOS)
|
||||
pid_t pid;
|
||||
gchar buf[16];
|
||||
gchar *args[4] = { "gdb", NULL, NULL, NULL };
|
||||
int status;
|
||||
|
||||
if (!prg_name)
|
||||
return;
|
||||
|
||||
_g_sprintf (buf, "%u", (guint) getpid ());
|
||||
|
||||
args[1] = (gchar*) prg_name;
|
||||
args[2] = buf;
|
||||
|
||||
pid = fork ();
|
||||
if (pid == 0)
|
||||
{
|
||||
stack_trace (args);
|
||||
_exit (0);
|
||||
}
|
||||
else if (pid == (pid_t) -1)
|
||||
{
|
||||
perror ("unable to fork gdb");
|
||||
return;
|
||||
}
|
||||
|
||||
waitpid (pid, &status, 0);
|
||||
#else
|
||||
if (IsDebuggerPresent ())
|
||||
G_BREAKPOINT ();
|
||||
else
|
||||
abort ();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
|
||||
static gboolean stack_trace_done = FALSE;
|
||||
|
||||
static void
|
||||
stack_trace_sigchld (int signum)
|
||||
{
|
||||
stack_trace_done = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
stack_trace (char **args)
|
||||
{
|
||||
pid_t pid;
|
||||
int in_fd[2];
|
||||
int out_fd[2];
|
||||
SELECT_MASK fdset;
|
||||
SELECT_MASK readset;
|
||||
struct timeval tv;
|
||||
int sel, idx, state;
|
||||
char buffer[256];
|
||||
char c;
|
||||
|
||||
stack_trace_done = FALSE;
|
||||
signal (SIGCHLD, stack_trace_sigchld);
|
||||
|
||||
if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
|
||||
{
|
||||
perror ("unable to open pipe");
|
||||
_exit (0);
|
||||
}
|
||||
|
||||
pid = fork ();
|
||||
if (pid == 0)
|
||||
{
|
||||
close (0); dup (in_fd[0]); /* set the stdin to the in pipe */
|
||||
close (1); dup (out_fd[1]); /* set the stdout to the out pipe */
|
||||
close (2); dup (out_fd[1]); /* set the stderr to the out pipe */
|
||||
|
||||
execvp (args[0], args); /* exec gdb */
|
||||
perror ("exec failed");
|
||||
_exit (0);
|
||||
}
|
||||
else if (pid == (pid_t) -1)
|
||||
{
|
||||
perror ("unable to fork");
|
||||
_exit (0);
|
||||
}
|
||||
|
||||
FD_ZERO (&fdset);
|
||||
FD_SET (out_fd[0], &fdset);
|
||||
|
||||
write (in_fd[1], "backtrace\n", 10);
|
||||
write (in_fd[1], "p x = 0\n", 8);
|
||||
write (in_fd[1], "quit\n", 5);
|
||||
|
||||
idx = 0;
|
||||
state = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
readset = fdset;
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
sel = select (FD_SETSIZE, &readset, NULL, NULL, &tv);
|
||||
if (sel == -1)
|
||||
break;
|
||||
|
||||
if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
|
||||
{
|
||||
if (read (out_fd[0], &c, 1))
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case 0:
|
||||
if (c == '#')
|
||||
{
|
||||
state = 1;
|
||||
idx = 0;
|
||||
buffer[idx++] = c;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
buffer[idx++] = c;
|
||||
if ((c == '\n') || (c == '\r'))
|
||||
{
|
||||
buffer[idx] = 0;
|
||||
_g_fprintf (stdout, "%s", buffer);
|
||||
state = 0;
|
||||
idx = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (stack_trace_done)
|
||||
break;
|
||||
}
|
||||
|
||||
close (in_fd[0]);
|
||||
close (in_fd[1]);
|
||||
close (out_fd[0]);
|
||||
close (out_fd[1]);
|
||||
_exit (0);
|
||||
}
|
||||
|
||||
#endif /* !G_OS_WIN32 */
|
||||
64
glib/glib/gbacktrace.h
Normal file
64
glib/glib/gbacktrace.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_BACKTRACE_H__
|
||||
#define __G_BACKTRACE_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
#include <signal.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void g_on_error_query (const gchar *prg_name);
|
||||
void g_on_error_stack_trace (const gchar *prg_name);
|
||||
|
||||
/**
|
||||
* G_BREAKPOINT:
|
||||
*
|
||||
* Inserts a breakpoint instruction into the code.
|
||||
*
|
||||
* On x86 and alpha systems this is implemented as a soft interrupt
|
||||
* and on other architectures it raises a <literal>SIGTRAP</literal> signal.
|
||||
*/
|
||||
#if (defined (__i386__) || defined (__x86_64__)) && defined (__GNUC__) && __GNUC__ >= 2
|
||||
# define G_BREAKPOINT() G_STMT_START{ __asm__ __volatile__ ("int $03"); }G_STMT_END
|
||||
#elif (defined (_MSC_VER) || defined (__DMC__)) && defined (_M_IX86)
|
||||
# define G_BREAKPOINT() G_STMT_START{ __asm int 3h }G_STMT_END
|
||||
#elif defined (_MSC_VER)
|
||||
# define G_BREAKPOINT() G_STMT_START{ __debugbreak(); }G_STMT_END
|
||||
#elif defined (__alpha__) && !defined(__osf__) && defined (__GNUC__) && __GNUC__ >= 2
|
||||
# define G_BREAKPOINT() G_STMT_START{ __asm__ __volatile__ ("bpt"); }G_STMT_END
|
||||
#else /* !__i386__ && !__alpha__ */
|
||||
# define G_BREAKPOINT() G_STMT_START{ raise (SIGTRAP); }G_STMT_END
|
||||
#endif /* __i386__ */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_BACKTRACE_H__ */
|
||||
445
glib/glib/gbase64.c
Normal file
445
glib/glib/gbase64.c
Normal file
|
|
@ -0,0 +1,445 @@
|
|||
/* gbase64.c - Base64 encoding/decoding
|
||||
*
|
||||
* Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
|
||||
* Copyright (C) 2000-2003 Ximian Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* This is based on code in camel, written by:
|
||||
* Michael Zucchi <notzed@ximian.com>
|
||||
* Jeffrey Stedfast <fejj@ximian.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "gbase64.h"
|
||||
#include "gtestutils.h"
|
||||
#include "glibintl.h"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:base64
|
||||
* @title: Base64 Encoding
|
||||
* @short_description: encodes and decodes data in Base64 format
|
||||
*
|
||||
* Base64 is an encoding that allows a sequence of arbitrary bytes to be
|
||||
* encoded as a sequence of printable ASCII characters. For the definition
|
||||
* of Base64, see <ulink url="http://www.ietf.org/rfc/rfc1421.txt">RFC
|
||||
* 1421</ulink> or <ulink url="http://www.ietf.org/rfc/rfc2045.txt">RFC
|
||||
* 2045</ulink>. Base64 is most commonly used as a MIME transfer encoding
|
||||
* for email.
|
||||
*
|
||||
* GLib supports incremental encoding using g_base64_encode_step() and
|
||||
* g_base64_encode_close(). Incremental decoding can be done with
|
||||
* g_base64_decode_step(). To encode or decode data in one go, use
|
||||
* g_base64_encode() or g_base64_decode(). To avoid memory allocation when
|
||||
* decoding, you can use g_base64_decode_inplace().
|
||||
*
|
||||
* Support for Base64 encoding has been added in GLib 2.12.
|
||||
*/
|
||||
|
||||
static const char base64_alphabet[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
/**
|
||||
* g_base64_encode_step:
|
||||
* @in: (array length=len) (element-type guint8): the binary data to encode
|
||||
* @len: the length of @in
|
||||
* @break_lines: whether to break long lines
|
||||
* @out: (out) (array) (element-type guint8): pointer to destination buffer
|
||||
* @state: (inout): Saved state between steps, initialize to 0
|
||||
* @save: (inout): Saved state between steps, initialize to 0
|
||||
*
|
||||
* Incrementally encode a sequence of binary data into its Base-64 stringified
|
||||
* representation. By calling this function multiple times you can convert
|
||||
* data in chunks to avoid having to have the full encoded data in memory.
|
||||
*
|
||||
* When all of the data has been converted you must call
|
||||
* g_base64_encode_close() to flush the saved state.
|
||||
*
|
||||
* The output buffer must be large enough to fit all the data that will
|
||||
* be written to it. Due to the way base64 encodes you will need
|
||||
* at least: (@len / 3 + 1) * 4 + 4 bytes (+ 4 may be needed in case of
|
||||
* non-zero state). If you enable line-breaking you will need at least:
|
||||
* ((@len / 3 + 1) * 4 + 4) / 72 + 1 bytes of extra space.
|
||||
*
|
||||
* @break_lines is typically used when putting base64-encoded data in emails.
|
||||
* It breaks the lines at 72 columns instead of putting all of the text on
|
||||
* the same line. This avoids problems with long lines in the email system.
|
||||
* Note however that it breaks the lines with <literal>LF</literal>
|
||||
* characters, not <literal>CR LF</literal> sequences, so the result cannot
|
||||
* be passed directly to SMTP or certain other protocols.
|
||||
*
|
||||
* Return value: The number of bytes of output that was written
|
||||
*
|
||||
* Since: 2.12
|
||||
*/
|
||||
gsize
|
||||
g_base64_encode_step (const guchar *in,
|
||||
gsize len,
|
||||
gboolean break_lines,
|
||||
gchar *out,
|
||||
gint *state,
|
||||
gint *save)
|
||||
{
|
||||
char *outptr;
|
||||
const guchar *inptr;
|
||||
|
||||
g_return_val_if_fail (in != NULL, 0);
|
||||
g_return_val_if_fail (out != NULL, 0);
|
||||
g_return_val_if_fail (state != NULL, 0);
|
||||
g_return_val_if_fail (save != NULL, 0);
|
||||
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
|
||||
inptr = in;
|
||||
outptr = out;
|
||||
|
||||
if (len + ((char *) save) [0] > 2)
|
||||
{
|
||||
const guchar *inend = in+len-2;
|
||||
int c1, c2, c3;
|
||||
int already;
|
||||
|
||||
already = *state;
|
||||
|
||||
switch (((char *) save) [0])
|
||||
{
|
||||
case 1:
|
||||
c1 = ((unsigned char *) save) [1];
|
||||
goto skip1;
|
||||
case 2:
|
||||
c1 = ((unsigned char *) save) [1];
|
||||
c2 = ((unsigned char *) save) [2];
|
||||
goto skip2;
|
||||
}
|
||||
|
||||
/*
|
||||
* yes, we jump into the loop, no i'm not going to change it,
|
||||
* it's beautiful!
|
||||
*/
|
||||
while (inptr < inend)
|
||||
{
|
||||
c1 = *inptr++;
|
||||
skip1:
|
||||
c2 = *inptr++;
|
||||
skip2:
|
||||
c3 = *inptr++;
|
||||
*outptr++ = base64_alphabet [ c1 >> 2 ];
|
||||
*outptr++ = base64_alphabet [ c2 >> 4 |
|
||||
((c1&0x3) << 4) ];
|
||||
*outptr++ = base64_alphabet [ ((c2 &0x0f) << 2) |
|
||||
(c3 >> 6) ];
|
||||
*outptr++ = base64_alphabet [ c3 & 0x3f ];
|
||||
/* this is a bit ugly ... */
|
||||
if (break_lines && (++already) >= 19)
|
||||
{
|
||||
*outptr++ = '\n';
|
||||
already = 0;
|
||||
}
|
||||
}
|
||||
|
||||
((char *)save)[0] = 0;
|
||||
len = 2 - (inptr - inend);
|
||||
*state = already;
|
||||
}
|
||||
|
||||
if (len>0)
|
||||
{
|
||||
char *saveout;
|
||||
|
||||
/* points to the slot for the next char to save */
|
||||
saveout = & (((char *)save)[1]) + ((char *)save)[0];
|
||||
|
||||
/* len can only be 0 1 or 2 */
|
||||
switch(len)
|
||||
{
|
||||
case 2: *saveout++ = *inptr++;
|
||||
case 1: *saveout++ = *inptr++;
|
||||
}
|
||||
((char *)save)[0] += len;
|
||||
}
|
||||
|
||||
return outptr - out;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_base64_encode_close:
|
||||
* @break_lines: whether to break long lines
|
||||
* @out: (out) (array) (element-type guint8): pointer to destination buffer
|
||||
* @state: (inout): Saved state from g_base64_encode_step()
|
||||
* @save: (inout): Saved state from g_base64_encode_step()
|
||||
*
|
||||
* Flush the status from a sequence of calls to g_base64_encode_step().
|
||||
*
|
||||
* The output buffer must be large enough to fit all the data that will
|
||||
* be written to it. It will need up to 4 bytes, or up to 5 bytes if
|
||||
* line-breaking is enabled.
|
||||
*
|
||||
* Return value: The number of bytes of output that was written
|
||||
*
|
||||
* Since: 2.12
|
||||
*/
|
||||
gsize
|
||||
g_base64_encode_close (gboolean break_lines,
|
||||
gchar *out,
|
||||
gint *state,
|
||||
gint *save)
|
||||
{
|
||||
int c1, c2;
|
||||
char *outptr = out;
|
||||
|
||||
g_return_val_if_fail (out != NULL, 0);
|
||||
g_return_val_if_fail (state != NULL, 0);
|
||||
g_return_val_if_fail (save != NULL, 0);
|
||||
|
||||
c1 = ((unsigned char *) save) [1];
|
||||
c2 = ((unsigned char *) save) [2];
|
||||
|
||||
switch (((char *) save) [0])
|
||||
{
|
||||
case 2:
|
||||
outptr [2] = base64_alphabet[ ( (c2 &0x0f) << 2 ) ];
|
||||
g_assert (outptr [2] != 0);
|
||||
goto skip;
|
||||
case 1:
|
||||
outptr[2] = '=';
|
||||
skip:
|
||||
outptr [0] = base64_alphabet [ c1 >> 2 ];
|
||||
outptr [1] = base64_alphabet [ c2 >> 4 | ( (c1&0x3) << 4 )];
|
||||
outptr [3] = '=';
|
||||
outptr += 4;
|
||||
break;
|
||||
}
|
||||
if (break_lines)
|
||||
*outptr++ = '\n';
|
||||
|
||||
*save = 0;
|
||||
*state = 0;
|
||||
|
||||
return outptr - out;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_base64_encode:
|
||||
* @data: (array length=len) (element-type guint8): the binary data to encode
|
||||
* @len: the length of @data
|
||||
*
|
||||
* Encode a sequence of binary data into its Base-64 stringified
|
||||
* representation.
|
||||
*
|
||||
* Return value: (transfer full): a newly allocated, zero-terminated Base-64
|
||||
* encoded string representing @data. The returned string must
|
||||
* be freed with g_free().
|
||||
*
|
||||
* Since: 2.12
|
||||
*/
|
||||
gchar *
|
||||
g_base64_encode (const guchar *data,
|
||||
gsize len)
|
||||
{
|
||||
gchar *out;
|
||||
gint state = 0, outlen;
|
||||
gint save = 0;
|
||||
|
||||
g_return_val_if_fail (data != NULL || len == 0, NULL);
|
||||
|
||||
/* We can use a smaller limit here, since we know the saved state is 0,
|
||||
+1 is needed for trailing \0, also check for unlikely integer overflow */
|
||||
if (len >= ((G_MAXSIZE - 1) / 4 - 1) * 3)
|
||||
g_error("%s: input too large for Base64 encoding (%"G_GSIZE_FORMAT" chars)",
|
||||
G_STRLOC, len);
|
||||
|
||||
out = g_malloc ((len / 3 + 1) * 4 + 1);
|
||||
|
||||
outlen = g_base64_encode_step (data, len, FALSE, out, &state, &save);
|
||||
outlen += g_base64_encode_close (FALSE, out + outlen, &state, &save);
|
||||
out[outlen] = '\0';
|
||||
|
||||
return (gchar *) out;
|
||||
}
|
||||
|
||||
static const unsigned char mime_base64_rank[256] = {
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255,
|
||||
255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
|
||||
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
};
|
||||
|
||||
/**
|
||||
* g_base64_decode_step:
|
||||
* @in: (array length=len) (element-type guint8): binary input data
|
||||
* @len: max length of @in data to decode
|
||||
* @out: (out) (array) (element-type guint8): output buffer
|
||||
* @state: (inout): Saved state between steps, initialize to 0
|
||||
* @save: (inout): Saved state between steps, initialize to 0
|
||||
*
|
||||
* Incrementally decode a sequence of binary data from its Base-64 stringified
|
||||
* representation. By calling this function multiple times you can convert
|
||||
* data in chunks to avoid having to have the full encoded data in memory.
|
||||
*
|
||||
* The output buffer must be large enough to fit all the data that will
|
||||
* be written to it. Since base64 encodes 3 bytes in 4 chars you need
|
||||
* at least: (@len / 4) * 3 + 3 bytes (+ 3 may be needed in case of non-zero
|
||||
* state).
|
||||
*
|
||||
* Return value: The number of bytes of output that was written
|
||||
*
|
||||
* Since: 2.12
|
||||
**/
|
||||
gsize
|
||||
g_base64_decode_step (const gchar *in,
|
||||
gsize len,
|
||||
guchar *out,
|
||||
gint *state,
|
||||
guint *save)
|
||||
{
|
||||
const guchar *inptr;
|
||||
guchar *outptr;
|
||||
const guchar *inend;
|
||||
guchar c, rank;
|
||||
guchar last[2];
|
||||
unsigned int v;
|
||||
int i;
|
||||
|
||||
g_return_val_if_fail (in != NULL, 0);
|
||||
g_return_val_if_fail (out != NULL, 0);
|
||||
g_return_val_if_fail (state != NULL, 0);
|
||||
g_return_val_if_fail (save != NULL, 0);
|
||||
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
|
||||
inend = (const guchar *)in+len;
|
||||
outptr = out;
|
||||
|
||||
/* convert 4 base64 bytes to 3 normal bytes */
|
||||
v=*save;
|
||||
i=*state;
|
||||
inptr = (const guchar *)in;
|
||||
last[0] = last[1] = 0;
|
||||
while (inptr < inend)
|
||||
{
|
||||
c = *inptr++;
|
||||
rank = mime_base64_rank [c];
|
||||
if (rank != 0xff)
|
||||
{
|
||||
last[1] = last[0];
|
||||
last[0] = c;
|
||||
v = (v<<6) | rank;
|
||||
i++;
|
||||
if (i==4)
|
||||
{
|
||||
*outptr++ = v>>16;
|
||||
if (last[1] != '=')
|
||||
*outptr++ = v>>8;
|
||||
if (last[0] != '=')
|
||||
*outptr++ = v;
|
||||
i=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*save = v;
|
||||
*state = i;
|
||||
|
||||
return outptr - out;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_base64_decode:
|
||||
* @text: zero-terminated string with base64 text to decode
|
||||
* @out_len: (out): The length of the decoded data is written here
|
||||
*
|
||||
* Decode a sequence of Base-64 encoded text into binary data
|
||||
*
|
||||
* Return value: (transfer full) (array length=out_len) (element-type guint8):
|
||||
* newly allocated buffer containing the binary data
|
||||
* that @text represents. The returned buffer must
|
||||
* be freed with g_free().
|
||||
*
|
||||
* Since: 2.12
|
||||
*/
|
||||
guchar *
|
||||
g_base64_decode (const gchar *text,
|
||||
gsize *out_len)
|
||||
{
|
||||
guchar *ret;
|
||||
gsize input_length;
|
||||
gint state = 0;
|
||||
guint save = 0;
|
||||
|
||||
g_return_val_if_fail (text != NULL, NULL);
|
||||
g_return_val_if_fail (out_len != NULL, NULL);
|
||||
|
||||
input_length = strlen (text);
|
||||
|
||||
/* We can use a smaller limit here, since we know the saved state is 0,
|
||||
+1 used to avoid calling g_malloc0(0), and hence returning NULL */
|
||||
ret = g_malloc0 ((input_length / 4) * 3 + 1);
|
||||
|
||||
*out_len = g_base64_decode_step (text, input_length, ret, &state, &save);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_base64_decode_inplace:
|
||||
* @text: (inout) (array length=out_len) (element-type guint8): zero-terminated
|
||||
* string with base64 text to decode
|
||||
* @out_len: (inout): The length of the decoded data is written here
|
||||
*
|
||||
* Decode a sequence of Base-64 encoded text into binary data
|
||||
* by overwriting the input data.
|
||||
*
|
||||
* Return value: (transfer none): The binary data that @text responds. This pointer
|
||||
* is the same as the input @text.
|
||||
*
|
||||
* Since: 2.20
|
||||
*/
|
||||
guchar *
|
||||
g_base64_decode_inplace (gchar *text,
|
||||
gsize *out_len)
|
||||
{
|
||||
gint input_length, state = 0;
|
||||
guint save = 0;
|
||||
|
||||
g_return_val_if_fail (text != NULL, NULL);
|
||||
g_return_val_if_fail (out_len != NULL, NULL);
|
||||
|
||||
input_length = strlen (text);
|
||||
|
||||
g_return_val_if_fail (input_length > 1, NULL);
|
||||
|
||||
*out_len = g_base64_decode_step (text, input_length, (guchar *) text, &state, &save);
|
||||
|
||||
return (guchar *) text;
|
||||
}
|
||||
57
glib/glib/gbase64.h
Normal file
57
glib/glib/gbase64.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/* gbase64.h - Base64 coding functions
|
||||
*
|
||||
* Copyright (C) 2005 Alexander Larsson <alexl@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_BASE64_H__
|
||||
#define __G_BASE64_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gsize g_base64_encode_step (const guchar *in,
|
||||
gsize len,
|
||||
gboolean break_lines,
|
||||
gchar *out,
|
||||
gint *state,
|
||||
gint *save);
|
||||
gsize g_base64_encode_close (gboolean break_lines,
|
||||
gchar *out,
|
||||
gint *state,
|
||||
gint *save);
|
||||
gchar* g_base64_encode (const guchar *data,
|
||||
gsize len) G_GNUC_MALLOC;
|
||||
gsize g_base64_decode_step (const gchar *in,
|
||||
gsize len,
|
||||
guchar *out,
|
||||
gint *state,
|
||||
guint *save);
|
||||
guchar *g_base64_decode (const gchar *text,
|
||||
gsize *out_len) G_GNUC_MALLOC;
|
||||
guchar *g_base64_decode_inplace (gchar *text,
|
||||
gsize *out_len);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_BASE64_H__ */
|
||||
536
glib/glib/gbitlock.c
Normal file
536
glib/glib/gbitlock.c
Normal file
|
|
@ -0,0 +1,536 @@
|
|||
/*
|
||||
* Copyright © 2008 Ryan Lortie
|
||||
* Copyright © 2010 Codethink Limited
|
||||
*
|
||||
* 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 of the licence, 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#include "gbitlock.h"
|
||||
|
||||
#include <glib/gmessages.h>
|
||||
#include <glib/gatomic.h>
|
||||
#include <glib/gslist.h>
|
||||
#include <glib/gthread.h>
|
||||
#include <glib/gslice.h>
|
||||
|
||||
#include "gthreadprivate.h"
|
||||
#include "config.h"
|
||||
|
||||
#undef HAVE_FUTEX
|
||||
#ifdef G_BIT_LOCK_FORCE_FUTEX_EMULATION
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FUTEX
|
||||
static GMutex g_futex_mutex;
|
||||
static GSList *g_futex_address_list = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FUTEX
|
||||
/*
|
||||
* We have headers for futex(2) on the build machine. This does not
|
||||
* imply that every system that ever runs the resulting glib will have
|
||||
* kernel support for futex, but you'd have to have a pretty old
|
||||
* kernel in order for that not to be the case.
|
||||
*
|
||||
* If anyone actually gets bit by this, please file a bug. :)
|
||||
*/
|
||||
#include <linux/futex.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* < private >
|
||||
* g_futex_wait:
|
||||
* @address: a pointer to an integer
|
||||
* @value: the value that should be at @address
|
||||
*
|
||||
* Atomically checks that the value stored at @address is equal to
|
||||
* @value and then blocks. If the value stored at @address is not
|
||||
* equal to @value then this function returns immediately.
|
||||
*
|
||||
* To unblock, call g_futex_wake() on @address.
|
||||
*
|
||||
* This call may spuriously unblock (for example, in response to the
|
||||
* process receiving a signal) but this is not guaranteed. Unlike the
|
||||
* Linux system call of a similar name, there is no guarantee that a
|
||||
* waiting process will unblock due to a g_futex_wake() call in a
|
||||
* separate process.
|
||||
*/
|
||||
static void
|
||||
g_futex_wait (const volatile gint *address,
|
||||
gint value)
|
||||
{
|
||||
syscall (__NR_futex, address, (gsize) FUTEX_WAIT, (gsize) value, NULL);
|
||||
}
|
||||
|
||||
/* < private >
|
||||
* g_futex_wake:
|
||||
* @address: a pointer to an integer
|
||||
*
|
||||
* Nominally, wakes one thread that is blocked in g_futex_wait() on
|
||||
* @address (if any thread is currently waiting).
|
||||
*
|
||||
* As mentioned in the documention for g_futex_wait(), spurious
|
||||
* wakeups may occur. As such, this call may result in more than one
|
||||
* thread being woken up.
|
||||
*/
|
||||
static void
|
||||
g_futex_wake (const volatile gint *address)
|
||||
{
|
||||
syscall (__NR_futex, address, (gsize) FUTEX_WAKE, (gsize) 1, NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* emulate futex(2) */
|
||||
typedef struct
|
||||
{
|
||||
const volatile gint *address;
|
||||
gint ref_count;
|
||||
GCond wait_queue;
|
||||
} WaitAddress;
|
||||
|
||||
static WaitAddress *
|
||||
g_futex_find_address (const volatile gint *address)
|
||||
{
|
||||
GSList *node;
|
||||
|
||||
for (node = g_futex_address_list; node; node = node->next)
|
||||
{
|
||||
WaitAddress *waiter = node->data;
|
||||
|
||||
if (waiter->address == address)
|
||||
return waiter;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
g_futex_wait (const volatile gint *address,
|
||||
gint value)
|
||||
{
|
||||
g_mutex_lock (&g_futex_mutex);
|
||||
if G_LIKELY (g_atomic_int_get (address) == value)
|
||||
{
|
||||
WaitAddress *waiter;
|
||||
|
||||
if ((waiter = g_futex_find_address (address)) == NULL)
|
||||
{
|
||||
waiter = g_slice_new (WaitAddress);
|
||||
waiter->address = address;
|
||||
g_cond_init (&waiter->wait_queue);
|
||||
waiter->ref_count = 0;
|
||||
g_futex_address_list =
|
||||
g_slist_prepend (g_futex_address_list, waiter);
|
||||
}
|
||||
|
||||
waiter->ref_count++;
|
||||
g_cond_wait (&waiter->wait_queue, &g_futex_mutex);
|
||||
|
||||
if (!--waiter->ref_count)
|
||||
{
|
||||
g_futex_address_list =
|
||||
g_slist_remove (g_futex_address_list, waiter);
|
||||
g_cond_clear (&waiter->wait_queue);
|
||||
g_slice_free (WaitAddress, waiter);
|
||||
}
|
||||
}
|
||||
g_mutex_unlock (&g_futex_mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
g_futex_wake (const volatile gint *address)
|
||||
{
|
||||
WaitAddress *waiter;
|
||||
|
||||
/* need to lock here for two reasons:
|
||||
* 1) need to acquire/release lock to ensure waiter is not in
|
||||
* the process of registering a wait
|
||||
* 2) need to -stay- locked until the end to ensure a wake()
|
||||
* in another thread doesn't cause 'waiter' to stop existing
|
||||
*/
|
||||
g_mutex_lock (&g_futex_mutex);
|
||||
if ((waiter = g_futex_find_address (address)))
|
||||
g_cond_signal (&waiter->wait_queue);
|
||||
g_mutex_unlock (&g_futex_mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define CONTENTION_CLASSES 11
|
||||
static volatile gint g_bit_lock_contended[CONTENTION_CLASSES];
|
||||
|
||||
#if (defined (i386) || defined (__amd64__))
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
|
||||
#define USE_ASM_GOTO 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* g_bit_lock:
|
||||
* @address: a pointer to an integer
|
||||
* @lock_bit: a bit value between 0 and 31
|
||||
*
|
||||
* Sets the indicated @lock_bit in @address. If the bit is already
|
||||
* set, this call will block until g_bit_unlock() unsets the
|
||||
* corresponding bit.
|
||||
*
|
||||
* Attempting to lock on two different bits within the same integer is
|
||||
* not supported and will very probably cause deadlocks.
|
||||
*
|
||||
* The value of the bit that is set is (1u << @bit). If @bit is not
|
||||
* between 0 and 31 then the result is undefined.
|
||||
*
|
||||
* This function accesses @address atomically. All other accesses to
|
||||
* @address must be atomic in order for this function to work
|
||||
* reliably.
|
||||
*
|
||||
* Since: 2.24
|
||||
**/
|
||||
void
|
||||
g_bit_lock (volatile gint *address,
|
||||
gint lock_bit)
|
||||
{
|
||||
#ifdef USE_ASM_GOTO
|
||||
retry:
|
||||
asm volatile goto ("lock bts %1, (%0)\n"
|
||||
"jc %l[contended]"
|
||||
: /* no output */
|
||||
: "r" (address), "r" (lock_bit)
|
||||
: "cc", "memory"
|
||||
: contended);
|
||||
return;
|
||||
|
||||
contended:
|
||||
{
|
||||
guint mask = 1u << lock_bit;
|
||||
guint v;
|
||||
|
||||
v = g_atomic_int_get (address);
|
||||
if (v & mask)
|
||||
{
|
||||
guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended);
|
||||
|
||||
g_atomic_int_add (&g_bit_lock_contended[class], +1);
|
||||
g_futex_wait (address, v);
|
||||
g_atomic_int_add (&g_bit_lock_contended[class], -1);
|
||||
}
|
||||
}
|
||||
goto retry;
|
||||
#else
|
||||
guint mask = 1u << lock_bit;
|
||||
guint v;
|
||||
|
||||
retry:
|
||||
v = g_atomic_int_or (address, mask);
|
||||
if (v & mask)
|
||||
/* already locked */
|
||||
{
|
||||
guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended);
|
||||
|
||||
g_atomic_int_add (&g_bit_lock_contended[class], +1);
|
||||
g_futex_wait (address, v);
|
||||
g_atomic_int_add (&g_bit_lock_contended[class], -1);
|
||||
|
||||
goto retry;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bit_trylock:
|
||||
* @address: a pointer to an integer
|
||||
* @lock_bit: a bit value between 0 and 31
|
||||
*
|
||||
* Sets the indicated @lock_bit in @address, returning %TRUE if
|
||||
* successful. If the bit is already set, returns %FALSE immediately.
|
||||
*
|
||||
* Attempting to lock on two different bits within the same integer is
|
||||
* not supported.
|
||||
*
|
||||
* The value of the bit that is set is (1u << @bit). If @bit is not
|
||||
* between 0 and 31 then the result is undefined.
|
||||
*
|
||||
* This function accesses @address atomically. All other accesses to
|
||||
* @address must be atomic in order for this function to work
|
||||
* reliably.
|
||||
*
|
||||
* Returns: %TRUE if the lock was acquired
|
||||
*
|
||||
* Since: 2.24
|
||||
**/
|
||||
gboolean
|
||||
g_bit_trylock (volatile gint *address,
|
||||
gint lock_bit)
|
||||
{
|
||||
#ifdef USE_ASM_GOTO
|
||||
gboolean result;
|
||||
|
||||
asm volatile ("lock bts %2, (%1)\n"
|
||||
"setnc %%al\n"
|
||||
"movzx %%al, %0"
|
||||
: "=r" (result)
|
||||
: "r" (address), "r" (lock_bit)
|
||||
: "cc", "memory");
|
||||
|
||||
return result;
|
||||
#else
|
||||
guint mask = 1u << lock_bit;
|
||||
guint v;
|
||||
|
||||
v = g_atomic_int_or (address, mask);
|
||||
|
||||
return ~v & mask;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bit_unlock:
|
||||
* @address: a pointer to an integer
|
||||
* @lock_bit: a bit value between 0 and 31
|
||||
*
|
||||
* Clears the indicated @lock_bit in @address. If another thread is
|
||||
* currently blocked in g_bit_lock() on this same bit then it will be
|
||||
* woken up.
|
||||
*
|
||||
* This function accesses @address atomically. All other accesses to
|
||||
* @address must be atomic in order for this function to work
|
||||
* reliably.
|
||||
*
|
||||
* Since: 2.24
|
||||
**/
|
||||
void
|
||||
g_bit_unlock (volatile gint *address,
|
||||
gint lock_bit)
|
||||
{
|
||||
#ifdef USE_ASM_GOTO
|
||||
asm volatile ("lock btr %1, (%0)"
|
||||
: /* no output */
|
||||
: "r" (address), "r" (lock_bit)
|
||||
: "cc", "memory");
|
||||
#else
|
||||
guint mask = 1u << lock_bit;
|
||||
|
||||
g_atomic_int_and (address, ~mask);
|
||||
#endif
|
||||
|
||||
{
|
||||
guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended);
|
||||
|
||||
if (g_atomic_int_get (&g_bit_lock_contended[class]))
|
||||
g_futex_wake (address);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* We emulate pointer-sized futex(2) because the kernel API only
|
||||
* supports integers.
|
||||
*
|
||||
* We assume that the 'interesting' part is always the lower order bits.
|
||||
* This assumption holds because pointer bitlocks are restricted to
|
||||
* using the low order bits of the pointer as the lock.
|
||||
*
|
||||
* On 32 bits, there is nothing to do since the pointer size is equal to
|
||||
* the integer size. On little endian the lower-order bits don't move,
|
||||
* so do nothing. Only on 64bit big endian do we need to do a bit of
|
||||
* pointer arithmetic: the low order bits are shifted by 4 bytes. We
|
||||
* have a helper function that always does the right thing here.
|
||||
*
|
||||
* Since we always consider the low-order bits of the integer value, a
|
||||
* simple cast from (gsize) to (guint) always takes care of that.
|
||||
*
|
||||
* After that, pointer-sized futex becomes as simple as:
|
||||
*
|
||||
* g_futex_wait (g_futex_int_address (address), (guint) value);
|
||||
*
|
||||
* and
|
||||
*
|
||||
* g_futex_wake (g_futex_int_address (int_address));
|
||||
*/
|
||||
static const volatile gint *
|
||||
g_futex_int_address (const volatile void *address)
|
||||
{
|
||||
const volatile gint *int_address = address;
|
||||
|
||||
/* this implementation makes these (reasonable) assumptions: */
|
||||
G_STATIC_ASSERT (G_BYTE_ORDER == G_LITTLE_ENDIAN ||
|
||||
(G_BYTE_ORDER == G_BIG_ENDIAN &&
|
||||
sizeof (int) == 4 &&
|
||||
(sizeof (gpointer) == 4 || sizeof (gpointer) == 8)));
|
||||
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN && GLIB_SIZEOF_VOID_P == 8
|
||||
int_address++;
|
||||
#endif
|
||||
|
||||
return int_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_pointer_bit_lock:
|
||||
* @address: a pointer to a #gpointer-sized value
|
||||
* @lock_bit: a bit value between 0 and 31
|
||||
*
|
||||
* This is equivalent to g_bit_lock, but working on pointers (or other
|
||||
* pointer-sized values).
|
||||
*
|
||||
* For portability reasons, you may only lock on the bottom 32 bits of
|
||||
* the pointer.
|
||||
*
|
||||
* Since: 2.30
|
||||
**/
|
||||
void
|
||||
(g_pointer_bit_lock) (volatile void *address,
|
||||
gint lock_bit)
|
||||
{
|
||||
g_return_if_fail (lock_bit < 32);
|
||||
|
||||
{
|
||||
#ifdef USE_ASM_GOTO
|
||||
retry:
|
||||
asm volatile goto ("lock bts %1, (%0)\n"
|
||||
"jc %l[contended]"
|
||||
: /* no output */
|
||||
: "r" (address), "r" ((gsize) lock_bit)
|
||||
: "cc", "memory"
|
||||
: contended);
|
||||
return;
|
||||
|
||||
contended:
|
||||
{
|
||||
volatile gsize *pointer_address = address;
|
||||
gsize mask = 1u << lock_bit;
|
||||
gsize v;
|
||||
|
||||
v = (gsize) g_atomic_pointer_get (pointer_address);
|
||||
if (v & mask)
|
||||
{
|
||||
guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended);
|
||||
|
||||
g_atomic_int_add (&g_bit_lock_contended[class], +1);
|
||||
g_futex_wait (g_futex_int_address (address), v);
|
||||
g_atomic_int_add (&g_bit_lock_contended[class], -1);
|
||||
}
|
||||
}
|
||||
goto retry;
|
||||
#else
|
||||
volatile gsize *pointer_address = address;
|
||||
gsize mask = 1u << lock_bit;
|
||||
gsize v;
|
||||
|
||||
retry:
|
||||
v = g_atomic_pointer_or (pointer_address, mask);
|
||||
if (v & mask)
|
||||
/* already locked */
|
||||
{
|
||||
guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended);
|
||||
|
||||
g_atomic_int_add (&g_bit_lock_contended[class], +1);
|
||||
g_futex_wait (g_futex_int_address (address), (guint) v);
|
||||
g_atomic_int_add (&g_bit_lock_contended[class], -1);
|
||||
|
||||
goto retry;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_pointer_bit_trylock:
|
||||
* @address: a pointer to a #gpointer-sized value
|
||||
* @lock_bit: a bit value between 0 and 31
|
||||
*
|
||||
* This is equivalent to g_bit_trylock, but working on pointers (or
|
||||
* other pointer-sized values).
|
||||
*
|
||||
* For portability reasons, you may only lock on the bottom 32 bits of
|
||||
* the pointer.
|
||||
*
|
||||
* Returns: %TRUE if the lock was acquired
|
||||
*
|
||||
* Since: 2.30
|
||||
**/
|
||||
gboolean
|
||||
(g_pointer_bit_trylock) (volatile void *address,
|
||||
gint lock_bit)
|
||||
{
|
||||
g_return_val_if_fail (lock_bit < 32, FALSE);
|
||||
|
||||
{
|
||||
#ifdef USE_ASM_GOTO
|
||||
gboolean result;
|
||||
|
||||
asm volatile ("lock bts %2, (%1)\n"
|
||||
"setnc %%al\n"
|
||||
"movzx %%al, %0"
|
||||
: "=r" (result)
|
||||
: "r" (address), "r" ((gsize) lock_bit)
|
||||
: "cc", "memory");
|
||||
|
||||
return result;
|
||||
#else
|
||||
volatile gsize *pointer_address = address;
|
||||
gsize mask = 1u << lock_bit;
|
||||
gsize v;
|
||||
|
||||
g_return_val_if_fail (lock_bit < 32, FALSE);
|
||||
|
||||
v = g_atomic_pointer_or (pointer_address, mask);
|
||||
|
||||
return ~v & mask;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_pointer_bit_unlock:
|
||||
* @address: a pointer to a #gpointer-sized value
|
||||
* @lock_bit: a bit value between 0 and 31
|
||||
*
|
||||
* This is equivalent to g_bit_unlock, but working on pointers (or other
|
||||
* pointer-sized values).
|
||||
*
|
||||
* For portability reasons, you may only lock on the bottom 32 bits of
|
||||
* the pointer.
|
||||
*
|
||||
* Since: 2.30
|
||||
**/
|
||||
void
|
||||
(g_pointer_bit_unlock) (volatile void *address,
|
||||
gint lock_bit)
|
||||
{
|
||||
g_return_if_fail (lock_bit < 32);
|
||||
|
||||
{
|
||||
#ifdef USE_ASM_GOTO
|
||||
asm volatile ("lock btr %1, (%0)"
|
||||
: /* no output */
|
||||
: "r" (address), "r" ((gsize) lock_bit)
|
||||
: "cc", "memory");
|
||||
#else
|
||||
volatile gsize *pointer_address = address;
|
||||
gsize mask = 1u << lock_bit;
|
||||
|
||||
g_atomic_pointer_and (pointer_address, ~mask);
|
||||
#endif
|
||||
|
||||
{
|
||||
guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended);
|
||||
if (g_atomic_int_get (&g_bit_lock_contended[class]))
|
||||
g_futex_wake (g_futex_int_address (address));
|
||||
}
|
||||
}
|
||||
}
|
||||
72
glib/glib/gbitlock.h
Normal file
72
glib/glib/gbitlock.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright © 2008 Ryan Lortie
|
||||
* Copyright © 2010 Codethink Limited
|
||||
*
|
||||
* 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 of the licence, 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#ifndef __G_BITLOCK_H__
|
||||
#define __G_BITLOCK_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void g_bit_lock (volatile gint *address,
|
||||
gint lock_bit);
|
||||
gboolean g_bit_trylock (volatile gint *address,
|
||||
gint lock_bit);
|
||||
void g_bit_unlock (volatile gint *address,
|
||||
gint lock_bit);
|
||||
|
||||
void g_pointer_bit_lock (volatile void *address,
|
||||
gint lock_bit);
|
||||
gboolean g_pointer_bit_trylock (volatile void *address,
|
||||
gint lock_bit);
|
||||
void g_pointer_bit_unlock (volatile void *address,
|
||||
gint lock_bit);
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
#define g_pointer_bit_lock(address, lock_bit) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(address) == sizeof (gpointer)); \
|
||||
g_pointer_bit_lock ((address), (lock_bit)); \
|
||||
}))
|
||||
|
||||
#define g_pointer_bit_trylock(address, lock_bit) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(address) == sizeof (gpointer)); \
|
||||
g_pointer_bit_trylock ((address), (lock_bit)); \
|
||||
}))
|
||||
|
||||
#define g_pointer_bit_unlock(address, lock_bit) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_STATIC_ASSERT (sizeof *(address) == sizeof (gpointer)); \
|
||||
g_pointer_bit_unlock ((address), (lock_bit)); \
|
||||
}))
|
||||
|
||||
#endif
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_BITLOCK_H_ */
|
||||
3713
glib/glib/gbookmarkfile.c
Normal file
3713
glib/glib/gbookmarkfile.c
Normal file
File diff suppressed because it is too large
Load diff
215
glib/glib/gbookmarkfile.h
Normal file
215
glib/glib/gbookmarkfile.h
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
/* gbookmarkfile.h: parsing and building desktop bookmarks
|
||||
*
|
||||
* Copyright (C) 2005-2006 Emmanuele Bassi
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_BOOKMARK_FILE_H__
|
||||
#define __G_BOOKMARK_FILE_H__
|
||||
|
||||
#include <glib/gerror.h>
|
||||
#include <time.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* G_BOOKMARK_FILE_ERROR:
|
||||
*
|
||||
* Error domain for bookmark file parsing.
|
||||
* Errors in this domain will be from the #GBookmarkFileError
|
||||
* enumeration. See #GError for information on error domains.
|
||||
*/
|
||||
#define G_BOOKMARK_FILE_ERROR (g_bookmark_file_error_quark ())
|
||||
|
||||
|
||||
/**
|
||||
* GBookmarkFileError:
|
||||
* @G_BOOKMARK_FILE_ERROR_INVALID_URI: URI was ill-formed
|
||||
* @G_BOOKMARK_FILE_ERROR_INVALID_VALUE: a requested field was not found
|
||||
* @G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED: a requested application did
|
||||
* not register a bookmark
|
||||
* @G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND: a requested URI was not found
|
||||
* @G_BOOKMARK_FILE_ERROR_READ: document was ill formed
|
||||
* @G_BOOKMARK_FILE_ERROR_UNKNOWN_ENCODING: the text being parsed was
|
||||
* in an unknown encoding
|
||||
* @G_BOOKMARK_FILE_ERROR_WRITE: an error occurred while writing
|
||||
* @G_BOOKMARK_FILE_ERROR_FILE_NOT_FOUND: requested file was not found
|
||||
*
|
||||
* Error codes returned by bookmark file parsing.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
G_BOOKMARK_FILE_ERROR_INVALID_URI,
|
||||
G_BOOKMARK_FILE_ERROR_INVALID_VALUE,
|
||||
G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED,
|
||||
G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
|
||||
G_BOOKMARK_FILE_ERROR_READ,
|
||||
G_BOOKMARK_FILE_ERROR_UNKNOWN_ENCODING,
|
||||
G_BOOKMARK_FILE_ERROR_WRITE,
|
||||
G_BOOKMARK_FILE_ERROR_FILE_NOT_FOUND
|
||||
} GBookmarkFileError;
|
||||
|
||||
GQuark g_bookmark_file_error_quark (void);
|
||||
|
||||
/**
|
||||
* GBookmarkFile:
|
||||
*
|
||||
* The <structname>GBookmarkFile</structname> struct contains only
|
||||
* private data and should not be directly accessed.
|
||||
*/
|
||||
typedef struct _GBookmarkFile GBookmarkFile;
|
||||
|
||||
GBookmarkFile *g_bookmark_file_new (void);
|
||||
void g_bookmark_file_free (GBookmarkFile *bookmark);
|
||||
|
||||
gboolean g_bookmark_file_load_from_file (GBookmarkFile *bookmark,
|
||||
const gchar *filename,
|
||||
GError **error);
|
||||
gboolean g_bookmark_file_load_from_data (GBookmarkFile *bookmark,
|
||||
const gchar *data,
|
||||
gsize length,
|
||||
GError **error);
|
||||
gboolean g_bookmark_file_load_from_data_dirs (GBookmarkFile *bookmark,
|
||||
const gchar *file,
|
||||
gchar **full_path,
|
||||
GError **error);
|
||||
gchar * g_bookmark_file_to_data (GBookmarkFile *bookmark,
|
||||
gsize *length,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
gboolean g_bookmark_file_to_file (GBookmarkFile *bookmark,
|
||||
const gchar *filename,
|
||||
GError **error);
|
||||
|
||||
void g_bookmark_file_set_title (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
const gchar *title);
|
||||
gchar * g_bookmark_file_get_title (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
void g_bookmark_file_set_description (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
const gchar *description);
|
||||
gchar * g_bookmark_file_get_description (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
void g_bookmark_file_set_mime_type (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
const gchar *mime_type);
|
||||
gchar * g_bookmark_file_get_mime_type (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
void g_bookmark_file_set_groups (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
const gchar **groups,
|
||||
gsize length);
|
||||
void g_bookmark_file_add_group (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
const gchar *group);
|
||||
gboolean g_bookmark_file_has_group (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
const gchar *group,
|
||||
GError **error);
|
||||
gchar ** g_bookmark_file_get_groups (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
gsize *length,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
void g_bookmark_file_add_application (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
const gchar *name,
|
||||
const gchar *exec);
|
||||
gboolean g_bookmark_file_has_application (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
const gchar *name,
|
||||
GError **error);
|
||||
gchar ** g_bookmark_file_get_applications (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
gsize *length,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
gboolean g_bookmark_file_set_app_info (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
const gchar *name,
|
||||
const gchar *exec,
|
||||
gint count,
|
||||
time_t stamp,
|
||||
GError **error);
|
||||
gboolean g_bookmark_file_get_app_info (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
const gchar *name,
|
||||
gchar **exec,
|
||||
guint *count,
|
||||
time_t *stamp,
|
||||
GError **error);
|
||||
void g_bookmark_file_set_is_private (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
gboolean is_private);
|
||||
gboolean g_bookmark_file_get_is_private (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
GError **error);
|
||||
void g_bookmark_file_set_icon (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
const gchar *href,
|
||||
const gchar *mime_type);
|
||||
gboolean g_bookmark_file_get_icon (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
gchar **href,
|
||||
gchar **mime_type,
|
||||
GError **error);
|
||||
void g_bookmark_file_set_added (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
time_t added);
|
||||
time_t g_bookmark_file_get_added (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
GError **error);
|
||||
void g_bookmark_file_set_modified (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
time_t modified);
|
||||
time_t g_bookmark_file_get_modified (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
GError **error);
|
||||
void g_bookmark_file_set_visited (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
time_t visited);
|
||||
time_t g_bookmark_file_get_visited (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
GError **error);
|
||||
gboolean g_bookmark_file_has_item (GBookmarkFile *bookmark,
|
||||
const gchar *uri);
|
||||
gint g_bookmark_file_get_size (GBookmarkFile *bookmark);
|
||||
gchar ** g_bookmark_file_get_uris (GBookmarkFile *bookmark,
|
||||
gsize *length) G_GNUC_MALLOC;
|
||||
gboolean g_bookmark_file_remove_group (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
const gchar *group,
|
||||
GError **error);
|
||||
gboolean g_bookmark_file_remove_application (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
const gchar *name,
|
||||
GError **error);
|
||||
gboolean g_bookmark_file_remove_item (GBookmarkFile *bookmark,
|
||||
const gchar *uri,
|
||||
GError **error);
|
||||
gboolean g_bookmark_file_move_item (GBookmarkFile *bookmark,
|
||||
const gchar *old_uri,
|
||||
const gchar *new_uri,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_BOOKMARK_FILE_H__ */
|
||||
303
glib/glib/gbsearcharray.h
Normal file
303
glib/glib/gbsearcharray.h
Normal file
|
|
@ -0,0 +1,303 @@
|
|||
/* GBSearchArray - Binary Searchable Array implementation
|
||||
* Copyright (C) 2000-2003 Tim Janik
|
||||
*
|
||||
* This software is provided "as is"; redistribution and modification
|
||||
* is permitted, provided that the following disclaimer is retained.
|
||||
*
|
||||
* This software 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.
|
||||
* In no event shall the authors 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.
|
||||
*/
|
||||
#ifndef __G_BSEARCH_ARRAY_H__
|
||||
#define __G_BSEARCH_ARRAY_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
G_BEGIN_DECLS /* c++ guards */
|
||||
|
||||
/* this implementation is intended to be usable in third-party code
|
||||
* simply by pasting the contents of this file. as such, the
|
||||
* implementation needs to be self-contained within this file.
|
||||
*/
|
||||
|
||||
/* convenience macro to avoid signed overflow for value comparisons */
|
||||
#define G_BSEARCH_ARRAY_CMP(v1,v2) ((v1) > (v2) ? +1 : (v1) == (v2) ? 0 : -1)
|
||||
|
||||
|
||||
/* --- typedefs --- */
|
||||
typedef gint (*GBSearchCompareFunc) (gconstpointer bsearch_node1, /* key */
|
||||
gconstpointer bsearch_node2);
|
||||
typedef enum
|
||||
{
|
||||
G_BSEARCH_ARRAY_ALIGN_POWER2 = 1 << 0, /* align memory to power2 sizes */
|
||||
G_BSEARCH_ARRAY_AUTO_SHRINK = 1 << 1 /* shrink array upon removal */
|
||||
} GBSearchArrayFlags;
|
||||
|
||||
|
||||
/* --- structures --- */
|
||||
typedef struct
|
||||
{
|
||||
guint sizeof_node;
|
||||
GBSearchCompareFunc cmp_nodes;
|
||||
guint flags;
|
||||
} GBSearchConfig;
|
||||
typedef union
|
||||
{
|
||||
guint n_nodes;
|
||||
/*< private >*/
|
||||
gpointer alignment_dummy1;
|
||||
glong alignment_dummy2;
|
||||
gdouble alignment_dummy3;
|
||||
} GBSearchArray;
|
||||
|
||||
|
||||
/* --- public API --- */
|
||||
static inline GBSearchArray* g_bsearch_array_create (const GBSearchConfig *bconfig);
|
||||
static inline gpointer g_bsearch_array_get_nth (GBSearchArray *barray,
|
||||
const GBSearchConfig *bconfig,
|
||||
guint nth);
|
||||
static inline guint g_bsearch_array_get_index (GBSearchArray *barray,
|
||||
const GBSearchConfig *bconfig,
|
||||
gconstpointer node_in_array);
|
||||
static inline GBSearchArray* g_bsearch_array_remove (GBSearchArray *barray,
|
||||
const GBSearchConfig *bconfig,
|
||||
guint index_);
|
||||
/* provide uninitialized space at index for node insertion */
|
||||
static inline GBSearchArray* g_bsearch_array_grow (GBSearchArray *barray,
|
||||
const GBSearchConfig *bconfig,
|
||||
guint index);
|
||||
/* insert key_node into array if it does not exist, otherwise do nothing */
|
||||
static inline GBSearchArray* g_bsearch_array_insert (GBSearchArray *barray,
|
||||
const GBSearchConfig *bconfig,
|
||||
gconstpointer key_node);
|
||||
/* insert key_node into array if it does not exist,
|
||||
* otherwise replace the existing node's contents with key_node
|
||||
*/
|
||||
static inline GBSearchArray* g_bsearch_array_replace (GBSearchArray *barray,
|
||||
const GBSearchConfig *bconfig,
|
||||
gconstpointer key_node);
|
||||
static inline void g_bsearch_array_free (GBSearchArray *barray,
|
||||
const GBSearchConfig *bconfig);
|
||||
#define g_bsearch_array_get_n_nodes(barray) (((GBSearchArray*) (barray))->n_nodes)
|
||||
|
||||
/* g_bsearch_array_lookup():
|
||||
* return NULL or exact match node
|
||||
*/
|
||||
#define g_bsearch_array_lookup(barray, bconfig, key_node) \
|
||||
g_bsearch_array_lookup_fuzzy ((barray), (bconfig), (key_node), 0)
|
||||
|
||||
/* g_bsearch_array_lookup_sibling():
|
||||
* return NULL for barray->n_nodes==0, otherwise return the
|
||||
* exact match node, or, if there's no such node, return the
|
||||
* node last visited, which is pretty close to an exact match
|
||||
* (will be one off into either direction).
|
||||
*/
|
||||
#define g_bsearch_array_lookup_sibling(barray, bconfig, key_node) \
|
||||
g_bsearch_array_lookup_fuzzy ((barray), (bconfig), (key_node), 1)
|
||||
|
||||
/* g_bsearch_array_lookup_insertion():
|
||||
* return NULL for barray->n_nodes==0 or exact match, otherwise
|
||||
* return the node where key_node should be inserted (may be one
|
||||
* after end, i.e. g_bsearch_array_get_index(result) <= barray->n_nodes).
|
||||
*/
|
||||
#define g_bsearch_array_lookup_insertion(barray, bconfig, key_node) \
|
||||
g_bsearch_array_lookup_fuzzy ((barray), (bconfig), (key_node), 2)
|
||||
|
||||
|
||||
/* --- implementation --- */
|
||||
/* helper macro to cut down realloc()s */
|
||||
#ifdef DISABLE_MEM_POOLS
|
||||
#define G_BSEARCH_UPPER_POWER2(n) (n)
|
||||
#else /* !DISABLE_MEM_POOLS */
|
||||
#define G_BSEARCH_UPPER_POWER2(n) ((n) ? 1 << g_bit_storage ((n) - 1) : 0)
|
||||
#endif /* !DISABLE_MEM_POOLS */
|
||||
#define G_BSEARCH_ARRAY_NODES(barray) (((guint8*) (barray)) + sizeof (GBSearchArray))
|
||||
static inline GBSearchArray*
|
||||
g_bsearch_array_create (const GBSearchConfig *bconfig)
|
||||
{
|
||||
GBSearchArray *barray;
|
||||
guint size;
|
||||
|
||||
g_return_val_if_fail (bconfig != NULL, NULL);
|
||||
|
||||
size = sizeof (GBSearchArray) + bconfig->sizeof_node;
|
||||
if (bconfig->flags & G_BSEARCH_ARRAY_ALIGN_POWER2)
|
||||
size = G_BSEARCH_UPPER_POWER2 (size);
|
||||
barray = (GBSearchArray *) g_malloc (size);
|
||||
memset (barray, 0, sizeof (GBSearchArray));
|
||||
|
||||
return barray;
|
||||
}
|
||||
static inline gpointer
|
||||
g_bsearch_array_lookup_fuzzy (GBSearchArray *barray,
|
||||
const GBSearchConfig *bconfig,
|
||||
gconstpointer key_node,
|
||||
const guint sibling_or_after);
|
||||
static inline gpointer
|
||||
g_bsearch_array_lookup_fuzzy (GBSearchArray *barray,
|
||||
const GBSearchConfig *bconfig,
|
||||
gconstpointer key_node,
|
||||
const guint sibling_or_after)
|
||||
{
|
||||
GBSearchCompareFunc cmp_nodes = bconfig->cmp_nodes;
|
||||
guint8 *check = NULL, *nodes = G_BSEARCH_ARRAY_NODES (barray);
|
||||
guint n_nodes = barray->n_nodes, offs = 0;
|
||||
guint sizeof_node = bconfig->sizeof_node;
|
||||
gint cmp = 0;
|
||||
|
||||
while (offs < n_nodes)
|
||||
{
|
||||
guint i = (offs + n_nodes) >> 1;
|
||||
|
||||
check = nodes + i * sizeof_node;
|
||||
cmp = cmp_nodes (key_node, check);
|
||||
if (cmp == 0)
|
||||
return sibling_or_after > 1 ? NULL : check;
|
||||
else if (cmp < 0)
|
||||
n_nodes = i;
|
||||
else /* (cmp > 0) */
|
||||
offs = i + 1;
|
||||
}
|
||||
|
||||
/* check is last mismatch, cmp > 0 indicates greater key */
|
||||
return G_LIKELY (!sibling_or_after) ? NULL : (sibling_or_after > 1 && cmp > 0) ? check + sizeof_node : check;
|
||||
}
|
||||
static inline gpointer
|
||||
g_bsearch_array_get_nth (GBSearchArray *barray,
|
||||
const GBSearchConfig *bconfig,
|
||||
guint nth)
|
||||
{
|
||||
return (G_LIKELY (nth < barray->n_nodes) ?
|
||||
G_BSEARCH_ARRAY_NODES (barray) + nth * bconfig->sizeof_node :
|
||||
NULL);
|
||||
}
|
||||
static inline guint
|
||||
g_bsearch_array_get_index (GBSearchArray *barray,
|
||||
const GBSearchConfig *bconfig,
|
||||
gconstpointer node_in_array)
|
||||
{
|
||||
guint distance = ((guint8*) node_in_array) - G_BSEARCH_ARRAY_NODES (barray);
|
||||
|
||||
g_return_val_if_fail (node_in_array != NULL, barray->n_nodes);
|
||||
|
||||
distance /= bconfig->sizeof_node;
|
||||
|
||||
return MIN (distance, barray->n_nodes + 1); /* may return one after end */
|
||||
}
|
||||
static inline GBSearchArray*
|
||||
g_bsearch_array_grow (GBSearchArray *barray,
|
||||
const GBSearchConfig *bconfig,
|
||||
guint index_)
|
||||
{
|
||||
guint old_size = barray->n_nodes * bconfig->sizeof_node;
|
||||
guint new_size = old_size + bconfig->sizeof_node;
|
||||
guint8 *node;
|
||||
|
||||
g_return_val_if_fail (index_ <= barray->n_nodes, NULL);
|
||||
|
||||
if (G_UNLIKELY (bconfig->flags & G_BSEARCH_ARRAY_ALIGN_POWER2))
|
||||
{
|
||||
new_size = G_BSEARCH_UPPER_POWER2 (sizeof (GBSearchArray) + new_size);
|
||||
old_size = G_BSEARCH_UPPER_POWER2 (sizeof (GBSearchArray) + old_size);
|
||||
if (old_size != new_size)
|
||||
barray = (GBSearchArray *) g_realloc (barray, new_size);
|
||||
}
|
||||
else
|
||||
barray = (GBSearchArray *) g_realloc (barray, sizeof (GBSearchArray) + new_size);
|
||||
node = G_BSEARCH_ARRAY_NODES (barray) + index_ * bconfig->sizeof_node;
|
||||
g_memmove (node + bconfig->sizeof_node, node, (barray->n_nodes - index_) * bconfig->sizeof_node);
|
||||
barray->n_nodes += 1;
|
||||
return barray;
|
||||
}
|
||||
static inline GBSearchArray*
|
||||
g_bsearch_array_insert (GBSearchArray *barray,
|
||||
const GBSearchConfig *bconfig,
|
||||
gconstpointer key_node)
|
||||
{
|
||||
guint8 *node;
|
||||
|
||||
if (G_UNLIKELY (!barray->n_nodes))
|
||||
{
|
||||
barray = g_bsearch_array_grow (barray, bconfig, 0);
|
||||
node = G_BSEARCH_ARRAY_NODES (barray);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = (guint8 *) g_bsearch_array_lookup_insertion (barray, bconfig, key_node);
|
||||
if (G_LIKELY (node))
|
||||
{
|
||||
guint index_ = g_bsearch_array_get_index (barray, bconfig, node);
|
||||
|
||||
/* grow and insert */
|
||||
barray = g_bsearch_array_grow (barray, bconfig, index_);
|
||||
node = G_BSEARCH_ARRAY_NODES (barray) + index_ * bconfig->sizeof_node;
|
||||
}
|
||||
else /* no insertion needed, node already there */
|
||||
return barray;
|
||||
}
|
||||
memcpy (node, key_node, bconfig->sizeof_node);
|
||||
return barray;
|
||||
}
|
||||
static inline GBSearchArray*
|
||||
g_bsearch_array_replace (GBSearchArray *barray,
|
||||
const GBSearchConfig *bconfig,
|
||||
gconstpointer key_node)
|
||||
{
|
||||
guint8 *node = (guint8 *) g_bsearch_array_lookup (barray, bconfig, key_node);
|
||||
if (G_LIKELY (node)) /* expected path */
|
||||
memcpy (node, key_node, bconfig->sizeof_node);
|
||||
else /* revert to insertion */
|
||||
barray = g_bsearch_array_insert (barray, bconfig, key_node);
|
||||
return barray;
|
||||
}
|
||||
static inline GBSearchArray*
|
||||
g_bsearch_array_remove (GBSearchArray *barray,
|
||||
const GBSearchConfig *bconfig,
|
||||
guint index_)
|
||||
{
|
||||
guint8 *node;
|
||||
|
||||
g_return_val_if_fail (index_ < barray->n_nodes, NULL);
|
||||
|
||||
barray->n_nodes -= 1;
|
||||
node = G_BSEARCH_ARRAY_NODES (barray) + index_ * bconfig->sizeof_node;
|
||||
g_memmove (node, node + bconfig->sizeof_node, (barray->n_nodes - index_) * bconfig->sizeof_node);
|
||||
if (G_UNLIKELY (bconfig->flags & G_BSEARCH_ARRAY_AUTO_SHRINK))
|
||||
{
|
||||
guint new_size = barray->n_nodes * bconfig->sizeof_node;
|
||||
guint old_size = new_size + bconfig->sizeof_node;
|
||||
|
||||
if (G_UNLIKELY (bconfig->flags & G_BSEARCH_ARRAY_ALIGN_POWER2))
|
||||
{
|
||||
new_size = G_BSEARCH_UPPER_POWER2 (sizeof (GBSearchArray) + new_size);
|
||||
old_size = G_BSEARCH_UPPER_POWER2 (sizeof (GBSearchArray) + old_size);
|
||||
if (old_size != new_size)
|
||||
barray = (GBSearchArray *) g_realloc (barray, new_size);
|
||||
}
|
||||
else
|
||||
barray = (GBSearchArray *) g_realloc (barray, sizeof (GBSearchArray) + new_size);
|
||||
}
|
||||
return barray;
|
||||
}
|
||||
static inline void
|
||||
g_bsearch_array_free (GBSearchArray *barray,
|
||||
const GBSearchConfig *bconfig)
|
||||
{
|
||||
g_return_if_fail (barray != NULL);
|
||||
|
||||
g_free (barray);
|
||||
}
|
||||
|
||||
G_END_DECLS /* c++ guards */
|
||||
|
||||
#endif /* !__G_BSEARCH_ARRAY_H__ */
|
||||
482
glib/glib/gbytes.c
Normal file
482
glib/glib/gbytes.c
Normal file
|
|
@ -0,0 +1,482 @@
|
|||
/*
|
||||
* Copyright © 2009, 2010 Codethink Limited
|
||||
* Copyright © 2011 Collabora Ltd.
|
||||
*
|
||||
* 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 of the licence, 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Ryan Lortie <desrt@desrt.ca>
|
||||
* Stef Walter <stefw@collabora.co.uk>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gbytes.h"
|
||||
|
||||
#include <glib/garray.h>
|
||||
#include <glib/gstrfuncs.h>
|
||||
#include <glib/gatomic.h>
|
||||
#include <glib/gslice.h>
|
||||
#include <glib/gtestutils.h>
|
||||
#include <glib/gmem.h>
|
||||
#include <glib/gmessages.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* GBytes:
|
||||
*
|
||||
* A simple refcounted data type representing an immutable byte sequence
|
||||
* from an unspecified origin.
|
||||
*
|
||||
* The purpose of a #GBytes is to keep the memory region that it holds
|
||||
* alive for as long as anyone holds a reference to the bytes. When
|
||||
* the last reference count is dropped, the memory is released. Multiple
|
||||
* unrelated callers can use byte data in the #GBytes without coordinating
|
||||
* their activities, resting assured that the byte data will not change or
|
||||
* move while they hold a reference.
|
||||
*
|
||||
* A #GBytes can come from many different origins that may have
|
||||
* different procedures for freeing the memory region. Examples are
|
||||
* memory from g_malloc(), from memory slices, from a #GMappedFile or
|
||||
* memory from other allocators.
|
||||
*
|
||||
* #GBytes work well as keys in #GHashTable. Use g_bytes_equal() and
|
||||
* g_bytes_hash() as parameters to g_hash_table_new() or g_hash_table_new_full().
|
||||
* #GBytes can also be used as keys in a #GTree by passing the g_bytes_compare()
|
||||
* function to g_tree_new().
|
||||
*
|
||||
* The data pointed to by this bytes must not be modified. For a mutable
|
||||
* array of bytes see #GByteArray. Use g_bytes_unref_to_array() to create a
|
||||
* mutable array for a #GBytes sequence. To create an immutable #GBytes from
|
||||
* a mutable #GByteArray, use the g_byte_array_free_to_bytes() function.
|
||||
*
|
||||
* Since: 2.32
|
||||
**/
|
||||
|
||||
struct _GBytes
|
||||
{
|
||||
gconstpointer data;
|
||||
gsize size;
|
||||
gint ref_count;
|
||||
GDestroyNotify free_func;
|
||||
gpointer user_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* g_bytes_new:
|
||||
* @data: (array length=size): the data to be used for the bytes
|
||||
* @size: the size of @data
|
||||
*
|
||||
* Creates a new #GBytes from @data.
|
||||
*
|
||||
* @data is copied.
|
||||
*
|
||||
* Returns: (transfer full): a new #GBytes
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
GBytes *
|
||||
g_bytes_new (gconstpointer data,
|
||||
gsize size)
|
||||
{
|
||||
return g_bytes_new_take (g_memdup (data, size), size);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bytes_new_take:
|
||||
* @data: (transfer full) (array length=size): the data to be used for the bytes
|
||||
* @size: the size of @data
|
||||
*
|
||||
* Creates a new #GBytes from @data.
|
||||
*
|
||||
* After this call, @data belongs to the bytes and may no longer be
|
||||
* modified by the caller. g_free() will be called on @data when the
|
||||
* bytes is no longer in use. Because of this @data must have been created by
|
||||
* a call to g_malloc(), g_malloc0() or g_realloc() or by one of the many
|
||||
* functions that wrap these calls (such as g_new(), g_strdup(), etc).
|
||||
*
|
||||
* For creating #GBytes with memory from other allocators, see
|
||||
* g_bytes_new_with_free_func().
|
||||
*
|
||||
* Returns: (transfer full): a new #GBytes
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
GBytes *
|
||||
g_bytes_new_take (gpointer data,
|
||||
gsize size)
|
||||
{
|
||||
return g_bytes_new_with_free_func (data, size, g_free, data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* g_bytes_new_static:
|
||||
* @data: (array length=size): the data to be used for the bytes
|
||||
* @size: the size of @data
|
||||
*
|
||||
* Creates a new #GBytes from static data.
|
||||
*
|
||||
* @data must be static (ie: never modified or freed).
|
||||
*
|
||||
* Returns: (transfer full): a new #GBytes
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
GBytes *
|
||||
g_bytes_new_static (gconstpointer data,
|
||||
gsize size)
|
||||
{
|
||||
return g_bytes_new_with_free_func (data, size, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bytes_new_with_free_func:
|
||||
* @data: (array length=size): the data to be used for the bytes
|
||||
* @size: the size of @data
|
||||
* @free_func: the function to call to release the data
|
||||
* @user_data: data to pass to @free_func
|
||||
*
|
||||
* Creates a #GBytes from @data.
|
||||
*
|
||||
* When the last reference is dropped, @free_func will be called with the
|
||||
* @user_data argument.
|
||||
*
|
||||
* @data must not be modified after this call is made until @free_func has
|
||||
* been called to indicate that the bytes is no longer in use.
|
||||
*
|
||||
* Returns: (transfer full): a new #GBytes
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
GBytes *
|
||||
g_bytes_new_with_free_func (gconstpointer data,
|
||||
gsize size,
|
||||
GDestroyNotify free_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = g_slice_new (GBytes);
|
||||
bytes->data = data;
|
||||
bytes->size = size;
|
||||
bytes->free_func = free_func;
|
||||
bytes->user_data = user_data;
|
||||
bytes->ref_count = 1;
|
||||
|
||||
return (GBytes *)bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bytes_new_from_bytes:
|
||||
* @bytes: a #GBytes
|
||||
* @offset: offset which subsection starts at
|
||||
* @length: length of subsection
|
||||
*
|
||||
* Creates a #GBytes which is a subsection of another #GBytes. The @offset +
|
||||
* @length may not be longer than the size of @bytes.
|
||||
*
|
||||
* A reference to @bytes will be held by the newly created #GBytes until
|
||||
* the byte data is no longer needed.
|
||||
*
|
||||
* Returns: (transfer full): a new #GBytes
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
GBytes *
|
||||
g_bytes_new_from_bytes (GBytes *bytes,
|
||||
gsize offset,
|
||||
gsize length)
|
||||
{
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
g_return_val_if_fail (offset <= bytes->size, NULL);
|
||||
g_return_val_if_fail (offset + length <= bytes->size, NULL);
|
||||
|
||||
return g_bytes_new_with_free_func ((gchar *)bytes->data + offset, length,
|
||||
(GDestroyNotify)g_bytes_unref, g_bytes_ref (bytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bytes_get_data:
|
||||
* @bytes: a #GBytes
|
||||
* @size: (out) (allow-none): location to return size of byte data
|
||||
*
|
||||
* Get the byte data in the #GBytes. This data should not be modified.
|
||||
*
|
||||
* This function will always return the same pointer for a given #GBytes.
|
||||
*
|
||||
* Returns: (array length=size) (type guint8): a pointer to the byte data
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
gconstpointer
|
||||
g_bytes_get_data (GBytes *bytes,
|
||||
gsize *size)
|
||||
{
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
if (size)
|
||||
*size = bytes->size;
|
||||
return bytes->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bytes_get_size:
|
||||
* @bytes: a #GBytes
|
||||
*
|
||||
* Get the size of the byte data in the #GBytes.
|
||||
*
|
||||
* This function will always return the same value for a given #GBytes.
|
||||
*
|
||||
* Returns: the size
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
gsize
|
||||
g_bytes_get_size (GBytes *bytes)
|
||||
{
|
||||
g_return_val_if_fail (bytes != NULL, 0);
|
||||
return bytes->size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* g_bytes_ref:
|
||||
* @bytes: a #GBytes
|
||||
*
|
||||
* Increase the reference count on @bytes.
|
||||
*
|
||||
* Returns: the #GBytes
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
GBytes *
|
||||
g_bytes_ref (GBytes *bytes)
|
||||
{
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
|
||||
g_atomic_int_inc (&bytes->ref_count);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bytes_unref:
|
||||
* @bytes: (allow-none): a #GBytes
|
||||
*
|
||||
* Releases a reference on @bytes. This may result in the bytes being
|
||||
* freed.
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
void
|
||||
g_bytes_unref (GBytes *bytes)
|
||||
{
|
||||
if (bytes == NULL)
|
||||
return;
|
||||
|
||||
if (g_atomic_int_dec_and_test (&bytes->ref_count))
|
||||
{
|
||||
if (bytes->free_func != NULL)
|
||||
bytes->free_func (bytes->user_data);
|
||||
g_slice_free (GBytes, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bytes_equal:
|
||||
* @bytes1: (type GLib.Bytes): a pointer to a #GBytes
|
||||
* @bytes2: (type GLib.Bytes): a pointer to a #GBytes to compare with @bytes1
|
||||
*
|
||||
* Compares the two #GBytes values being pointed to and returns
|
||||
* %TRUE if they are equal.
|
||||
*
|
||||
* This function can be passed to g_hash_table_new() as the @key_equal_func
|
||||
* parameter, when using non-%NULL #GBytes pointers as keys in a #GHashTable.
|
||||
*
|
||||
* Returns: %TRUE if the two keys match.
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
gboolean
|
||||
g_bytes_equal (gconstpointer bytes1,
|
||||
gconstpointer bytes2)
|
||||
{
|
||||
const GBytes *b1 = bytes1;
|
||||
const GBytes *b2 = bytes2;
|
||||
|
||||
g_return_val_if_fail (bytes1 != NULL, FALSE);
|
||||
g_return_val_if_fail (bytes2 != NULL, FALSE);
|
||||
|
||||
return b1->size == b2->size &&
|
||||
memcmp (b1->data, b2->data, b1->size) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bytes_hash:
|
||||
* @bytes: (type GLib.Bytes): a pointer to a #GBytes key
|
||||
*
|
||||
* Creates an integer hash code for the byte data in the #GBytes.
|
||||
*
|
||||
* This function can be passed to g_hash_table_new() as the @key_equal_func
|
||||
* parameter, when using non-%NULL #GBytes pointers as keys in a #GHashTable.
|
||||
*
|
||||
* Returns: a hash value corresponding to the key.
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
guint
|
||||
g_bytes_hash (gconstpointer bytes)
|
||||
{
|
||||
const GBytes *a = bytes;
|
||||
const signed char *p, *e;
|
||||
guint32 h = 5381;
|
||||
|
||||
g_return_val_if_fail (bytes != NULL, 0);
|
||||
|
||||
for (p = (signed char *)a->data, e = (signed char *)a->data + a->size; p != e; p++)
|
||||
h = (h << 5) + h + *p;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bytes_compare:
|
||||
* @bytes1: (type GLib.Bytes): a pointer to a #GBytes
|
||||
* @bytes2: (type GLib.Bytes): a pointer to a #GBytes to compare with @bytes1
|
||||
*
|
||||
* Compares the two #GBytes values.
|
||||
*
|
||||
* This function can be used to sort GBytes instances in lexographical order.
|
||||
*
|
||||
* Returns: a negative value if bytes2 is lesser, a positive value if bytes2 is
|
||||
* greater, and zero if bytes2 is equal to bytes1
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
gint
|
||||
g_bytes_compare (gconstpointer bytes1,
|
||||
gconstpointer bytes2)
|
||||
{
|
||||
const GBytes *b1 = bytes1;
|
||||
const GBytes *b2 = bytes2;
|
||||
gint ret;
|
||||
|
||||
g_return_val_if_fail (bytes1 != NULL, 0);
|
||||
g_return_val_if_fail (bytes2 != NULL, 0);
|
||||
|
||||
ret = memcmp (b1->data, b2->data, MIN (b1->size, b2->size));
|
||||
if (ret == 0 && b1->size != b2->size)
|
||||
ret = b1->size < b2->size ? -1 : 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
try_steal_and_unref (GBytes *bytes,
|
||||
GDestroyNotify free_func,
|
||||
gsize *size)
|
||||
{
|
||||
gpointer result;
|
||||
|
||||
if (bytes->free_func != free_func)
|
||||
return NULL;
|
||||
|
||||
/* Are we the only reference? */
|
||||
if (g_atomic_int_get (&bytes->ref_count) == 1)
|
||||
{
|
||||
*size = bytes->size;
|
||||
result = (gpointer)bytes->data;
|
||||
g_slice_free (GBytes, bytes);
|
||||
return result;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* g_bytes_unref_to_data:
|
||||
* @bytes: (transfer full): a #GBytes
|
||||
* @size: location to place the length of the returned data
|
||||
*
|
||||
* Unreferences the bytes, and returns a pointer the same byte data
|
||||
* contents.
|
||||
*
|
||||
* As an optimization, the byte data is returned without copying if this was
|
||||
* the last reference to bytes and bytes was created with g_bytes_new(),
|
||||
* g_bytes_new_take() or g_byte_array_free_to_bytes(). In all other cases the
|
||||
* data is copied.
|
||||
*
|
||||
* Returns: (transfer full): a pointer to the same byte data, which should
|
||||
* be freed with g_free()
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
gpointer
|
||||
g_bytes_unref_to_data (GBytes *bytes,
|
||||
gsize *size)
|
||||
{
|
||||
gpointer result;
|
||||
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
g_return_val_if_fail (size != NULL, NULL);
|
||||
|
||||
/*
|
||||
* Optimal path: if this is was the last reference, then we can return
|
||||
* the data from this GBytes without copying.
|
||||
*/
|
||||
|
||||
result = try_steal_and_unref (bytes, g_free, size);
|
||||
if (result == NULL)
|
||||
{
|
||||
/*
|
||||
* Copy: Non g_malloc (or compatible) allocator, or static memory,
|
||||
* so we have to copy, and then unref.
|
||||
*/
|
||||
result = g_memdup (bytes->data, bytes->size);
|
||||
*size = bytes->size;
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_bytes_unref_to_array:
|
||||
* @bytes: (transfer full): a #GBytes
|
||||
*
|
||||
* Unreferences the bytes, and returns a new mutable #GByteArray containing
|
||||
* the same byte data.
|
||||
*
|
||||
* As an optimization, the byte data is transferred to the array without copying
|
||||
* if this was the last reference to bytes and bytes was created with
|
||||
* g_bytes_new(), g_bytes_new_take() or g_byte_array_free_to_bytes(). In all
|
||||
* other cases the data is copied.
|
||||
*
|
||||
* Returns: (transfer full): a new mutable #GByteArray containing the same byte data
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
GByteArray *
|
||||
g_bytes_unref_to_array (GBytes *bytes)
|
||||
{
|
||||
gpointer data;
|
||||
gsize size;
|
||||
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
|
||||
data = g_bytes_unref_to_data (bytes, &size);
|
||||
return g_byte_array_new_take (data, size);
|
||||
}
|
||||
74
glib/glib/gbytes.h
Normal file
74
glib/glib/gbytes.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright © 2009, 2010 Codethink Limited
|
||||
* Copyright © 2011 Collabora Ltd.
|
||||
*
|
||||
* 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 of the licence, 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Ryan Lortie <desrt@desrt.ca>
|
||||
* Stef Walter <stefw@collabora.co.uk>
|
||||
*/
|
||||
|
||||
#ifndef __G_BYTES_H__
|
||||
#define __G_BYTES_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
#include <glib/garray.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GBytes * g_bytes_new (gconstpointer data,
|
||||
gsize size);
|
||||
|
||||
GBytes * g_bytes_new_take (gpointer data,
|
||||
gsize size);
|
||||
|
||||
GBytes * g_bytes_new_static (gconstpointer data,
|
||||
gsize size);
|
||||
|
||||
GBytes * g_bytes_new_with_free_func (gconstpointer data,
|
||||
gsize size,
|
||||
GDestroyNotify free_func,
|
||||
gpointer user_data);
|
||||
|
||||
GBytes * g_bytes_new_from_bytes (GBytes *bytes,
|
||||
gsize offset,
|
||||
gsize length);
|
||||
|
||||
gconstpointer g_bytes_get_data (GBytes *bytes,
|
||||
gsize *size);
|
||||
|
||||
gsize g_bytes_get_size (GBytes *bytes);
|
||||
|
||||
GBytes * g_bytes_ref (GBytes *bytes);
|
||||
|
||||
void g_bytes_unref (GBytes *bytes);
|
||||
|
||||
gpointer g_bytes_unref_to_data (GBytes *bytes,
|
||||
gsize *size);
|
||||
|
||||
GByteArray * g_bytes_unref_to_array (GBytes *bytes);
|
||||
|
||||
guint g_bytes_hash (gconstpointer bytes);
|
||||
|
||||
gboolean g_bytes_equal (gconstpointer bytes1,
|
||||
gconstpointer bytes2);
|
||||
|
||||
gint g_bytes_compare (gconstpointer bytes1,
|
||||
gconstpointer bytes2);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_BYTES_H__ */
|
||||
592
glib/glib/gcharset.c
Normal file
592
glib/glib/gcharset.c
Normal file
|
|
@ -0,0 +1,592 @@
|
|||
/* gcharset.c - Charset information
|
||||
*
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gcharset.h"
|
||||
|
||||
#include "garray.h"
|
||||
#include "genviron.h"
|
||||
#include "ghash.h"
|
||||
#include "gmessages.h"
|
||||
#include "gstrfuncs.h"
|
||||
#include "gthread.h"
|
||||
#ifdef G_OS_WIN32
|
||||
#include "gwin32.h"
|
||||
#endif
|
||||
|
||||
#include "libcharset/libcharset.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
G_LOCK_DEFINE_STATIC (aliases);
|
||||
|
||||
static GHashTable *
|
||||
get_alias_hash (void)
|
||||
{
|
||||
static GHashTable *alias_hash = NULL;
|
||||
const char *aliases;
|
||||
|
||||
G_LOCK (aliases);
|
||||
|
||||
if (!alias_hash)
|
||||
{
|
||||
alias_hash = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
aliases = _g_locale_get_charset_aliases ();
|
||||
while (*aliases != '\0')
|
||||
{
|
||||
const char *canonical;
|
||||
const char *alias;
|
||||
const char **alias_array;
|
||||
int count = 0;
|
||||
|
||||
alias = aliases;
|
||||
aliases += strlen (aliases) + 1;
|
||||
canonical = aliases;
|
||||
aliases += strlen (aliases) + 1;
|
||||
|
||||
alias_array = g_hash_table_lookup (alias_hash, canonical);
|
||||
if (alias_array)
|
||||
{
|
||||
while (alias_array[count])
|
||||
count++;
|
||||
}
|
||||
|
||||
alias_array = g_renew (const char *, alias_array, count + 2);
|
||||
alias_array[count] = alias;
|
||||
alias_array[count + 1] = NULL;
|
||||
|
||||
g_hash_table_insert (alias_hash, (char *)canonical, alias_array);
|
||||
}
|
||||
}
|
||||
|
||||
G_UNLOCK (aliases);
|
||||
|
||||
return alias_hash;
|
||||
}
|
||||
|
||||
/* As an abuse of the alias table, the following routines gets
|
||||
* the charsets that are aliases for the canonical name.
|
||||
*/
|
||||
G_GNUC_INTERNAL const char **
|
||||
_g_charset_get_aliases (const char *canonical_name)
|
||||
{
|
||||
GHashTable *alias_hash = get_alias_hash ();
|
||||
|
||||
return g_hash_table_lookup (alias_hash, canonical_name);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_utf8_get_charset_internal (const char *raw_data,
|
||||
const char **a)
|
||||
{
|
||||
const char *charset = g_getenv ("CHARSET");
|
||||
|
||||
if (charset && *charset)
|
||||
{
|
||||
*a = charset;
|
||||
|
||||
if (charset && strstr (charset, "UTF-8"))
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* The libcharset code tries to be thread-safe without
|
||||
* a lock, but has a memory leak and a missing memory
|
||||
* barrier, so we lock for it
|
||||
*/
|
||||
G_LOCK (aliases);
|
||||
charset = _g_locale_charset_unalias (raw_data);
|
||||
G_UNLOCK (aliases);
|
||||
|
||||
if (charset && *charset)
|
||||
{
|
||||
*a = charset;
|
||||
|
||||
if (charset && strstr (charset, "UTF-8"))
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Assume this for compatibility at present. */
|
||||
*a = "US-ASCII";
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
typedef struct _GCharsetCache GCharsetCache;
|
||||
|
||||
struct _GCharsetCache {
|
||||
gboolean is_utf8;
|
||||
gchar *raw;
|
||||
gchar *charset;
|
||||
};
|
||||
|
||||
static void
|
||||
charset_cache_free (gpointer data)
|
||||
{
|
||||
GCharsetCache *cache = data;
|
||||
g_free (cache->raw);
|
||||
g_free (cache->charset);
|
||||
g_free (cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_get_charset:
|
||||
* @charset: return location for character set name
|
||||
*
|
||||
* Obtains the character set for the <link linkend="setlocale">current
|
||||
* locale</link>; you might use this character set as an argument to
|
||||
* g_convert(), to convert from the current locale's encoding to some
|
||||
* other encoding. (Frequently g_locale_to_utf8() and g_locale_from_utf8()
|
||||
* are nice shortcuts, though.)
|
||||
*
|
||||
* On Windows the character set returned by this function is the
|
||||
* so-called system default ANSI code-page. That is the character set
|
||||
* used by the "narrow" versions of C library and Win32 functions that
|
||||
* handle file names. It might be different from the character set
|
||||
* used by the C library's current locale.
|
||||
*
|
||||
* The return value is %TRUE if the locale's encoding is UTF-8, in that
|
||||
* case you can perhaps avoid calling g_convert().
|
||||
*
|
||||
* The string returned in @charset is not allocated, and should not be
|
||||
* freed.
|
||||
*
|
||||
* Return value: %TRUE if the returned charset is UTF-8
|
||||
*/
|
||||
gboolean
|
||||
g_get_charset (const char **charset)
|
||||
{
|
||||
static GPrivate cache_private = G_PRIVATE_INIT (charset_cache_free);
|
||||
GCharsetCache *cache = g_private_get (&cache_private);
|
||||
const gchar *raw;
|
||||
|
||||
if (!cache)
|
||||
{
|
||||
cache = g_new0 (GCharsetCache, 1);
|
||||
g_private_set (&cache_private, cache);
|
||||
}
|
||||
|
||||
G_LOCK (aliases);
|
||||
raw = _g_locale_charset_raw ();
|
||||
G_UNLOCK (aliases);
|
||||
|
||||
if (!(cache->raw && strcmp (cache->raw, raw) == 0))
|
||||
{
|
||||
const gchar *new_charset;
|
||||
|
||||
g_free (cache->raw);
|
||||
g_free (cache->charset);
|
||||
cache->raw = g_strdup (raw);
|
||||
cache->is_utf8 = g_utf8_get_charset_internal (raw, &new_charset);
|
||||
cache->charset = g_strdup (new_charset);
|
||||
}
|
||||
|
||||
if (charset)
|
||||
*charset = cache->charset;
|
||||
|
||||
return cache->is_utf8;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_get_codeset:
|
||||
*
|
||||
* Gets the character set for the current locale.
|
||||
*
|
||||
* Return value: a newly allocated string containing the name
|
||||
* of the character set. This string must be freed with g_free().
|
||||
*/
|
||||
gchar *
|
||||
g_get_codeset (void)
|
||||
{
|
||||
const gchar *charset;
|
||||
|
||||
g_get_charset (&charset);
|
||||
|
||||
return g_strdup (charset);
|
||||
}
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
|
||||
static GHashTable *alias_table = NULL;
|
||||
|
||||
/* read an alias file for the locales */
|
||||
static void
|
||||
read_aliases (gchar *file)
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[256];
|
||||
|
||||
if (!alias_table)
|
||||
alias_table = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
fp = fopen (file,"r");
|
||||
if (!fp)
|
||||
return;
|
||||
while (fgets (buf, 256, fp))
|
||||
{
|
||||
char *p, *q;
|
||||
|
||||
g_strstrip (buf);
|
||||
|
||||
/* Line is a comment */
|
||||
if ((buf[0] == '#') || (buf[0] == '\0'))
|
||||
continue;
|
||||
|
||||
/* Reads first column */
|
||||
for (p = buf, q = NULL; *p; p++) {
|
||||
if ((*p == '\t') || (*p == ' ') || (*p == ':')) {
|
||||
*p = '\0';
|
||||
q = p+1;
|
||||
while ((*q == '\t') || (*q == ' ')) {
|
||||
q++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* The line only had one column */
|
||||
if (!q || *q == '\0')
|
||||
continue;
|
||||
|
||||
/* Read second column */
|
||||
for (p = q; *p; p++) {
|
||||
if ((*p == '\t') || (*p == ' ')) {
|
||||
*p = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add to alias table if necessary */
|
||||
if (!g_hash_table_lookup (alias_table, buf)) {
|
||||
g_hash_table_insert (alias_table, g_strdup (buf), g_strdup (q));
|
||||
}
|
||||
}
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static char *
|
||||
unalias_lang (char *lang)
|
||||
{
|
||||
#ifndef G_OS_WIN32
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
if (!alias_table)
|
||||
read_aliases ("/usr/share/locale/locale.alias");
|
||||
|
||||
i = 0;
|
||||
while ((p = g_hash_table_lookup (alias_table, lang)) && (strcmp (p, lang) != 0))
|
||||
{
|
||||
lang = p;
|
||||
if (i++ == 30)
|
||||
{
|
||||
static gboolean said_before = FALSE;
|
||||
if (!said_before)
|
||||
g_warning ("Too many alias levels for a locale, "
|
||||
"may indicate a loop");
|
||||
said_before = TRUE;
|
||||
return lang;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return lang;
|
||||
}
|
||||
|
||||
/* Mask for components of locale spec. The ordering here is from
|
||||
* least significant to most significant
|
||||
*/
|
||||
enum
|
||||
{
|
||||
COMPONENT_CODESET = 1 << 0,
|
||||
COMPONENT_TERRITORY = 1 << 1,
|
||||
COMPONENT_MODIFIER = 1 << 2
|
||||
};
|
||||
|
||||
/* Break an X/Open style locale specification into components
|
||||
*/
|
||||
static guint
|
||||
explode_locale (const gchar *locale,
|
||||
gchar **language,
|
||||
gchar **territory,
|
||||
gchar **codeset,
|
||||
gchar **modifier)
|
||||
{
|
||||
const gchar *uscore_pos;
|
||||
const gchar *at_pos;
|
||||
const gchar *dot_pos;
|
||||
|
||||
guint mask = 0;
|
||||
|
||||
uscore_pos = strchr (locale, '_');
|
||||
dot_pos = strchr (uscore_pos ? uscore_pos : locale, '.');
|
||||
at_pos = strchr (dot_pos ? dot_pos : (uscore_pos ? uscore_pos : locale), '@');
|
||||
|
||||
if (at_pos)
|
||||
{
|
||||
mask |= COMPONENT_MODIFIER;
|
||||
*modifier = g_strdup (at_pos);
|
||||
}
|
||||
else
|
||||
at_pos = locale + strlen (locale);
|
||||
|
||||
if (dot_pos)
|
||||
{
|
||||
mask |= COMPONENT_CODESET;
|
||||
*codeset = g_strndup (dot_pos, at_pos - dot_pos);
|
||||
}
|
||||
else
|
||||
dot_pos = at_pos;
|
||||
|
||||
if (uscore_pos)
|
||||
{
|
||||
mask |= COMPONENT_TERRITORY;
|
||||
*territory = g_strndup (uscore_pos, dot_pos - uscore_pos);
|
||||
}
|
||||
else
|
||||
uscore_pos = dot_pos;
|
||||
|
||||
*language = g_strndup (locale, uscore_pos - locale);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute all interesting variants for a given locale name -
|
||||
* by stripping off different components of the value.
|
||||
*
|
||||
* For simplicity, we assume that the locale is in
|
||||
* X/Open format: language[_territory][.codeset][@modifier]
|
||||
*
|
||||
* TODO: Extend this to handle the CEN format (see the GNUlibc docs)
|
||||
* as well. We could just copy the code from glibc wholesale
|
||||
* but it is big, ugly, and complicated, so I'm reluctant
|
||||
* to do so when this should handle 99% of the time...
|
||||
*/
|
||||
static void
|
||||
append_locale_variants (GPtrArray *array,
|
||||
const gchar *locale)
|
||||
{
|
||||
gchar *language = NULL;
|
||||
gchar *territory = NULL;
|
||||
gchar *codeset = NULL;
|
||||
gchar *modifier = NULL;
|
||||
|
||||
guint mask;
|
||||
guint i, j;
|
||||
|
||||
g_return_if_fail (locale != NULL);
|
||||
|
||||
mask = explode_locale (locale, &language, &territory, &codeset, &modifier);
|
||||
|
||||
/* Iterate through all possible combinations, from least attractive
|
||||
* to most attractive.
|
||||
*/
|
||||
for (j = 0; j <= mask; ++j)
|
||||
{
|
||||
i = mask - j;
|
||||
|
||||
if ((i & ~mask) == 0)
|
||||
{
|
||||
gchar *val = g_strconcat (language,
|
||||
(i & COMPONENT_TERRITORY) ? territory : "",
|
||||
(i & COMPONENT_CODESET) ? codeset : "",
|
||||
(i & COMPONENT_MODIFIER) ? modifier : "",
|
||||
NULL);
|
||||
g_ptr_array_add (array, val);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (language);
|
||||
if (mask & COMPONENT_CODESET)
|
||||
g_free (codeset);
|
||||
if (mask & COMPONENT_TERRITORY)
|
||||
g_free (territory);
|
||||
if (mask & COMPONENT_MODIFIER)
|
||||
g_free (modifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_get_locale_variants:
|
||||
* @locale: a locale identifier
|
||||
*
|
||||
* Returns a list of derived variants of @locale, which can be used to
|
||||
* e.g. construct locale-dependent filenames or search paths. The returned
|
||||
* list is sorted from most desirable to least desirable.
|
||||
* This function handles territory, charset and extra locale modifiers.
|
||||
*
|
||||
* For example, if @locale is "fr_BE", then the returned list
|
||||
* is "fr_BE", "fr".
|
||||
*
|
||||
* If you need the list of variants for the <emphasis>current locale</emphasis>,
|
||||
* use g_get_language_names().
|
||||
*
|
||||
* Returns: (transfer full) (array zero-terminated=1) (element-type utf8): a newly
|
||||
* allocated array of newly allocated strings with the locale variants. Free with
|
||||
* g_strfreev().
|
||||
*
|
||||
* Since: 2.28
|
||||
*/
|
||||
gchar **
|
||||
g_get_locale_variants (const gchar *locale)
|
||||
{
|
||||
GPtrArray *array;
|
||||
|
||||
g_return_val_if_fail (locale != NULL, NULL);
|
||||
|
||||
array = g_ptr_array_sized_new (8);
|
||||
append_locale_variants (array, locale);
|
||||
g_ptr_array_add (array, NULL);
|
||||
|
||||
return (gchar **) g_ptr_array_free (array, FALSE);
|
||||
}
|
||||
|
||||
/* The following is (partly) taken from the gettext package.
|
||||
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. */
|
||||
|
||||
static const gchar *
|
||||
guess_category_value (const gchar *category_name)
|
||||
{
|
||||
const gchar *retval;
|
||||
|
||||
/* The highest priority value is the `LANGUAGE' environment
|
||||
variable. This is a GNU extension. */
|
||||
retval = g_getenv ("LANGUAGE");
|
||||
if ((retval != NULL) && (retval[0] != '\0'))
|
||||
return retval;
|
||||
|
||||
/* `LANGUAGE' is not set. So we have to proceed with the POSIX
|
||||
methods of looking to `LC_ALL', `LC_xxx', and `LANG'. On some
|
||||
systems this can be done by the `setlocale' function itself. */
|
||||
|
||||
/* Setting of LC_ALL overwrites all other. */
|
||||
retval = g_getenv ("LC_ALL");
|
||||
if ((retval != NULL) && (retval[0] != '\0'))
|
||||
return retval;
|
||||
|
||||
/* Next comes the name of the desired category. */
|
||||
retval = g_getenv (category_name);
|
||||
if ((retval != NULL) && (retval[0] != '\0'))
|
||||
return retval;
|
||||
|
||||
/* Last possibility is the LANG environment variable. */
|
||||
retval = g_getenv ("LANG");
|
||||
if ((retval != NULL) && (retval[0] != '\0'))
|
||||
return retval;
|
||||
|
||||
#ifdef G_PLATFORM_WIN32
|
||||
/* g_win32_getlocale() first checks for LC_ALL, LC_MESSAGES and
|
||||
* LANG, which we already did above. Oh well. The main point of
|
||||
* calling g_win32_getlocale() is to get the thread's locale as used
|
||||
* by Windows and the Microsoft C runtime (in the "English_United
|
||||
* States" format) translated into the Unixish format.
|
||||
*/
|
||||
{
|
||||
char *locale = g_win32_getlocale ();
|
||||
retval = g_intern_string (locale);
|
||||
g_free (locale);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef struct _GLanguageNamesCache GLanguageNamesCache;
|
||||
|
||||
struct _GLanguageNamesCache {
|
||||
gchar *languages;
|
||||
gchar **language_names;
|
||||
};
|
||||
|
||||
static void
|
||||
language_names_cache_free (gpointer data)
|
||||
{
|
||||
GLanguageNamesCache *cache = data;
|
||||
g_free (cache->languages);
|
||||
g_strfreev (cache->language_names);
|
||||
g_free (cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_get_language_names:
|
||||
*
|
||||
* Computes a list of applicable locale names, which can be used to
|
||||
* e.g. construct locale-dependent filenames or search paths. The returned
|
||||
* list is sorted from most desirable to least desirable and always contains
|
||||
* the default locale "C".
|
||||
*
|
||||
* For example, if LANGUAGE=de:en_US, then the returned list is
|
||||
* "de", "en_US", "en", "C".
|
||||
*
|
||||
* This function consults the environment variables <envar>LANGUAGE</envar>,
|
||||
* <envar>LC_ALL</envar>, <envar>LC_MESSAGES</envar> and <envar>LANG</envar>
|
||||
* to find the list of locales specified by the user.
|
||||
*
|
||||
* Return value: (array zero-terminated=1) (transfer none): a %NULL-terminated array of strings owned by GLib
|
||||
* that must not be modified or freed.
|
||||
*
|
||||
* Since: 2.6
|
||||
**/
|
||||
const gchar * const *
|
||||
g_get_language_names (void)
|
||||
{
|
||||
static GPrivate cache_private = G_PRIVATE_INIT (language_names_cache_free);
|
||||
GLanguageNamesCache *cache = g_private_get (&cache_private);
|
||||
const gchar *value;
|
||||
|
||||
if (!cache)
|
||||
{
|
||||
cache = g_new0 (GLanguageNamesCache, 1);
|
||||
g_private_set (&cache_private, cache);
|
||||
}
|
||||
|
||||
value = guess_category_value ("LC_MESSAGES");
|
||||
if (!value)
|
||||
value = "C";
|
||||
|
||||
if (!(cache->languages && strcmp (cache->languages, value) == 0))
|
||||
{
|
||||
GPtrArray *array;
|
||||
gchar **alist, **a;
|
||||
|
||||
g_free (cache->languages);
|
||||
g_strfreev (cache->language_names);
|
||||
cache->languages = g_strdup (value);
|
||||
|
||||
array = g_ptr_array_sized_new (8);
|
||||
|
||||
alist = g_strsplit (value, ":", 0);
|
||||
for (a = alist; *a; a++)
|
||||
append_locale_variants (array, unalias_lang (*a));
|
||||
g_strfreev (alist);
|
||||
g_ptr_array_add (array, g_strdup ("C"));
|
||||
g_ptr_array_add (array, NULL);
|
||||
|
||||
cache->language_names = (gchar **) g_ptr_array_free (array, FALSE);
|
||||
}
|
||||
|
||||
return (const gchar * const *) cache->language_names;
|
||||
}
|
||||
40
glib/glib/gcharset.h
Normal file
40
glib/glib/gcharset.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/* gcharset.h - Charset functions
|
||||
*
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
*
|
||||
* The GLib 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 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* The GLib 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 the Gnome Library; see the file COPYING.LIB. If not,
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_CHARSET_H__
|
||||
#define __G_CHARSET_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gboolean g_get_charset (const char **charset);
|
||||
gchar * g_get_codeset (void);
|
||||
|
||||
const gchar * const * g_get_language_names (void);
|
||||
gchar ** g_get_locale_variants (const gchar *locale);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_CHARSET_H__ */
|
||||
1461
glib/glib/gchecksum.c
Normal file
1461
glib/glib/gchecksum.c
Normal file
File diff suppressed because it is too large
Load diff
86
glib/glib/gchecksum.h
Normal file
86
glib/glib/gchecksum.h
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/* gchecksum.h - data hashing functions
|
||||
*
|
||||
* Copyright (C) 2007 Emmanuele Bassi <ebassi@gnome.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_CHECKSUM_H__
|
||||
#define __G_CHECKSUM_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* GChecksumType:
|
||||
* @G_CHECKSUM_MD5: Use the MD5 hashing algorithm
|
||||
* @G_CHECKSUM_SHA1: Use the SHA-1 hashing algorithm
|
||||
* @G_CHECKSUM_SHA256: Use the SHA-256 hashing algorithm
|
||||
*
|
||||
* The hashing algorithm to be used by #GChecksum when performing the
|
||||
* digest of some data.
|
||||
*
|
||||
* Note that the #GChecksumType enumeration may be extended at a later
|
||||
* date to include new hashing algorithm types.
|
||||
*
|
||||
* Since: 2.16
|
||||
*/
|
||||
typedef enum {
|
||||
G_CHECKSUM_MD5,
|
||||
G_CHECKSUM_SHA1,
|
||||
G_CHECKSUM_SHA256
|
||||
} GChecksumType;
|
||||
|
||||
/**
|
||||
* GChecksum:
|
||||
*
|
||||
* An opaque structure representing a checksumming operation.
|
||||
* To create a new GChecksum, use g_checksum_new(). To free
|
||||
* a GChecksum, use g_checksum_free().
|
||||
*
|
||||
* Since: 2.16
|
||||
*/
|
||||
typedef struct _GChecksum GChecksum;
|
||||
|
||||
gssize g_checksum_type_get_length (GChecksumType checksum_type);
|
||||
|
||||
GChecksum * g_checksum_new (GChecksumType checksum_type);
|
||||
void g_checksum_reset (GChecksum *checksum);
|
||||
GChecksum * g_checksum_copy (const GChecksum *checksum);
|
||||
void g_checksum_free (GChecksum *checksum);
|
||||
void g_checksum_update (GChecksum *checksum,
|
||||
const guchar *data,
|
||||
gssize length);
|
||||
const gchar * g_checksum_get_string (GChecksum *checksum);
|
||||
void g_checksum_get_digest (GChecksum *checksum,
|
||||
guint8 *buffer,
|
||||
gsize *digest_len);
|
||||
|
||||
gchar *g_compute_checksum_for_data (GChecksumType checksum_type,
|
||||
const guchar *data,
|
||||
gsize length);
|
||||
gchar *g_compute_checksum_for_string (GChecksumType checksum_type,
|
||||
const gchar *str,
|
||||
gssize length);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_CHECKSUM_H__ */
|
||||
91
glib/glib/gconstructor.h
Normal file
91
glib/glib/gconstructor.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
If G_HAS_CONSTRUCTORS is true then the compiler support *both* constructors and
|
||||
destructors, in a sane way, including e.g. on library unload. If not you're on
|
||||
your own.
|
||||
|
||||
Some compilers need #pragma to handle this, which does not work with macros,
|
||||
so the way you need to use this is (for constructors):
|
||||
|
||||
#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
|
||||
#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(my_constructor)
|
||||
#endif
|
||||
G_DEFINE_CONSTRUCTOR(my_constructor)
|
||||
static void my_constructor(void) {
|
||||
...
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
|
||||
|
||||
#define G_HAS_CONSTRUCTORS 1
|
||||
|
||||
#define G_DEFINE_CONSTRUCTOR(_func) static void __attribute__((constructor)) _func (void);
|
||||
#define G_DEFINE_DESTRUCTOR(_func) static void __attribute__((destructor)) _func (void);
|
||||
|
||||
#elif defined (_MSC_VER) && (_MSC_VER >= 1500)
|
||||
/* Visual studio 2008 and later has _Pragma */
|
||||
|
||||
#define G_HAS_CONSTRUCTORS 1
|
||||
|
||||
#define G_DEFINE_CONSTRUCTOR(_func) \
|
||||
static void _func(void); \
|
||||
static int _func ## _wrapper(void) { _func(); return 0; } \
|
||||
__pragma(section(".CRT$XCU",read)) \
|
||||
__declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _wrapper;
|
||||
|
||||
#define G_DEFINE_DESTRUCTOR(_func) \
|
||||
static void _func(void); \
|
||||
static int _func ## _constructor(void) { atexit (_func); return 0; } \
|
||||
__pragma(section(".CRT$XCU",read)) \
|
||||
__declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor;
|
||||
|
||||
#elif defined (_MSC_VER)
|
||||
|
||||
#define G_HAS_CONSTRUCTORS 1
|
||||
|
||||
/* Pre Visual studio 2008 must use #pragma section */
|
||||
#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
|
||||
#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
|
||||
|
||||
#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
|
||||
section(".CRT$XCU",read)
|
||||
#define G_DEFINE_CONSTRUCTOR(_func) \
|
||||
static void _func(void); \
|
||||
static int _func ## _wrapper(void) { _func(); return 0; } \
|
||||
__declspec(allocate(".CRT$XCU")) static int (*p)(void) = _func ## _wrapper;
|
||||
|
||||
#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
|
||||
section(".CRT$XCU",read)
|
||||
#define G_DEFINE_DESTRUCTOR(_func) \
|
||||
static void _func(void); \
|
||||
static int _func ## _constructor(void) { atexit (_func); return 0; } \
|
||||
__declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor;
|
||||
|
||||
#elif defined(__SUNPRO_C)
|
||||
|
||||
/* This is not tested, but i believe it should work, based on:
|
||||
* http://opensource.apple.com/source/OpenSSL098/OpenSSL098-35/src/fips/fips_premain.c
|
||||
*/
|
||||
|
||||
#define G_HAS_CONSTRUCTORS 1
|
||||
|
||||
#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
|
||||
#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
|
||||
|
||||
#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
|
||||
init(_func)
|
||||
#define G_DEFINE_CONSTRUCTOR(_func) \
|
||||
static void _func(void);
|
||||
|
||||
#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
|
||||
fini(_func)
|
||||
#define G_DEFINE_DESTRUCTOR(_func) \
|
||||
static void _func(void);
|
||||
|
||||
#else
|
||||
|
||||
/* constructors not supported for this compiler */
|
||||
|
||||
#endif
|
||||
|
||||
2250
glib/glib/gconvert.c
Normal file
2250
glib/glib/gconvert.c
Normal file
File diff suppressed because it is too large
Load diff
164
glib/glib/gconvert.h
Normal file
164
glib/glib/gconvert.h
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_CONVERT_H__
|
||||
#define __G_CONVERT_H__
|
||||
|
||||
#include <glib/gerror.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* GConvertError:
|
||||
* @G_CONVERT_ERROR_NO_CONVERSION: Conversion between the requested character
|
||||
* sets is not supported.
|
||||
* @G_CONVERT_ERROR_ILLEGAL_SEQUENCE: Invalid byte sequence in conversion input.
|
||||
* @G_CONVERT_ERROR_FAILED: Conversion failed for some reason.
|
||||
* @G_CONVERT_ERROR_PARTIAL_INPUT: Partial character sequence at end of input.
|
||||
* @G_CONVERT_ERROR_BAD_URI: URI is invalid.
|
||||
* @G_CONVERT_ERROR_NOT_ABSOLUTE_PATH: Pathname is not an absolute path.
|
||||
*
|
||||
* Error codes returned by character set conversion routines.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
G_CONVERT_ERROR_NO_CONVERSION,
|
||||
G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
|
||||
G_CONVERT_ERROR_FAILED,
|
||||
G_CONVERT_ERROR_PARTIAL_INPUT,
|
||||
G_CONVERT_ERROR_BAD_URI,
|
||||
G_CONVERT_ERROR_NOT_ABSOLUTE_PATH
|
||||
} GConvertError;
|
||||
|
||||
/**
|
||||
* G_CONVERT_ERROR:
|
||||
*
|
||||
* Error domain for character set conversions. Errors in this domain will
|
||||
* be from the #GConvertError enumeration. See #GError for information on
|
||||
* error domains.
|
||||
*/
|
||||
#define G_CONVERT_ERROR g_convert_error_quark()
|
||||
GQuark g_convert_error_quark (void);
|
||||
|
||||
/**
|
||||
* GIconv:
|
||||
*
|
||||
* The <structname>GIConv</structname> struct wraps an
|
||||
* iconv() conversion descriptor. It contains private data
|
||||
* and should only be accessed using the following functions.
|
||||
*/
|
||||
typedef struct _GIConv *GIConv;
|
||||
|
||||
GIConv g_iconv_open (const gchar *to_codeset,
|
||||
const gchar *from_codeset);
|
||||
gsize g_iconv (GIConv converter,
|
||||
gchar **inbuf,
|
||||
gsize *inbytes_left,
|
||||
gchar **outbuf,
|
||||
gsize *outbytes_left);
|
||||
gint g_iconv_close (GIConv converter);
|
||||
|
||||
|
||||
gchar* g_convert (const gchar *str,
|
||||
gssize len,
|
||||
const gchar *to_codeset,
|
||||
const gchar *from_codeset,
|
||||
gsize *bytes_read,
|
||||
gsize *bytes_written,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
gchar* g_convert_with_iconv (const gchar *str,
|
||||
gssize len,
|
||||
GIConv converter,
|
||||
gsize *bytes_read,
|
||||
gsize *bytes_written,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
gchar* g_convert_with_fallback (const gchar *str,
|
||||
gssize len,
|
||||
const gchar *to_codeset,
|
||||
const gchar *from_codeset,
|
||||
const gchar *fallback,
|
||||
gsize *bytes_read,
|
||||
gsize *bytes_written,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
|
||||
|
||||
/* Convert between libc's idea of strings and UTF-8.
|
||||
*/
|
||||
gchar* g_locale_to_utf8 (const gchar *opsysstring,
|
||||
gssize len,
|
||||
gsize *bytes_read,
|
||||
gsize *bytes_written,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
gchar* g_locale_from_utf8 (const gchar *utf8string,
|
||||
gssize len,
|
||||
gsize *bytes_read,
|
||||
gsize *bytes_written,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
|
||||
/* Convert between the operating system (or C runtime)
|
||||
* representation of file names and UTF-8.
|
||||
*/
|
||||
#ifndef __GTK_DOC_IGNORE__
|
||||
#ifdef G_OS_WIN32
|
||||
#define g_filename_to_utf8 g_filename_to_utf8_utf8
|
||||
#define g_filename_from_utf8 g_filename_from_utf8_utf8
|
||||
#define g_filename_from_uri g_filename_from_uri_utf8
|
||||
#define g_filename_to_uri g_filename_to_uri_utf8
|
||||
#endif
|
||||
#endif
|
||||
|
||||
gchar* g_filename_to_utf8 (const gchar *opsysstring,
|
||||
gssize len,
|
||||
gsize *bytes_read,
|
||||
gsize *bytes_written,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
gchar* g_filename_from_utf8 (const gchar *utf8string,
|
||||
gssize len,
|
||||
gsize *bytes_read,
|
||||
gsize *bytes_written,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
|
||||
gchar *g_filename_from_uri (const gchar *uri,
|
||||
gchar **hostname,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
|
||||
gchar *g_filename_to_uri (const gchar *filename,
|
||||
const gchar *hostname,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
gchar *g_filename_display_name (const gchar *filename) G_GNUC_MALLOC;
|
||||
gboolean g_get_filename_charsets (const gchar ***charsets);
|
||||
|
||||
gchar *g_filename_display_basename (const gchar *filename) G_GNUC_MALLOC;
|
||||
|
||||
gchar **g_uri_list_extract_uris (const gchar *uri_list) G_GNUC_MALLOC;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_CONVERT_H__ */
|
||||
1362
glib/glib/gdataset.c
Normal file
1362
glib/glib/gdataset.c
Normal file
File diff suppressed because it is too large
Load diff
122
glib/glib/gdataset.h
Normal file
122
glib/glib/gdataset.h
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_DATASET_H__
|
||||
#define __G_DATASET_H__
|
||||
|
||||
#include <glib/gquark.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GData GData;
|
||||
|
||||
typedef void (*GDataForeachFunc) (GQuark key_id,
|
||||
gpointer data,
|
||||
gpointer user_data);
|
||||
|
||||
/* Keyed Data List
|
||||
*/
|
||||
void g_datalist_init (GData **datalist);
|
||||
void g_datalist_clear (GData **datalist);
|
||||
gpointer g_datalist_id_get_data (GData **datalist,
|
||||
GQuark key_id);
|
||||
void g_datalist_id_set_data_full (GData **datalist,
|
||||
GQuark key_id,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy_func);
|
||||
gpointer g_datalist_id_remove_no_notify (GData **datalist,
|
||||
GQuark key_id);
|
||||
void g_datalist_foreach (GData **datalist,
|
||||
GDataForeachFunc func,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* G_DATALIST_FLAGS_MASK:
|
||||
*
|
||||
* A bitmask that restricts the possible flags passed to
|
||||
* g_datalist_set_flags(). Passing a flags value where
|
||||
* flags & ~G_DATALIST_FLAGS_MASK != 0 is an error.
|
||||
*/
|
||||
#define G_DATALIST_FLAGS_MASK 0x3
|
||||
|
||||
void g_datalist_set_flags (GData **datalist,
|
||||
guint flags);
|
||||
void g_datalist_unset_flags (GData **datalist,
|
||||
guint flags);
|
||||
guint g_datalist_get_flags (GData **datalist);
|
||||
|
||||
#define g_datalist_id_set_data(dl, q, d) \
|
||||
g_datalist_id_set_data_full ((dl), (q), (d), NULL)
|
||||
#define g_datalist_id_remove_data(dl, q) \
|
||||
g_datalist_id_set_data ((dl), (q), NULL)
|
||||
#define g_datalist_set_data_full(dl, k, d, f) \
|
||||
g_datalist_id_set_data_full ((dl), g_quark_from_string (k), (d), (f))
|
||||
#define g_datalist_remove_no_notify(dl, k) \
|
||||
g_datalist_id_remove_no_notify ((dl), g_quark_try_string (k))
|
||||
#define g_datalist_set_data(dl, k, d) \
|
||||
g_datalist_set_data_full ((dl), (k), (d), NULL)
|
||||
#define g_datalist_remove_data(dl, k) \
|
||||
g_datalist_id_set_data ((dl), g_quark_try_string (k), NULL)
|
||||
|
||||
|
||||
/* Location Associated Keyed Data
|
||||
*/
|
||||
void g_dataset_destroy (gconstpointer dataset_location);
|
||||
gpointer g_dataset_id_get_data (gconstpointer dataset_location,
|
||||
GQuark key_id);
|
||||
gpointer g_datalist_get_data (GData **datalist,
|
||||
const gchar *key);
|
||||
void g_dataset_id_set_data_full (gconstpointer dataset_location,
|
||||
GQuark key_id,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy_func);
|
||||
gpointer g_dataset_id_remove_no_notify (gconstpointer dataset_location,
|
||||
GQuark key_id);
|
||||
void g_dataset_foreach (gconstpointer dataset_location,
|
||||
GDataForeachFunc func,
|
||||
gpointer user_data);
|
||||
#define g_dataset_id_set_data(l, k, d) \
|
||||
g_dataset_id_set_data_full ((l), (k), (d), NULL)
|
||||
#define g_dataset_id_remove_data(l, k) \
|
||||
g_dataset_id_set_data ((l), (k), NULL)
|
||||
#define g_dataset_get_data(l, k) \
|
||||
(g_dataset_id_get_data ((l), g_quark_try_string (k)))
|
||||
#define g_dataset_set_data_full(l, k, d, f) \
|
||||
g_dataset_id_set_data_full ((l), g_quark_from_string (k), (d), (f))
|
||||
#define g_dataset_remove_no_notify(l, k) \
|
||||
g_dataset_id_remove_no_notify ((l), g_quark_try_string (k))
|
||||
#define g_dataset_set_data(l, k, d) \
|
||||
g_dataset_set_data_full ((l), (k), (d), NULL)
|
||||
#define g_dataset_remove_data(l, k) \
|
||||
g_dataset_id_set_data ((l), g_quark_try_string (k), NULL)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_DATASET_H__ */
|
||||
44
glib/glib/gdatasetprivate.h
Normal file
44
glib/glib/gdatasetprivate.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* gdataset-private.h: Internal macros for accessing dataset values
|
||||
* Copyright (C) 2005 Red Hat
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#ifndef __G_DATASETPRIVATE_H__
|
||||
#define __G_DATASETPRIVATE_H__
|
||||
|
||||
#include <gatomic.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* GET_FLAGS is implemented via atomic pointer access, to allow memory
|
||||
* barriers to take effect without acquiring the global dataset mutex.
|
||||
*/
|
||||
#define G_DATALIST_GET_FLAGS(datalist) \
|
||||
((gsize) g_atomic_pointer_get (datalist) & G_DATALIST_FLAGS_MASK)
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_DATASETPRIVATE_H__ */
|
||||
2551
glib/glib/gdate.c
Normal file
2551
glib/glib/gdate.c
Normal file
File diff suppressed because it is too large
Load diff
264
glib/glib/gdate.h
Normal file
264
glib/glib/gdate.h
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_DATE_H__
|
||||
#define __G_DATE_H__
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
#include <glib/gquark.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* GDate
|
||||
*
|
||||
* Date calculations (not time for now, to be resolved). These are a
|
||||
* mutant combination of Steffen Beyer's DateCalc routines
|
||||
* (http://www.perl.com/CPAN/authors/id/STBEY/) and Jon Trowbridge's
|
||||
* date routines (written for in-house software). Written by Havoc
|
||||
* Pennington <hp@pobox.com>
|
||||
*/
|
||||
|
||||
typedef gint32 GTime;
|
||||
typedef guint16 GDateYear;
|
||||
typedef guint8 GDateDay; /* day of the month */
|
||||
typedef struct _GDate GDate;
|
||||
|
||||
/* enum used to specify order of appearance in parsed date strings */
|
||||
typedef enum
|
||||
{
|
||||
G_DATE_DAY = 0,
|
||||
G_DATE_MONTH = 1,
|
||||
G_DATE_YEAR = 2
|
||||
} GDateDMY;
|
||||
|
||||
/* actual week and month values */
|
||||
typedef enum
|
||||
{
|
||||
G_DATE_BAD_WEEKDAY = 0,
|
||||
G_DATE_MONDAY = 1,
|
||||
G_DATE_TUESDAY = 2,
|
||||
G_DATE_WEDNESDAY = 3,
|
||||
G_DATE_THURSDAY = 4,
|
||||
G_DATE_FRIDAY = 5,
|
||||
G_DATE_SATURDAY = 6,
|
||||
G_DATE_SUNDAY = 7
|
||||
} GDateWeekday;
|
||||
typedef enum
|
||||
{
|
||||
G_DATE_BAD_MONTH = 0,
|
||||
G_DATE_JANUARY = 1,
|
||||
G_DATE_FEBRUARY = 2,
|
||||
G_DATE_MARCH = 3,
|
||||
G_DATE_APRIL = 4,
|
||||
G_DATE_MAY = 5,
|
||||
G_DATE_JUNE = 6,
|
||||
G_DATE_JULY = 7,
|
||||
G_DATE_AUGUST = 8,
|
||||
G_DATE_SEPTEMBER = 9,
|
||||
G_DATE_OCTOBER = 10,
|
||||
G_DATE_NOVEMBER = 11,
|
||||
G_DATE_DECEMBER = 12
|
||||
} GDateMonth;
|
||||
|
||||
#define G_DATE_BAD_JULIAN 0U
|
||||
#define G_DATE_BAD_DAY 0U
|
||||
#define G_DATE_BAD_YEAR 0U
|
||||
|
||||
/* Note: directly manipulating structs is generally a bad idea, but
|
||||
* in this case it's an *incredibly* bad idea, because all or part
|
||||
* of this struct can be invalid at any given time. Use the functions,
|
||||
* or you will get hosed, I promise.
|
||||
*/
|
||||
struct _GDate
|
||||
{
|
||||
guint julian_days : 32; /* julian days representation - we use a
|
||||
* bitfield hoping that 64 bit platforms
|
||||
* will pack this whole struct in one big
|
||||
* int
|
||||
*/
|
||||
|
||||
guint julian : 1; /* julian is valid */
|
||||
guint dmy : 1; /* dmy is valid */
|
||||
|
||||
/* DMY representation */
|
||||
guint day : 6;
|
||||
guint month : 4;
|
||||
guint year : 16;
|
||||
};
|
||||
|
||||
/* g_date_new() returns an invalid date, you then have to _set() stuff
|
||||
* to get a usable object. You can also allocate a GDate statically,
|
||||
* then call g_date_clear() to initialize.
|
||||
*/
|
||||
GDate* g_date_new (void);
|
||||
GDate* g_date_new_dmy (GDateDay day,
|
||||
GDateMonth month,
|
||||
GDateYear year);
|
||||
GDate* g_date_new_julian (guint32 julian_day);
|
||||
void g_date_free (GDate *date);
|
||||
|
||||
/* check g_date_valid() after doing an operation that might fail, like
|
||||
* _parse. Almost all g_date operations are undefined on invalid
|
||||
* dates (the exceptions are the mutators, since you need those to
|
||||
* return to validity).
|
||||
*/
|
||||
gboolean g_date_valid (const GDate *date);
|
||||
gboolean g_date_valid_day (GDateDay day) G_GNUC_CONST;
|
||||
gboolean g_date_valid_month (GDateMonth month) G_GNUC_CONST;
|
||||
gboolean g_date_valid_year (GDateYear year) G_GNUC_CONST;
|
||||
gboolean g_date_valid_weekday (GDateWeekday weekday) G_GNUC_CONST;
|
||||
gboolean g_date_valid_julian (guint32 julian_date) G_GNUC_CONST;
|
||||
gboolean g_date_valid_dmy (GDateDay day,
|
||||
GDateMonth month,
|
||||
GDateYear year) G_GNUC_CONST;
|
||||
|
||||
GDateWeekday g_date_get_weekday (const GDate *date);
|
||||
GDateMonth g_date_get_month (const GDate *date);
|
||||
GDateYear g_date_get_year (const GDate *date);
|
||||
GDateDay g_date_get_day (const GDate *date);
|
||||
guint32 g_date_get_julian (const GDate *date);
|
||||
guint g_date_get_day_of_year (const GDate *date);
|
||||
/* First monday/sunday is the start of week 1; if we haven't reached
|
||||
* that day, return 0. These are not ISO weeks of the year; that
|
||||
* routine needs to be added.
|
||||
* these functions return the number of weeks, starting on the
|
||||
* corrsponding day
|
||||
*/
|
||||
guint g_date_get_monday_week_of_year (const GDate *date);
|
||||
guint g_date_get_sunday_week_of_year (const GDate *date);
|
||||
guint g_date_get_iso8601_week_of_year (const GDate *date);
|
||||
|
||||
/* If you create a static date struct you need to clear it to get it
|
||||
* in a sane state before use. You can clear a whole array at
|
||||
* once with the ndates argument.
|
||||
*/
|
||||
void g_date_clear (GDate *date,
|
||||
guint n_dates);
|
||||
|
||||
/* The parse routine is meant for dates typed in by a user, so it
|
||||
* permits many formats but tries to catch common typos. If your data
|
||||
* needs to be strictly validated, it is not an appropriate function.
|
||||
*/
|
||||
void g_date_set_parse (GDate *date,
|
||||
const gchar *str);
|
||||
void g_date_set_time_t (GDate *date,
|
||||
time_t timet);
|
||||
void g_date_set_time_val (GDate *date,
|
||||
GTimeVal *timeval);
|
||||
#ifndef G_DISABLE_DEPRECATED
|
||||
GLIB_DEPRECATED_FOR(g_date_set_time_t)
|
||||
void g_date_set_time (GDate *date,
|
||||
GTime time_);
|
||||
#endif
|
||||
void g_date_set_month (GDate *date,
|
||||
GDateMonth month);
|
||||
void g_date_set_day (GDate *date,
|
||||
GDateDay day);
|
||||
void g_date_set_year (GDate *date,
|
||||
GDateYear year);
|
||||
void g_date_set_dmy (GDate *date,
|
||||
GDateDay day,
|
||||
GDateMonth month,
|
||||
GDateYear y);
|
||||
void g_date_set_julian (GDate *date,
|
||||
guint32 julian_date);
|
||||
gboolean g_date_is_first_of_month (const GDate *date);
|
||||
gboolean g_date_is_last_of_month (const GDate *date);
|
||||
|
||||
/* To go forward by some number of weeks just go forward weeks*7 days */
|
||||
void g_date_add_days (GDate *date,
|
||||
guint n_days);
|
||||
void g_date_subtract_days (GDate *date,
|
||||
guint n_days);
|
||||
|
||||
/* If you add/sub months while day > 28, the day might change */
|
||||
void g_date_add_months (GDate *date,
|
||||
guint n_months);
|
||||
void g_date_subtract_months (GDate *date,
|
||||
guint n_months);
|
||||
|
||||
/* If it's feb 29, changing years can move you to the 28th */
|
||||
void g_date_add_years (GDate *date,
|
||||
guint n_years);
|
||||
void g_date_subtract_years (GDate *date,
|
||||
guint n_years);
|
||||
gboolean g_date_is_leap_year (GDateYear year) G_GNUC_CONST;
|
||||
guint8 g_date_get_days_in_month (GDateMonth month,
|
||||
GDateYear year) G_GNUC_CONST;
|
||||
guint8 g_date_get_monday_weeks_in_year (GDateYear year) G_GNUC_CONST;
|
||||
guint8 g_date_get_sunday_weeks_in_year (GDateYear year) G_GNUC_CONST;
|
||||
|
||||
/* Returns the number of days between the two dates. If date2 comes
|
||||
before date1, a negative value is return. */
|
||||
gint g_date_days_between (const GDate *date1,
|
||||
const GDate *date2);
|
||||
|
||||
/* qsort-friendly (with a cast...) */
|
||||
gint g_date_compare (const GDate *lhs,
|
||||
const GDate *rhs);
|
||||
void g_date_to_struct_tm (const GDate *date,
|
||||
struct tm *tm);
|
||||
|
||||
void g_date_clamp (GDate *date,
|
||||
const GDate *min_date,
|
||||
const GDate *max_date);
|
||||
|
||||
/* Swap date1 and date2's values if date1 > date2. */
|
||||
void g_date_order (GDate *date1, GDate *date2);
|
||||
|
||||
/* Just like strftime() except you can only use date-related formats.
|
||||
* Using a time format is undefined.
|
||||
*/
|
||||
gsize g_date_strftime (gchar *s,
|
||||
gsize slen,
|
||||
const gchar *format,
|
||||
const GDate *date);
|
||||
|
||||
#ifndef G_DISABLE_DEPRECATED
|
||||
|
||||
#define g_date_weekday g_date_get_weekday
|
||||
#define g_date_month g_date_get_month
|
||||
#define g_date_year g_date_get_year
|
||||
#define g_date_day g_date_get_day
|
||||
#define g_date_julian g_date_get_julian
|
||||
#define g_date_day_of_year g_date_get_day_of_year
|
||||
#define g_date_monday_week_of_year g_date_get_monday_week_of_year
|
||||
#define g_date_sunday_week_of_year g_date_get_sunday_week_of_year
|
||||
#define g_date_days_in_month g_date_get_days_in_month
|
||||
#define g_date_monday_weeks_in_year g_date_get_monday_weeks_in_year
|
||||
#define g_date_sunday_weeks_in_year g_date_get_sunday_weeks_in_year
|
||||
|
||||
#endif /* G_DISABLE_DEPRECATED */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_DATE_H__ */
|
||||
2754
glib/glib/gdatetime.c
Normal file
2754
glib/glib/gdatetime.c
Normal file
File diff suppressed because it is too large
Load diff
217
glib/glib/gdatetime.h
Normal file
217
glib/glib/gdatetime.h
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2010 Christian Hergert <chris@dronelabs.com>
|
||||
* Copyright © 2010 Codethink Limited
|
||||
*
|
||||
* 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
|
||||
* licence, or (at your option) any later version.
|
||||
*
|
||||
* This is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA.
|
||||
*
|
||||
* Authors: Christian Hergert <chris@dronelabs.com>
|
||||
* Thiago Santos <thiago.sousa.santos@collabora.co.uk>
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
* Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_DATE_TIME_H__
|
||||
#define __G_DATE_TIME_H__
|
||||
|
||||
#include <glib/gtimezone.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* G_TIME_SPAN_DAY:
|
||||
*
|
||||
* Evaluates to a time span of one day.
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
#define G_TIME_SPAN_DAY (G_GINT64_CONSTANT (86400000000))
|
||||
|
||||
/**
|
||||
* G_TIME_SPAN_HOUR:
|
||||
*
|
||||
* Evaluates to a time span of one hour.
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
#define G_TIME_SPAN_HOUR (G_GINT64_CONSTANT (3600000000))
|
||||
|
||||
/**
|
||||
* G_TIME_SPAN_MINUTE:
|
||||
*
|
||||
* Evaluates to a time span of one minute.
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
#define G_TIME_SPAN_MINUTE (G_GINT64_CONSTANT (60000000))
|
||||
|
||||
/**
|
||||
* G_TIME_SPAN_SECOND:
|
||||
*
|
||||
* Evaluates to a time span of one second.
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
#define G_TIME_SPAN_SECOND (G_GINT64_CONSTANT (1000000))
|
||||
|
||||
/**
|
||||
* G_TIME_SPAN_MILLISECOND:
|
||||
*
|
||||
* Evaluates to a time span of one millisecond.
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
#define G_TIME_SPAN_MILLISECOND (G_GINT64_CONSTANT (1000))
|
||||
|
||||
/**
|
||||
* GTimeSpan:
|
||||
*
|
||||
* A value representing an interval of time, in microseconds.
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
typedef gint64 GTimeSpan;
|
||||
|
||||
/**
|
||||
* GDateTime:
|
||||
*
|
||||
* <structname>GDateTime</structname> is an opaque structure whose members
|
||||
* cannot be accessed directly.
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
typedef struct _GDateTime GDateTime;
|
||||
|
||||
void g_date_time_unref (GDateTime *datetime);
|
||||
GDateTime * g_date_time_ref (GDateTime *datetime);
|
||||
|
||||
GDateTime * g_date_time_new_now (GTimeZone *tz);
|
||||
GDateTime * g_date_time_new_now_local (void);
|
||||
GDateTime * g_date_time_new_now_utc (void);
|
||||
|
||||
GDateTime * g_date_time_new_from_unix_local (gint64 t);
|
||||
GDateTime * g_date_time_new_from_unix_utc (gint64 t);
|
||||
|
||||
GDateTime * g_date_time_new_from_timeval_local (const GTimeVal *tv);
|
||||
GDateTime * g_date_time_new_from_timeval_utc (const GTimeVal *tv);
|
||||
|
||||
GDateTime * g_date_time_new (GTimeZone *tz,
|
||||
gint year,
|
||||
gint month,
|
||||
gint day,
|
||||
gint hour,
|
||||
gint minute,
|
||||
gdouble seconds);
|
||||
GDateTime * g_date_time_new_local (gint year,
|
||||
gint month,
|
||||
gint day,
|
||||
gint hour,
|
||||
gint minute,
|
||||
gdouble seconds);
|
||||
GDateTime * g_date_time_new_utc (gint year,
|
||||
gint month,
|
||||
gint day,
|
||||
gint hour,
|
||||
gint minute,
|
||||
gdouble seconds);
|
||||
|
||||
G_GNUC_WARN_UNUSED_RESULT
|
||||
GDateTime * g_date_time_add (GDateTime *datetime,
|
||||
GTimeSpan timespan);
|
||||
|
||||
G_GNUC_WARN_UNUSED_RESULT
|
||||
GDateTime * g_date_time_add_years (GDateTime *datetime,
|
||||
gint years);
|
||||
G_GNUC_WARN_UNUSED_RESULT
|
||||
GDateTime * g_date_time_add_months (GDateTime *datetime,
|
||||
gint months);
|
||||
G_GNUC_WARN_UNUSED_RESULT
|
||||
GDateTime * g_date_time_add_weeks (GDateTime *datetime,
|
||||
gint weeks);
|
||||
G_GNUC_WARN_UNUSED_RESULT
|
||||
GDateTime * g_date_time_add_days (GDateTime *datetime,
|
||||
gint days);
|
||||
|
||||
G_GNUC_WARN_UNUSED_RESULT
|
||||
GDateTime * g_date_time_add_hours (GDateTime *datetime,
|
||||
gint hours);
|
||||
G_GNUC_WARN_UNUSED_RESULT
|
||||
GDateTime * g_date_time_add_minutes (GDateTime *datetime,
|
||||
gint minutes);
|
||||
G_GNUC_WARN_UNUSED_RESULT
|
||||
GDateTime * g_date_time_add_seconds (GDateTime *datetime,
|
||||
gdouble seconds);
|
||||
|
||||
G_GNUC_WARN_UNUSED_RESULT
|
||||
GDateTime * g_date_time_add_full (GDateTime *datetime,
|
||||
gint years,
|
||||
gint months,
|
||||
gint days,
|
||||
gint hours,
|
||||
gint minutes,
|
||||
gdouble seconds);
|
||||
|
||||
gint g_date_time_compare (gconstpointer dt1,
|
||||
gconstpointer dt2);
|
||||
GTimeSpan g_date_time_difference (GDateTime *end,
|
||||
GDateTime *begin);
|
||||
guint g_date_time_hash (gconstpointer datetime);
|
||||
gboolean g_date_time_equal (gconstpointer dt1,
|
||||
gconstpointer dt2);
|
||||
|
||||
void g_date_time_get_ymd (GDateTime *datetime,
|
||||
gint *year,
|
||||
gint *month,
|
||||
gint *day);
|
||||
|
||||
gint g_date_time_get_year (GDateTime *datetime);
|
||||
gint g_date_time_get_month (GDateTime *datetime);
|
||||
gint g_date_time_get_day_of_month (GDateTime *datetime);
|
||||
|
||||
gint g_date_time_get_week_numbering_year (GDateTime *datetime);
|
||||
gint g_date_time_get_week_of_year (GDateTime *datetime);
|
||||
gint g_date_time_get_day_of_week (GDateTime *datetime);
|
||||
|
||||
gint g_date_time_get_day_of_year (GDateTime *datetime);
|
||||
|
||||
gint g_date_time_get_hour (GDateTime *datetime);
|
||||
gint g_date_time_get_minute (GDateTime *datetime);
|
||||
gint g_date_time_get_second (GDateTime *datetime);
|
||||
gint g_date_time_get_microsecond (GDateTime *datetime);
|
||||
gdouble g_date_time_get_seconds (GDateTime *datetime);
|
||||
|
||||
gint64 g_date_time_to_unix (GDateTime *datetime);
|
||||
gboolean g_date_time_to_timeval (GDateTime *datetime,
|
||||
GTimeVal *tv);
|
||||
|
||||
GTimeSpan g_date_time_get_utc_offset (GDateTime *datetime);
|
||||
const gchar * g_date_time_get_timezone_abbreviation (GDateTime *datetime);
|
||||
gboolean g_date_time_is_daylight_savings (GDateTime *datetime);
|
||||
|
||||
GDateTime * g_date_time_to_timezone (GDateTime *datetime,
|
||||
GTimeZone *tz);
|
||||
GDateTime * g_date_time_to_local (GDateTime *datetime);
|
||||
GDateTime * g_date_time_to_utc (GDateTime *datetime);
|
||||
|
||||
gchar * g_date_time_format (GDateTime *datetime,
|
||||
const gchar *format) G_GNUC_MALLOC;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_DATE_TIME_H__ */
|
||||
320
glib/glib/gdir.c
Normal file
320
glib/glib/gdir.c
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* gdir.c: Simplified wrapper around the DIRENT functions.
|
||||
*
|
||||
* Copyright 2001 Hans Breuer
|
||||
* Copyright 2004 Tor Lillqvist
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef HAVE_DIRENT_H
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#include "gdir.h"
|
||||
|
||||
#include "gconvert.h"
|
||||
#include "gfileutils.h"
|
||||
#include "gstrfuncs.h"
|
||||
#include "gtestutils.h"
|
||||
#include "glibintl.h"
|
||||
|
||||
|
||||
#if defined (_MSC_VER) && !defined (HAVE_DIRENT_H)
|
||||
#include "../build/win32/dirent/dirent.h"
|
||||
#include "../build/win32/dirent/wdirent.c"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* GDir:
|
||||
*
|
||||
* An opaque structure representing an opened directory.
|
||||
*/
|
||||
|
||||
struct _GDir
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
_WDIR *wdirp;
|
||||
#else
|
||||
DIR *dirp;
|
||||
#endif
|
||||
#ifdef G_OS_WIN32
|
||||
gchar utf8_buf[FILENAME_MAX*4];
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* g_dir_open:
|
||||
* @path: the path to the directory you are interested in. On Unix
|
||||
* in the on-disk encoding. On Windows in UTF-8
|
||||
* @flags: Currently must be set to 0. Reserved for future use.
|
||||
* @error: return location for a #GError, or %NULL.
|
||||
* If non-%NULL, an error will be set if and only if
|
||||
* g_dir_open() fails.
|
||||
*
|
||||
* Opens a directory for reading. The names of the files in the
|
||||
* directory can then be retrieved using g_dir_read_name(). Note
|
||||
* that the ordering is not defined.
|
||||
*
|
||||
* Return value: a newly allocated #GDir on success, %NULL on failure.
|
||||
* If non-%NULL, you must free the result with g_dir_close()
|
||||
* when you are finished with it.
|
||||
**/
|
||||
GDir *
|
||||
g_dir_open (const gchar *path,
|
||||
guint flags,
|
||||
GError **error)
|
||||
{
|
||||
GDir *dir;
|
||||
int errsv;
|
||||
#ifdef G_OS_WIN32
|
||||
wchar_t *wpath;
|
||||
#else
|
||||
gchar *utf8_path;
|
||||
#endif
|
||||
|
||||
g_return_val_if_fail (path != NULL, NULL);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
wpath = g_utf8_to_utf16 (path, -1, NULL, NULL, error);
|
||||
|
||||
if (wpath == NULL)
|
||||
return NULL;
|
||||
|
||||
dir = g_new (GDir, 1);
|
||||
|
||||
dir->wdirp = _wopendir (wpath);
|
||||
g_free (wpath);
|
||||
|
||||
if (dir->wdirp)
|
||||
return dir;
|
||||
|
||||
/* error case */
|
||||
errsv = errno;
|
||||
|
||||
g_set_error (error,
|
||||
G_FILE_ERROR,
|
||||
g_file_error_from_errno (errsv),
|
||||
_("Error opening directory '%s': %s"),
|
||||
path, g_strerror (errsv));
|
||||
|
||||
g_free (dir);
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
dir = g_new (GDir, 1);
|
||||
|
||||
dir->dirp = opendir (path);
|
||||
|
||||
if (dir->dirp)
|
||||
return dir;
|
||||
|
||||
/* error case */
|
||||
errsv = errno;
|
||||
|
||||
utf8_path = g_filename_to_utf8 (path, -1,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
g_set_error (error,
|
||||
G_FILE_ERROR,
|
||||
g_file_error_from_errno (errsv),
|
||||
_("Error opening directory '%s': %s"),
|
||||
utf8_path, g_strerror (errsv));
|
||||
|
||||
g_free (utf8_path);
|
||||
g_free (dir);
|
||||
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (G_OS_WIN32) && !defined (_WIN64)
|
||||
|
||||
/* The above function actually is called g_dir_open_utf8, and it's
|
||||
* that what applications compiled with this GLib version will
|
||||
* use.
|
||||
*/
|
||||
|
||||
#undef g_dir_open
|
||||
|
||||
/* Binary compatibility version. Not for newly compiled code. */
|
||||
|
||||
GDir *
|
||||
g_dir_open (const gchar *path,
|
||||
guint flags,
|
||||
GError **error)
|
||||
{
|
||||
gchar *utf8_path = g_locale_to_utf8 (path, -1, NULL, NULL, error);
|
||||
GDir *retval;
|
||||
|
||||
if (utf8_path == NULL)
|
||||
return NULL;
|
||||
|
||||
retval = g_dir_open_utf8 (utf8_path, flags, error);
|
||||
|
||||
g_free (utf8_path);
|
||||
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* g_dir_read_name:
|
||||
* @dir: a #GDir* created by g_dir_open()
|
||||
*
|
||||
* Retrieves the name of another entry in the directory, or %NULL.
|
||||
* The order of entries returned from this function is not defined,
|
||||
* and may vary by file system or other operating-system dependent
|
||||
* factors.
|
||||
*
|
||||
* On Unix, the '.' and '..' entries are omitted, and the returned
|
||||
* name is in the on-disk encoding.
|
||||
*
|
||||
* On Windows, as is true of all GLib functions which operate on
|
||||
* filenames, the returned name is in UTF-8.
|
||||
*
|
||||
* Return value: The entry's name or %NULL if there are no
|
||||
* more entries. The return value is owned by GLib and
|
||||
* must not be modified or freed.
|
||||
**/
|
||||
const gchar *
|
||||
g_dir_read_name (GDir *dir)
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
gchar *utf8_name;
|
||||
struct _wdirent *wentry;
|
||||
#else
|
||||
struct dirent *entry;
|
||||
#endif
|
||||
|
||||
g_return_val_if_fail (dir != NULL, NULL);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
while (1)
|
||||
{
|
||||
wentry = _wreaddir (dir->wdirp);
|
||||
while (wentry
|
||||
&& (0 == wcscmp (wentry->d_name, L".") ||
|
||||
0 == wcscmp (wentry->d_name, L"..")))
|
||||
wentry = _wreaddir (dir->wdirp);
|
||||
|
||||
if (wentry == NULL)
|
||||
return NULL;
|
||||
|
||||
utf8_name = g_utf16_to_utf8 (wentry->d_name, -1, NULL, NULL, NULL);
|
||||
|
||||
if (utf8_name == NULL)
|
||||
continue; /* Huh, impossible? Skip it anyway */
|
||||
|
||||
strcpy (dir->utf8_buf, utf8_name);
|
||||
g_free (utf8_name);
|
||||
|
||||
return dir->utf8_buf;
|
||||
}
|
||||
#else
|
||||
entry = readdir (dir->dirp);
|
||||
while (entry
|
||||
&& (0 == strcmp (entry->d_name, ".") ||
|
||||
0 == strcmp (entry->d_name, "..")))
|
||||
entry = readdir (dir->dirp);
|
||||
|
||||
if (entry)
|
||||
return entry->d_name;
|
||||
else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (G_OS_WIN32) && !defined (_WIN64)
|
||||
|
||||
/* Ditto for g_dir_read_name */
|
||||
|
||||
#undef g_dir_read_name
|
||||
|
||||
/* Binary compatibility version. Not for newly compiled code. */
|
||||
|
||||
const gchar *
|
||||
g_dir_read_name (GDir *dir)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
const gchar *utf8_name = g_dir_read_name_utf8 (dir);
|
||||
gchar *retval;
|
||||
|
||||
if (utf8_name == NULL)
|
||||
return NULL;
|
||||
|
||||
retval = g_locale_from_utf8 (utf8_name, -1, NULL, NULL, NULL);
|
||||
|
||||
if (retval != NULL)
|
||||
{
|
||||
strcpy (dir->utf8_buf, retval);
|
||||
g_free (retval);
|
||||
|
||||
return dir->utf8_buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* g_dir_rewind:
|
||||
* @dir: a #GDir* created by g_dir_open()
|
||||
*
|
||||
* Resets the given directory. The next call to g_dir_read_name()
|
||||
* will return the first entry again.
|
||||
**/
|
||||
void
|
||||
g_dir_rewind (GDir *dir)
|
||||
{
|
||||
g_return_if_fail (dir != NULL);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
_wrewinddir (dir->wdirp);
|
||||
#else
|
||||
rewinddir (dir->dirp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* g_dir_close:
|
||||
* @dir: a #GDir* created by g_dir_open()
|
||||
*
|
||||
* Closes the directory and deallocates all related resources.
|
||||
**/
|
||||
void
|
||||
g_dir_close (GDir *dir)
|
||||
{
|
||||
g_return_if_fail (dir != NULL);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
_wclosedir (dir->wdirp);
|
||||
#else
|
||||
closedir (dir->dirp);
|
||||
#endif
|
||||
g_free (dir);
|
||||
}
|
||||
54
glib/glib/gdir.h
Normal file
54
glib/glib/gdir.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* gdir.c: Simplified wrapper around the DIRENT functions.
|
||||
*
|
||||
* Copyright 2001 Hans Breuer
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_DIR_H__
|
||||
#define __G_DIR_H__
|
||||
|
||||
#include <glib/gerror.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GDir GDir;
|
||||
|
||||
#ifndef __GTK_DOC_IGNORE__
|
||||
#ifdef G_OS_WIN32
|
||||
/* For DLL ABI stability, keep old names for old (non-UTF-8) functionality. */
|
||||
#define g_dir_open g_dir_open_utf8
|
||||
#define g_dir_read_name g_dir_read_name_utf8
|
||||
#endif
|
||||
#endif
|
||||
|
||||
GDir * g_dir_open (const gchar *path,
|
||||
guint flags,
|
||||
GError **error);
|
||||
const gchar * g_dir_read_name (GDir *dir);
|
||||
void g_dir_rewind (GDir *dir);
|
||||
void g_dir_close (GDir *dir);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_DIR_H__ */
|
||||
58
glib/glib/gen-iswide-table.py
Executable file
58
glib/glib/gen-iswide-table.py
Executable file
|
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
|
||||
W = {}
|
||||
W['A'] = []
|
||||
W['W'] = []
|
||||
W['F'] = W['W']
|
||||
|
||||
for line in sys.stdin:
|
||||
i = line.find ('#')
|
||||
if i >= 0:
|
||||
line = line[:i]
|
||||
line = line.strip ()
|
||||
if not len (line):
|
||||
continue
|
||||
|
||||
fields = [x.strip () for x in line.split (';')]
|
||||
chars = fields[0]
|
||||
width = fields[1]
|
||||
|
||||
if width not in ['A', 'W', 'F']:
|
||||
continue
|
||||
|
||||
if chars.find ('..') > 0:
|
||||
(start,end) = chars.split ('..')
|
||||
else:
|
||||
start = chars
|
||||
end = chars
|
||||
start, end = int(start,16), int(end,16)
|
||||
|
||||
for i in range (start, end+1):
|
||||
W[width].append (i)
|
||||
|
||||
|
||||
def write_intervals (S):
|
||||
S.sort ()
|
||||
start = S[0];
|
||||
end = start - 1
|
||||
for c in S:
|
||||
if c == end+1:
|
||||
end += 1
|
||||
continue
|
||||
else:
|
||||
print "{0x%04X, 0x%04X}, " % (start, end)
|
||||
start = c
|
||||
end = start
|
||||
print "{0x%04X, 0x%04X} " % (start, end)
|
||||
|
||||
|
||||
|
||||
print "table for g_unichar_iswide():"
|
||||
print
|
||||
write_intervals (W['W'])
|
||||
print
|
||||
print "table for g_unichar_iswide_cjk():"
|
||||
print
|
||||
write_intervals (W['A'])
|
||||
119
glib/glib/gen-script-table.pl
Executable file
119
glib/glib/gen-script-table.pl
Executable file
|
|
@ -0,0 +1,119 @@
|
|||
#!/usr/bin/perl -w
|
||||
#
|
||||
# Script to convert http://www.unicode.org/Public/UNIDATA/Scripts.txt
|
||||
# into a machine-readable table.
|
||||
#
|
||||
######################################################################
|
||||
|
||||
if (@ARGV != 1) {
|
||||
die "Usage: gen-script-table.pl Scripts.txt > gscripttable.h\n";
|
||||
}
|
||||
|
||||
open IN, $ARGV[0] || die "Cannot open $ARGV[0]: $!\n";
|
||||
|
||||
my @ranges;
|
||||
my $file;
|
||||
my $easy_range;
|
||||
my $i;
|
||||
my $start;
|
||||
my $end;
|
||||
my $script;
|
||||
|
||||
|
||||
while (<IN>) {
|
||||
if (/^\#\s+(Scripts-.*.txt)/) {
|
||||
$file = $1;
|
||||
}
|
||||
|
||||
s/#.*//;
|
||||
next if /^\s*$/;
|
||||
if (!/^([0-9A-F]+)(?:\.\.([0-9A-F]+))?\s*;\s*([A-Za-z_]+)\s*$/) {
|
||||
die "Cannot parse line: '$_'\n";
|
||||
}
|
||||
|
||||
if (defined $2) {
|
||||
push @ranges, [ hex $1, hex $2, uc $3 ];
|
||||
} else {
|
||||
push @ranges, [ hex $1, hex $1, uc $3 ];
|
||||
}
|
||||
}
|
||||
|
||||
@ranges = sort { $a->[0] <=> $b->[0] } @ranges;
|
||||
$date = gmtime;
|
||||
|
||||
print <<"EOT";
|
||||
/* gscripttable.h: Generated by gen-script-table.pl
|
||||
*
|
||||
* Date: $date
|
||||
* Source: $file
|
||||
*
|
||||
* Do not edit.
|
||||
*/
|
||||
|
||||
EOT
|
||||
|
||||
$easy_range = 0x2000;
|
||||
|
||||
print <<"EOT";
|
||||
#define G_EASY_SCRIPTS_RANGE $easy_range
|
||||
|
||||
static const guchar g_script_easy_table[$easy_range] = {
|
||||
EOT
|
||||
|
||||
$i = 0;
|
||||
$end = -1;
|
||||
|
||||
for (my $c = 0; $c < $easy_range; $c++) {
|
||||
|
||||
if ($c % 3 == 0) {
|
||||
printf "\n ";
|
||||
}
|
||||
|
||||
if ($c > $end) {
|
||||
$start = $ranges[$i]->[0];
|
||||
$end = $ranges[$i]->[1];
|
||||
$script = $ranges[$i]->[2];
|
||||
$i++;
|
||||
}
|
||||
|
||||
if ($c < $start) {
|
||||
printf " G_UNICODE_SCRIPT_UNKNOWN,";
|
||||
} else {
|
||||
printf " G_UNICODE_SCRIPT_%s,", $script;
|
||||
}
|
||||
}
|
||||
|
||||
if ($end >= $easy_range) {
|
||||
$i--;
|
||||
$ranges[$i]->[0] = $easy_range;
|
||||
}
|
||||
|
||||
|
||||
print <<"EOT";
|
||||
|
||||
};
|
||||
|
||||
static const struct {
|
||||
gunichar start;
|
||||
guint16 chars;
|
||||
guint16 script;
|
||||
} g_script_table[] = {
|
||||
EOT
|
||||
|
||||
for (; $i <= $#ranges; $i++) {
|
||||
$start = $ranges[$i]->[0];
|
||||
$end = $ranges[$i]->[1];
|
||||
$script = $ranges[$i]->[2];
|
||||
|
||||
while ($i <= $#ranges - 1 &&
|
||||
$ranges[$i + 1]->[0] == $end + 1 &&
|
||||
$ranges[$i + 1]->[2] eq $script) {
|
||||
$i++;
|
||||
$end = $ranges[$i]->[1];
|
||||
}
|
||||
|
||||
printf " { %#06x, %5d, G_UNICODE_SCRIPT_%s },\n", $start, $end - $start + 1, $script;
|
||||
}
|
||||
|
||||
printf "};\n";
|
||||
|
||||
1339
glib/glib/gen-unicode-tables.pl
Executable file
1339
glib/glib/gen-unicode-tables.pl
Executable file
File diff suppressed because it is too large
Load diff
697
glib/glib/genviron.c
Normal file
697
glib/glib/genviron.c
Normal file
|
|
@ -0,0 +1,697 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1998 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "genviron.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_CRT_EXTERNS_H
|
||||
#include <crt_externs.h> /* for _NSGetEnviron */
|
||||
#endif
|
||||
#ifdef G_OS_WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "gmem.h"
|
||||
#include "gmessages.h"
|
||||
#include "gstrfuncs.h"
|
||||
#include "gunicode.h"
|
||||
#include "gconvert.h"
|
||||
#include "gquark.h"
|
||||
|
||||
/* Environ array functions {{{1 */
|
||||
static gint
|
||||
g_environ_find (gchar **envp,
|
||||
const gchar *variable)
|
||||
{
|
||||
gint len, i;
|
||||
|
||||
len = strlen (variable);
|
||||
|
||||
for (i = 0; envp[i]; i++)
|
||||
{
|
||||
if (strncmp (envp[i], variable, len) == 0 &&
|
||||
envp[i][len] == '=')
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_environ_getenv:
|
||||
* @envp: (array zero-terminated=1) (transfer none): an environment
|
||||
* list (eg, as returned from g_get_environ())
|
||||
* @variable: the environment variable to get, in the GLib file name
|
||||
* encoding
|
||||
*
|
||||
* Returns the value of the environment variable @variable in the
|
||||
* provided list @envp.
|
||||
*
|
||||
* The name and value are in the GLib file name encoding.
|
||||
* On UNIX, this means the actual bytes which might or might not
|
||||
* be in some consistent character set and encoding. On Windows,
|
||||
* it is in UTF-8. On Windows, in case the environment variable's
|
||||
* value contains references to other environment variables, they
|
||||
* are expanded.
|
||||
*
|
||||
* Return value: the value of the environment variable, or %NULL if
|
||||
* the environment variable is not set in @envp. The returned
|
||||
* string is owned by @envp, and will be freed if @variable is
|
||||
* set or unset again.
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
const gchar *
|
||||
g_environ_getenv (gchar **envp,
|
||||
const gchar *variable)
|
||||
{
|
||||
gint index;
|
||||
|
||||
g_return_val_if_fail (envp != NULL, NULL);
|
||||
g_return_val_if_fail (variable != NULL, NULL);
|
||||
|
||||
index = g_environ_find (envp, variable);
|
||||
if (index != -1)
|
||||
return envp[index] + strlen (variable) + 1;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_environ_setenv:
|
||||
* @envp: (array zero-terminated=1) (transfer full): an environment
|
||||
* list that can be freed using g_strfreev() (e.g., as returned from g_get_environ())
|
||||
* @variable: the environment variable to set, must not contain '='
|
||||
* @value: the value for to set the variable to
|
||||
* @overwrite: whether to change the variable if it already exists
|
||||
*
|
||||
* Sets the environment variable @variable in the provided list
|
||||
* @envp to @value.
|
||||
*
|
||||
* Both the variable's name and value should be in the GLib
|
||||
* file name encoding. On UNIX, this means that they can be
|
||||
* arbitrary byte strings. On Windows, they should be in UTF-8.
|
||||
*
|
||||
* Return value: (array zero-terminated=1) (transfer full): the
|
||||
* updated environment list. Free it using g_strfreev().
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
gchar **
|
||||
g_environ_setenv (gchar **envp,
|
||||
const gchar *variable,
|
||||
const gchar *value,
|
||||
gboolean overwrite)
|
||||
{
|
||||
gint index;
|
||||
|
||||
g_return_val_if_fail (envp != NULL, NULL);
|
||||
g_return_val_if_fail (variable != NULL, NULL);
|
||||
g_return_val_if_fail (strchr (variable, '=') == NULL, NULL);
|
||||
|
||||
index = g_environ_find (envp, variable);
|
||||
if (index != -1)
|
||||
{
|
||||
if (overwrite)
|
||||
{
|
||||
g_free (envp[index]);
|
||||
envp[index] = g_strdup_printf ("%s=%s", variable, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gint length;
|
||||
|
||||
length = g_strv_length (envp);
|
||||
envp = g_renew (gchar *, envp, length + 2);
|
||||
envp[length] = g_strdup_printf ("%s=%s", variable, value);
|
||||
envp[length + 1] = NULL;
|
||||
}
|
||||
|
||||
return envp;
|
||||
}
|
||||
|
||||
static gchar **
|
||||
g_environ_unsetenv_internal (gchar **envp,
|
||||
const gchar *variable,
|
||||
gboolean free_value)
|
||||
{
|
||||
gint len;
|
||||
gchar **e, **f;
|
||||
|
||||
len = strlen (variable);
|
||||
|
||||
/* Note that we remove *all* environment entries for
|
||||
* the variable name, not just the first.
|
||||
*/
|
||||
e = f = envp;
|
||||
while (*e != NULL)
|
||||
{
|
||||
if (strncmp (*e, variable, len) != 0 || (*e)[len] != '=')
|
||||
{
|
||||
*f = *e;
|
||||
f++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (free_value)
|
||||
g_free (*e);
|
||||
}
|
||||
|
||||
e++;
|
||||
}
|
||||
*f = NULL;
|
||||
|
||||
return envp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* g_environ_unsetenv:
|
||||
* @envp: (array zero-terminated=1) (transfer full): an environment
|
||||
* list that can be freed using g_strfreev() (e.g., as returned from g_get_environ())
|
||||
* @variable: the environment variable to remove, must not contain '='
|
||||
*
|
||||
* Removes the environment variable @variable from the provided
|
||||
* environment @envp.
|
||||
*
|
||||
* Return value: (array zero-terminated=1) (transfer full): the
|
||||
* updated environment list. Free it using g_strfreev().
|
||||
*
|
||||
* Since: 2.32
|
||||
*/
|
||||
gchar **
|
||||
g_environ_unsetenv (gchar **envp,
|
||||
const gchar *variable)
|
||||
{
|
||||
g_return_val_if_fail (envp != NULL, NULL);
|
||||
g_return_val_if_fail (variable != NULL, NULL);
|
||||
g_return_val_if_fail (strchr (variable, '=') == NULL, NULL);
|
||||
|
||||
return g_environ_unsetenv_internal (envp, variable, TRUE);
|
||||
}
|
||||
|
||||
/* UNIX implemention {{{1 */
|
||||
#ifndef G_OS_WIN32
|
||||
|
||||
/**
|
||||
* g_getenv:
|
||||
* @variable: the environment variable to get, in the GLib file name
|
||||
* encoding
|
||||
*
|
||||
* Returns the value of an environment variable.
|
||||
*
|
||||
* The name and value are in the GLib file name encoding. On UNIX,
|
||||
* this means the actual bytes which might or might not be in some
|
||||
* consistent character set and encoding. On Windows, it is in UTF-8.
|
||||
* On Windows, in case the environment variable's value contains
|
||||
* references to other environment variables, they are expanded.
|
||||
*
|
||||
* Return value: the value of the environment variable, or %NULL if
|
||||
* the environment variable is not found. The returned string
|
||||
* may be overwritten by the next call to g_getenv(), g_setenv()
|
||||
* or g_unsetenv().
|
||||
*/
|
||||
const gchar *
|
||||
g_getenv (const gchar *variable)
|
||||
{
|
||||
g_return_val_if_fail (variable != NULL, NULL);
|
||||
|
||||
return getenv (variable);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_setenv:
|
||||
* @variable: the environment variable to set, must not contain '='.
|
||||
* @value: the value for to set the variable to.
|
||||
* @overwrite: whether to change the variable if it already exists.
|
||||
*
|
||||
* Sets an environment variable. Both the variable's name and value
|
||||
* should be in the GLib file name encoding. On UNIX, this means that
|
||||
* they can be arbitrary byte strings. On Windows, they should be in
|
||||
* UTF-8.
|
||||
*
|
||||
* Note that on some systems, when variables are overwritten, the memory
|
||||
* used for the previous variables and its value isn't reclaimed.
|
||||
*
|
||||
* <warning><para>
|
||||
* Environment variable handling in UNIX is not thread-safe, and your
|
||||
* program may crash if one thread calls g_setenv() while another
|
||||
* thread is calling getenv(). (And note that many functions, such as
|
||||
* gettext(), call getenv() internally.) This function is only safe to
|
||||
* use at the very start of your program, before creating any other
|
||||
* threads (or creating objects that create worker threads of their
|
||||
* own).
|
||||
* </para><para>
|
||||
* If you need to set up the environment for a child process, you can
|
||||
* use g_get_environ() to get an environment array, modify that with
|
||||
* g_environ_setenv() and g_environ_unsetenv(), and then pass that
|
||||
* array directly to execvpe(), g_spawn_async(), or the like.
|
||||
* </para></warning>
|
||||
*
|
||||
* Returns: %FALSE if the environment variable couldn't be set.
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
gboolean
|
||||
g_setenv (const gchar *variable,
|
||||
const gchar *value,
|
||||
gboolean overwrite)
|
||||
{
|
||||
gint result;
|
||||
#ifndef HAVE_SETENV
|
||||
gchar *string;
|
||||
#endif
|
||||
|
||||
g_return_val_if_fail (variable != NULL, FALSE);
|
||||
g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
|
||||
|
||||
#ifdef HAVE_SETENV
|
||||
result = setenv (variable, value, overwrite);
|
||||
#else
|
||||
if (!overwrite && getenv (variable) != NULL)
|
||||
return TRUE;
|
||||
|
||||
/* This results in a leak when you overwrite existing
|
||||
* settings. It would be fairly easy to fix this by keeping
|
||||
* our own parallel array or hash table.
|
||||
*/
|
||||
string = g_strconcat (variable, "=", value, NULL);
|
||||
result = putenv (string);
|
||||
#endif
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE__NSGETENVIRON
|
||||
#define environ (*_NSGetEnviron())
|
||||
#else
|
||||
/* According to the Single Unix Specification, environ is not
|
||||
* in any system header, although unistd.h often declares it.
|
||||
*/
|
||||
extern char **environ;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* g_unsetenv:
|
||||
* @variable: the environment variable to remove, must not contain '='
|
||||
*
|
||||
* Removes an environment variable from the environment.
|
||||
*
|
||||
* Note that on some systems, when variables are overwritten, the
|
||||
* memory used for the previous variables and its value isn't reclaimed.
|
||||
*
|
||||
* <warning><para>
|
||||
* Environment variable handling in UNIX is not thread-safe, and your
|
||||
* program may crash if one thread calls g_unsetenv() while another
|
||||
* thread is calling getenv(). (And note that many functions, such as
|
||||
* gettext(), call getenv() internally.) This function is only safe
|
||||
* to use at the very start of your program, before creating any other
|
||||
* threads (or creating objects that create worker threads of their
|
||||
* own).
|
||||
* </para><para>
|
||||
* If you need to set up the environment for a child process, you can
|
||||
* use g_get_environ() to get an environment array, modify that with
|
||||
* g_environ_setenv() and g_environ_unsetenv(), and then pass that
|
||||
* array directly to execvpe(), g_spawn_async(), or the like.
|
||||
* </para></warning>
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
void
|
||||
g_unsetenv (const gchar *variable)
|
||||
{
|
||||
#ifdef HAVE_UNSETENV
|
||||
g_return_if_fail (variable != NULL);
|
||||
g_return_if_fail (strchr (variable, '=') == NULL);
|
||||
|
||||
unsetenv (variable);
|
||||
#else /* !HAVE_UNSETENV */
|
||||
g_return_if_fail (variable != NULL);
|
||||
g_return_if_fail (strchr (variable, '=') == NULL);
|
||||
|
||||
/* Mess directly with the environ array.
|
||||
* This seems to be the only portable way to do this.
|
||||
*/
|
||||
g_environ_unsetenv_internal (environ, variable, FALSE);
|
||||
#endif /* !HAVE_UNSETENV */
|
||||
}
|
||||
|
||||
/**
|
||||
* g_listenv:
|
||||
*
|
||||
* Gets the names of all variables set in the environment.
|
||||
*
|
||||
* Programs that want to be portable to Windows should typically use
|
||||
* this function and g_getenv() instead of using the environ array
|
||||
* from the C library directly. On Windows, the strings in the environ
|
||||
* array are in system codepage encoding, while in most of the typical
|
||||
* use cases for environment variables in GLib-using programs you want
|
||||
* the UTF-8 encoding that this function and g_getenv() provide.
|
||||
*
|
||||
* Returns: (array zero-terminated=1) (transfer full): a %NULL-terminated
|
||||
* list of strings which must be freed with g_strfreev().
|
||||
*
|
||||
* Since: 2.8
|
||||
*/
|
||||
gchar **
|
||||
g_listenv (void)
|
||||
{
|
||||
gchar **result, *eq;
|
||||
gint len, i, j;
|
||||
|
||||
len = g_strv_length (environ);
|
||||
result = g_new0 (gchar *, len + 1);
|
||||
|
||||
j = 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
eq = strchr (environ[i], '=');
|
||||
if (eq)
|
||||
result[j++] = g_strndup (environ[i], eq - environ[i]);
|
||||
}
|
||||
|
||||
result[j] = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_get_environ:
|
||||
*
|
||||
* Gets the list of environment variables for the current process.
|
||||
*
|
||||
* The list is %NULL terminated and each item in the list is of the
|
||||
* form 'NAME=VALUE'.
|
||||
*
|
||||
* This is equivalent to direct access to the 'environ' global variable,
|
||||
* except portable.
|
||||
*
|
||||
* The return value is freshly allocated and it should be freed with
|
||||
* g_strfreev() when it is no longer needed.
|
||||
*
|
||||
* Returns: (array zero-terminated=1) (transfer full): the list of
|
||||
* environment variables
|
||||
*
|
||||
* Since: 2.28
|
||||
*/
|
||||
gchar **
|
||||
g_get_environ (void)
|
||||
{
|
||||
return g_strdupv (environ);
|
||||
}
|
||||
|
||||
/* Win32 implementation {{{1 */
|
||||
#else /* G_OS_WIN32 */
|
||||
|
||||
const gchar *
|
||||
g_getenv (const gchar *variable)
|
||||
{
|
||||
GQuark quark;
|
||||
gchar *value;
|
||||
wchar_t dummy[2], *wname, *wvalue;
|
||||
int len;
|
||||
|
||||
g_return_val_if_fail (variable != NULL, NULL);
|
||||
g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), NULL);
|
||||
|
||||
/* On Windows NT, it is relatively typical that environment
|
||||
* variables contain references to other environment variables. If
|
||||
* so, use ExpandEnvironmentStrings(). (In an ideal world, such
|
||||
* environment variables would be stored in the Registry as
|
||||
* REG_EXPAND_SZ type values, and would then get automatically
|
||||
* expanded before a program sees them. But there is broken software
|
||||
* that stores environment variables as REG_SZ values even if they
|
||||
* contain references to other environment variables.)
|
||||
*/
|
||||
|
||||
wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
|
||||
|
||||
len = GetEnvironmentVariableW (wname, dummy, 2);
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
g_free (wname);
|
||||
return NULL;
|
||||
}
|
||||
else if (len == 1)
|
||||
len = 2;
|
||||
|
||||
wvalue = g_new (wchar_t, len);
|
||||
|
||||
if (GetEnvironmentVariableW (wname, wvalue, len) != len - 1)
|
||||
{
|
||||
g_free (wname);
|
||||
g_free (wvalue);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (wcschr (wvalue, L'%') != NULL)
|
||||
{
|
||||
wchar_t *tem = wvalue;
|
||||
|
||||
len = ExpandEnvironmentStringsW (wvalue, dummy, 2);
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
wvalue = g_new (wchar_t, len);
|
||||
|
||||
if (ExpandEnvironmentStringsW (tem, wvalue, len) != len)
|
||||
{
|
||||
g_free (wvalue);
|
||||
wvalue = tem;
|
||||
}
|
||||
else
|
||||
g_free (tem);
|
||||
}
|
||||
}
|
||||
|
||||
value = g_utf16_to_utf8 (wvalue, -1, NULL, NULL, NULL);
|
||||
|
||||
g_free (wname);
|
||||
g_free (wvalue);
|
||||
|
||||
quark = g_quark_from_string (value);
|
||||
g_free (value);
|
||||
|
||||
return g_quark_to_string (quark);
|
||||
}
|
||||
|
||||
gboolean
|
||||
g_setenv (const gchar *variable,
|
||||
const gchar *value,
|
||||
gboolean overwrite)
|
||||
{
|
||||
gboolean retval;
|
||||
wchar_t *wname, *wvalue, *wassignment;
|
||||
gchar *tem;
|
||||
|
||||
g_return_val_if_fail (variable != NULL, FALSE);
|
||||
g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
|
||||
g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), FALSE);
|
||||
g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
|
||||
|
||||
if (!overwrite && g_getenv (variable) != NULL)
|
||||
return TRUE;
|
||||
|
||||
/* We want to (if possible) set both the environment variable copy
|
||||
* kept by the C runtime and the one kept by the system.
|
||||
*
|
||||
* We can't use only the C runtime's putenv or _wputenv() as that
|
||||
* won't work for arbitrary Unicode strings in a "non-Unicode" app
|
||||
* (with main() and not wmain()). In a "main()" app the C runtime
|
||||
* initializes the C runtime's environment table by converting the
|
||||
* real (wide char) environment variables to system codepage, thus
|
||||
* breaking those that aren't representable in the system codepage.
|
||||
*
|
||||
* As the C runtime's putenv() will also set the system copy, we do
|
||||
* the putenv() first, then call SetEnvironmentValueW ourselves.
|
||||
*/
|
||||
|
||||
wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
|
||||
wvalue = g_utf8_to_utf16 (value, -1, NULL, NULL, NULL);
|
||||
tem = g_strconcat (variable, "=", value, NULL);
|
||||
wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL);
|
||||
|
||||
g_free (tem);
|
||||
_wputenv (wassignment);
|
||||
g_free (wassignment);
|
||||
|
||||
retval = (SetEnvironmentVariableW (wname, wvalue) != 0);
|
||||
|
||||
g_free (wname);
|
||||
g_free (wvalue);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
g_unsetenv (const gchar *variable)
|
||||
{
|
||||
wchar_t *wname, *wassignment;
|
||||
gchar *tem;
|
||||
|
||||
g_return_if_fail (variable != NULL);
|
||||
g_return_if_fail (strchr (variable, '=') == NULL);
|
||||
g_return_if_fail (g_utf8_validate (variable, -1, NULL));
|
||||
|
||||
wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
|
||||
tem = g_strconcat (variable, "=", NULL);
|
||||
wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL);
|
||||
|
||||
g_free (tem);
|
||||
_wputenv (wassignment);
|
||||
g_free (wassignment);
|
||||
|
||||
SetEnvironmentVariableW (wname, NULL);
|
||||
|
||||
g_free (wname);
|
||||
}
|
||||
|
||||
gchar **
|
||||
g_listenv (void)
|
||||
{
|
||||
gchar **result, *eq;
|
||||
gint len = 0, j;
|
||||
wchar_t *p, *q;
|
||||
|
||||
p = (wchar_t *) GetEnvironmentStringsW ();
|
||||
if (p != NULL)
|
||||
{
|
||||
q = p;
|
||||
while (*q)
|
||||
{
|
||||
q += wcslen (q) + 1;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
result = g_new0 (gchar *, len + 1);
|
||||
|
||||
j = 0;
|
||||
q = p;
|
||||
while (*q)
|
||||
{
|
||||
result[j] = g_utf16_to_utf8 (q, -1, NULL, NULL, NULL);
|
||||
if (result[j] != NULL)
|
||||
{
|
||||
eq = strchr (result[j], '=');
|
||||
if (eq && eq > result[j])
|
||||
{
|
||||
*eq = '\0';
|
||||
j++;
|
||||
}
|
||||
else
|
||||
g_free (result[j]);
|
||||
}
|
||||
q += wcslen (q) + 1;
|
||||
}
|
||||
result[j] = NULL;
|
||||
FreeEnvironmentStringsW (p);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
gchar **
|
||||
g_get_environ (void)
|
||||
{
|
||||
gunichar2 *strings;
|
||||
gchar **result;
|
||||
gint i, n;
|
||||
|
||||
strings = GetEnvironmentStringsW ();
|
||||
for (n = 0; strings[n]; n += wcslen (strings + n) + 1);
|
||||
result = g_new (char *, n + 1);
|
||||
for (i = 0; strings[i]; i += wcslen (strings + i) + 1)
|
||||
result[i] = g_utf16_to_utf8 (strings + i, -1, NULL, NULL, NULL);
|
||||
FreeEnvironmentStringsW (strings);
|
||||
result[i] = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Win32 binary compatibility versions {{{1 */
|
||||
#ifndef _WIN64
|
||||
|
||||
#undef g_getenv
|
||||
|
||||
const gchar *
|
||||
g_getenv (const gchar *variable)
|
||||
{
|
||||
gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
|
||||
const gchar *utf8_value = g_getenv_utf8 (utf8_variable);
|
||||
gchar *value;
|
||||
GQuark quark;
|
||||
|
||||
g_free (utf8_variable);
|
||||
if (!utf8_value)
|
||||
return NULL;
|
||||
value = g_locale_from_utf8 (utf8_value, -1, NULL, NULL, NULL);
|
||||
quark = g_quark_from_string (value);
|
||||
g_free (value);
|
||||
|
||||
return g_quark_to_string (quark);
|
||||
}
|
||||
|
||||
#undef g_setenv
|
||||
|
||||
gboolean
|
||||
g_setenv (const gchar *variable,
|
||||
const gchar *value,
|
||||
gboolean overwrite)
|
||||
{
|
||||
gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
|
||||
gchar *utf8_value = g_locale_to_utf8 (value, -1, NULL, NULL, NULL);
|
||||
gboolean retval = g_setenv_utf8 (utf8_variable, utf8_value, overwrite);
|
||||
|
||||
g_free (utf8_variable);
|
||||
g_free (utf8_value);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#undef g_unsetenv
|
||||
|
||||
void
|
||||
g_unsetenv (const gchar *variable)
|
||||
{
|
||||
gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
|
||||
|
||||
g_unsetenv_utf8 (utf8_variable);
|
||||
|
||||
g_free (utf8_variable);
|
||||
}
|
||||
|
||||
#endif /* _WIN64 */
|
||||
|
||||
#endif /* G_OS_WIN32 */
|
||||
|
||||
/* Epilogue {{{1 */
|
||||
/* vim: set foldmethod=marker: */
|
||||
65
glib/glib/genviron.h
Normal file
65
glib/glib/genviron.h
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_ENVIRON_H__
|
||||
#define __G_ENVIRON_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifndef __GTK_DOC_IGNORE__
|
||||
#ifdef G_OS_WIN32
|
||||
#define g_getenv g_getenv_utf8
|
||||
#define g_setenv g_setenv_utf8
|
||||
#define g_unsetenv g_unsetenv_utf8
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const gchar * g_getenv (const gchar *variable);
|
||||
gboolean g_setenv (const gchar *variable,
|
||||
const gchar *value,
|
||||
gboolean overwrite);
|
||||
void g_unsetenv (const gchar *variable);
|
||||
gchar ** g_listenv (void);
|
||||
|
||||
gchar ** g_get_environ (void);
|
||||
const gchar * g_environ_getenv (gchar **envp,
|
||||
const gchar *variable);
|
||||
gchar ** g_environ_setenv (gchar **envp,
|
||||
const gchar *variable,
|
||||
const gchar *value,
|
||||
gboolean overwrite) G_GNUC_WARN_UNUSED_RESULT;
|
||||
gchar ** g_environ_unsetenv (gchar **envp,
|
||||
const gchar *variable) G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_ENVIRON_H__ */
|
||||
727
glib/glib/gerror.c
Normal file
727
glib/glib/gerror.c
Normal file
|
|
@ -0,0 +1,727 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:error_reporting
|
||||
* @Title: Error Reporting
|
||||
* @Short_description: a system for reporting errors
|
||||
*
|
||||
* GLib provides a standard method of reporting errors from a called
|
||||
* function to the calling code. (This is the same problem solved by
|
||||
* exceptions in other languages.) It's important to understand that
|
||||
* this method is both a <emphasis>data type</emphasis> (the #GError
|
||||
* object) and a <emphasis>set of rules.</emphasis> If you use #GError
|
||||
* incorrectly, then your code will not properly interoperate with other
|
||||
* code that uses #GError, and users of your API will probably get confused.
|
||||
*
|
||||
* First and foremost: <emphasis>#GError should only be used to report
|
||||
* recoverable runtime errors, never to report programming
|
||||
* errors.</emphasis> If the programmer has screwed up, then you should
|
||||
* use g_warning(), g_return_if_fail(), g_assert(), g_error(), or some
|
||||
* similar facility. (Incidentally, remember that the g_error() function
|
||||
* should <emphasis>only</emphasis> be used for programming errors, it
|
||||
* should not be used to print any error reportable via #GError.)
|
||||
*
|
||||
* Examples of recoverable runtime errors are "file not found" or
|
||||
* "failed to parse input." Examples of programming errors are "NULL
|
||||
* passed to strcmp()" or "attempted to free the same pointer twice."
|
||||
* These two kinds of errors are fundamentally different: runtime errors
|
||||
* should be handled or reported to the user, programming errors should
|
||||
* be eliminated by fixing the bug in the program. This is why most
|
||||
* functions in GLib and GTK+ do not use the #GError facility.
|
||||
*
|
||||
* Functions that can fail take a return location for a #GError as their
|
||||
* last argument. For example:
|
||||
* |[
|
||||
* gboolean g_file_get_contents (const gchar *filename,
|
||||
* gchar **contents,
|
||||
* gsize *length,
|
||||
* GError **error);
|
||||
* ]|
|
||||
* If you pass a non-%NULL value for the <literal>error</literal>
|
||||
* argument, it should point to a location where an error can be placed.
|
||||
* For example:
|
||||
* |[
|
||||
* gchar *contents;
|
||||
* GError *err = NULL;
|
||||
* g_file_get_contents ("foo.txt", &contents, NULL, &err);
|
||||
* g_assert ((contents == NULL && err != NULL) || (contents != NULL && err == NULL));
|
||||
* if (err != NULL)
|
||||
* {
|
||||
* /* Report error to user, and free error */
|
||||
* g_assert (contents == NULL);
|
||||
* fprintf (stderr, "Unable to read file: %s\n", err->message);
|
||||
* g_error_free (err);
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* /* Use file contents */
|
||||
* g_assert (contents != NULL);
|
||||
* }
|
||||
* ]|
|
||||
* Note that <literal>err != NULL</literal> in this example is a
|
||||
* <emphasis>reliable</emphasis> indicator of whether
|
||||
* g_file_get_contents() failed. Additionally, g_file_get_contents()
|
||||
* returns a boolean which indicates whether it was successful.
|
||||
*
|
||||
* Because g_file_get_contents() returns %FALSE on failure, if you
|
||||
* are only interested in whether it failed and don't need to display
|
||||
* an error message, you can pass %NULL for the <literal>error</literal>
|
||||
* argument:
|
||||
* |[
|
||||
* if (g_file_get_contents ("foo.txt", &contents, NULL, NULL)) /* ignore errors */
|
||||
* /* no error occurred */ ;
|
||||
* else
|
||||
* /* error */ ;
|
||||
* ]|
|
||||
*
|
||||
* The #GError object contains three fields: <literal>domain</literal>
|
||||
* indicates the module the error-reporting function is located in,
|
||||
* <literal>code</literal> indicates the specific error that occurred,
|
||||
* and <literal>message</literal> is a user-readable error message with
|
||||
* as many details as possible. Several functions are provided to deal
|
||||
* with an error received from a called function: g_error_matches()
|
||||
* returns %TRUE if the error matches a given domain and code,
|
||||
* g_propagate_error() copies an error into an error location (so the
|
||||
* calling function will receive it), and g_clear_error() clears an
|
||||
* error location by freeing the error and resetting the location to
|
||||
* %NULL. To display an error to the user, simply display
|
||||
* <literal>error->message</literal>, perhaps along with additional
|
||||
* context known only to the calling function (the file being opened,
|
||||
* or whatever -- though in the g_file_get_contents() case,
|
||||
* <literal>error->message</literal> already contains a filename).
|
||||
*
|
||||
* When implementing a function that can report errors, the basic
|
||||
* tool is g_set_error(). Typically, if a fatal error occurs you
|
||||
* want to g_set_error(), then return immediately. g_set_error()
|
||||
* does nothing if the error location passed to it is %NULL.
|
||||
* Here's an example:
|
||||
* |[
|
||||
* gint
|
||||
* foo_open_file (GError **error)
|
||||
* {
|
||||
* gint fd;
|
||||
*
|
||||
* fd = open ("file.txt", O_RDONLY);
|
||||
*
|
||||
* if (fd < 0)
|
||||
* {
|
||||
* g_set_error (error,
|
||||
* FOO_ERROR, /* error domain */
|
||||
* FOO_ERROR_BLAH, /* error code */
|
||||
* "Failed to open file: %s", /* error message format string */
|
||||
* g_strerror (errno));
|
||||
* return -1;
|
||||
* }
|
||||
* else
|
||||
* return fd;
|
||||
* }
|
||||
* ]|
|
||||
*
|
||||
* Things are somewhat more complicated if you yourself call another
|
||||
* function that can report a #GError. If the sub-function indicates
|
||||
* fatal errors in some way other than reporting a #GError, such as
|
||||
* by returning %TRUE on success, you can simply do the following:
|
||||
* |[
|
||||
* gboolean
|
||||
* my_function_that_can_fail (GError **err)
|
||||
* {
|
||||
* g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
|
||||
*
|
||||
* if (!sub_function_that_can_fail (err))
|
||||
* {
|
||||
* /* assert that error was set by the sub-function */
|
||||
* g_assert (err == NULL || *err != NULL);
|
||||
* return FALSE;
|
||||
* }
|
||||
*
|
||||
* /* otherwise continue, no error occurred */
|
||||
* g_assert (err == NULL || *err == NULL);
|
||||
* }
|
||||
* ]|
|
||||
*
|
||||
* If the sub-function does not indicate errors other than by
|
||||
* reporting a #GError, you need to create a temporary #GError
|
||||
* since the passed-in one may be %NULL. g_propagate_error() is
|
||||
* intended for use in this case.
|
||||
* |[
|
||||
* gboolean
|
||||
* my_function_that_can_fail (GError **err)
|
||||
* {
|
||||
* GError *tmp_error;
|
||||
*
|
||||
* g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
|
||||
*
|
||||
* tmp_error = NULL;
|
||||
* sub_function_that_can_fail (&tmp_error);
|
||||
*
|
||||
* if (tmp_error != NULL)
|
||||
* {
|
||||
* /* store tmp_error in err, if err != NULL,
|
||||
* * otherwise call g_error_free() on tmp_error
|
||||
* */
|
||||
* g_propagate_error (err, tmp_error);
|
||||
* return FALSE;
|
||||
* }
|
||||
*
|
||||
* /* otherwise continue, no error occurred */
|
||||
* }
|
||||
* ]|
|
||||
*
|
||||
* Error pileups are always a bug. For example, this code is incorrect:
|
||||
* |[
|
||||
* gboolean
|
||||
* my_function_that_can_fail (GError **err)
|
||||
* {
|
||||
* GError *tmp_error;
|
||||
*
|
||||
* g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
|
||||
*
|
||||
* tmp_error = NULL;
|
||||
* sub_function_that_can_fail (&tmp_error);
|
||||
* other_function_that_can_fail (&tmp_error);
|
||||
*
|
||||
* if (tmp_error != NULL)
|
||||
* {
|
||||
* g_propagate_error (err, tmp_error);
|
||||
* return FALSE;
|
||||
* }
|
||||
* }
|
||||
* ]|
|
||||
* <literal>tmp_error</literal> should be checked immediately after
|
||||
* sub_function_that_can_fail(), and either cleared or propagated
|
||||
* upward. The rule is: <emphasis>after each error, you must either
|
||||
* handle the error, or return it to the calling function</emphasis>.
|
||||
* Note that passing %NULL for the error location is the equivalent
|
||||
* of handling an error by always doing nothing about it. So the
|
||||
* following code is fine, assuming errors in sub_function_that_can_fail()
|
||||
* are not fatal to my_function_that_can_fail():
|
||||
* |[
|
||||
* gboolean
|
||||
* my_function_that_can_fail (GError **err)
|
||||
* {
|
||||
* GError *tmp_error;
|
||||
*
|
||||
* g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
|
||||
*
|
||||
* sub_function_that_can_fail (NULL); /* ignore errors */
|
||||
*
|
||||
* tmp_error = NULL;
|
||||
* other_function_that_can_fail (&tmp_error);
|
||||
*
|
||||
* if (tmp_error != NULL)
|
||||
* {
|
||||
* g_propagate_error (err, tmp_error);
|
||||
* return FALSE;
|
||||
* }
|
||||
* }
|
||||
* ]|
|
||||
*
|
||||
* Note that passing %NULL for the error location
|
||||
* <emphasis>ignores</emphasis> errors; it's equivalent to
|
||||
* <literal>try { sub_function_that_can_fail (); } catch (...) {}</literal>
|
||||
* in C++. It does <emphasis>not</emphasis> mean to leave errors
|
||||
* unhandled; it means to handle them by doing nothing.
|
||||
*
|
||||
* Error domains and codes are conventionally named as follows:
|
||||
* <itemizedlist>
|
||||
* <listitem><para>
|
||||
* The error domain is called
|
||||
* <literal><NAMESPACE>_<MODULE>_ERROR</literal>,
|
||||
* for example %G_SPAWN_ERROR or %G_THREAD_ERROR:
|
||||
* |[
|
||||
* #define G_SPAWN_ERROR g_spawn_error_quark ()
|
||||
*
|
||||
* GQuark
|
||||
* g_spawn_error_quark (void)
|
||||
* {
|
||||
* return g_quark_from_static_string ("g-spawn-error-quark");
|
||||
* }
|
||||
* ]|
|
||||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* The quark function for the error domain is called
|
||||
* <literal><namespace>_<module>_error_quark</literal>,
|
||||
* for example g_spawn_error_quark() or g_thread_error_quark().
|
||||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* The error codes are in an enumeration called
|
||||
* <literal><Namespace><Module>Error</literal>;
|
||||
* for example,#GThreadError or #GSpawnError.
|
||||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* Members of the error code enumeration are called
|
||||
* <literal><NAMESPACE>_<MODULE>_ERROR_<CODE></literal>,
|
||||
* for example %G_SPAWN_ERROR_FORK or %G_THREAD_ERROR_AGAIN.
|
||||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* If there's a "generic" or "unknown" error code for unrecoverable
|
||||
* errors it doesn't make sense to distinguish with specific codes,
|
||||
* it should be called <literal><NAMESPACE>_<MODULE>_ERROR_FAILED</literal>,
|
||||
* for example %G_SPAWN_ERROR_FAILED.
|
||||
* </para></listitem>
|
||||
* </itemizedlist>
|
||||
*
|
||||
* Summary of rules for use of #GError:
|
||||
* <itemizedlist>
|
||||
* <listitem><para>
|
||||
* Do not report programming errors via #GError.
|
||||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* The last argument of a function that returns an error should
|
||||
* be a location where a #GError can be placed (i.e. "#GError** error").
|
||||
* If #GError is used with varargs, the #GError** should be the last
|
||||
* argument before the "...".
|
||||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* The caller may pass %NULL for the #GError** if they are not interested
|
||||
* in details of the exact error that occurred.
|
||||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* If %NULL is passed for the #GError** argument, then errors should
|
||||
* not be returned to the caller, but your function should still
|
||||
* abort and return if an error occurs. That is, control flow should
|
||||
* not be affected by whether the caller wants to get a #GError.
|
||||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* If a #GError is reported, then your function by definition
|
||||
* <emphasis>had a fatal failure and did not complete whatever
|
||||
* it was supposed to do</emphasis>. If the failure was not fatal,
|
||||
* then you handled it and you should not report it. If it was fatal,
|
||||
* then you must report it and discontinue whatever you were doing
|
||||
* immediately.
|
||||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* If a #GError is reported, out parameters are not guaranteed to
|
||||
* be set to any defined value.
|
||||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* A #GError* must be initialized to %NULL before passing its address
|
||||
* to a function that can report errors.
|
||||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* "Piling up" errors is always a bug. That is, if you assign a
|
||||
* new #GError to a #GError* that is non-%NULL, thus overwriting
|
||||
* the previous error, it indicates that you should have aborted
|
||||
* the operation instead of continuing. If you were able to continue,
|
||||
* you should have cleared the previous error with g_clear_error().
|
||||
* g_set_error() will complain if you pile up errors.
|
||||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* By convention, if you return a boolean value indicating success
|
||||
* then %TRUE means success and %FALSE means failure. If %FALSE is
|
||||
* returned, the error <emphasis>must</emphasis> be set to a non-%NULL
|
||||
* value.
|
||||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* A %NULL return value is also frequently used to mean that an error
|
||||
* occurred. You should make clear in your documentation whether %NULL
|
||||
* is a valid return value in non-error cases; if %NULL is a valid value,
|
||||
* then users must check whether an error was returned to see if the
|
||||
* function succeeded.
|
||||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* When implementing a function that can report errors, you may want
|
||||
* to add a check at the top of your function that the error return
|
||||
* location is either %NULL or contains a %NULL error (e.g.
|
||||
* <literal>g_return_if_fail (error == NULL || *error == NULL);</literal>).
|
||||
* </para></listitem>
|
||||
* </itemizedlist>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gerror.h"
|
||||
|
||||
#include "gslice.h"
|
||||
#include "gstrfuncs.h"
|
||||
#include "gtestutils.h"
|
||||
|
||||
/**
|
||||
* g_error_new_valist:
|
||||
* @domain: error domain
|
||||
* @code: error code
|
||||
* @format: printf()-style format for error message
|
||||
* @args: #va_list of parameters for the message format
|
||||
*
|
||||
* Creates a new #GError with the given @domain and @code,
|
||||
* and a message formatted with @format.
|
||||
*
|
||||
* Returns: a new #GError
|
||||
*
|
||||
* Since: 2.22
|
||||
*/
|
||||
GError*
|
||||
g_error_new_valist (GQuark domain,
|
||||
gint code,
|
||||
const gchar *format,
|
||||
va_list args)
|
||||
{
|
||||
GError *error;
|
||||
|
||||
/* Historically, GError allowed this (although it was never meant to work),
|
||||
* and it has significant use in the wild, which g_return_val_if_fail
|
||||
* would break. It should maybe g_return_val_if_fail in GLib 4.
|
||||
* (GNOME#660371, GNOME#560482)
|
||||
*/
|
||||
g_warn_if_fail (domain != 0);
|
||||
g_warn_if_fail (format != NULL);
|
||||
|
||||
error = g_slice_new (GError);
|
||||
|
||||
error->domain = domain;
|
||||
error->code = code;
|
||||
error->message = g_strdup_vprintf (format, args);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_error_new:
|
||||
* @domain: error domain
|
||||
* @code: error code
|
||||
* @format: printf()-style format for error message
|
||||
* @...: parameters for message format
|
||||
*
|
||||
* Creates a new #GError with the given @domain and @code,
|
||||
* and a message formatted with @format.
|
||||
*
|
||||
* Return value: a new #GError
|
||||
*/
|
||||
GError*
|
||||
g_error_new (GQuark domain,
|
||||
gint code,
|
||||
const gchar *format,
|
||||
...)
|
||||
{
|
||||
GError* error;
|
||||
va_list args;
|
||||
|
||||
g_return_val_if_fail (format != NULL, NULL);
|
||||
g_return_val_if_fail (domain != 0, NULL);
|
||||
|
||||
va_start (args, format);
|
||||
error = g_error_new_valist (domain, code, format, args);
|
||||
va_end (args);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_error_new_literal:
|
||||
* @domain: error domain
|
||||
* @code: error code
|
||||
* @message: error message
|
||||
*
|
||||
* Creates a new #GError; unlike g_error_new(), @message is
|
||||
* not a printf()-style format string. Use this function if
|
||||
* @message contains text you don't have control over,
|
||||
* that could include printf() escape sequences.
|
||||
*
|
||||
* Return value: a new #GError
|
||||
**/
|
||||
GError*
|
||||
g_error_new_literal (GQuark domain,
|
||||
gint code,
|
||||
const gchar *message)
|
||||
{
|
||||
GError* err;
|
||||
|
||||
g_return_val_if_fail (message != NULL, NULL);
|
||||
g_return_val_if_fail (domain != 0, NULL);
|
||||
|
||||
err = g_slice_new (GError);
|
||||
|
||||
err->domain = domain;
|
||||
err->code = code;
|
||||
err->message = g_strdup (message);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_error_free:
|
||||
* @error: a #GError
|
||||
*
|
||||
* Frees a #GError and associated resources.
|
||||
*/
|
||||
void
|
||||
g_error_free (GError *error)
|
||||
{
|
||||
g_return_if_fail (error != NULL);
|
||||
|
||||
g_free (error->message);
|
||||
|
||||
g_slice_free (GError, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_error_copy:
|
||||
* @error: a #GError
|
||||
*
|
||||
* Makes a copy of @error.
|
||||
*
|
||||
* Return value: a new #GError
|
||||
*/
|
||||
GError*
|
||||
g_error_copy (const GError *error)
|
||||
{
|
||||
GError *copy;
|
||||
|
||||
g_return_val_if_fail (error != NULL, NULL);
|
||||
/* See g_error_new_valist for why these don't return */
|
||||
g_warn_if_fail (error->domain != 0);
|
||||
g_warn_if_fail (error->message != NULL);
|
||||
|
||||
copy = g_slice_new (GError);
|
||||
|
||||
*copy = *error;
|
||||
|
||||
copy->message = g_strdup (error->message);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_error_matches:
|
||||
* @error: a #GError or %NULL
|
||||
* @domain: an error domain
|
||||
* @code: an error code
|
||||
*
|
||||
* Returns %TRUE if @error matches @domain and @code, %FALSE
|
||||
* otherwise. In particular, when @error is %NULL, %FALSE will
|
||||
* be returned.
|
||||
*
|
||||
* Return value: whether @error has @domain and @code
|
||||
*/
|
||||
gboolean
|
||||
g_error_matches (const GError *error,
|
||||
GQuark domain,
|
||||
gint code)
|
||||
{
|
||||
return error &&
|
||||
error->domain == domain &&
|
||||
error->code == code;
|
||||
}
|
||||
|
||||
#define ERROR_OVERWRITTEN_WARNING "GError set over the top of a previous GError or uninitialized memory.\n" \
|
||||
"This indicates a bug in someone's code. You must ensure an error is NULL before it's set.\n" \
|
||||
"The overwriting error message was: %s"
|
||||
|
||||
/**
|
||||
* g_set_error:
|
||||
* @err: a return location for a #GError, or %NULL
|
||||
* @domain: error domain
|
||||
* @code: error code
|
||||
* @format: printf()-style format
|
||||
* @...: args for @format
|
||||
*
|
||||
* Does nothing if @err is %NULL; if @err is non-%NULL, then *@err
|
||||
* must be %NULL. A new #GError is created and assigned to *@err.
|
||||
*/
|
||||
void
|
||||
g_set_error (GError **err,
|
||||
GQuark domain,
|
||||
gint code,
|
||||
const gchar *format,
|
||||
...)
|
||||
{
|
||||
GError *new;
|
||||
|
||||
va_list args;
|
||||
|
||||
if (err == NULL)
|
||||
return;
|
||||
|
||||
va_start (args, format);
|
||||
new = g_error_new_valist (domain, code, format, args);
|
||||
va_end (args);
|
||||
|
||||
if (*err == NULL)
|
||||
*err = new;
|
||||
else
|
||||
g_warning (ERROR_OVERWRITTEN_WARNING, new->message);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_set_error_literal:
|
||||
* @err: a return location for a #GError, or %NULL
|
||||
* @domain: error domain
|
||||
* @code: error code
|
||||
* @message: error message
|
||||
*
|
||||
* Does nothing if @err is %NULL; if @err is non-%NULL, then *@err
|
||||
* must be %NULL. A new #GError is created and assigned to *@err.
|
||||
* Unlike g_set_error(), @message is not a printf()-style format string.
|
||||
* Use this function if @message contains text you don't have control over,
|
||||
* that could include printf() escape sequences.
|
||||
*
|
||||
* Since: 2.18
|
||||
*/
|
||||
void
|
||||
g_set_error_literal (GError **err,
|
||||
GQuark domain,
|
||||
gint code,
|
||||
const gchar *message)
|
||||
{
|
||||
GError *new;
|
||||
|
||||
if (err == NULL)
|
||||
return;
|
||||
|
||||
new = g_error_new_literal (domain, code, message);
|
||||
if (*err == NULL)
|
||||
*err = new;
|
||||
else
|
||||
g_warning (ERROR_OVERWRITTEN_WARNING, new->message);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_propagate_error:
|
||||
* @dest: error return location
|
||||
* @src: error to move into the return location
|
||||
*
|
||||
* If @dest is %NULL, free @src; otherwise, moves @src into *@dest.
|
||||
* The error variable @dest points to must be %NULL.
|
||||
*/
|
||||
void
|
||||
g_propagate_error (GError **dest,
|
||||
GError *src)
|
||||
{
|
||||
g_return_if_fail (src != NULL);
|
||||
|
||||
if (dest == NULL)
|
||||
{
|
||||
if (src)
|
||||
g_error_free (src);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*dest != NULL)
|
||||
g_warning (ERROR_OVERWRITTEN_WARNING, src->message);
|
||||
else
|
||||
*dest = src;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_clear_error:
|
||||
* @err: a #GError return location
|
||||
*
|
||||
* If @err is %NULL, does nothing. If @err is non-%NULL,
|
||||
* calls g_error_free() on *@err and sets *@err to %NULL.
|
||||
*/
|
||||
void
|
||||
g_clear_error (GError **err)
|
||||
{
|
||||
if (err && *err)
|
||||
{
|
||||
g_error_free (*err);
|
||||
*err = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
g_error_add_prefix (gchar **string,
|
||||
const gchar *format,
|
||||
va_list ap)
|
||||
{
|
||||
gchar *oldstring;
|
||||
gchar *prefix;
|
||||
|
||||
prefix = g_strdup_vprintf (format, ap);
|
||||
oldstring = *string;
|
||||
*string = g_strconcat (prefix, oldstring, NULL);
|
||||
g_free (oldstring);
|
||||
g_free (prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_prefix_error:
|
||||
* @err: a return location for a #GError, or %NULL
|
||||
* @format: printf()-style format string
|
||||
* @...: arguments to @format
|
||||
*
|
||||
* Formats a string according to @format and
|
||||
* prefix it to an existing error message. If
|
||||
* @err is %NULL (ie: no error variable) then do
|
||||
* nothing.
|
||||
*
|
||||
* If *@err is %NULL (ie: an error variable is
|
||||
* present but there is no error condition) then
|
||||
* also do nothing. Whether or not it makes
|
||||
* sense to take advantage of this feature is up
|
||||
* to you.
|
||||
*
|
||||
* Since: 2.16
|
||||
*/
|
||||
void
|
||||
g_prefix_error (GError **err,
|
||||
const gchar *format,
|
||||
...)
|
||||
{
|
||||
if (err && *err)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, format);
|
||||
g_error_add_prefix (&(*err)->message, format, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_propagate_prefixed_error:
|
||||
* @dest: error return location
|
||||
* @src: error to move into the return location
|
||||
* @format: printf()-style format string
|
||||
* @...: arguments to @format
|
||||
*
|
||||
* If @dest is %NULL, free @src; otherwise,
|
||||
* moves @src into *@dest. *@dest must be %NULL.
|
||||
* After the move, add a prefix as with
|
||||
* g_prefix_error().
|
||||
*
|
||||
* Since: 2.16
|
||||
**/
|
||||
void
|
||||
g_propagate_prefixed_error (GError **dest,
|
||||
GError *src,
|
||||
const gchar *format,
|
||||
...)
|
||||
{
|
||||
g_propagate_error (dest, src);
|
||||
|
||||
if (dest && *dest)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, format);
|
||||
g_error_add_prefix (&(*dest)->message, format, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
}
|
||||
107
glib/glib/gerror.h
Normal file
107
glib/glib/gerror.h
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/* gerror.h - Error reporting system
|
||||
*
|
||||
* Copyright 2000 Red Hat, Inc.
|
||||
*
|
||||
* The Gnome 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 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* The Gnome 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 the Gnome Library; see the file COPYING.LIB. If not,
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_ERROR_H__
|
||||
#define __G_ERROR_H__
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <glib/gquark.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* GError:
|
||||
* @domain: error domain, e.g. #G_FILE_ERROR
|
||||
* @code: error code, e.g. %G_FILE_ERROR_NOENT
|
||||
* @message: human-readable informative error message
|
||||
*
|
||||
* The <structname>GError</structname> structure contains
|
||||
* information about an error that has occurred.
|
||||
*/
|
||||
typedef struct _GError GError;
|
||||
|
||||
struct _GError
|
||||
{
|
||||
GQuark domain;
|
||||
gint code;
|
||||
gchar *message;
|
||||
};
|
||||
|
||||
GError* g_error_new (GQuark domain,
|
||||
gint code,
|
||||
const gchar *format,
|
||||
...) G_GNUC_PRINTF (3, 4);
|
||||
|
||||
GError* g_error_new_literal (GQuark domain,
|
||||
gint code,
|
||||
const gchar *message);
|
||||
GError* g_error_new_valist (GQuark domain,
|
||||
gint code,
|
||||
const gchar *format,
|
||||
va_list args);
|
||||
|
||||
void g_error_free (GError *error);
|
||||
GError* g_error_copy (const GError *error);
|
||||
|
||||
gboolean g_error_matches (const GError *error,
|
||||
GQuark domain,
|
||||
gint code);
|
||||
|
||||
/* if (err) *err = g_error_new(domain, code, format, ...), also has
|
||||
* some sanity checks.
|
||||
*/
|
||||
void g_set_error (GError **err,
|
||||
GQuark domain,
|
||||
gint code,
|
||||
const gchar *format,
|
||||
...) G_GNUC_PRINTF (4, 5);
|
||||
|
||||
void g_set_error_literal (GError **err,
|
||||
GQuark domain,
|
||||
gint code,
|
||||
const gchar *message);
|
||||
|
||||
/* if (dest) *dest = src; also has some sanity checks.
|
||||
*/
|
||||
void g_propagate_error (GError **dest,
|
||||
GError *src);
|
||||
|
||||
/* if (err && *err) { g_error_free(*err); *err = NULL; } */
|
||||
void g_clear_error (GError **err);
|
||||
|
||||
/* if (err) prefix the formatted string to the ->message */
|
||||
void g_prefix_error (GError **err,
|
||||
const gchar *format,
|
||||
...) G_GNUC_PRINTF (2, 3);
|
||||
|
||||
/* g_propagate_error then g_error_prefix on dest */
|
||||
void g_propagate_prefixed_error (GError **dest,
|
||||
GError *src,
|
||||
const gchar *format,
|
||||
...) G_GNUC_PRINTF (3, 4);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_ERROR_H__ */
|
||||
2654
glib/glib/gfileutils.c
Normal file
2654
glib/glib/gfileutils.c
Normal file
File diff suppressed because it is too large
Load diff
176
glib/glib/gfileutils.h
Normal file
176
glib/glib/gfileutils.h
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
/* gfileutils.h - File utility functions
|
||||
*
|
||||
* Copyright 2000 Red Hat, Inc.
|
||||
*
|
||||
* GLib 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 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* GLib 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 GLib; see the file COPYING.LIB. If not,
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_FILEUTILS_H__
|
||||
#define __G_FILEUTILS_H__
|
||||
|
||||
#include <glib/gerror.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define G_FILE_ERROR g_file_error_quark ()
|
||||
|
||||
typedef enum
|
||||
{
|
||||
G_FILE_ERROR_EXIST,
|
||||
G_FILE_ERROR_ISDIR,
|
||||
G_FILE_ERROR_ACCES,
|
||||
G_FILE_ERROR_NAMETOOLONG,
|
||||
G_FILE_ERROR_NOENT,
|
||||
G_FILE_ERROR_NOTDIR,
|
||||
G_FILE_ERROR_NXIO,
|
||||
G_FILE_ERROR_NODEV,
|
||||
G_FILE_ERROR_ROFS,
|
||||
G_FILE_ERROR_TXTBSY,
|
||||
G_FILE_ERROR_FAULT,
|
||||
G_FILE_ERROR_LOOP,
|
||||
G_FILE_ERROR_NOSPC,
|
||||
G_FILE_ERROR_NOMEM,
|
||||
G_FILE_ERROR_MFILE,
|
||||
G_FILE_ERROR_NFILE,
|
||||
G_FILE_ERROR_BADF,
|
||||
G_FILE_ERROR_INVAL,
|
||||
G_FILE_ERROR_PIPE,
|
||||
G_FILE_ERROR_AGAIN,
|
||||
G_FILE_ERROR_INTR,
|
||||
G_FILE_ERROR_IO,
|
||||
G_FILE_ERROR_PERM,
|
||||
G_FILE_ERROR_NOSYS,
|
||||
G_FILE_ERROR_FAILED
|
||||
} GFileError;
|
||||
|
||||
/* For backward-compat reasons, these are synced to an old
|
||||
* anonymous enum in libgnome. But don't use that enum
|
||||
* in new code.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
G_FILE_TEST_IS_REGULAR = 1 << 0,
|
||||
G_FILE_TEST_IS_SYMLINK = 1 << 1,
|
||||
G_FILE_TEST_IS_DIR = 1 << 2,
|
||||
G_FILE_TEST_IS_EXECUTABLE = 1 << 3,
|
||||
G_FILE_TEST_EXISTS = 1 << 4
|
||||
} GFileTest;
|
||||
|
||||
GQuark g_file_error_quark (void);
|
||||
/* So other code can generate a GFileError */
|
||||
GFileError g_file_error_from_errno (gint err_no);
|
||||
|
||||
#ifndef __GTK_DOC_IGNORE__
|
||||
#ifdef G_OS_WIN32
|
||||
#define g_file_test g_file_test_utf8
|
||||
#define g_file_get_contents g_file_get_contents_utf8
|
||||
#define g_mkstemp g_mkstemp_utf8
|
||||
#define g_file_open_tmp g_file_open_tmp_utf8
|
||||
#endif
|
||||
#endif
|
||||
|
||||
gboolean g_file_test (const gchar *filename,
|
||||
GFileTest test);
|
||||
gboolean g_file_get_contents (const gchar *filename,
|
||||
gchar **contents,
|
||||
gsize *length,
|
||||
GError **error);
|
||||
gboolean g_file_set_contents (const gchar *filename,
|
||||
const gchar *contents,
|
||||
gssize length,
|
||||
GError **error);
|
||||
gchar *g_file_read_link (const gchar *filename,
|
||||
GError **error);
|
||||
|
||||
/* Wrapper / workalike for mkdtemp() */
|
||||
gchar *g_mkdtemp (gchar *tmpl);
|
||||
gchar *g_mkdtemp_full (gchar *tmpl,
|
||||
gint mode);
|
||||
|
||||
/* Wrapper / workalike for mkstemp() */
|
||||
gint g_mkstemp (gchar *tmpl);
|
||||
gint g_mkstemp_full (gchar *tmpl,
|
||||
gint flags,
|
||||
gint mode);
|
||||
|
||||
/* Wrappers for g_mkstemp and g_mkdtemp() */
|
||||
gint g_file_open_tmp (const gchar *tmpl,
|
||||
gchar **name_used,
|
||||
GError **error);
|
||||
gchar *g_dir_make_tmp (const gchar *tmpl,
|
||||
GError **error);
|
||||
|
||||
gchar *g_build_path (const gchar *separator,
|
||||
const gchar *first_element,
|
||||
...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED;
|
||||
gchar *g_build_pathv (const gchar *separator,
|
||||
gchar **args) G_GNUC_MALLOC;
|
||||
|
||||
gchar *g_build_filename (const gchar *first_element,
|
||||
...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED;
|
||||
gchar *g_build_filenamev (gchar **args) G_GNUC_MALLOC;
|
||||
|
||||
gint g_mkdir_with_parents (const gchar *pathname,
|
||||
gint mode);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
|
||||
/* On Win32, the canonical directory separator is the backslash, and
|
||||
* the search path separator is the semicolon. Note that also the
|
||||
* (forward) slash works as directory separator.
|
||||
*/
|
||||
#define G_DIR_SEPARATOR '\\'
|
||||
#define G_DIR_SEPARATOR_S "\\"
|
||||
#define G_IS_DIR_SEPARATOR(c) ((c) == G_DIR_SEPARATOR || (c) == '/')
|
||||
#define G_SEARCHPATH_SEPARATOR ';'
|
||||
#define G_SEARCHPATH_SEPARATOR_S ";"
|
||||
|
||||
#else /* !G_OS_WIN32 */
|
||||
|
||||
#define G_DIR_SEPARATOR '/'
|
||||
#define G_DIR_SEPARATOR_S "/"
|
||||
#define G_IS_DIR_SEPARATOR(c) ((c) == G_DIR_SEPARATOR)
|
||||
#define G_SEARCHPATH_SEPARATOR ':'
|
||||
#define G_SEARCHPATH_SEPARATOR_S ":"
|
||||
|
||||
#endif /* !G_OS_WIN32 */
|
||||
|
||||
gboolean g_path_is_absolute (const gchar *file_name);
|
||||
const gchar *g_path_skip_root (const gchar *file_name);
|
||||
|
||||
GLIB_DEPRECATED_FOR(g_path_get_basename)
|
||||
const gchar *g_basename (const gchar *file_name);
|
||||
#ifndef G_DISABLE_DEPRECATED
|
||||
#define g_dirname g_path_get_dirname
|
||||
#endif
|
||||
|
||||
#ifndef __GTK_DOC_IGNORE__
|
||||
#ifdef G_OS_WIN32
|
||||
#define g_get_current_dir g_get_current_dir_utf8
|
||||
#endif
|
||||
#endif
|
||||
|
||||
gchar *g_get_current_dir (void);
|
||||
gchar *g_path_get_basename (const gchar *file_name) G_GNUC_MALLOC;
|
||||
gchar *g_path_get_dirname (const gchar *file_name) G_GNUC_MALLOC;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_FILEUTILS_H__ */
|
||||
614
glib/glib/ggettext.c
Normal file
614
glib/glib/ggettext.c
Normal file
|
|
@ -0,0 +1,614 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1998 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ggettext.h"
|
||||
|
||||
#include "galloca.h"
|
||||
#include "gthread.h"
|
||||
#include "gmem.h"
|
||||
#ifdef G_OS_WIN32
|
||||
#include "gwin32.h"
|
||||
#include "gfileutils.h"
|
||||
#include "gstrfuncs.h"
|
||||
#include "glib-init.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
#include <libintl.h>
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
|
||||
/**
|
||||
* _glib_get_locale_dir:
|
||||
*
|
||||
* Return the path to the share\locale or lib\locale subfolder of the
|
||||
* GLib installation folder. The path is in the system codepage. We
|
||||
* have to use system codepage as bindtextdomain() doesn't have a
|
||||
* UTF-8 interface.
|
||||
*/
|
||||
gchar *
|
||||
_glib_get_locale_dir (void)
|
||||
{
|
||||
gchar *install_dir = NULL, *locale_dir;
|
||||
gchar *retval = NULL;
|
||||
|
||||
if (glib_dll != NULL)
|
||||
install_dir = g_win32_get_package_installation_directory_of_module (glib_dll);
|
||||
|
||||
if (install_dir)
|
||||
{
|
||||
/*
|
||||
* Append "/share/locale" or "/lib/locale" depending on whether
|
||||
* autoconfigury detected GNU gettext or not.
|
||||
*/
|
||||
const char *p = GLIB_LOCALE_DIR + strlen (GLIB_LOCALE_DIR);
|
||||
while (*--p != '/')
|
||||
;
|
||||
while (*--p != '/')
|
||||
;
|
||||
|
||||
locale_dir = g_build_filename (install_dir, p, NULL);
|
||||
|
||||
retval = g_win32_locale_filename_from_utf8 (locale_dir);
|
||||
|
||||
g_free (install_dir);
|
||||
g_free (locale_dir);
|
||||
}
|
||||
|
||||
if (retval)
|
||||
return retval;
|
||||
else
|
||||
return g_strdup ("");
|
||||
}
|
||||
|
||||
#undef GLIB_LOCALE_DIR
|
||||
|
||||
#endif /* G_OS_WIN32 */
|
||||
|
||||
|
||||
static void
|
||||
ensure_gettext_initialized (void)
|
||||
{
|
||||
static gsize initialised;
|
||||
|
||||
if (g_once_init_enter (&initialised))
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
gchar *tmp = _glib_get_locale_dir ();
|
||||
bindtextdomain (GETTEXT_PACKAGE, tmp);
|
||||
g_free (tmp);
|
||||
#else
|
||||
bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
|
||||
#endif
|
||||
# ifdef HAVE_BIND_TEXTDOMAIN_CODESET
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
# endif
|
||||
g_once_init_leave (&initialised, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* glib_gettext:
|
||||
* @str: The string to be translated
|
||||
*
|
||||
* Returns the translated string from the glib translations.
|
||||
* This is an internal function and should only be used by
|
||||
* the internals of glib (such as libgio).
|
||||
*
|
||||
* Returns: the transation of @str to the current locale
|
||||
*/
|
||||
const gchar *
|
||||
glib_gettext (const gchar *str)
|
||||
{
|
||||
ensure_gettext_initialized ();
|
||||
|
||||
return g_dgettext (GETTEXT_PACKAGE, str);
|
||||
}
|
||||
|
||||
/**
|
||||
* glib_pgettext:
|
||||
* @msgctxtid: a combined message context and message id, separated
|
||||
* by a \004 character
|
||||
* @msgidoffset: the offset of the message id in @msgctxid
|
||||
*
|
||||
* This function is a variant of glib_gettext() which supports
|
||||
* a disambiguating message context. See g_dpgettext() for full
|
||||
* details.
|
||||
*
|
||||
* This is an internal function and should only be used by
|
||||
* the internals of glib (such as libgio).
|
||||
*
|
||||
* Returns: the translation of @str to the current locale
|
||||
*/
|
||||
const gchar *
|
||||
glib_pgettext (const gchar *msgctxtid,
|
||||
gsize msgidoffset)
|
||||
{
|
||||
ensure_gettext_initialized ();
|
||||
|
||||
return g_dpgettext (GETTEXT_PACKAGE, msgctxtid, msgidoffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_strip_context:
|
||||
* @msgid: a string
|
||||
* @msgval: another string
|
||||
*
|
||||
* An auxiliary function for gettext() support (see Q_()).
|
||||
*
|
||||
* Return value: @msgval, unless @msgval is identical to @msgid
|
||||
* and contains a '|' character, in which case a pointer to
|
||||
* the substring of msgid after the first '|' character is returned.
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
const gchar *
|
||||
g_strip_context (const gchar *msgid,
|
||||
const gchar *msgval)
|
||||
{
|
||||
if (msgval == msgid)
|
||||
{
|
||||
const char *c = strchr (msgid, '|');
|
||||
if (c != NULL)
|
||||
return c + 1;
|
||||
}
|
||||
|
||||
return msgval;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_dpgettext:
|
||||
* @domain: the translation domain to use, or %NULL to use
|
||||
* the domain set with textdomain()
|
||||
* @msgctxtid: a combined message context and message id, separated
|
||||
* by a \004 character
|
||||
* @msgidoffset: the offset of the message id in @msgctxid
|
||||
*
|
||||
* This function is a variant of g_dgettext() which supports
|
||||
* a disambiguating message context. GNU gettext uses the
|
||||
* '\004' character to separate the message context and
|
||||
* message id in @msgctxtid.
|
||||
* If 0 is passed as @msgidoffset, this function will fall back to
|
||||
* trying to use the deprecated convention of using "|" as a separation
|
||||
* character.
|
||||
*
|
||||
* This uses g_dgettext() internally. See that functions for differences
|
||||
* with dgettext() proper.
|
||||
*
|
||||
* Applications should normally not use this function directly,
|
||||
* but use the C_() macro for translations with context.
|
||||
*
|
||||
* Returns: The translated string
|
||||
*
|
||||
* Since: 2.16
|
||||
*/
|
||||
const gchar *
|
||||
g_dpgettext (const gchar *domain,
|
||||
const gchar *msgctxtid,
|
||||
gsize msgidoffset)
|
||||
{
|
||||
const gchar *translation;
|
||||
gchar *sep;
|
||||
|
||||
translation = g_dgettext (domain, msgctxtid);
|
||||
|
||||
if (translation == msgctxtid)
|
||||
{
|
||||
if (msgidoffset > 0)
|
||||
return msgctxtid + msgidoffset;
|
||||
sep = strchr (msgctxtid, '|');
|
||||
|
||||
if (sep)
|
||||
{
|
||||
/* try with '\004' instead of '|', in case
|
||||
* xgettext -kQ_:1g was used
|
||||
*/
|
||||
gchar *tmp = g_alloca (strlen (msgctxtid) + 1);
|
||||
strcpy (tmp, msgctxtid);
|
||||
tmp[sep - msgctxtid] = '\004';
|
||||
|
||||
translation = g_dgettext (domain, tmp);
|
||||
|
||||
if (translation == tmp)
|
||||
return sep + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return translation;
|
||||
}
|
||||
|
||||
/* This function is taken from gettext.h
|
||||
* GNU gettext uses '\004' to separate context and msgid in .mo files.
|
||||
*/
|
||||
/**
|
||||
* g_dpgettext2:
|
||||
* @domain: the translation domain to use, or %NULL to use
|
||||
* the domain set with textdomain()
|
||||
* @context: the message context
|
||||
* @msgid: the message
|
||||
*
|
||||
* This function is a variant of g_dgettext() which supports
|
||||
* a disambiguating message context. GNU gettext uses the
|
||||
* '\004' character to separate the message context and
|
||||
* message id in @msgctxtid.
|
||||
*
|
||||
* This uses g_dgettext() internally. See that functions for differences
|
||||
* with dgettext() proper.
|
||||
*
|
||||
* This function differs from C_() in that it is not a macro and
|
||||
* thus you may use non-string-literals as context and msgid arguments.
|
||||
*
|
||||
* Returns: The translated string
|
||||
*
|
||||
* Since: 2.18
|
||||
*/
|
||||
const gchar *
|
||||
g_dpgettext2 (const gchar *domain,
|
||||
const gchar *msgctxt,
|
||||
const gchar *msgid)
|
||||
{
|
||||
size_t msgctxt_len = strlen (msgctxt) + 1;
|
||||
size_t msgid_len = strlen (msgid) + 1;
|
||||
const char *translation;
|
||||
char* msg_ctxt_id;
|
||||
|
||||
msg_ctxt_id = g_alloca (msgctxt_len + msgid_len);
|
||||
|
||||
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
|
||||
msg_ctxt_id[msgctxt_len - 1] = '\004';
|
||||
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
|
||||
|
||||
translation = g_dgettext (domain, msg_ctxt_id);
|
||||
|
||||
if (translation == msg_ctxt_id)
|
||||
{
|
||||
/* try the old way of doing message contexts, too */
|
||||
msg_ctxt_id[msgctxt_len - 1] = '|';
|
||||
translation = g_dgettext (domain, msg_ctxt_id);
|
||||
|
||||
if (translation == msg_ctxt_id)
|
||||
return msgid;
|
||||
}
|
||||
|
||||
return translation;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_g_dgettext_should_translate (void)
|
||||
{
|
||||
static gsize translate = 0;
|
||||
enum {
|
||||
SHOULD_TRANSLATE = 1,
|
||||
SHOULD_NOT_TRANSLATE = 2
|
||||
};
|
||||
|
||||
if (G_UNLIKELY (g_once_init_enter (&translate)))
|
||||
{
|
||||
gboolean should_translate = TRUE;
|
||||
|
||||
const char *default_domain = textdomain (NULL);
|
||||
const char *translator_comment = gettext ("");
|
||||
#ifndef G_OS_WIN32
|
||||
const char *translate_locale = setlocale (LC_MESSAGES, NULL);
|
||||
#else
|
||||
const char *translate_locale = g_win32_getlocale ();
|
||||
#endif
|
||||
/* We should NOT translate only if all the following hold:
|
||||
* - user has called textdomain() and set textdomain to non-default
|
||||
* - default domain has no translations
|
||||
* - locale does not start with "en_" and is not "C"
|
||||
*
|
||||
* Rationale:
|
||||
* - If text domain is still the default domain, maybe user calls
|
||||
* it later. Continue with old behavior of translating.
|
||||
* - If locale starts with "en_", we can continue using the
|
||||
* translations even if the app doesn't have translations for
|
||||
* this locale. That is, en_UK and en_CA for example.
|
||||
* - If locale is "C", maybe user calls setlocale(LC_ALL,"") later.
|
||||
* Continue with old behavior of translating.
|
||||
*/
|
||||
if (0 != strcmp (default_domain, "messages") &&
|
||||
'\0' == *translator_comment &&
|
||||
0 != strncmp (translate_locale, "en_", 3) &&
|
||||
0 != strcmp (translate_locale, "C"))
|
||||
should_translate = FALSE;
|
||||
|
||||
g_once_init_leave (&translate,
|
||||
should_translate ?
|
||||
SHOULD_TRANSLATE :
|
||||
SHOULD_NOT_TRANSLATE);
|
||||
}
|
||||
|
||||
return translate == SHOULD_TRANSLATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_dgettext:
|
||||
* @domain: the translation domain to use, or %NULL to use
|
||||
* the domain set with textdomain()
|
||||
* @msgid: message to translate
|
||||
*
|
||||
* This function is a wrapper of dgettext() which does not translate
|
||||
* the message if the default domain as set with textdomain() has no
|
||||
* translations for the current locale.
|
||||
*
|
||||
* The advantage of using this function over dgettext() proper is that
|
||||
* libraries using this function (like GTK+) will not use translations
|
||||
* if the application using the library does not have translations for
|
||||
* the current locale. This results in a consistent English-only
|
||||
* interface instead of one having partial translations. For this
|
||||
* feature to work, the call to textdomain() and setlocale() should
|
||||
* precede any g_dgettext() invocations. For GTK+, it means calling
|
||||
* textdomain() before gtk_init or its variants.
|
||||
*
|
||||
* This function disables translations if and only if upon its first
|
||||
* call all the following conditions hold:
|
||||
* <itemizedlist>
|
||||
* <listitem>@domain is not %NULL</listitem>
|
||||
* <listitem>textdomain() has been called to set a default text domain</listitem>
|
||||
* <listitem>there is no translations available for the default text domain
|
||||
* and the current locale</listitem>
|
||||
* <listitem>current locale is not "C" or any English locales (those
|
||||
* starting with "en_")</listitem>
|
||||
* </itemizedlist>
|
||||
*
|
||||
* Note that this behavior may not be desired for example if an application
|
||||
* has its untranslated messages in a language other than English. In those
|
||||
* cases the application should call textdomain() after initializing GTK+.
|
||||
*
|
||||
* Applications should normally not use this function directly,
|
||||
* but use the _() macro for translations.
|
||||
*
|
||||
* Returns: The translated string
|
||||
*
|
||||
* Since: 2.18
|
||||
*/
|
||||
const gchar *
|
||||
g_dgettext (const gchar *domain,
|
||||
const gchar *msgid)
|
||||
{
|
||||
if (domain && G_UNLIKELY (!_g_dgettext_should_translate ()))
|
||||
return msgid;
|
||||
|
||||
return dgettext (domain, msgid);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_dcgettext:
|
||||
* @domain: (allow-none): the translation domain to use, or %NULL to use
|
||||
* the domain set with textdomain()
|
||||
* @msgid: message to translate
|
||||
* @category: a locale category
|
||||
*
|
||||
* This is a variant of g_dgettext() that allows specifying a locale
|
||||
* category instead of always using <envar>LC_MESSAGES</envar>. See g_dgettext() for
|
||||
* more information about how this functions differs from calling
|
||||
* dcgettext() directly.
|
||||
*
|
||||
* Returns: the translated string for the given locale category
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
const gchar *
|
||||
g_dcgettext (const gchar *domain,
|
||||
const gchar *msgid,
|
||||
gint category)
|
||||
{
|
||||
if (domain && G_UNLIKELY (!_g_dgettext_should_translate ()))
|
||||
return msgid;
|
||||
|
||||
return dcgettext (domain, msgid, category);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_dngettext:
|
||||
* @domain: the translation domain to use, or %NULL to use
|
||||
* the domain set with textdomain()
|
||||
* @msgid: message to translate
|
||||
* @msgid_plural: plural form of the message
|
||||
* @n: the quantity for which translation is needed
|
||||
*
|
||||
* This function is a wrapper of dngettext() which does not translate
|
||||
* the message if the default domain as set with textdomain() has no
|
||||
* translations for the current locale.
|
||||
*
|
||||
* See g_dgettext() for details of how this differs from dngettext()
|
||||
* proper.
|
||||
*
|
||||
* Returns: The translated string
|
||||
*
|
||||
* Since: 2.18
|
||||
*/
|
||||
const gchar *
|
||||
g_dngettext (const gchar *domain,
|
||||
const gchar *msgid,
|
||||
const gchar *msgid_plural,
|
||||
gulong n)
|
||||
{
|
||||
if (domain && G_UNLIKELY (!_g_dgettext_should_translate ()))
|
||||
return n == 1 ? msgid : msgid_plural;
|
||||
|
||||
return dngettext (domain, msgid, msgid_plural, n);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:i18n
|
||||
* @title: Internationalization
|
||||
* @short_description: gettext support macros
|
||||
* @see_also: the gettext manual
|
||||
*
|
||||
* GLib doesn't force any particular localization method upon its users.
|
||||
* But since GLib itself is localized using the gettext() mechanism, it seems
|
||||
* natural to offer the de-facto standard gettext() support macros in an
|
||||
* easy-to-use form.
|
||||
*
|
||||
* In order to use these macros in an application, you must include
|
||||
* <filename>glib/gi18n.h</filename>. For use in a library, must include
|
||||
* <filename>glib/gi18n-lib.h</filename> <emphasis>after</emphasis> defining
|
||||
* the GETTEXT_PACKAGE macro suitably for your library:
|
||||
* |[
|
||||
* #define GETTEXT_PACKAGE "gtk20"
|
||||
* #include <glib/gi18n-lib.h>
|
||||
* ]|
|
||||
* Note that you also have to call setlocale() and textdomain() (as well as
|
||||
* bindtextdomain() and bind_textdomain_codeset()) early on in your main()
|
||||
* to make gettext() work.
|
||||
*
|
||||
* The gettext manual covers details of how to set up message extraction
|
||||
* with xgettext.
|
||||
*/
|
||||
|
||||
/**
|
||||
* _:
|
||||
* @String: the string to be translated
|
||||
*
|
||||
* Marks a string for translation, gets replaced with the translated string
|
||||
* at runtime.
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
|
||||
/**
|
||||
* Q_:
|
||||
* @String: the string to be translated, with a '|'-separated prefix
|
||||
* which must not be translated
|
||||
*
|
||||
* Like _(), but handles context in message ids. This has the advantage
|
||||
* that the string can be adorned with a prefix to guarantee uniqueness
|
||||
* and provide context to the translator.
|
||||
*
|
||||
* One use case given in the gettext manual is GUI translation, where one
|
||||
* could e.g. disambiguate two "Open" menu entries as "File|Open" and
|
||||
* "Printer|Open". Another use case is the string "Russian" which may
|
||||
* have to be translated differently depending on whether it's the name
|
||||
* of a character set or a language. This could be solved by using
|
||||
* "charset|Russian" and "language|Russian".
|
||||
*
|
||||
* See the C_() macro for a different way to mark up translatable strings
|
||||
* with context.
|
||||
*
|
||||
* <note><para>If you are using the Q_() macro, you need to make sure
|
||||
* that you pass <option>--keyword=Q_</option> to xgettext when extracting
|
||||
* messages. If you are using GNU gettext >= 0.15, you can also use
|
||||
* <option>--keyword=Q_:1g</option> to let xgettext split the context
|
||||
* string off into a msgctxt line in the po file.</para></note>
|
||||
*
|
||||
* Returns: the translated message
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
|
||||
/**
|
||||
* C_:
|
||||
* @Context: a message context, must be a string literal
|
||||
* @String: a message id, must be a string literal
|
||||
*
|
||||
* Uses gettext to get the translation for @String. @Context is
|
||||
* used as a context. This is mainly useful for short strings which
|
||||
* may need different translations, depending on the context in which
|
||||
* they are used.
|
||||
* |[
|
||||
* label1 = C_("Navigation", "Back");
|
||||
* label2 = C_("Body part", "Back");
|
||||
* ]|
|
||||
*
|
||||
* <note><para>If you are using the C_() macro, you need to make sure
|
||||
* that you pass <option>--keyword=C_:1c,2</option> to xgettext when
|
||||
* extracting messages. Note that this only works with GNU
|
||||
* gettext >= 0.15.</para></note>
|
||||
*
|
||||
* Returns: the translated message
|
||||
*
|
||||
* Since: 2.16
|
||||
*/
|
||||
|
||||
/**
|
||||
* N_:
|
||||
* @String: the string to be translated
|
||||
*
|
||||
* Only marks a string for translation. This is useful in situations
|
||||
* where the translated strings can't be directly used, e.g. in string
|
||||
* array initializers. To get the translated string, call gettext()
|
||||
* at runtime.
|
||||
* |[
|
||||
* {
|
||||
* static const char *messages[] = {
|
||||
* N_("some very meaningful message"),
|
||||
* N_("and another one")
|
||||
* };
|
||||
* const char *string;
|
||||
* ...
|
||||
* string
|
||||
* = index > 1 ? _("a default message") : gettext (messages[index]);
|
||||
*
|
||||
* fputs (string);
|
||||
* ...
|
||||
* }
|
||||
* ]|
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
|
||||
/**
|
||||
* NC_:
|
||||
* @Context: a message context, must be a string literal
|
||||
* @String: a message id, must be a string literal
|
||||
*
|
||||
* Only marks a string for translation, with context.
|
||||
* This is useful in situations where the translated strings can't
|
||||
* be directly used, e.g. in string array initializers. To get the
|
||||
* translated string, you should call g_dpgettext2() at runtime.
|
||||
*
|
||||
* |[
|
||||
* {
|
||||
* static const char *messages[] = {
|
||||
* NC_("some context", "some very meaningful message"),
|
||||
* NC_("some context", "and another one")
|
||||
* };
|
||||
* const char *string;
|
||||
* ...
|
||||
* string
|
||||
* = index > 1 ? g_dpgettext2 (NULL, "some context", "a default message")
|
||||
* : g_dpgettext2 (NULL, "some context", messages[index]);
|
||||
*
|
||||
* fputs (string);
|
||||
* ...
|
||||
* }
|
||||
* ]|
|
||||
*
|
||||
* <note><para>If you are using the NC_() macro, you need to make sure
|
||||
* that you pass <option>--keyword=NC_:1c,2</option> to xgettext when
|
||||
* extracting messages. Note that this only works with GNU gettext >= 0.15.
|
||||
* Intltool has support for the NC_() macro since version 0.40.1.
|
||||
* </para></note>
|
||||
*
|
||||
* Since: 2.18
|
||||
*/
|
||||
|
||||
59
glib/glib/ggettext.h
Normal file
59
glib/glib/ggettext.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_GETTEXT_H__
|
||||
#define __G_GETTEXT_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
const gchar *g_strip_context (const gchar *msgid,
|
||||
const gchar *msgval) G_GNUC_FORMAT(1);
|
||||
|
||||
const gchar *g_dgettext (const gchar *domain,
|
||||
const gchar *msgid) G_GNUC_FORMAT(2);
|
||||
const gchar *g_dcgettext (const gchar *domain,
|
||||
const gchar *msgid,
|
||||
gint category) G_GNUC_FORMAT(2);
|
||||
const gchar *g_dngettext (const gchar *domain,
|
||||
const gchar *msgid,
|
||||
const gchar *msgid_plural,
|
||||
gulong n) G_GNUC_FORMAT(3);
|
||||
const gchar *g_dpgettext (const gchar *domain,
|
||||
const gchar *msgctxtid,
|
||||
gsize msgidoffset) G_GNUC_FORMAT(2);
|
||||
const gchar *g_dpgettext2 (const gchar *domain,
|
||||
const gchar *context,
|
||||
const gchar *msgid) G_GNUC_FORMAT(3);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_GETTEXT_H__ */
|
||||
1903
glib/glib/ghash.c
Normal file
1903
glib/glib/ghash.c
Normal file
File diff suppressed because it is too large
Load diff
146
glib/glib/ghash.h
Normal file
146
glib/glib/ghash.h
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_HASH_H__
|
||||
#define __G_HASH_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
#include <glib/glist.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GHashTable GHashTable;
|
||||
|
||||
typedef gboolean (*GHRFunc) (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data);
|
||||
|
||||
typedef struct _GHashTableIter GHashTableIter;
|
||||
|
||||
struct _GHashTableIter
|
||||
{
|
||||
/*< private >*/
|
||||
gpointer dummy1;
|
||||
gpointer dummy2;
|
||||
gpointer dummy3;
|
||||
int dummy4;
|
||||
gboolean dummy5;
|
||||
gpointer dummy6;
|
||||
};
|
||||
|
||||
GHashTable* g_hash_table_new (GHashFunc hash_func,
|
||||
GEqualFunc key_equal_func);
|
||||
GHashTable* g_hash_table_new_full (GHashFunc hash_func,
|
||||
GEqualFunc key_equal_func,
|
||||
GDestroyNotify key_destroy_func,
|
||||
GDestroyNotify value_destroy_func);
|
||||
void g_hash_table_destroy (GHashTable *hash_table);
|
||||
void g_hash_table_insert (GHashTable *hash_table,
|
||||
gpointer key,
|
||||
gpointer value);
|
||||
void g_hash_table_replace (GHashTable *hash_table,
|
||||
gpointer key,
|
||||
gpointer value);
|
||||
void g_hash_table_add (GHashTable *hash_table,
|
||||
gpointer key);
|
||||
gboolean g_hash_table_remove (GHashTable *hash_table,
|
||||
gconstpointer key);
|
||||
void g_hash_table_remove_all (GHashTable *hash_table);
|
||||
gboolean g_hash_table_steal (GHashTable *hash_table,
|
||||
gconstpointer key);
|
||||
void g_hash_table_steal_all (GHashTable *hash_table);
|
||||
gpointer g_hash_table_lookup (GHashTable *hash_table,
|
||||
gconstpointer key);
|
||||
gboolean g_hash_table_contains (GHashTable *hash_table,
|
||||
gconstpointer key);
|
||||
gboolean g_hash_table_lookup_extended (GHashTable *hash_table,
|
||||
gconstpointer lookup_key,
|
||||
gpointer *orig_key,
|
||||
gpointer *value);
|
||||
void g_hash_table_foreach (GHashTable *hash_table,
|
||||
GHFunc func,
|
||||
gpointer user_data);
|
||||
gpointer g_hash_table_find (GHashTable *hash_table,
|
||||
GHRFunc predicate,
|
||||
gpointer user_data);
|
||||
guint g_hash_table_foreach_remove (GHashTable *hash_table,
|
||||
GHRFunc func,
|
||||
gpointer user_data);
|
||||
guint g_hash_table_foreach_steal (GHashTable *hash_table,
|
||||
GHRFunc func,
|
||||
gpointer user_data);
|
||||
guint g_hash_table_size (GHashTable *hash_table);
|
||||
GList * g_hash_table_get_keys (GHashTable *hash_table);
|
||||
GList * g_hash_table_get_values (GHashTable *hash_table);
|
||||
|
||||
void g_hash_table_iter_init (GHashTableIter *iter,
|
||||
GHashTable *hash_table);
|
||||
gboolean g_hash_table_iter_next (GHashTableIter *iter,
|
||||
gpointer *key,
|
||||
gpointer *value);
|
||||
GHashTable* g_hash_table_iter_get_hash_table (GHashTableIter *iter);
|
||||
void g_hash_table_iter_remove (GHashTableIter *iter);
|
||||
void g_hash_table_iter_replace (GHashTableIter *iter,
|
||||
gpointer value);
|
||||
void g_hash_table_iter_steal (GHashTableIter *iter);
|
||||
|
||||
GHashTable* g_hash_table_ref (GHashTable *hash_table);
|
||||
void g_hash_table_unref (GHashTable *hash_table);
|
||||
|
||||
#ifndef G_DISABLE_DEPRECATED
|
||||
#define g_hash_table_freeze(hash_table) ((void)0)
|
||||
#define g_hash_table_thaw(hash_table) ((void)0)
|
||||
#endif
|
||||
|
||||
/* Hash Functions
|
||||
*/
|
||||
gboolean g_str_equal (gconstpointer v1,
|
||||
gconstpointer v2);
|
||||
guint g_str_hash (gconstpointer v);
|
||||
|
||||
gboolean g_int_equal (gconstpointer v1,
|
||||
gconstpointer v2);
|
||||
guint g_int_hash (gconstpointer v);
|
||||
|
||||
gboolean g_int64_equal (gconstpointer v1,
|
||||
gconstpointer v2);
|
||||
guint g_int64_hash (gconstpointer v);
|
||||
|
||||
gboolean g_double_equal (gconstpointer v1,
|
||||
gconstpointer v2);
|
||||
guint g_double_hash (gconstpointer v);
|
||||
|
||||
guint g_direct_hash (gconstpointer v) G_GNUC_CONST;
|
||||
gboolean g_direct_equal (gconstpointer v1,
|
||||
gconstpointer v2) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_HASH_H__ */
|
||||
400
glib/glib/ghmac.c
Normal file
400
glib/glib/ghmac.c
Normal file
|
|
@ -0,0 +1,400 @@
|
|||
/* ghmac.h - data hashing functions
|
||||
*
|
||||
* Copyright (C) 2011 Collabora Ltd.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Stef Walter <stefw@collabora.co.uk>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ghmac.h"
|
||||
|
||||
#include "glib/galloca.h"
|
||||
#include "gatomic.h"
|
||||
#include "gslice.h"
|
||||
#include "gmem.h"
|
||||
#include "gstrfuncs.h"
|
||||
#include "gtestutils.h"
|
||||
#include "gtypes.h"
|
||||
#include "glibintl.h"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:hmac
|
||||
* @title: Secure HMAC Digests
|
||||
* @short_description: computes the HMAC for data
|
||||
*
|
||||
* HMACs should be used when producing a cookie or hash based on data
|
||||
* and a key. Simple mechanisms for using SHA1 and other algorithms to
|
||||
* digest a key and data together are vulnerable to various security
|
||||
* issues. <ulink url="http://en.wikipedia.org/wiki/HMAC">HMAC</ulink>
|
||||
* uses algorithms like SHA1 in a secure way to produce a digest of a
|
||||
* key and data.
|
||||
*
|
||||
* Both the key and data are arbitrary byte arrays of bytes or characters.
|
||||
*
|
||||
* Support for HMAC Digests has been added in GLib 2.30.
|
||||
*/
|
||||
|
||||
struct _GHmac
|
||||
{
|
||||
int ref_count;
|
||||
GChecksumType digest_type;
|
||||
GChecksum *digesti;
|
||||
GChecksum *digesto;
|
||||
};
|
||||
|
||||
/**
|
||||
* g_hmac_new:
|
||||
* @digest_type: the desired type of digest
|
||||
* @key: (array length=key_len): the key for the HMAC
|
||||
* @key_len: the length of the keys
|
||||
*
|
||||
* Creates a new #GHmac, using the digest algorithm @digest_type.
|
||||
* If the @digest_type is not known, %NULL is returned.
|
||||
* A #GHmac can be used to compute the HMAC of a key and an
|
||||
* arbitrary binary blob, using different hashing algorithms.
|
||||
*
|
||||
* A #GHmac works by feeding a binary blob through g_hmac_update()
|
||||
* until the data is complete; the digest can then be extracted
|
||||
* using g_hmac_get_string(), which will return the checksum as a
|
||||
* hexadecimal string; or g_hmac_get_digest(), which will return a
|
||||
* array of raw bytes. Once either g_hmac_get_string() or
|
||||
* g_hmac_get_digest() have been called on a #GHmac, the HMAC
|
||||
* will be closed and it won't be possible to call g_hmac_update()
|
||||
* on it anymore.
|
||||
*
|
||||
* Return value: the newly created #GHmac, or %NULL.
|
||||
* Use g_hmac_unref() to free the memory allocated by it.
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
GHmac *
|
||||
g_hmac_new (GChecksumType digest_type,
|
||||
const guchar *key,
|
||||
gsize key_len)
|
||||
{
|
||||
GChecksum *checksum;
|
||||
GHmac *hmac;
|
||||
guchar *buffer;
|
||||
guchar *pad;
|
||||
gsize i, len;
|
||||
gsize block_size;
|
||||
|
||||
checksum = g_checksum_new (digest_type);
|
||||
g_return_val_if_fail (checksum != NULL, NULL);
|
||||
|
||||
switch (digest_type)
|
||||
{
|
||||
case G_CHECKSUM_MD5:
|
||||
case G_CHECKSUM_SHA1:
|
||||
block_size = 64; /* RFC 2104 */
|
||||
break;
|
||||
case G_CHECKSUM_SHA256:
|
||||
block_size = 64; /* RFC draft-kelly-ipsec-ciph-sha2-01 */
|
||||
break;
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
hmac = g_slice_new0 (GHmac);
|
||||
hmac->ref_count = 1;
|
||||
hmac->digest_type = digest_type;
|
||||
hmac->digesti = checksum;
|
||||
hmac->digesto = g_checksum_new (digest_type);
|
||||
|
||||
buffer = g_alloca (block_size);
|
||||
pad = g_alloca (block_size);
|
||||
|
||||
memset (buffer, 0, block_size);
|
||||
|
||||
/* If the key is too long, hash it */
|
||||
if (key_len > block_size)
|
||||
{
|
||||
len = block_size;
|
||||
g_checksum_update (hmac->digesti, key, key_len);
|
||||
g_checksum_get_digest (hmac->digesti, buffer, &len);
|
||||
g_checksum_reset (hmac->digesti);
|
||||
}
|
||||
|
||||
/* Otherwise pad it with zeros */
|
||||
else
|
||||
{
|
||||
memcpy (buffer, key, key_len);
|
||||
}
|
||||
|
||||
/* First pad */
|
||||
for (i = 0; i < block_size; i++)
|
||||
pad[i] = 0x36 ^ buffer[i]; /* ipad value */
|
||||
g_checksum_update (hmac->digesti, pad, block_size);
|
||||
|
||||
/* Second pad */
|
||||
for (i = 0; i < block_size; i++)
|
||||
pad[i] = 0x5c ^ buffer[i]; /* opad value */
|
||||
g_checksum_update (hmac->digesto, pad, block_size);
|
||||
|
||||
return hmac;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hmac_copy:
|
||||
* @hmac: the #GHmac to copy
|
||||
*
|
||||
* Copies a #GHmac. If @hmac has been closed, by calling
|
||||
* g_hmac_get_string() or g_hmac_get_digest(), the copied
|
||||
* HMAC will be closed as well.
|
||||
*
|
||||
* Return value: the copy of the passed #GHmac. Use g_hmac_unref()
|
||||
* when finished using it.
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
GHmac *
|
||||
g_hmac_copy (const GHmac *hmac)
|
||||
{
|
||||
GHmac *copy;
|
||||
|
||||
g_return_val_if_fail (hmac != NULL, NULL);
|
||||
|
||||
copy = g_slice_new (GHmac);
|
||||
copy->ref_count = 1;
|
||||
copy->digest_type = hmac->digest_type;
|
||||
copy->digesti = g_checksum_copy (hmac->digesti);
|
||||
copy->digesto = g_checksum_copy (hmac->digesto);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hmac_ref:
|
||||
* @hmac: a valid #GHmac
|
||||
*
|
||||
* Atomically increments the reference count of @hmac by one.
|
||||
*
|
||||
* This function is MT-safe and may be called from any thread.
|
||||
*
|
||||
* Return value: the passed in #GHmac.
|
||||
*
|
||||
* Since: 2.30
|
||||
**/
|
||||
GHmac *
|
||||
g_hmac_ref (GHmac *hmac)
|
||||
{
|
||||
g_return_val_if_fail (hmac != NULL, NULL);
|
||||
|
||||
g_atomic_int_inc (&hmac->ref_count);
|
||||
|
||||
return hmac;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hmac_unref:
|
||||
* @hmac: a #GHmac
|
||||
*
|
||||
* Atomically decrements the reference count of @hmac by one.
|
||||
*
|
||||
* If the reference count drops to 0, all keys and values will be
|
||||
* destroyed, and all memory allocated by the hash table is released.
|
||||
* This function is MT-safe and may be called from any thread.
|
||||
* Frees the memory allocated for @hmac.
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
void
|
||||
g_hmac_unref (GHmac *hmac)
|
||||
{
|
||||
g_return_if_fail (hmac != NULL);
|
||||
|
||||
if (g_atomic_int_dec_and_test (&hmac->ref_count))
|
||||
{
|
||||
g_checksum_free (hmac->digesti);
|
||||
g_checksum_free (hmac->digesto);
|
||||
g_slice_free (GHmac, hmac);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hmac_update:
|
||||
* @hmac: a #GHmac
|
||||
* @data: (array length=length): buffer used to compute the checksum
|
||||
* @length: size of the buffer, or -1 if it is a nul-terminated string
|
||||
*
|
||||
* Feeds @data into an existing #GHmac.
|
||||
*
|
||||
* The HMAC must still be open, that is g_hmac_get_string() or
|
||||
* g_hmac_get_digest() must not have been called on @hmac.
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
void
|
||||
g_hmac_update (GHmac *hmac,
|
||||
const guchar *data,
|
||||
gssize length)
|
||||
{
|
||||
g_return_if_fail (hmac != NULL);
|
||||
g_return_if_fail (length == 0 || data != NULL);
|
||||
|
||||
g_checksum_update (hmac->digesti, data, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hmac_get_string:
|
||||
* @hmac: a #GHmac
|
||||
*
|
||||
* Gets the HMAC as an hexadecimal string.
|
||||
*
|
||||
* Once this function has been called the #GHmac can no longer be
|
||||
* updated with g_hmac_update().
|
||||
*
|
||||
* The hexadecimal characters will be lower case.
|
||||
*
|
||||
* Return value: the hexadecimal representation of the HMAC. The
|
||||
* returned string is owned by the HMAC and should not be modified
|
||||
* or freed.
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
const gchar *
|
||||
g_hmac_get_string (GHmac *hmac)
|
||||
{
|
||||
guint8 *buffer;
|
||||
gsize digest_len;
|
||||
|
||||
g_return_val_if_fail (hmac != NULL, NULL);
|
||||
|
||||
digest_len = g_checksum_type_get_length (hmac->digest_type);
|
||||
buffer = g_alloca (digest_len);
|
||||
|
||||
/* This is only called for its side-effect of updating hmac->digesto... */
|
||||
g_hmac_get_digest (hmac, buffer, &digest_len);
|
||||
/* ... because we get the string from the checksum rather than
|
||||
* stringifying buffer ourselves
|
||||
*/
|
||||
return g_checksum_get_string (hmac->digesto);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hmac_get_digest:
|
||||
* @hmac: a #GHmac
|
||||
* @buffer: output buffer
|
||||
* @digest_len: an inout parameter. The caller initializes it to the
|
||||
* size of @buffer. After the call it contains the length of the digest
|
||||
*
|
||||
* Gets the digest from @checksum as a raw binary array and places it
|
||||
* into @buffer. The size of the digest depends on the type of checksum.
|
||||
*
|
||||
* Once this function has been called, the #GHmac is closed and can
|
||||
* no longer be updated with g_checksum_update().
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
void
|
||||
g_hmac_get_digest (GHmac *hmac,
|
||||
guint8 *buffer,
|
||||
gsize *digest_len)
|
||||
{
|
||||
gsize len;
|
||||
|
||||
g_return_if_fail (hmac != NULL);
|
||||
|
||||
len = g_checksum_type_get_length (hmac->digest_type);
|
||||
g_return_if_fail (*digest_len >= len);
|
||||
|
||||
/* Use the same buffer, because we can :) */
|
||||
g_checksum_get_digest (hmac->digesti, buffer, &len);
|
||||
g_checksum_update (hmac->digesto, buffer, len);
|
||||
g_checksum_get_digest (hmac->digesto, buffer, digest_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_compute_hmac_for_data:
|
||||
* @digest_type: a #GChecksumType to use for the HMAC
|
||||
* @key: (array length=key_len): the key to use in the HMAC
|
||||
* @key_len: the length of the key
|
||||
* @data: binary blob to compute the HMAC of
|
||||
* @length: length of @data
|
||||
*
|
||||
* Computes the HMAC for a binary @data of @length. This is a
|
||||
* convenience wrapper for g_hmac_new(), g_hmac_get_string()
|
||||
* and g_hmac_unref().
|
||||
*
|
||||
* The hexadecimal string returned will be in lower case.
|
||||
*
|
||||
* Return value: the HMAC of the binary data as a string in hexadecimal.
|
||||
* The returned string should be freed with g_free() when done using it.
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
gchar *
|
||||
g_compute_hmac_for_data (GChecksumType digest_type,
|
||||
const guchar *key,
|
||||
gsize key_len,
|
||||
const guchar *data,
|
||||
gsize length)
|
||||
{
|
||||
GHmac *hmac;
|
||||
gchar *retval;
|
||||
|
||||
g_return_val_if_fail (length == 0 || data != NULL, NULL);
|
||||
|
||||
hmac = g_hmac_new (digest_type, key, key_len);
|
||||
if (!hmac)
|
||||
return NULL;
|
||||
|
||||
g_hmac_update (hmac, data, length);
|
||||
retval = g_strdup (g_hmac_get_string (hmac));
|
||||
g_hmac_unref (hmac);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_compute_hmac_for_string:
|
||||
* @digest_type: a #GChecksumType to use for the HMAC
|
||||
* @key: (array length=key_len): the key to use in the HMAC
|
||||
* @key_len: the length of the key
|
||||
* @str: the string to compute the HMAC for
|
||||
* @length: the length of the string, or -1 if the string is nul-terminated
|
||||
*
|
||||
* Computes the HMAC for a string.
|
||||
*
|
||||
* The hexadecimal string returned will be in lower case.
|
||||
*
|
||||
* Return value: the HMAC as a hexadecimal string.
|
||||
* The returned string should be freed with g_free()
|
||||
* when done using it.
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
gchar *
|
||||
g_compute_hmac_for_string (GChecksumType digest_type,
|
||||
const guchar *key,
|
||||
gsize key_len,
|
||||
const gchar *str,
|
||||
gssize length)
|
||||
{
|
||||
g_return_val_if_fail (length == 0 || str != NULL, NULL);
|
||||
|
||||
if (length < 0)
|
||||
length = strlen (str);
|
||||
|
||||
return g_compute_hmac_for_data (digest_type, key, key_len,
|
||||
(const guchar *) str, length);
|
||||
}
|
||||
71
glib/glib/ghmac.h
Normal file
71
glib/glib/ghmac.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/* ghmac.h - secure data hashing
|
||||
*
|
||||
* Copyright (C) 2011 Stef Walter <stefw@collabora.co.uk>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_HMAC_H__
|
||||
#define __G_HMAC_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
#include "gchecksum.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* GHmac:
|
||||
*
|
||||
* An opaque structure representing a HMAC operation.
|
||||
* To create a new GHmac, use g_hmac_new(). To free
|
||||
* a GHmac, use g_hmac_unref().
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
typedef struct _GHmac GHmac;
|
||||
|
||||
GHmac * g_hmac_new (GChecksumType digest_type,
|
||||
const guchar *key,
|
||||
gsize key_len);
|
||||
GHmac * g_hmac_copy (const GHmac *hmac);
|
||||
GHmac * g_hmac_ref (GHmac *hmac);
|
||||
void g_hmac_unref (GHmac *hmac);
|
||||
void g_hmac_update (GHmac *hmac,
|
||||
const guchar *data,
|
||||
gssize length);
|
||||
const gchar * g_hmac_get_string (GHmac *hmac);
|
||||
void g_hmac_get_digest (GHmac *hmac,
|
||||
guint8 *buffer,
|
||||
gsize *digest_len);
|
||||
|
||||
gchar *g_compute_hmac_for_data (GChecksumType digest_type,
|
||||
const guchar *key,
|
||||
gsize key_len,
|
||||
const guchar *data,
|
||||
gsize length);
|
||||
gchar *g_compute_hmac_for_string (GChecksumType digest_type,
|
||||
const guchar *key,
|
||||
gsize key_len,
|
||||
const gchar *str,
|
||||
gssize length);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_CHECKSUM_H__ */
|
||||
1054
glib/glib/ghook.c
Normal file
1054
glib/glib/ghook.c
Normal file
File diff suppressed because it is too large
Load diff
181
glib/glib/ghook.h
Normal file
181
glib/glib/ghook.h
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_HOOK_H__
|
||||
#define __G_HOOK_H__
|
||||
|
||||
#include <glib/gmem.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
/* --- typedefs --- */
|
||||
typedef struct _GHook GHook;
|
||||
typedef struct _GHookList GHookList;
|
||||
|
||||
typedef gint (*GHookCompareFunc) (GHook *new_hook,
|
||||
GHook *sibling);
|
||||
typedef gboolean (*GHookFindFunc) (GHook *hook,
|
||||
gpointer data);
|
||||
typedef void (*GHookMarshaller) (GHook *hook,
|
||||
gpointer marshal_data);
|
||||
typedef gboolean (*GHookCheckMarshaller) (GHook *hook,
|
||||
gpointer marshal_data);
|
||||
typedef void (*GHookFunc) (gpointer data);
|
||||
typedef gboolean (*GHookCheckFunc) (gpointer data);
|
||||
typedef void (*GHookFinalizeFunc) (GHookList *hook_list,
|
||||
GHook *hook);
|
||||
typedef enum
|
||||
{
|
||||
G_HOOK_FLAG_ACTIVE = 1 << 0,
|
||||
G_HOOK_FLAG_IN_CALL = 1 << 1,
|
||||
G_HOOK_FLAG_MASK = 0x0f
|
||||
} GHookFlagMask;
|
||||
#define G_HOOK_FLAG_USER_SHIFT (4)
|
||||
|
||||
|
||||
/* --- structures --- */
|
||||
struct _GHookList
|
||||
{
|
||||
gulong seq_id;
|
||||
guint hook_size : 16;
|
||||
guint is_setup : 1;
|
||||
GHook *hooks;
|
||||
gpointer dummy3;
|
||||
GHookFinalizeFunc finalize_hook;
|
||||
gpointer dummy[2];
|
||||
};
|
||||
struct _GHook
|
||||
{
|
||||
gpointer data;
|
||||
GHook *next;
|
||||
GHook *prev;
|
||||
guint ref_count;
|
||||
gulong hook_id;
|
||||
guint flags;
|
||||
gpointer func;
|
||||
GDestroyNotify destroy;
|
||||
};
|
||||
|
||||
|
||||
/* --- macros --- */
|
||||
#define G_HOOK(hook) ((GHook*) (hook))
|
||||
#define G_HOOK_FLAGS(hook) (G_HOOK (hook)->flags)
|
||||
#define G_HOOK_ACTIVE(hook) ((G_HOOK_FLAGS (hook) & \
|
||||
G_HOOK_FLAG_ACTIVE) != 0)
|
||||
#define G_HOOK_IN_CALL(hook) ((G_HOOK_FLAGS (hook) & \
|
||||
G_HOOK_FLAG_IN_CALL) != 0)
|
||||
#define G_HOOK_IS_VALID(hook) (G_HOOK (hook)->hook_id != 0 && \
|
||||
(G_HOOK_FLAGS (hook) & \
|
||||
G_HOOK_FLAG_ACTIVE))
|
||||
#define G_HOOK_IS_UNLINKED(hook) (G_HOOK (hook)->next == NULL && \
|
||||
G_HOOK (hook)->prev == NULL && \
|
||||
G_HOOK (hook)->hook_id == 0 && \
|
||||
G_HOOK (hook)->ref_count == 0)
|
||||
|
||||
|
||||
/* --- prototypes --- */
|
||||
/* callback maintenance functions */
|
||||
void g_hook_list_init (GHookList *hook_list,
|
||||
guint hook_size);
|
||||
void g_hook_list_clear (GHookList *hook_list);
|
||||
GHook* g_hook_alloc (GHookList *hook_list);
|
||||
void g_hook_free (GHookList *hook_list,
|
||||
GHook *hook);
|
||||
GHook * g_hook_ref (GHookList *hook_list,
|
||||
GHook *hook);
|
||||
void g_hook_unref (GHookList *hook_list,
|
||||
GHook *hook);
|
||||
gboolean g_hook_destroy (GHookList *hook_list,
|
||||
gulong hook_id);
|
||||
void g_hook_destroy_link (GHookList *hook_list,
|
||||
GHook *hook);
|
||||
void g_hook_prepend (GHookList *hook_list,
|
||||
GHook *hook);
|
||||
void g_hook_insert_before (GHookList *hook_list,
|
||||
GHook *sibling,
|
||||
GHook *hook);
|
||||
void g_hook_insert_sorted (GHookList *hook_list,
|
||||
GHook *hook,
|
||||
GHookCompareFunc func);
|
||||
GHook* g_hook_get (GHookList *hook_list,
|
||||
gulong hook_id);
|
||||
GHook* g_hook_find (GHookList *hook_list,
|
||||
gboolean need_valids,
|
||||
GHookFindFunc func,
|
||||
gpointer data);
|
||||
GHook* g_hook_find_data (GHookList *hook_list,
|
||||
gboolean need_valids,
|
||||
gpointer data);
|
||||
GHook* g_hook_find_func (GHookList *hook_list,
|
||||
gboolean need_valids,
|
||||
gpointer func);
|
||||
GHook* g_hook_find_func_data (GHookList *hook_list,
|
||||
gboolean need_valids,
|
||||
gpointer func,
|
||||
gpointer data);
|
||||
/* return the first valid hook, and increment its reference count */
|
||||
GHook* g_hook_first_valid (GHookList *hook_list,
|
||||
gboolean may_be_in_call);
|
||||
/* return the next valid hook with incremented reference count, and
|
||||
* decrement the reference count of the original hook
|
||||
*/
|
||||
GHook* g_hook_next_valid (GHookList *hook_list,
|
||||
GHook *hook,
|
||||
gboolean may_be_in_call);
|
||||
/* GHookCompareFunc implementation to insert hooks sorted by their id */
|
||||
gint g_hook_compare_ids (GHook *new_hook,
|
||||
GHook *sibling);
|
||||
/* convenience macros */
|
||||
#define g_hook_append( hook_list, hook ) \
|
||||
g_hook_insert_before ((hook_list), NULL, (hook))
|
||||
/* invoke all valid hooks with the (*GHookFunc) signature.
|
||||
*/
|
||||
void g_hook_list_invoke (GHookList *hook_list,
|
||||
gboolean may_recurse);
|
||||
/* invoke all valid hooks with the (*GHookCheckFunc) signature,
|
||||
* and destroy the hook if FALSE is returned.
|
||||
*/
|
||||
void g_hook_list_invoke_check (GHookList *hook_list,
|
||||
gboolean may_recurse);
|
||||
/* invoke a marshaller on all valid hooks.
|
||||
*/
|
||||
void g_hook_list_marshal (GHookList *hook_list,
|
||||
gboolean may_recurse,
|
||||
GHookMarshaller marshaller,
|
||||
gpointer marshal_data);
|
||||
void g_hook_list_marshal_check (GHookList *hook_list,
|
||||
gboolean may_recurse,
|
||||
GHookCheckMarshaller marshaller,
|
||||
gpointer marshal_data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_HOOK_H__ */
|
||||
800
glib/glib/ghostutils.c
Normal file
800
glib/glib/ghostutils.c
Normal file
|
|
@ -0,0 +1,800 @@
|
|||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
*
|
||||
* 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 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., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ghostutils.h"
|
||||
|
||||
#include "garray.h"
|
||||
#include "gmem.h"
|
||||
#include "gstring.h"
|
||||
#include "gstrfuncs.h"
|
||||
#include "glibintl.h"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:ghostutils
|
||||
* @short_description: Internet hostname utilities
|
||||
*
|
||||
* Functions for manipulating internet hostnames; in particular, for
|
||||
* converting between Unicode and ASCII-encoded forms of
|
||||
* Internationalized Domain Names (IDNs).
|
||||
*
|
||||
* The <ulink
|
||||
* url="http://www.ietf.org/rfc/rfc3490.txt">Internationalized Domain
|
||||
* Names for Applications (IDNA)</ulink> standards allow for the use
|
||||
* of Unicode domain names in applications, while providing
|
||||
* backward-compatibility with the old ASCII-only DNS, by defining an
|
||||
* ASCII-Compatible Encoding of any given Unicode name, which can be
|
||||
* used with non-IDN-aware applications and protocols. (For example,
|
||||
* "Παν語.org" maps to "xn--4wa8awb4637h.org".)
|
||||
**/
|
||||
|
||||
#define IDNA_ACE_PREFIX "xn--"
|
||||
#define IDNA_ACE_PREFIX_LEN 4
|
||||
|
||||
/* Punycode constants, from RFC 3492. */
|
||||
|
||||
#define PUNYCODE_BASE 36
|
||||
#define PUNYCODE_TMIN 1
|
||||
#define PUNYCODE_TMAX 26
|
||||
#define PUNYCODE_SKEW 38
|
||||
#define PUNYCODE_DAMP 700
|
||||
#define PUNYCODE_INITIAL_BIAS 72
|
||||
#define PUNYCODE_INITIAL_N 0x80
|
||||
|
||||
#define PUNYCODE_IS_BASIC(cp) ((guint)(cp) < 0x80)
|
||||
|
||||
/* Encode/decode a single base-36 digit */
|
||||
static inline gchar
|
||||
encode_digit (guint dig)
|
||||
{
|
||||
if (dig < 26)
|
||||
return dig + 'a';
|
||||
else
|
||||
return dig - 26 + '0';
|
||||
}
|
||||
|
||||
static inline guint
|
||||
decode_digit (gchar dig)
|
||||
{
|
||||
if (dig >= 'A' && dig <= 'Z')
|
||||
return dig - 'A';
|
||||
else if (dig >= 'a' && dig <= 'z')
|
||||
return dig - 'a';
|
||||
else if (dig >= '0' && dig <= '9')
|
||||
return dig - '0' + 26;
|
||||
else
|
||||
return G_MAXUINT;
|
||||
}
|
||||
|
||||
/* Punycode bias adaptation algorithm, RFC 3492 section 6.1 */
|
||||
static guint
|
||||
adapt (guint delta,
|
||||
guint numpoints,
|
||||
gboolean firsttime)
|
||||
{
|
||||
guint k;
|
||||
|
||||
delta = firsttime ? delta / PUNYCODE_DAMP : delta / 2;
|
||||
delta += delta / numpoints;
|
||||
|
||||
k = 0;
|
||||
while (delta > ((PUNYCODE_BASE - PUNYCODE_TMIN) * PUNYCODE_TMAX) / 2)
|
||||
{
|
||||
delta /= PUNYCODE_BASE - PUNYCODE_TMIN;
|
||||
k += PUNYCODE_BASE;
|
||||
}
|
||||
|
||||
return k + ((PUNYCODE_BASE - PUNYCODE_TMIN + 1) * delta /
|
||||
(delta + PUNYCODE_SKEW));
|
||||
}
|
||||
|
||||
/* Punycode encoder, RFC 3492 section 6.3. The algorithm is
|
||||
* sufficiently bizarre that it's not really worth trying to explain
|
||||
* here.
|
||||
*/
|
||||
static gboolean
|
||||
punycode_encode (const gchar *input_utf8,
|
||||
gsize input_utf8_length,
|
||||
GString *output)
|
||||
{
|
||||
guint delta, handled_chars, num_basic_chars, bias, j, q, k, t, digit;
|
||||
gunichar n, m, *input;
|
||||
glong input_length;
|
||||
gboolean success = FALSE;
|
||||
|
||||
/* Convert from UTF-8 to Unicode code points */
|
||||
input = g_utf8_to_ucs4 (input_utf8, input_utf8_length, NULL,
|
||||
&input_length, NULL);
|
||||
if (!input)
|
||||
return FALSE;
|
||||
|
||||
/* Copy basic chars */
|
||||
for (j = num_basic_chars = 0; j < input_length; j++)
|
||||
{
|
||||
if (PUNYCODE_IS_BASIC (input[j]))
|
||||
{
|
||||
g_string_append_c (output, g_ascii_tolower (input[j]));
|
||||
num_basic_chars++;
|
||||
}
|
||||
}
|
||||
if (num_basic_chars)
|
||||
g_string_append_c (output, '-');
|
||||
|
||||
handled_chars = num_basic_chars;
|
||||
|
||||
/* Encode non-basic chars */
|
||||
delta = 0;
|
||||
bias = PUNYCODE_INITIAL_BIAS;
|
||||
n = PUNYCODE_INITIAL_N;
|
||||
while (handled_chars < input_length)
|
||||
{
|
||||
/* let m = the minimum {non-basic} code point >= n in the input */
|
||||
for (m = G_MAXUINT, j = 0; j < input_length; j++)
|
||||
{
|
||||
if (input[j] >= n && input[j] < m)
|
||||
m = input[j];
|
||||
}
|
||||
|
||||
if (m - n > (G_MAXUINT - delta) / (handled_chars + 1))
|
||||
goto fail;
|
||||
delta += (m - n) * (handled_chars + 1);
|
||||
n = m;
|
||||
|
||||
for (j = 0; j < input_length; j++)
|
||||
{
|
||||
if (input[j] < n)
|
||||
{
|
||||
if (++delta == 0)
|
||||
goto fail;
|
||||
}
|
||||
else if (input[j] == n)
|
||||
{
|
||||
q = delta;
|
||||
for (k = PUNYCODE_BASE; ; k += PUNYCODE_BASE)
|
||||
{
|
||||
if (k <= bias)
|
||||
t = PUNYCODE_TMIN;
|
||||
else if (k >= bias + PUNYCODE_TMAX)
|
||||
t = PUNYCODE_TMAX;
|
||||
else
|
||||
t = k - bias;
|
||||
if (q < t)
|
||||
break;
|
||||
digit = t + (q - t) % (PUNYCODE_BASE - t);
|
||||
g_string_append_c (output, encode_digit (digit));
|
||||
q = (q - t) / (PUNYCODE_BASE - t);
|
||||
}
|
||||
|
||||
g_string_append_c (output, encode_digit (q));
|
||||
bias = adapt (delta, handled_chars + 1, handled_chars == num_basic_chars);
|
||||
delta = 0;
|
||||
handled_chars++;
|
||||
}
|
||||
}
|
||||
|
||||
delta++;
|
||||
n++;
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
|
||||
fail:
|
||||
g_free (input);
|
||||
return success;
|
||||
}
|
||||
|
||||
/* From RFC 3454, Table B.1 */
|
||||
#define idna_is_junk(ch) ((ch) == 0x00AD || (ch) == 0x1806 || (ch) == 0x200B || (ch) == 0x2060 || (ch) == 0xFEFF || (ch) == 0x034F || (ch) == 0x180B || (ch) == 0x180C || (ch) == 0x180D || (ch) == 0x200C || (ch) == 0x200D || ((ch) >= 0xFE00 && (ch) <= 0xFE0F))
|
||||
|
||||
/* Scan @str for "junk" and return a cleaned-up string if any junk
|
||||
* is found. Else return %NULL.
|
||||
*/
|
||||
static gchar *
|
||||
remove_junk (const gchar *str,
|
||||
gint len)
|
||||
{
|
||||
GString *cleaned = NULL;
|
||||
const gchar *p;
|
||||
gunichar ch;
|
||||
|
||||
for (p = str; len == -1 ? *p : p < str + len; p = g_utf8_next_char (p))
|
||||
{
|
||||
ch = g_utf8_get_char (p);
|
||||
if (idna_is_junk (ch))
|
||||
{
|
||||
if (!cleaned)
|
||||
{
|
||||
cleaned = g_string_new (NULL);
|
||||
g_string_append_len (cleaned, str, p - str);
|
||||
}
|
||||
}
|
||||
else if (cleaned)
|
||||
g_string_append_unichar (cleaned, ch);
|
||||
}
|
||||
|
||||
if (cleaned)
|
||||
return g_string_free (cleaned, FALSE);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
contains_uppercase_letters (const gchar *str,
|
||||
gint len)
|
||||
{
|
||||
const gchar *p;
|
||||
|
||||
for (p = str; len == -1 ? *p : p < str + len; p = g_utf8_next_char (p))
|
||||
{
|
||||
if (g_unichar_isupper (g_utf8_get_char (p)))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
contains_non_ascii (const gchar *str,
|
||||
gint len)
|
||||
{
|
||||
const gchar *p;
|
||||
|
||||
for (p = str; len == -1 ? *p : p < str + len; p++)
|
||||
{
|
||||
if ((guchar)*p > 0x80)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* RFC 3454, Appendix C. ish. */
|
||||
static inline gboolean
|
||||
idna_is_prohibited (gunichar ch)
|
||||
{
|
||||
switch (g_unichar_type (ch))
|
||||
{
|
||||
case G_UNICODE_CONTROL:
|
||||
case G_UNICODE_FORMAT:
|
||||
case G_UNICODE_UNASSIGNED:
|
||||
case G_UNICODE_PRIVATE_USE:
|
||||
case G_UNICODE_SURROGATE:
|
||||
case G_UNICODE_LINE_SEPARATOR:
|
||||
case G_UNICODE_PARAGRAPH_SEPARATOR:
|
||||
case G_UNICODE_SPACE_SEPARATOR:
|
||||
return TRUE;
|
||||
|
||||
case G_UNICODE_OTHER_SYMBOL:
|
||||
if (ch == 0xFFFC || ch == 0xFFFD ||
|
||||
(ch >= 0x2FF0 && ch <= 0x2FFB))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
|
||||
case G_UNICODE_NON_SPACING_MARK:
|
||||
if (ch == 0x0340 || ch == 0x0341)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* RFC 3491 IDN cleanup algorithm. */
|
||||
static gchar *
|
||||
nameprep (const gchar *hostname,
|
||||
gint len,
|
||||
gboolean *is_unicode)
|
||||
{
|
||||
gchar *name, *tmp = NULL, *p;
|
||||
|
||||
/* It would be nice if we could do this without repeatedly
|
||||
* allocating strings and converting back and forth between
|
||||
* gunichars and UTF-8... The code does at least avoid doing most of
|
||||
* the sub-operations when they would just be equivalent to a
|
||||
* g_strdup().
|
||||
*/
|
||||
|
||||
/* Remove presentation-only characters */
|
||||
name = remove_junk (hostname, len);
|
||||
if (name)
|
||||
{
|
||||
tmp = name;
|
||||
len = -1;
|
||||
}
|
||||
else
|
||||
name = (gchar *)hostname;
|
||||
|
||||
/* Convert to lowercase */
|
||||
if (contains_uppercase_letters (name, len))
|
||||
{
|
||||
name = g_utf8_strdown (name, len);
|
||||
g_free (tmp);
|
||||
tmp = name;
|
||||
len = -1;
|
||||
}
|
||||
|
||||
/* If there are no UTF8 characters, we're done. */
|
||||
if (!contains_non_ascii (name, len))
|
||||
{
|
||||
*is_unicode = FALSE;
|
||||
if (name == (gchar *)hostname)
|
||||
return len == -1 ? g_strdup (hostname) : g_strndup (hostname, len);
|
||||
else
|
||||
return name;
|
||||
}
|
||||
|
||||
*is_unicode = TRUE;
|
||||
|
||||
/* Normalize */
|
||||
name = g_utf8_normalize (name, len, G_NORMALIZE_NFKC);
|
||||
g_free (tmp);
|
||||
tmp = name;
|
||||
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
/* KC normalization may have created more capital letters (eg,
|
||||
* angstrom -> capital A with ring). So we have to lowercasify a
|
||||
* second time. (This is more-or-less how the nameprep algorithm
|
||||
* does it. If tolower(nfkc(tolower(X))) is guaranteed to be the
|
||||
* same as tolower(nfkc(X)), then we could skip the first tolower,
|
||||
* but I'm not sure it is.)
|
||||
*/
|
||||
if (contains_uppercase_letters (name, -1))
|
||||
{
|
||||
name = g_utf8_strdown (name, -1);
|
||||
g_free (tmp);
|
||||
tmp = name;
|
||||
}
|
||||
|
||||
/* Check for prohibited characters */
|
||||
for (p = name; *p; p = g_utf8_next_char (p))
|
||||
{
|
||||
if (idna_is_prohibited (g_utf8_get_char (p)))
|
||||
{
|
||||
name = NULL;
|
||||
g_free (tmp);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: We're supposed to verify certain constraints on bidi
|
||||
* characters, but glib does not appear to have that information.
|
||||
*/
|
||||
|
||||
done:
|
||||
return name;
|
||||
}
|
||||
|
||||
/* RFC 3490, section 3.1 says '.', 0x3002, 0xFF0E, and 0xFF61 count as
|
||||
* label-separating dots. @str must be '\0'-terminated.
|
||||
*/
|
||||
#define idna_is_dot(str) ( \
|
||||
((guchar)(str)[0] == '.') || \
|
||||
((guchar)(str)[0] == 0xE3 && (guchar)(str)[1] == 0x80 && (guchar)(str)[2] == 0x82) || \
|
||||
((guchar)(str)[0] == 0xEF && (guchar)(str)[1] == 0xBC && (guchar)(str)[2] == 0x8E) || \
|
||||
((guchar)(str)[0] == 0xEF && (guchar)(str)[1] == 0xBD && (guchar)(str)[2] == 0xA1) )
|
||||
|
||||
static const gchar *
|
||||
idna_end_of_label (const gchar *str)
|
||||
{
|
||||
for (; *str; str = g_utf8_next_char (str))
|
||||
{
|
||||
if (idna_is_dot (str))
|
||||
return str;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hostname_to_ascii:
|
||||
* @hostname: a valid UTF-8 or ASCII hostname
|
||||
*
|
||||
* Converts @hostname to its canonical ASCII form; an ASCII-only
|
||||
* string containing no uppercase letters and not ending with a
|
||||
* trailing dot.
|
||||
*
|
||||
* Return value: an ASCII hostname, which must be freed, or %NULL if
|
||||
* @hostname is in some way invalid.
|
||||
*
|
||||
* Since: 2.22
|
||||
**/
|
||||
gchar *
|
||||
g_hostname_to_ascii (const gchar *hostname)
|
||||
{
|
||||
gchar *name, *label, *p;
|
||||
GString *out;
|
||||
gssize llen, oldlen;
|
||||
gboolean unicode;
|
||||
|
||||
label = name = nameprep (hostname, -1, &unicode);
|
||||
if (!name || !unicode)
|
||||
return name;
|
||||
|
||||
out = g_string_new (NULL);
|
||||
|
||||
do
|
||||
{
|
||||
unicode = FALSE;
|
||||
for (p = label; *p && !idna_is_dot (p); p++)
|
||||
{
|
||||
if ((guchar)*p > 0x80)
|
||||
unicode = TRUE;
|
||||
}
|
||||
|
||||
oldlen = out->len;
|
||||
llen = p - label;
|
||||
if (unicode)
|
||||
{
|
||||
if (!strncmp (label, IDNA_ACE_PREFIX, IDNA_ACE_PREFIX_LEN))
|
||||
goto fail;
|
||||
|
||||
g_string_append (out, IDNA_ACE_PREFIX);
|
||||
if (!punycode_encode (label, llen, out))
|
||||
goto fail;
|
||||
}
|
||||
else
|
||||
g_string_append_len (out, label, llen);
|
||||
|
||||
if (out->len - oldlen > 63)
|
||||
goto fail;
|
||||
|
||||
label += llen;
|
||||
if (*label)
|
||||
label = g_utf8_next_char (label);
|
||||
if (*label)
|
||||
g_string_append_c (out, '.');
|
||||
}
|
||||
while (*label);
|
||||
|
||||
g_free (name);
|
||||
return g_string_free (out, FALSE);
|
||||
|
||||
fail:
|
||||
g_free (name);
|
||||
g_string_free (out, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hostname_is_non_ascii:
|
||||
* @hostname: a hostname
|
||||
*
|
||||
* Tests if @hostname contains Unicode characters. If this returns
|
||||
* %TRUE, you need to encode the hostname with g_hostname_to_ascii()
|
||||
* before using it in non-IDN-aware contexts.
|
||||
*
|
||||
* Note that a hostname might contain a mix of encoded and unencoded
|
||||
* segments, and so it is possible for g_hostname_is_non_ascii() and
|
||||
* g_hostname_is_ascii_encoded() to both return %TRUE for a name.
|
||||
*
|
||||
* Return value: %TRUE if @hostname contains any non-ASCII characters
|
||||
*
|
||||
* Since: 2.22
|
||||
**/
|
||||
gboolean
|
||||
g_hostname_is_non_ascii (const gchar *hostname)
|
||||
{
|
||||
return contains_non_ascii (hostname, -1);
|
||||
}
|
||||
|
||||
/* Punycode decoder, RFC 3492 section 6.2. As with punycode_encode(),
|
||||
* read the RFC if you want to understand what this is actually doing.
|
||||
*/
|
||||
static gboolean
|
||||
punycode_decode (const gchar *input,
|
||||
gsize input_length,
|
||||
GString *output)
|
||||
{
|
||||
GArray *output_chars;
|
||||
gunichar n;
|
||||
guint i, bias;
|
||||
guint oldi, w, k, digit, t;
|
||||
const gchar *split;
|
||||
|
||||
n = PUNYCODE_INITIAL_N;
|
||||
i = 0;
|
||||
bias = PUNYCODE_INITIAL_BIAS;
|
||||
|
||||
split = input + input_length - 1;
|
||||
while (split > input && *split != '-')
|
||||
split--;
|
||||
if (split > input)
|
||||
{
|
||||
output_chars = g_array_sized_new (FALSE, FALSE, sizeof (gunichar),
|
||||
split - input);
|
||||
input_length -= (split - input) + 1;
|
||||
while (input < split)
|
||||
{
|
||||
gunichar ch = (gunichar)*input++;
|
||||
if (!PUNYCODE_IS_BASIC (ch))
|
||||
goto fail;
|
||||
g_array_append_val (output_chars, ch);
|
||||
}
|
||||
input++;
|
||||
}
|
||||
else
|
||||
output_chars = g_array_new (FALSE, FALSE, sizeof (gunichar));
|
||||
|
||||
while (input_length)
|
||||
{
|
||||
oldi = i;
|
||||
w = 1;
|
||||
for (k = PUNYCODE_BASE; ; k += PUNYCODE_BASE)
|
||||
{
|
||||
if (!input_length--)
|
||||
goto fail;
|
||||
digit = decode_digit (*input++);
|
||||
if (digit >= PUNYCODE_BASE)
|
||||
goto fail;
|
||||
if (digit > (G_MAXUINT - i) / w)
|
||||
goto fail;
|
||||
i += digit * w;
|
||||
if (k <= bias)
|
||||
t = PUNYCODE_TMIN;
|
||||
else if (k >= bias + PUNYCODE_TMAX)
|
||||
t = PUNYCODE_TMAX;
|
||||
else
|
||||
t = k - bias;
|
||||
if (digit < t)
|
||||
break;
|
||||
if (w > G_MAXUINT / (PUNYCODE_BASE - t))
|
||||
goto fail;
|
||||
w *= (PUNYCODE_BASE - t);
|
||||
}
|
||||
|
||||
bias = adapt (i - oldi, output_chars->len + 1, oldi == 0);
|
||||
|
||||
if (i / (output_chars->len + 1) > G_MAXUINT - n)
|
||||
goto fail;
|
||||
n += i / (output_chars->len + 1);
|
||||
i %= (output_chars->len + 1);
|
||||
|
||||
g_array_insert_val (output_chars, i++, n);
|
||||
}
|
||||
|
||||
for (i = 0; i < output_chars->len; i++)
|
||||
g_string_append_unichar (output, g_array_index (output_chars, gunichar, i));
|
||||
g_array_free (output_chars, TRUE);
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
g_array_free (output_chars, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hostname_to_unicode:
|
||||
* @hostname: a valid UTF-8 or ASCII hostname
|
||||
*
|
||||
* Converts @hostname to its canonical presentation form; a UTF-8
|
||||
* string in Unicode normalization form C, containing no uppercase
|
||||
* letters, no forbidden characters, and no ASCII-encoded segments,
|
||||
* and not ending with a trailing dot.
|
||||
*
|
||||
* Of course if @hostname is not an internationalized hostname, then
|
||||
* the canonical presentation form will be entirely ASCII.
|
||||
*
|
||||
* Return value: a UTF-8 hostname, which must be freed, or %NULL if
|
||||
* @hostname is in some way invalid.
|
||||
*
|
||||
* Since: 2.22
|
||||
**/
|
||||
gchar *
|
||||
g_hostname_to_unicode (const gchar *hostname)
|
||||
{
|
||||
GString *out;
|
||||
gssize llen;
|
||||
|
||||
out = g_string_new (NULL);
|
||||
|
||||
do
|
||||
{
|
||||
llen = idna_end_of_label (hostname) - hostname;
|
||||
if (!g_ascii_strncasecmp (hostname, IDNA_ACE_PREFIX, IDNA_ACE_PREFIX_LEN))
|
||||
{
|
||||
hostname += IDNA_ACE_PREFIX_LEN;
|
||||
llen -= IDNA_ACE_PREFIX_LEN;
|
||||
if (!punycode_decode (hostname, llen, out))
|
||||
{
|
||||
g_string_free (out, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gboolean unicode;
|
||||
gchar *canonicalized = nameprep (hostname, llen, &unicode);
|
||||
|
||||
if (!canonicalized)
|
||||
{
|
||||
g_string_free (out, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
g_string_append (out, canonicalized);
|
||||
g_free (canonicalized);
|
||||
}
|
||||
|
||||
hostname += llen;
|
||||
if (*hostname)
|
||||
hostname = g_utf8_next_char (hostname);
|
||||
if (*hostname)
|
||||
g_string_append_c (out, '.');
|
||||
}
|
||||
while (*hostname);
|
||||
|
||||
return g_string_free (out, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hostname_is_ascii_encoded:
|
||||
* @hostname: a hostname
|
||||
*
|
||||
* Tests if @hostname contains segments with an ASCII-compatible
|
||||
* encoding of an Internationalized Domain Name. If this returns
|
||||
* %TRUE, you should decode the hostname with g_hostname_to_unicode()
|
||||
* before displaying it to the user.
|
||||
*
|
||||
* Note that a hostname might contain a mix of encoded and unencoded
|
||||
* segments, and so it is possible for g_hostname_is_non_ascii() and
|
||||
* g_hostname_is_ascii_encoded() to both return %TRUE for a name.
|
||||
*
|
||||
* Return value: %TRUE if @hostname contains any ASCII-encoded
|
||||
* segments.
|
||||
*
|
||||
* Since: 2.22
|
||||
**/
|
||||
gboolean
|
||||
g_hostname_is_ascii_encoded (const gchar *hostname)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (!g_ascii_strncasecmp (hostname, IDNA_ACE_PREFIX, IDNA_ACE_PREFIX_LEN))
|
||||
return TRUE;
|
||||
hostname = idna_end_of_label (hostname);
|
||||
if (*hostname)
|
||||
hostname = g_utf8_next_char (hostname);
|
||||
if (!*hostname)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_hostname_is_ip_address:
|
||||
* @hostname: a hostname (or IP address in string form)
|
||||
*
|
||||
* Tests if @hostname is the string form of an IPv4 or IPv6 address.
|
||||
* (Eg, "192.168.0.1".)
|
||||
*
|
||||
* Return value: %TRUE if @hostname is an IP address
|
||||
*
|
||||
* Since: 2.22
|
||||
**/
|
||||
gboolean
|
||||
g_hostname_is_ip_address (const gchar *hostname)
|
||||
{
|
||||
gchar *p, *end;
|
||||
gint nsegments, octet;
|
||||
|
||||
/* On Linux we could implement this using inet_pton, but the Windows
|
||||
* equivalent of that requires linking against winsock, so we just
|
||||
* figure this out ourselves. Tested by tests/hostutils.c.
|
||||
*/
|
||||
|
||||
p = (char *)hostname;
|
||||
|
||||
if (strchr (p, ':'))
|
||||
{
|
||||
gboolean skipped;
|
||||
|
||||
/* If it contains a ':', it's an IPv6 address (assuming it's an
|
||||
* IP address at all). This consists of eight ':'-separated
|
||||
* segments, each containing a 1-4 digit hex number, except that
|
||||
* optionally: (a) the last two segments can be replaced by an
|
||||
* IPv4 address, and (b) a single span of 1 to 8 "0000" segments
|
||||
* can be replaced with just "::".
|
||||
*/
|
||||
|
||||
nsegments = 0;
|
||||
skipped = FALSE;
|
||||
while (*p && nsegments < 8)
|
||||
{
|
||||
/* Each segment after the first must be preceded by a ':'.
|
||||
* (We also handle half of the "string starts with ::" case
|
||||
* here.)
|
||||
*/
|
||||
if (p != (char *)hostname || (p[0] == ':' && p[1] == ':'))
|
||||
{
|
||||
if (*p != ':')
|
||||
return FALSE;
|
||||
p++;
|
||||
}
|
||||
|
||||
/* If there's another ':', it means we're skipping some segments */
|
||||
if (*p == ':' && !skipped)
|
||||
{
|
||||
skipped = TRUE;
|
||||
nsegments++;
|
||||
|
||||
/* Handle the "string ends with ::" case */
|
||||
if (!p[1])
|
||||
p++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Read the segment, make sure it's valid. */
|
||||
for (end = p; g_ascii_isxdigit (*end); end++)
|
||||
;
|
||||
if (end == p || end > p + 4)
|
||||
return FALSE;
|
||||
|
||||
if (*end == '.')
|
||||
{
|
||||
if ((nsegments == 6 && !skipped) || (nsegments <= 6 && skipped))
|
||||
goto parse_ipv4;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
nsegments++;
|
||||
p = end;
|
||||
}
|
||||
|
||||
return !*p && (nsegments == 8 || skipped);
|
||||
}
|
||||
|
||||
parse_ipv4:
|
||||
|
||||
/* Parse IPv4: N.N.N.N, where each N <= 255 and doesn't have leading 0s. */
|
||||
for (nsegments = 0; nsegments < 4; nsegments++)
|
||||
{
|
||||
if (nsegments != 0)
|
||||
{
|
||||
if (*p != '.')
|
||||
return FALSE;
|
||||
p++;
|
||||
}
|
||||
|
||||
/* Check the segment; a little tricker than the IPv6 case since
|
||||
* we can't allow extra leading 0s, and we can't assume that all
|
||||
* strings of valid length are within range.
|
||||
*/
|
||||
octet = 0;
|
||||
if (*p == '0')
|
||||
end = p + 1;
|
||||
else
|
||||
{
|
||||
for (end = p; g_ascii_isdigit (*end); end++)
|
||||
octet = 10 * octet + (*end - '0');
|
||||
}
|
||||
if (end == p || end > p + 3 || octet > 255)
|
||||
return FALSE;
|
||||
|
||||
p = end;
|
||||
}
|
||||
|
||||
/* If there's nothing left to parse, then it's ok. */
|
||||
return !*p;
|
||||
}
|
||||
40
glib/glib/ghostutils.h
Normal file
40
glib/glib/ghostutils.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
*
|
||||
* 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 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., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_HOST_UTILS_H__
|
||||
#define __G_HOST_UTILS_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gboolean g_hostname_is_non_ascii (const gchar *hostname);
|
||||
gboolean g_hostname_is_ascii_encoded (const gchar *hostname);
|
||||
gboolean g_hostname_is_ip_address (const gchar *hostname);
|
||||
|
||||
gchar *g_hostname_to_ascii (const gchar *hostname);
|
||||
gchar *g_hostname_to_unicode (const gchar *hostname);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_HOST_UTILS_H__ */
|
||||
38
glib/glib/gi18n-lib.h
Normal file
38
glib/glib/gi18n-lib.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997, 2002 Peter Mattis, Red Hat, Inc.
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __G_I18N_LIB_H__
|
||||
#define __G_I18N_LIB_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <libintl.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef GETTEXT_PACKAGE
|
||||
#error You must define GETTEXT_PACKAGE before including gi18n-lib.h. Did you forget to include config.h?
|
||||
#endif
|
||||
|
||||
#define _(String) ((char *) g_dgettext (GETTEXT_PACKAGE, String))
|
||||
#define Q_(String) g_dpgettext (GETTEXT_PACKAGE, String, 0)
|
||||
#define N_(String) (String)
|
||||
#define C_(Context,String) g_dpgettext (GETTEXT_PACKAGE, Context "\004" String, strlen (Context) + 1)
|
||||
#define NC_(Context, String) (String)
|
||||
|
||||
#endif /* __G_I18N_LIB_H__ */
|
||||
34
glib/glib/gi18n.h
Normal file
34
glib/glib/gi18n.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997, 2002 Peter Mattis, Red Hat, Inc.
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __G_I18N_H__
|
||||
#define __G_I18N_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <libintl.h>
|
||||
#include <string.h>
|
||||
|
||||
#define _(String) gettext (String)
|
||||
#define Q_(String) g_dpgettext (NULL, String, 0)
|
||||
#define N_(String) (String)
|
||||
#define C_(Context,String) g_dpgettext (NULL, Context "\004" String, strlen (Context) + 1)
|
||||
#define NC_(Context, String) (String)
|
||||
|
||||
#endif /* __G_I18N_H__ */
|
||||
2587
glib/glib/giochannel.c
Normal file
2587
glib/glib/giochannel.c
Normal file
File diff suppressed because it is too large
Load diff
374
glib/glib/giochannel.h
Normal file
374
glib/glib/giochannel.h
Normal file
|
|
@ -0,0 +1,374 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_IOCHANNEL_H__
|
||||
#define __G_IOCHANNEL_H__
|
||||
|
||||
#include <glib/gconvert.h>
|
||||
#include <glib/gmain.h>
|
||||
#include <glib/gstring.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* GIOChannel
|
||||
*/
|
||||
|
||||
typedef struct _GIOChannel GIOChannel;
|
||||
typedef struct _GIOFuncs GIOFuncs;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
G_IO_ERROR_NONE,
|
||||
G_IO_ERROR_AGAIN,
|
||||
G_IO_ERROR_INVAL,
|
||||
G_IO_ERROR_UNKNOWN
|
||||
} GIOError;
|
||||
|
||||
#define G_IO_CHANNEL_ERROR g_io_channel_error_quark()
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* Derived from errno */
|
||||
G_IO_CHANNEL_ERROR_FBIG,
|
||||
G_IO_CHANNEL_ERROR_INVAL,
|
||||
G_IO_CHANNEL_ERROR_IO,
|
||||
G_IO_CHANNEL_ERROR_ISDIR,
|
||||
G_IO_CHANNEL_ERROR_NOSPC,
|
||||
G_IO_CHANNEL_ERROR_NXIO,
|
||||
G_IO_CHANNEL_ERROR_OVERFLOW,
|
||||
G_IO_CHANNEL_ERROR_PIPE,
|
||||
/* Other */
|
||||
G_IO_CHANNEL_ERROR_FAILED
|
||||
} GIOChannelError;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
G_IO_STATUS_ERROR,
|
||||
G_IO_STATUS_NORMAL,
|
||||
G_IO_STATUS_EOF,
|
||||
G_IO_STATUS_AGAIN
|
||||
} GIOStatus;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
G_SEEK_CUR,
|
||||
G_SEEK_SET,
|
||||
G_SEEK_END
|
||||
} GSeekType;
|
||||
|
||||
typedef enum /*< flags >*/
|
||||
{
|
||||
G_IO_IN GLIB_SYSDEF_POLLIN,
|
||||
G_IO_OUT GLIB_SYSDEF_POLLOUT,
|
||||
G_IO_PRI GLIB_SYSDEF_POLLPRI,
|
||||
G_IO_ERR GLIB_SYSDEF_POLLERR,
|
||||
G_IO_HUP GLIB_SYSDEF_POLLHUP,
|
||||
G_IO_NVAL GLIB_SYSDEF_POLLNVAL
|
||||
} GIOCondition;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
G_IO_FLAG_APPEND = 1 << 0,
|
||||
G_IO_FLAG_NONBLOCK = 1 << 1,
|
||||
G_IO_FLAG_IS_READABLE = 1 << 2, /* Read only flag */
|
||||
G_IO_FLAG_IS_WRITABLE = 1 << 3, /* Read only flag */
|
||||
G_IO_FLAG_IS_SEEKABLE = 1 << 4, /* Read only flag */
|
||||
G_IO_FLAG_MASK = (1 << 5) - 1,
|
||||
G_IO_FLAG_GET_MASK = G_IO_FLAG_MASK,
|
||||
G_IO_FLAG_SET_MASK = G_IO_FLAG_APPEND | G_IO_FLAG_NONBLOCK
|
||||
} GIOFlags;
|
||||
|
||||
/* Misspelling in enum in 2.29.10 and earlier */
|
||||
#define G_IO_FLAG_IS_WRITEABLE (G_IO_FLAG_IS_WRITABLE)
|
||||
|
||||
struct _GIOChannel
|
||||
{
|
||||
/*< private >*/
|
||||
gint ref_count;
|
||||
GIOFuncs *funcs;
|
||||
|
||||
gchar *encoding;
|
||||
GIConv read_cd;
|
||||
GIConv write_cd;
|
||||
gchar *line_term; /* String which indicates the end of a line of text */
|
||||
guint line_term_len; /* So we can have null in the line term */
|
||||
|
||||
gsize buf_size;
|
||||
GString *read_buf; /* Raw data from the channel */
|
||||
GString *encoded_read_buf; /* Channel data converted to UTF-8 */
|
||||
GString *write_buf; /* Data ready to be written to the file */
|
||||
gchar partial_write_buf[6]; /* UTF-8 partial characters, null terminated */
|
||||
|
||||
/* Group the flags together, immediately after partial_write_buf, to save memory */
|
||||
|
||||
guint use_buffer : 1; /* The encoding uses the buffers */
|
||||
guint do_encode : 1; /* The encoding uses the GIConv coverters */
|
||||
guint close_on_unref : 1; /* Close the channel on final unref */
|
||||
guint is_readable : 1; /* Cached GIOFlag */
|
||||
guint is_writeable : 1; /* ditto */
|
||||
guint is_seekable : 1; /* ditto */
|
||||
|
||||
gpointer reserved1;
|
||||
gpointer reserved2;
|
||||
};
|
||||
|
||||
typedef gboolean (*GIOFunc) (GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
gpointer data);
|
||||
struct _GIOFuncs
|
||||
{
|
||||
GIOStatus (*io_read) (GIOChannel *channel,
|
||||
gchar *buf,
|
||||
gsize count,
|
||||
gsize *bytes_read,
|
||||
GError **err);
|
||||
GIOStatus (*io_write) (GIOChannel *channel,
|
||||
const gchar *buf,
|
||||
gsize count,
|
||||
gsize *bytes_written,
|
||||
GError **err);
|
||||
GIOStatus (*io_seek) (GIOChannel *channel,
|
||||
gint64 offset,
|
||||
GSeekType type,
|
||||
GError **err);
|
||||
GIOStatus (*io_close) (GIOChannel *channel,
|
||||
GError **err);
|
||||
GSource* (*io_create_watch) (GIOChannel *channel,
|
||||
GIOCondition condition);
|
||||
void (*io_free) (GIOChannel *channel);
|
||||
GIOStatus (*io_set_flags) (GIOChannel *channel,
|
||||
GIOFlags flags,
|
||||
GError **err);
|
||||
GIOFlags (*io_get_flags) (GIOChannel *channel);
|
||||
};
|
||||
|
||||
void g_io_channel_init (GIOChannel *channel);
|
||||
GIOChannel *g_io_channel_ref (GIOChannel *channel);
|
||||
void g_io_channel_unref (GIOChannel *channel);
|
||||
|
||||
GLIB_DEPRECATED_FOR(g_io_channel_read_for)
|
||||
GIOError g_io_channel_read (GIOChannel *channel,
|
||||
gchar *buf,
|
||||
gsize count,
|
||||
gsize *bytes_read);
|
||||
|
||||
GLIB_DEPRECATED_FOR(g_io_channel_write_chars)
|
||||
GIOError g_io_channel_write (GIOChannel *channel,
|
||||
const gchar *buf,
|
||||
gsize count,
|
||||
gsize *bytes_written);
|
||||
|
||||
GLIB_DEPRECATED_FOR(g_io_channel_seek_position)
|
||||
GIOError g_io_channel_seek (GIOChannel *channel,
|
||||
gint64 offset,
|
||||
GSeekType type);
|
||||
|
||||
GLIB_DEPRECATED_FOR(g_io_channel_shutdown)
|
||||
void g_io_channel_close (GIOChannel *channel);
|
||||
|
||||
GIOStatus g_io_channel_shutdown (GIOChannel *channel,
|
||||
gboolean flush,
|
||||
GError **err);
|
||||
guint g_io_add_watch_full (GIOChannel *channel,
|
||||
gint priority,
|
||||
GIOCondition condition,
|
||||
GIOFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify);
|
||||
GSource * g_io_create_watch (GIOChannel *channel,
|
||||
GIOCondition condition);
|
||||
guint g_io_add_watch (GIOChannel *channel,
|
||||
GIOCondition condition,
|
||||
GIOFunc func,
|
||||
gpointer user_data);
|
||||
|
||||
/* character encoding conversion involved functions.
|
||||
*/
|
||||
|
||||
void g_io_channel_set_buffer_size (GIOChannel *channel,
|
||||
gsize size);
|
||||
gsize g_io_channel_get_buffer_size (GIOChannel *channel);
|
||||
GIOCondition g_io_channel_get_buffer_condition (GIOChannel *channel);
|
||||
GIOStatus g_io_channel_set_flags (GIOChannel *channel,
|
||||
GIOFlags flags,
|
||||
GError **error);
|
||||
GIOFlags g_io_channel_get_flags (GIOChannel *channel);
|
||||
void g_io_channel_set_line_term (GIOChannel *channel,
|
||||
const gchar *line_term,
|
||||
gint length);
|
||||
const gchar * g_io_channel_get_line_term (GIOChannel *channel,
|
||||
gint *length);
|
||||
void g_io_channel_set_buffered (GIOChannel *channel,
|
||||
gboolean buffered);
|
||||
gboolean g_io_channel_get_buffered (GIOChannel *channel);
|
||||
GIOStatus g_io_channel_set_encoding (GIOChannel *channel,
|
||||
const gchar *encoding,
|
||||
GError **error);
|
||||
const gchar * g_io_channel_get_encoding (GIOChannel *channel);
|
||||
void g_io_channel_set_close_on_unref (GIOChannel *channel,
|
||||
gboolean do_close);
|
||||
gboolean g_io_channel_get_close_on_unref (GIOChannel *channel);
|
||||
|
||||
|
||||
GIOStatus g_io_channel_flush (GIOChannel *channel,
|
||||
GError **error);
|
||||
GIOStatus g_io_channel_read_line (GIOChannel *channel,
|
||||
gchar **str_return,
|
||||
gsize *length,
|
||||
gsize *terminator_pos,
|
||||
GError **error);
|
||||
GIOStatus g_io_channel_read_line_string (GIOChannel *channel,
|
||||
GString *buffer,
|
||||
gsize *terminator_pos,
|
||||
GError **error);
|
||||
GIOStatus g_io_channel_read_to_end (GIOChannel *channel,
|
||||
gchar **str_return,
|
||||
gsize *length,
|
||||
GError **error);
|
||||
GIOStatus g_io_channel_read_chars (GIOChannel *channel,
|
||||
gchar *buf,
|
||||
gsize count,
|
||||
gsize *bytes_read,
|
||||
GError **error);
|
||||
GIOStatus g_io_channel_read_unichar (GIOChannel *channel,
|
||||
gunichar *thechar,
|
||||
GError **error);
|
||||
GIOStatus g_io_channel_write_chars (GIOChannel *channel,
|
||||
const gchar *buf,
|
||||
gssize count,
|
||||
gsize *bytes_written,
|
||||
GError **error);
|
||||
GIOStatus g_io_channel_write_unichar (GIOChannel *channel,
|
||||
gunichar thechar,
|
||||
GError **error);
|
||||
GIOStatus g_io_channel_seek_position (GIOChannel *channel,
|
||||
gint64 offset,
|
||||
GSeekType type,
|
||||
GError **error);
|
||||
#ifdef G_OS_WIN32
|
||||
#define g_io_channel_new_file g_io_channel_new_file_utf8
|
||||
#endif
|
||||
|
||||
GIOChannel* g_io_channel_new_file (const gchar *filename,
|
||||
const gchar *mode,
|
||||
GError **error);
|
||||
|
||||
/* Error handling */
|
||||
|
||||
GQuark g_io_channel_error_quark (void);
|
||||
GIOChannelError g_io_channel_error_from_errno (gint en);
|
||||
|
||||
/* On Unix, IO channels created with this function for any file
|
||||
* descriptor or socket.
|
||||
*
|
||||
* On Win32, this can be used either for files opened with the MSVCRT
|
||||
* (the Microsoft run-time C library) _open() or _pipe, including file
|
||||
* descriptors 0, 1 and 2 (corresponding to stdin, stdout and stderr),
|
||||
* or for Winsock SOCKETs. If the parameter is a legal file
|
||||
* descriptor, it is assumed to be such, otherwise it should be a
|
||||
* SOCKET. This relies on SOCKETs and file descriptors not
|
||||
* overlapping. If you want to be certain, call either
|
||||
* g_io_channel_win32_new_fd() or g_io_channel_win32_new_socket()
|
||||
* instead as appropriate.
|
||||
*
|
||||
* The term file descriptor as used in the context of Win32 refers to
|
||||
* the emulated Unix-like file descriptors MSVCRT provides. The native
|
||||
* corresponding concept is file HANDLE. There isn't as of yet a way to
|
||||
* get GIOChannels for Win32 file HANDLEs.
|
||||
*/
|
||||
GIOChannel* g_io_channel_unix_new (int fd);
|
||||
gint g_io_channel_unix_get_fd (GIOChannel *channel);
|
||||
|
||||
|
||||
/* Hook for GClosure / GSource integration. Don't touch */
|
||||
GLIB_VAR GSourceFuncs g_io_watch_funcs;
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
|
||||
/* You can use this "pseudo file descriptor" in a GPollFD to add
|
||||
* polling for Windows messages. GTK applications should not do that.
|
||||
*/
|
||||
|
||||
#define G_WIN32_MSG_HANDLE 19981206
|
||||
|
||||
/* Use this to get a GPollFD from a GIOChannel, so that you can call
|
||||
* g_io_channel_win32_poll(). After calling this you should only use
|
||||
* g_io_channel_read() to read from the GIOChannel, i.e. never read()
|
||||
* from the underlying file descriptor. For SOCKETs, it is possible to call
|
||||
* recv().
|
||||
*/
|
||||
void g_io_channel_win32_make_pollfd (GIOChannel *channel,
|
||||
GIOCondition condition,
|
||||
GPollFD *fd);
|
||||
|
||||
/* This can be used to wait a until at least one of the channels is readable.
|
||||
* On Unix you would do a select() on the file descriptors of the channels.
|
||||
*/
|
||||
gint g_io_channel_win32_poll (GPollFD *fds,
|
||||
gint n_fds,
|
||||
gint timeout_);
|
||||
|
||||
/* Create an IO channel for Windows messages for window handle hwnd. */
|
||||
#if GLIB_SIZEOF_VOID_P == 8
|
||||
/* We use gsize here so that it is still an integer type and not a
|
||||
* pointer, like the guint in the traditional prototype. We can't use
|
||||
* intptr_t as that is not portable enough.
|
||||
*/
|
||||
GIOChannel *g_io_channel_win32_new_messages (gsize hwnd);
|
||||
#else
|
||||
GIOChannel *g_io_channel_win32_new_messages (guint hwnd);
|
||||
#endif
|
||||
|
||||
/* Create an IO channel for C runtime (emulated Unix-like) file
|
||||
* descriptors. After calling g_io_add_watch() on a IO channel
|
||||
* returned by this function, you shouldn't call read() on the file
|
||||
* descriptor. This is because adding polling for a file descriptor is
|
||||
* implemented on Win32 by starting a thread that sits blocked in a
|
||||
* read() from the file descriptor most of the time. All reads from
|
||||
* the file descriptor should be done by this internal GLib
|
||||
* thread. Your code should call only g_io_channel_read_chars().
|
||||
*/
|
||||
GIOChannel* g_io_channel_win32_new_fd (gint fd);
|
||||
|
||||
/* Get the C runtime file descriptor of a channel. */
|
||||
gint g_io_channel_win32_get_fd (GIOChannel *channel);
|
||||
|
||||
/* Create an IO channel for a winsock socket. The parameter should be
|
||||
* a SOCKET. Contrary to IO channels for file descriptors (on *Win32),
|
||||
* you can use normal recv() or recvfrom() on sockets even if GLib
|
||||
* is polling them.
|
||||
*/
|
||||
GIOChannel *g_io_channel_win32_new_socket (gint socket);
|
||||
|
||||
#endif
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_IOCHANNEL_H__ */
|
||||
658
glib/glib/giounix.c
Normal file
658
glib/glib/giounix.c
Normal file
|
|
@ -0,0 +1,658 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* giounix.c: IO Channels using unix file descriptors
|
||||
* Copyright 1998 Owen Taylor
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define _POSIX_SOURCE /* for SSIZE_MAX */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "giochannel.h"
|
||||
|
||||
#include "gerror.h"
|
||||
#include "gfileutils.h"
|
||||
#include "gstrfuncs.h"
|
||||
#include "gtestutils.h"
|
||||
|
||||
/*
|
||||
* Unix IO Channels
|
||||
*/
|
||||
|
||||
typedef struct _GIOUnixChannel GIOUnixChannel;
|
||||
typedef struct _GIOUnixWatch GIOUnixWatch;
|
||||
|
||||
struct _GIOUnixChannel
|
||||
{
|
||||
GIOChannel channel;
|
||||
gint fd;
|
||||
};
|
||||
|
||||
struct _GIOUnixWatch
|
||||
{
|
||||
GSource source;
|
||||
GPollFD pollfd;
|
||||
GIOChannel *channel;
|
||||
GIOCondition condition;
|
||||
};
|
||||
|
||||
|
||||
static GIOStatus g_io_unix_read (GIOChannel *channel,
|
||||
gchar *buf,
|
||||
gsize count,
|
||||
gsize *bytes_read,
|
||||
GError **err);
|
||||
static GIOStatus g_io_unix_write (GIOChannel *channel,
|
||||
const gchar *buf,
|
||||
gsize count,
|
||||
gsize *bytes_written,
|
||||
GError **err);
|
||||
static GIOStatus g_io_unix_seek (GIOChannel *channel,
|
||||
gint64 offset,
|
||||
GSeekType type,
|
||||
GError **err);
|
||||
static GIOStatus g_io_unix_close (GIOChannel *channel,
|
||||
GError **err);
|
||||
static void g_io_unix_free (GIOChannel *channel);
|
||||
static GSource* g_io_unix_create_watch (GIOChannel *channel,
|
||||
GIOCondition condition);
|
||||
static GIOStatus g_io_unix_set_flags (GIOChannel *channel,
|
||||
GIOFlags flags,
|
||||
GError **err);
|
||||
static GIOFlags g_io_unix_get_flags (GIOChannel *channel);
|
||||
|
||||
static gboolean g_io_unix_prepare (GSource *source,
|
||||
gint *timeout);
|
||||
static gboolean g_io_unix_check (GSource *source);
|
||||
static gboolean g_io_unix_dispatch (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data);
|
||||
static void g_io_unix_finalize (GSource *source);
|
||||
|
||||
GSourceFuncs g_io_watch_funcs = {
|
||||
g_io_unix_prepare,
|
||||
g_io_unix_check,
|
||||
g_io_unix_dispatch,
|
||||
g_io_unix_finalize
|
||||
};
|
||||
|
||||
static GIOFuncs unix_channel_funcs = {
|
||||
g_io_unix_read,
|
||||
g_io_unix_write,
|
||||
g_io_unix_seek,
|
||||
g_io_unix_close,
|
||||
g_io_unix_create_watch,
|
||||
g_io_unix_free,
|
||||
g_io_unix_set_flags,
|
||||
g_io_unix_get_flags,
|
||||
};
|
||||
|
||||
static gboolean
|
||||
g_io_unix_prepare (GSource *source,
|
||||
gint *timeout)
|
||||
{
|
||||
GIOUnixWatch *watch = (GIOUnixWatch *)source;
|
||||
GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
|
||||
|
||||
*timeout = -1;
|
||||
|
||||
/* Only return TRUE here if _all_ bits in watch->condition will be set
|
||||
*/
|
||||
return ((watch->condition & buffer_condition) == watch->condition);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_io_unix_check (GSource *source)
|
||||
{
|
||||
GIOUnixWatch *watch = (GIOUnixWatch *)source;
|
||||
GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
|
||||
GIOCondition poll_condition = watch->pollfd.revents;
|
||||
|
||||
return ((poll_condition | buffer_condition) & watch->condition);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_io_unix_dispatch (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
|
||||
{
|
||||
GIOFunc func = (GIOFunc)callback;
|
||||
GIOUnixWatch *watch = (GIOUnixWatch *)source;
|
||||
GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
|
||||
|
||||
if (!func)
|
||||
{
|
||||
g_warning ("IO watch dispatched without callback\n"
|
||||
"You must call g_source_connect().");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return (*func) (watch->channel,
|
||||
(watch->pollfd.revents | buffer_condition) & watch->condition,
|
||||
user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
g_io_unix_finalize (GSource *source)
|
||||
{
|
||||
GIOUnixWatch *watch = (GIOUnixWatch *)source;
|
||||
|
||||
g_io_channel_unref (watch->channel);
|
||||
}
|
||||
|
||||
static GIOStatus
|
||||
g_io_unix_read (GIOChannel *channel,
|
||||
gchar *buf,
|
||||
gsize count,
|
||||
gsize *bytes_read,
|
||||
GError **err)
|
||||
{
|
||||
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
|
||||
gssize result;
|
||||
|
||||
if (count > SSIZE_MAX) /* At least according to the Debian manpage for read */
|
||||
count = SSIZE_MAX;
|
||||
|
||||
retry:
|
||||
result = read (unix_channel->fd, buf, count);
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
int errsv = errno;
|
||||
*bytes_read = 0;
|
||||
|
||||
switch (errsv)
|
||||
{
|
||||
#ifdef EINTR
|
||||
case EINTR:
|
||||
goto retry;
|
||||
#endif
|
||||
#ifdef EAGAIN
|
||||
case EAGAIN:
|
||||
return G_IO_STATUS_AGAIN;
|
||||
#endif
|
||||
default:
|
||||
g_set_error_literal (err, G_IO_CHANNEL_ERROR,
|
||||
g_io_channel_error_from_errno (errsv),
|
||||
g_strerror (errsv));
|
||||
return G_IO_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
*bytes_read = result;
|
||||
|
||||
return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
|
||||
}
|
||||
|
||||
static GIOStatus
|
||||
g_io_unix_write (GIOChannel *channel,
|
||||
const gchar *buf,
|
||||
gsize count,
|
||||
gsize *bytes_written,
|
||||
GError **err)
|
||||
{
|
||||
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
|
||||
gssize result;
|
||||
|
||||
retry:
|
||||
result = write (unix_channel->fd, buf, count);
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
int errsv = errno;
|
||||
*bytes_written = 0;
|
||||
|
||||
switch (errsv)
|
||||
{
|
||||
#ifdef EINTR
|
||||
case EINTR:
|
||||
goto retry;
|
||||
#endif
|
||||
#ifdef EAGAIN
|
||||
case EAGAIN:
|
||||
return G_IO_STATUS_AGAIN;
|
||||
#endif
|
||||
default:
|
||||
g_set_error_literal (err, G_IO_CHANNEL_ERROR,
|
||||
g_io_channel_error_from_errno (errsv),
|
||||
g_strerror (errsv));
|
||||
return G_IO_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
*bytes_written = result;
|
||||
|
||||
return G_IO_STATUS_NORMAL;
|
||||
}
|
||||
|
||||
static GIOStatus
|
||||
g_io_unix_seek (GIOChannel *channel,
|
||||
gint64 offset,
|
||||
GSeekType type,
|
||||
GError **err)
|
||||
{
|
||||
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
|
||||
int whence;
|
||||
off_t tmp_offset;
|
||||
off_t result;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case G_SEEK_SET:
|
||||
whence = SEEK_SET;
|
||||
break;
|
||||
case G_SEEK_CUR:
|
||||
whence = SEEK_CUR;
|
||||
break;
|
||||
case G_SEEK_END:
|
||||
whence = SEEK_END;
|
||||
break;
|
||||
default:
|
||||
whence = -1; /* Shut the compiler up */
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
tmp_offset = offset;
|
||||
if (tmp_offset != offset)
|
||||
{
|
||||
g_set_error_literal (err, G_IO_CHANNEL_ERROR,
|
||||
g_io_channel_error_from_errno (EINVAL),
|
||||
g_strerror (EINVAL));
|
||||
return G_IO_STATUS_ERROR;
|
||||
}
|
||||
|
||||
result = lseek (unix_channel->fd, tmp_offset, whence);
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
int errsv = errno;
|
||||
g_set_error_literal (err, G_IO_CHANNEL_ERROR,
|
||||
g_io_channel_error_from_errno (errsv),
|
||||
g_strerror (errsv));
|
||||
return G_IO_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return G_IO_STATUS_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
static GIOStatus
|
||||
g_io_unix_close (GIOChannel *channel,
|
||||
GError **err)
|
||||
{
|
||||
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
|
||||
|
||||
if (close (unix_channel->fd) < 0)
|
||||
{
|
||||
int errsv = errno;
|
||||
g_set_error_literal (err, G_IO_CHANNEL_ERROR,
|
||||
g_io_channel_error_from_errno (errsv),
|
||||
g_strerror (errsv));
|
||||
return G_IO_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return G_IO_STATUS_NORMAL;
|
||||
}
|
||||
|
||||
static void
|
||||
g_io_unix_free (GIOChannel *channel)
|
||||
{
|
||||
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
|
||||
|
||||
g_free (unix_channel);
|
||||
}
|
||||
|
||||
static GSource *
|
||||
g_io_unix_create_watch (GIOChannel *channel,
|
||||
GIOCondition condition)
|
||||
{
|
||||
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
|
||||
GSource *source;
|
||||
GIOUnixWatch *watch;
|
||||
|
||||
|
||||
source = g_source_new (&g_io_watch_funcs, sizeof (GIOUnixWatch));
|
||||
g_source_set_name (source, "GIOChannel (Unix)");
|
||||
watch = (GIOUnixWatch *)source;
|
||||
|
||||
watch->channel = channel;
|
||||
g_io_channel_ref (channel);
|
||||
|
||||
watch->condition = condition;
|
||||
|
||||
watch->pollfd.fd = unix_channel->fd;
|
||||
watch->pollfd.events = condition;
|
||||
|
||||
g_source_add_poll (source, &watch->pollfd);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
static GIOStatus
|
||||
g_io_unix_set_flags (GIOChannel *channel,
|
||||
GIOFlags flags,
|
||||
GError **err)
|
||||
{
|
||||
glong fcntl_flags;
|
||||
GIOUnixChannel *unix_channel = (GIOUnixChannel *) channel;
|
||||
|
||||
fcntl_flags = 0;
|
||||
|
||||
if (flags & G_IO_FLAG_APPEND)
|
||||
fcntl_flags |= O_APPEND;
|
||||
if (flags & G_IO_FLAG_NONBLOCK)
|
||||
#ifdef O_NONBLOCK
|
||||
fcntl_flags |= O_NONBLOCK;
|
||||
#else
|
||||
fcntl_flags |= O_NDELAY;
|
||||
#endif
|
||||
|
||||
if (fcntl (unix_channel->fd, F_SETFL, fcntl_flags) == -1)
|
||||
{
|
||||
int errsv = errno;
|
||||
g_set_error_literal (err, G_IO_CHANNEL_ERROR,
|
||||
g_io_channel_error_from_errno (errsv),
|
||||
g_strerror (errsv));
|
||||
return G_IO_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return G_IO_STATUS_NORMAL;
|
||||
}
|
||||
|
||||
static GIOFlags
|
||||
g_io_unix_get_flags (GIOChannel *channel)
|
||||
{
|
||||
GIOFlags flags = 0;
|
||||
glong fcntl_flags;
|
||||
GIOUnixChannel *unix_channel = (GIOUnixChannel *) channel;
|
||||
|
||||
fcntl_flags = fcntl (unix_channel->fd, F_GETFL);
|
||||
|
||||
if (fcntl_flags == -1)
|
||||
{
|
||||
int err = errno;
|
||||
g_warning (G_STRLOC "Error while getting flags for FD: %s (%d)\n",
|
||||
g_strerror (err), err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fcntl_flags & O_APPEND)
|
||||
flags |= G_IO_FLAG_APPEND;
|
||||
#ifdef O_NONBLOCK
|
||||
if (fcntl_flags & O_NONBLOCK)
|
||||
#else
|
||||
if (fcntl_flags & O_NDELAY)
|
||||
#endif
|
||||
flags |= G_IO_FLAG_NONBLOCK;
|
||||
|
||||
switch (fcntl_flags & (O_RDONLY | O_WRONLY | O_RDWR))
|
||||
{
|
||||
case O_RDONLY:
|
||||
channel->is_readable = TRUE;
|
||||
channel->is_writeable = FALSE;
|
||||
break;
|
||||
case O_WRONLY:
|
||||
channel->is_readable = FALSE;
|
||||
channel->is_writeable = TRUE;
|
||||
break;
|
||||
case O_RDWR:
|
||||
channel->is_readable = TRUE;
|
||||
channel->is_writeable = TRUE;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
GIOChannel *
|
||||
g_io_channel_new_file (const gchar *filename,
|
||||
const gchar *mode,
|
||||
GError **error)
|
||||
{
|
||||
int fid, flags;
|
||||
mode_t create_mode;
|
||||
GIOChannel *channel;
|
||||
enum { /* Cheesy hack */
|
||||
MODE_R = 1 << 0,
|
||||
MODE_W = 1 << 1,
|
||||
MODE_A = 1 << 2,
|
||||
MODE_PLUS = 1 << 3,
|
||||
MODE_R_PLUS = MODE_R | MODE_PLUS,
|
||||
MODE_W_PLUS = MODE_W | MODE_PLUS,
|
||||
MODE_A_PLUS = MODE_A | MODE_PLUS
|
||||
} mode_num;
|
||||
struct stat buffer;
|
||||
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
g_return_val_if_fail (mode != NULL, NULL);
|
||||
g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
|
||||
|
||||
switch (mode[0])
|
||||
{
|
||||
case 'r':
|
||||
mode_num = MODE_R;
|
||||
break;
|
||||
case 'w':
|
||||
mode_num = MODE_W;
|
||||
break;
|
||||
case 'a':
|
||||
mode_num = MODE_A;
|
||||
break;
|
||||
default:
|
||||
g_warning ("Invalid GIOFileMode %s.\n", mode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (mode[1])
|
||||
{
|
||||
case '\0':
|
||||
break;
|
||||
case '+':
|
||||
if (mode[2] == '\0')
|
||||
{
|
||||
mode_num |= MODE_PLUS;
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
default:
|
||||
g_warning ("Invalid GIOFileMode %s.\n", mode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (mode_num)
|
||||
{
|
||||
case MODE_R:
|
||||
flags = O_RDONLY;
|
||||
break;
|
||||
case MODE_W:
|
||||
flags = O_WRONLY | O_TRUNC | O_CREAT;
|
||||
break;
|
||||
case MODE_A:
|
||||
flags = O_WRONLY | O_APPEND | O_CREAT;
|
||||
break;
|
||||
case MODE_R_PLUS:
|
||||
flags = O_RDWR;
|
||||
break;
|
||||
case MODE_W_PLUS:
|
||||
flags = O_RDWR | O_TRUNC | O_CREAT;
|
||||
break;
|
||||
case MODE_A_PLUS:
|
||||
flags = O_RDWR | O_APPEND | O_CREAT;
|
||||
break;
|
||||
case MODE_PLUS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
flags = 0;
|
||||
}
|
||||
|
||||
create_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
||||
|
||||
do
|
||||
{
|
||||
fid = open (filename, flags, create_mode);
|
||||
}
|
||||
while (fid == -1 && errno == EINTR);
|
||||
|
||||
if (fid == -1)
|
||||
{
|
||||
int err = errno;
|
||||
g_set_error_literal (error, G_FILE_ERROR,
|
||||
g_file_error_from_errno (err),
|
||||
g_strerror (err));
|
||||
return (GIOChannel *)NULL;
|
||||
}
|
||||
|
||||
if (fstat (fid, &buffer) == -1) /* In case someone opens a FIFO */
|
||||
{
|
||||
int err = errno;
|
||||
close (fid);
|
||||
g_set_error_literal (error, G_FILE_ERROR,
|
||||
g_file_error_from_errno (err),
|
||||
g_strerror (err));
|
||||
return (GIOChannel *)NULL;
|
||||
}
|
||||
|
||||
channel = (GIOChannel *) g_new (GIOUnixChannel, 1);
|
||||
|
||||
channel->is_seekable = S_ISREG (buffer.st_mode) || S_ISCHR (buffer.st_mode)
|
||||
|| S_ISBLK (buffer.st_mode);
|
||||
|
||||
switch (mode_num)
|
||||
{
|
||||
case MODE_R:
|
||||
channel->is_readable = TRUE;
|
||||
channel->is_writeable = FALSE;
|
||||
break;
|
||||
case MODE_W:
|
||||
case MODE_A:
|
||||
channel->is_readable = FALSE;
|
||||
channel->is_writeable = TRUE;
|
||||
break;
|
||||
case MODE_R_PLUS:
|
||||
case MODE_W_PLUS:
|
||||
case MODE_A_PLUS:
|
||||
channel->is_readable = TRUE;
|
||||
channel->is_writeable = TRUE;
|
||||
break;
|
||||
case MODE_PLUS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
g_io_channel_init (channel);
|
||||
channel->close_on_unref = TRUE; /* must be after g_io_channel_init () */
|
||||
channel->funcs = &unix_channel_funcs;
|
||||
|
||||
((GIOUnixChannel *) channel)->fd = fid;
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_io_channel_unix_new:
|
||||
* @fd: a file descriptor.
|
||||
* @Returns: a new #GIOChannel.
|
||||
*
|
||||
* Creates a new #GIOChannel given a file descriptor. On UNIX systems
|
||||
* this works for plain files, pipes, and sockets.
|
||||
*
|
||||
* The returned #GIOChannel has a reference count of 1.
|
||||
*
|
||||
* The default encoding for #GIOChannel is UTF-8. If your application
|
||||
* is reading output from a command using via pipe, you may need to set
|
||||
* the encoding to the encoding of the current locale (see
|
||||
* g_get_charset()) with the g_io_channel_set_encoding() function.
|
||||
*
|
||||
* If you want to read raw binary data without interpretation, then
|
||||
* call the g_io_channel_set_encoding() function with %NULL for the
|
||||
* encoding argument.
|
||||
*
|
||||
* This function is available in GLib on Windows, too, but you should
|
||||
* avoid using it on Windows. The domain of file descriptors and
|
||||
* sockets overlap. There is no way for GLib to know which one you mean
|
||||
* in case the argument you pass to this function happens to be both a
|
||||
* valid file descriptor and socket. If that happens a warning is
|
||||
* issued, and GLib assumes that it is the file descriptor you mean.
|
||||
**/
|
||||
GIOChannel *
|
||||
g_io_channel_unix_new (gint fd)
|
||||
{
|
||||
struct stat buffer;
|
||||
GIOUnixChannel *unix_channel = g_new (GIOUnixChannel, 1);
|
||||
GIOChannel *channel = (GIOChannel *)unix_channel;
|
||||
|
||||
g_io_channel_init (channel);
|
||||
channel->funcs = &unix_channel_funcs;
|
||||
|
||||
unix_channel->fd = fd;
|
||||
|
||||
/* I'm not sure if fstat on a non-file (e.g., socket) works
|
||||
* it should be safe to say if it fails, the fd isn't seekable.
|
||||
*/
|
||||
/* Newer UNIX versions support S_ISSOCK(), fstat() will probably
|
||||
* succeed in most cases.
|
||||
*/
|
||||
if (fstat (unix_channel->fd, &buffer) == 0)
|
||||
channel->is_seekable = S_ISREG (buffer.st_mode) || S_ISCHR (buffer.st_mode)
|
||||
|| S_ISBLK (buffer.st_mode);
|
||||
else /* Assume not seekable */
|
||||
channel->is_seekable = FALSE;
|
||||
|
||||
g_io_unix_get_flags (channel); /* Sets is_readable, is_writeable */
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_io_channel_unix_get_fd:
|
||||
* @channel: a #GIOChannel, created with g_io_channel_unix_new().
|
||||
* @Returns: the file descriptor of the #GIOChannel.
|
||||
*
|
||||
* Returns the file descriptor of the #GIOChannel.
|
||||
*
|
||||
* On Windows this function returns the file descriptor or socket of
|
||||
* the #GIOChannel.
|
||||
**/
|
||||
gint
|
||||
g_io_channel_unix_get_fd (GIOChannel *channel)
|
||||
{
|
||||
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
|
||||
return unix_channel->fd;
|
||||
}
|
||||
2241
glib/glib/giowin32.c
Normal file
2241
glib/glib/giowin32.c
Normal file
File diff suppressed because it is too large
Load diff
4383
glib/glib/gkeyfile.c
Normal file
4383
glib/glib/gkeyfile.c
Normal file
File diff suppressed because it is too large
Load diff
268
glib/glib/gkeyfile.h
Normal file
268
glib/glib/gkeyfile.h
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
/* gkeyfile.h - desktop entry file parser
|
||||
*
|
||||
* Copyright 2004 Red Hat, Inc.
|
||||
*
|
||||
* Ray Strode <halfline@hawaii.rr.com>
|
||||
*
|
||||
* GLib 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 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* GLib 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 GLib; see the file COPYING.LIB. If not,
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __G_KEY_FILE_H__
|
||||
#define __G_KEY_FILE_H__
|
||||
|
||||
#include <glib/gerror.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum
|
||||
{
|
||||
G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
|
||||
G_KEY_FILE_ERROR_PARSE,
|
||||
G_KEY_FILE_ERROR_NOT_FOUND,
|
||||
G_KEY_FILE_ERROR_KEY_NOT_FOUND,
|
||||
G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
|
||||
G_KEY_FILE_ERROR_INVALID_VALUE
|
||||
} GKeyFileError;
|
||||
|
||||
#define G_KEY_FILE_ERROR g_key_file_error_quark()
|
||||
|
||||
GQuark g_key_file_error_quark (void);
|
||||
|
||||
typedef struct _GKeyFile GKeyFile;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
G_KEY_FILE_NONE = 0,
|
||||
G_KEY_FILE_KEEP_COMMENTS = 1 << 0,
|
||||
G_KEY_FILE_KEEP_TRANSLATIONS = 1 << 1
|
||||
} GKeyFileFlags;
|
||||
|
||||
GKeyFile *g_key_file_new (void);
|
||||
GKeyFile *g_key_file_ref (GKeyFile *key_file);
|
||||
void g_key_file_unref (GKeyFile *key_file);
|
||||
void g_key_file_free (GKeyFile *key_file);
|
||||
void g_key_file_set_list_separator (GKeyFile *key_file,
|
||||
gchar separator);
|
||||
gboolean g_key_file_load_from_file (GKeyFile *key_file,
|
||||
const gchar *file,
|
||||
GKeyFileFlags flags,
|
||||
GError **error);
|
||||
gboolean g_key_file_load_from_data (GKeyFile *key_file,
|
||||
const gchar *data,
|
||||
gsize length,
|
||||
GKeyFileFlags flags,
|
||||
GError **error);
|
||||
gboolean g_key_file_load_from_dirs (GKeyFile *key_file,
|
||||
const gchar *file,
|
||||
const gchar **search_dirs,
|
||||
gchar **full_path,
|
||||
GKeyFileFlags flags,
|
||||
GError **error);
|
||||
gboolean g_key_file_load_from_data_dirs (GKeyFile *key_file,
|
||||
const gchar *file,
|
||||
gchar **full_path,
|
||||
GKeyFileFlags flags,
|
||||
GError **error);
|
||||
gchar *g_key_file_to_data (GKeyFile *key_file,
|
||||
gsize *length,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
gchar *g_key_file_get_start_group (GKeyFile *key_file) G_GNUC_MALLOC;
|
||||
gchar **g_key_file_get_groups (GKeyFile *key_file,
|
||||
gsize *length) G_GNUC_MALLOC;
|
||||
gchar **g_key_file_get_keys (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
gsize *length,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
gboolean g_key_file_has_group (GKeyFile *key_file,
|
||||
const gchar *group_name);
|
||||
gboolean g_key_file_has_key (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
GError **error);
|
||||
gchar *g_key_file_get_value (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
void g_key_file_set_value (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
const gchar *value);
|
||||
gchar *g_key_file_get_string (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
void g_key_file_set_string (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
const gchar *string);
|
||||
gchar *g_key_file_get_locale_string (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
const gchar *locale,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
void g_key_file_set_locale_string (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
const gchar *locale,
|
||||
const gchar *string);
|
||||
gboolean g_key_file_get_boolean (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
GError **error);
|
||||
void g_key_file_set_boolean (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
gboolean value);
|
||||
gint g_key_file_get_integer (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
GError **error);
|
||||
void g_key_file_set_integer (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
gint value);
|
||||
gint64 g_key_file_get_int64 (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
GError **error);
|
||||
void g_key_file_set_int64 (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
gint64 value);
|
||||
guint64 g_key_file_get_uint64 (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
GError **error);
|
||||
void g_key_file_set_uint64 (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
guint64 value);
|
||||
gdouble g_key_file_get_double (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
GError **error);
|
||||
void g_key_file_set_double (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
gdouble value);
|
||||
gchar **g_key_file_get_string_list (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
gsize *length,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
void g_key_file_set_string_list (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
const gchar * const list[],
|
||||
gsize length);
|
||||
gchar **g_key_file_get_locale_string_list (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
const gchar *locale,
|
||||
gsize *length,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
void g_key_file_set_locale_string_list (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
const gchar *locale,
|
||||
const gchar * const list[],
|
||||
gsize length);
|
||||
gboolean *g_key_file_get_boolean_list (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
gsize *length,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
void g_key_file_set_boolean_list (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
gboolean list[],
|
||||
gsize length);
|
||||
gint *g_key_file_get_integer_list (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
gsize *length,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
void g_key_file_set_double_list (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
gdouble list[],
|
||||
gsize length);
|
||||
gdouble *g_key_file_get_double_list (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
gsize *length,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
void g_key_file_set_integer_list (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
gint list[],
|
||||
gsize length);
|
||||
gboolean g_key_file_set_comment (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
const gchar *comment,
|
||||
GError **error);
|
||||
gchar *g_key_file_get_comment (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
GError **error) G_GNUC_MALLOC;
|
||||
|
||||
gboolean g_key_file_remove_comment (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
GError **error);
|
||||
gboolean g_key_file_remove_key (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
const gchar *key,
|
||||
GError **error);
|
||||
gboolean g_key_file_remove_group (GKeyFile *key_file,
|
||||
const gchar *group_name,
|
||||
GError **error);
|
||||
|
||||
/* Defines for handling freedesktop.org Desktop files */
|
||||
#define G_KEY_FILE_DESKTOP_GROUP "Desktop Entry"
|
||||
|
||||
#define G_KEY_FILE_DESKTOP_KEY_TYPE "Type"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_VERSION "Version"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_NAME "Name"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_GENERIC_NAME "GenericName"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY "NoDisplay"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_COMMENT "Comment"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_ICON "Icon"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_HIDDEN "Hidden"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_ONLY_SHOW_IN "OnlyShowIn"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_NOT_SHOW_IN "NotShowIn"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_TRY_EXEC "TryExec"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_EXEC "Exec"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_PATH "Path"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_TERMINAL "Terminal"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_MIME_TYPE "MimeType"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_CATEGORIES "Categories"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_STARTUP_NOTIFY "StartupNotify"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_STARTUP_WM_CLASS "StartupWMClass"
|
||||
#define G_KEY_FILE_DESKTOP_KEY_URL "URL"
|
||||
|
||||
#define G_KEY_FILE_DESKTOP_TYPE_APPLICATION "Application"
|
||||
#define G_KEY_FILE_DESKTOP_TYPE_LINK "Link"
|
||||
#define G_KEY_FILE_DESKTOP_TYPE_DIRECTORY "Directory"
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_KEY_FILE_H__ */
|
||||
269
glib/glib/glib-init.c
Normal file
269
glib/glib/glib-init.c
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
* Copyright © 2011 Canonical Limited
|
||||
*
|
||||
* 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 of the
|
||||
* licence, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*
|
||||
* Author: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "glib-init.h"
|
||||
|
||||
#include "gutils.h" /* for GDebugKey */
|
||||
#include "gconstructor.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/**
|
||||
* g_mem_gc_friendly:
|
||||
*
|
||||
* This variable is %TRUE if the <envar>G_DEBUG</envar> environment variable
|
||||
* includes the key <literal>gc-friendly</literal>.
|
||||
*/
|
||||
#ifdef ENABLE_GC_FRIENDLY_DEFAULT
|
||||
gboolean g_mem_gc_friendly = TRUE;
|
||||
#else
|
||||
gboolean g_mem_gc_friendly = FALSE;
|
||||
#endif
|
||||
GLogLevelFlags g_log_msg_prefix = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_WARNING |
|
||||
G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_DEBUG;
|
||||
GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK;
|
||||
|
||||
static gboolean
|
||||
debug_key_matches (const gchar *key,
|
||||
const gchar *token,
|
||||
guint length)
|
||||
{
|
||||
/* may not call GLib functions: see note in g_parse_debug_string() */
|
||||
for (; length; length--, key++, token++)
|
||||
{
|
||||
char k = (*key == '_') ? '-' : tolower (*key );
|
||||
char t = (*token == '_') ? '-' : tolower (*token);
|
||||
|
||||
if (k != t)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return *key == '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* g_parse_debug_string:
|
||||
* @string: (allow-none): a list of debug options separated by colons, spaces, or
|
||||
* commas, or %NULL.
|
||||
* @keys: (array length=nkeys): pointer to an array of #GDebugKey which associate
|
||||
* strings with bit flags.
|
||||
* @nkeys: the number of #GDebugKey<!-- -->s in the array.
|
||||
*
|
||||
* Parses a string containing debugging options
|
||||
* into a %guint containing bit flags. This is used
|
||||
* within GDK and GTK+ to parse the debug options passed on the
|
||||
* command line or through environment variables.
|
||||
*
|
||||
* If @string is equal to <code>"all"</code>, all flags are set. Any flags
|
||||
* specified along with <code>"all"</code> in @string are inverted; thus,
|
||||
* <code>"all,foo,bar"</code> or <code>"foo,bar,all"</code> sets all flags
|
||||
* except those corresponding to <code>"foo"</code> and <code>"bar"</code>.
|
||||
*
|
||||
* If @string is equal to <code>"help"</code>, all the available keys in @keys
|
||||
* are printed out to standard error.
|
||||
*
|
||||
* Returns: the combined set of bit flags.
|
||||
*/
|
||||
guint
|
||||
g_parse_debug_string (const gchar *string,
|
||||
const GDebugKey *keys,
|
||||
guint nkeys)
|
||||
{
|
||||
guint i;
|
||||
guint result = 0;
|
||||
|
||||
if (string == NULL)
|
||||
return 0;
|
||||
|
||||
/* this function is used during the initialisation of gmessages, gmem
|
||||
* and gslice, so it may not do anything that causes memory to be
|
||||
* allocated or risks messages being emitted.
|
||||
*
|
||||
* this means, more or less, that this code may not call anything
|
||||
* inside GLib.
|
||||
*/
|
||||
|
||||
if (!strcasecmp (string, "help"))
|
||||
{
|
||||
/* using stdio directly for the reason stated above */
|
||||
fprintf (stderr, "Supported debug values:");
|
||||
for (i = 0; i < nkeys; i++)
|
||||
fprintf (stderr, " %s", keys[i].key);
|
||||
fprintf (stderr, " all help\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
const gchar *p = string;
|
||||
const gchar *q;
|
||||
gboolean invert = FALSE;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
q = strpbrk (p, ":;, \t");
|
||||
if (!q)
|
||||
q = p + strlen (p);
|
||||
|
||||
if (debug_key_matches ("all", p, q - p))
|
||||
{
|
||||
invert = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < nkeys; i++)
|
||||
if (debug_key_matches (keys[i].key, p, q - p))
|
||||
result |= keys[i].value;
|
||||
}
|
||||
|
||||
p = q;
|
||||
if (*p)
|
||||
p++;
|
||||
}
|
||||
|
||||
if (invert)
|
||||
{
|
||||
guint all_flags = 0;
|
||||
|
||||
for (i = 0; i < nkeys; i++)
|
||||
all_flags |= keys[i].value;
|
||||
|
||||
result = all_flags & (~result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static guint
|
||||
g_parse_debug_envvar (const gchar *envvar,
|
||||
const GDebugKey *keys,
|
||||
gint n_keys,
|
||||
guint default_value)
|
||||
{
|
||||
const gchar *value;
|
||||
|
||||
#ifdef OS_WIN32
|
||||
/* "fatal-warnings,fatal-criticals,all,help" is pretty short */
|
||||
gchar buffer[100];
|
||||
|
||||
if (GetEnvironmentVariable (envvar, buffer, 100) < 100)
|
||||
value = buffer;
|
||||
else
|
||||
return 0;
|
||||
#else
|
||||
value = getenv (envvar);
|
||||
#endif
|
||||
|
||||
if (value == NULL)
|
||||
return default_value;
|
||||
|
||||
return g_parse_debug_string (value, keys, n_keys);
|
||||
}
|
||||
|
||||
static void
|
||||
g_messages_prefixed_init (void)
|
||||
{
|
||||
const GDebugKey keys[] = {
|
||||
{ "error", G_LOG_LEVEL_ERROR },
|
||||
{ "critical", G_LOG_LEVEL_CRITICAL },
|
||||
{ "warning", G_LOG_LEVEL_WARNING },
|
||||
{ "message", G_LOG_LEVEL_MESSAGE },
|
||||
{ "info", G_LOG_LEVEL_INFO },
|
||||
{ "debug", G_LOG_LEVEL_DEBUG }
|
||||
};
|
||||
|
||||
g_log_msg_prefix = g_parse_debug_envvar ("G_MESSAGES_PREFIXED", keys, G_N_ELEMENTS (keys), g_log_msg_prefix);
|
||||
}
|
||||
|
||||
static void
|
||||
g_debug_init (void)
|
||||
{
|
||||
const GDebugKey keys[] = {
|
||||
{ "gc-friendly", 1 },
|
||||
{"fatal-warnings", G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL },
|
||||
{"fatal-criticals", G_LOG_LEVEL_CRITICAL }
|
||||
};
|
||||
GLogLevelFlags flags;
|
||||
|
||||
flags = g_parse_debug_envvar ("G_DEBUG", keys, G_N_ELEMENTS (keys), 0);
|
||||
|
||||
g_log_always_fatal |= flags & G_LOG_LEVEL_MASK;
|
||||
|
||||
g_mem_gc_friendly = flags & 1;
|
||||
}
|
||||
|
||||
static void
|
||||
glib_init (void)
|
||||
{
|
||||
g_messages_prefixed_init ();
|
||||
g_debug_init ();
|
||||
}
|
||||
|
||||
#if defined (G_OS_WIN32)
|
||||
|
||||
HMODULE glib_dll;
|
||||
|
||||
BOOL WINAPI
|
||||
DllMain (HINSTANCE hinstDLL,
|
||||
DWORD fdwReason,
|
||||
LPVOID lpvReserved)
|
||||
{
|
||||
switch (fdwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
glib_dll = hinstDLL;
|
||||
g_clock_win32_init ();
|
||||
g_thread_win32_init ();
|
||||
glib_init ();
|
||||
break;
|
||||
|
||||
case DLL_THREAD_DETACH:
|
||||
g_thread_win32_thread_detach ();
|
||||
break;
|
||||
|
||||
default:
|
||||
/* do nothing */
|
||||
;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#elif defined (G_HAS_CONSTRUCTORS)
|
||||
|
||||
#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
|
||||
#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(glib_init_ctor)
|
||||
#endif
|
||||
G_DEFINE_CONSTRUCTOR(glib_init_ctor)
|
||||
|
||||
static void
|
||||
glib_init_ctor (void)
|
||||
{
|
||||
glib_init ();
|
||||
}
|
||||
|
||||
#else
|
||||
# error Your platform/compiler is missing constructor support
|
||||
#endif
|
||||
40
glib/glib/glib-init.h
Normal file
40
glib/glib/glib-init.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright © 2011 Canonical Limited
|
||||
*
|
||||
* 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 of the
|
||||
* licence, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*
|
||||
* Author: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#ifndef __GLIB_INIT_H__
|
||||
#define __GLIB_INIT_H__
|
||||
|
||||
#include "gmessages.h"
|
||||
|
||||
G_GNUC_INTERNAL extern GLogLevelFlags g_log_always_fatal;
|
||||
G_GNUC_INTERNAL extern GLogLevelFlags g_log_msg_prefix;
|
||||
GLIB_VAR gboolean g_mem_gc_friendly;
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include <windows.h>
|
||||
|
||||
G_GNUC_INTERNAL void g_thread_win32_thread_detach (void);
|
||||
G_GNUC_INTERNAL void g_thread_win32_init (void);
|
||||
G_GNUC_INTERNAL void g_clock_win32_init (void);
|
||||
G_GNUC_INTERNAL extern HMODULE glib_dll;
|
||||
#endif
|
||||
|
||||
#endif /* __GLIB_INIT_H__ */
|
||||
11
glib/glib/glib-mirroring-tab/Makefile
Normal file
11
glib/glib/glib-mirroring-tab/Makefile
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
CFLAGS = `pkg-config --cflags glib-2.0`
|
||||
LIBS = `pkg-config --libs glib-2.0`
|
||||
|
||||
|
||||
all: gen-mirroring-tab
|
||||
|
||||
gen-mirroring-tab: gen-mirroring-tab.o packtab.o
|
||||
|
||||
clean:
|
||||
$(RM) gen-mirroring-tab *.o
|
||||
232
glib/glib/glib-mirroring-tab/gen-mirroring-tab.c
Normal file
232
glib/glib/glib-mirroring-tab/gen-mirroring-tab.c
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
/* gen-mirroring-tab.c - generate gmirroringtable.h for glib
|
||||
* copied from FriBidi.
|
||||
*
|
||||
* $Id$
|
||||
* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
* $Source$
|
||||
*
|
||||
* Author:
|
||||
* Behdad Esfahbod, 2001, 2002, 2004
|
||||
*
|
||||
* Copyright (C) 2004 Sharif FarsiWeb, Inc
|
||||
* Copyright (C) 2001,2002,2004 Behdad Esfahbod
|
||||
*
|
||||
* 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, in a file named COPYING; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA
|
||||
*
|
||||
* For licensing issues, contact <license@farsiweb.info>.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "packtab.h"
|
||||
|
||||
#define appname "gen-mirroring-tab"
|
||||
#define outputname "gmirroringtable.h"
|
||||
|
||||
static void
|
||||
die (
|
||||
const char *msg
|
||||
)
|
||||
{
|
||||
fprintf (stderr, appname ": %s\n", msg);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
static void
|
||||
die2 (
|
||||
const char *fmt,
|
||||
const char *p
|
||||
)
|
||||
{
|
||||
fprintf (stderr, appname ": ");
|
||||
fprintf (stderr, fmt, p);
|
||||
fprintf (stderr, "\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
static void
|
||||
die4 (
|
||||
const char *fmt,
|
||||
unsigned long l,
|
||||
unsigned long p,
|
||||
unsigned long q
|
||||
)
|
||||
{
|
||||
fprintf (stderr, appname ": ");
|
||||
fprintf (stderr, fmt, l, p, q);
|
||||
fprintf (stderr, "\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
#define table_name "Mir"
|
||||
#define macro_name "GLIB_GET_MIRRORING"
|
||||
|
||||
#define UNICODE_CHARS 0x110000
|
||||
|
||||
static signed int table[UNICODE_CHARS];
|
||||
static char buf[4000];
|
||||
static signed long max_dist;
|
||||
|
||||
static void
|
||||
init (
|
||||
void
|
||||
)
|
||||
{
|
||||
max_dist = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_tab (
|
||||
void
|
||||
)
|
||||
{
|
||||
register gunichar c;
|
||||
|
||||
for (c = 0; c < UNICODE_CHARS; c++)
|
||||
table[c] = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
init_tab_mirroring_txt (
|
||||
void
|
||||
)
|
||||
{
|
||||
clear_tab ();
|
||||
}
|
||||
|
||||
static void
|
||||
read_bidi_mirroring_txt (
|
||||
FILE *f
|
||||
)
|
||||
{
|
||||
unsigned long l;
|
||||
|
||||
init_tab_mirroring_txt ();
|
||||
|
||||
l = 0;
|
||||
while (fgets (buf, sizeof buf, f))
|
||||
{
|
||||
unsigned long i, j;
|
||||
signed long dist;
|
||||
int k;
|
||||
const char *s = buf;
|
||||
|
||||
l++;
|
||||
|
||||
while (*s == ' ')
|
||||
s++;
|
||||
|
||||
if (s[0] == '#' || s[0] == '\0' || s[0] == '\n')
|
||||
continue;
|
||||
|
||||
k = sscanf (s, "%lx; %lx", &i, &j);
|
||||
if (k != 2 || i >= UNICODE_CHARS || j >= UNICODE_CHARS)
|
||||
die4 ("invalid pair in input at line %ld: %04lX, %04lX", l, i, j);
|
||||
dist = ((signed long) j - (signed long) i);
|
||||
table[i] = dist;
|
||||
if (dist > max_dist)
|
||||
max_dist = dist;
|
||||
else if (-dist > max_dist)
|
||||
max_dist = -dist;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
read_data (
|
||||
const char *data_file_type,
|
||||
const char *data_file_name
|
||||
)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
fprintf (stderr, "Reading `%s'\n", data_file_name);
|
||||
if (!(f = fopen (data_file_name, "rt")))
|
||||
die2 ("error: cannot open `%s' for reading", data_file_name);
|
||||
|
||||
if (!strcmp (data_file_type, "BidiMirroring.txt"))
|
||||
read_bidi_mirroring_txt (f);
|
||||
else
|
||||
die2 ("error: unknown data-file-type %s", data_file_type);
|
||||
|
||||
fclose (f);
|
||||
}
|
||||
|
||||
static void
|
||||
gen_mirroring_tab (
|
||||
int max_depth,
|
||||
const char *data_file_type
|
||||
)
|
||||
{
|
||||
int key_bytes;
|
||||
const char *key_type;
|
||||
|
||||
fprintf (stderr,
|
||||
"Generating `" outputname "', it may take up to a few minutes\n");
|
||||
printf ("/* " outputname "\n * generated by " appname " "
|
||||
"\n" " * from the file %s of */\n\n", data_file_type);
|
||||
|
||||
printf ("#define PACKTAB_UINT8 guint8\n"
|
||||
"#define PACKTAB_UINT16 guint16\n"
|
||||
"#define PACKTAB_UINT32 guint32\n\n");
|
||||
|
||||
key_bytes = max_dist <= 0x7f ? 1 : max_dist < 0x7fff ? 2 : 4;
|
||||
key_type = key_bytes == 1 ? "gint8" : key_bytes == 2 ?
|
||||
"gint16" : "gint32";
|
||||
|
||||
if (!pack_table
|
||||
(table, UNICODE_CHARS, key_bytes, 0, max_depth, 1, NULL,
|
||||
key_type, table_name, macro_name "_DELTA", stdout))
|
||||
die ("error: insufficient memory, decrease max_depth");
|
||||
|
||||
printf ("#undef PACKTAB_UINT8\n"
|
||||
"#undef PACKTAB_UINT16\n" "#undef PACKTAB_UINT32\n\n");
|
||||
|
||||
printf ("#define " macro_name "(x) ((x) + " macro_name "_DELTA(x))\n\n");
|
||||
|
||||
printf ("/* End of generated " outputname " */\n");
|
||||
}
|
||||
|
||||
int
|
||||
main (
|
||||
int argc,
|
||||
const char **argv
|
||||
)
|
||||
{
|
||||
const char *data_file_type = "BidiMirroring.txt";
|
||||
|
||||
if (argc < 3)
|
||||
die2 ("usage:\n " appname " max-lookups /path/to/%s [junk...]",
|
||||
data_file_type);
|
||||
|
||||
{
|
||||
int max_depth = atoi (argv[1]);
|
||||
const char *data_file_name = argv[2];
|
||||
|
||||
if (max_depth < 2)
|
||||
die ("invalid depth");
|
||||
|
||||
init ();
|
||||
read_data (data_file_type, data_file_name);
|
||||
gen_mirroring_tab (max_depth, data_file_type);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
424
glib/glib/glib-mirroring-tab/packtab.c
Normal file
424
glib/glib/glib-mirroring-tab/packtab.c
Normal file
|
|
@ -0,0 +1,424 @@
|
|||
/* PackTab - Pack a static table
|
||||
* Copyright (C) 2001 Behdad Esfahbod.
|
||||
*
|
||||
* 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, in a file named COPYING; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA
|
||||
*
|
||||
* For licensing issues, contact <fwpg@sharif.edu>.
|
||||
*/
|
||||
|
||||
/*
|
||||
8 <= N <= 2^21
|
||||
int key
|
||||
1 <= max_depth <= 21
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "packtab.h"
|
||||
|
||||
typedef signed int uni_table[1024 * 1024 * 2];
|
||||
static int n, a, max_depth, digits, tab_width, per_row;
|
||||
static long N;
|
||||
signed int def_key;
|
||||
static uni_table temp, x, perm, *tab;
|
||||
static long pow[22], cluster, cmpcluster;
|
||||
static const char *const *name, *key_type_name, *table_name, *macro_name;
|
||||
static FILE *f;
|
||||
|
||||
static long
|
||||
most_binary (
|
||||
long min,
|
||||
long max
|
||||
)
|
||||
{
|
||||
/* min should be less than max */
|
||||
register int i, ii;
|
||||
|
||||
if (min == max)
|
||||
return max;
|
||||
|
||||
for (i = 21; max < pow[i]; i--)
|
||||
;
|
||||
ii = i;
|
||||
while (i && !((min ^ max) & pow[i]))
|
||||
i--;
|
||||
|
||||
if (ii == i)
|
||||
{
|
||||
/* min is less than half of max */
|
||||
for (i = 21 - 1; min < pow[i]; i--)
|
||||
;
|
||||
i++;
|
||||
return pow[i];
|
||||
}
|
||||
|
||||
return max & (pow[i] - 1);
|
||||
}
|
||||
|
||||
static void
|
||||
init (
|
||||
const signed int *table
|
||||
)
|
||||
{
|
||||
register int i;
|
||||
|
||||
/* initialize powers of two */
|
||||
pow[0] = 1;
|
||||
for (i = 1; i <= 21; i++)
|
||||
pow[i] = pow[i - 1] << 1;
|
||||
|
||||
/* reduce number of elements to get a more binary number */
|
||||
{
|
||||
long essen;
|
||||
|
||||
/* find number of essential items */
|
||||
essen = N - 1;
|
||||
while (essen && table[essen] == def_key)
|
||||
essen--;
|
||||
essen++;
|
||||
|
||||
N = most_binary (essen, N);
|
||||
}
|
||||
|
||||
for (n = 21; N % pow[n]; n--)
|
||||
;
|
||||
digits = (n + 3) / 4;
|
||||
for (i = 6; i; i--)
|
||||
if (pow[i] * (tab_width + 1) < 80)
|
||||
break;
|
||||
per_row = pow[i];
|
||||
}
|
||||
|
||||
static int
|
||||
compare (
|
||||
const void *r,
|
||||
const void *s
|
||||
)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < cmpcluster; i++)
|
||||
if (((int *) r)[i] != ((int *) s)[i])
|
||||
return ((int *) r)[i] - ((int *) s)[i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lev, best_lev, p[22], best_p[22], nn;
|
||||
static long c[22], best_c[22], s, best_s;
|
||||
static long t[22], best_t[22], clusters[22], best_cluster[22];
|
||||
|
||||
static void
|
||||
found (
|
||||
void
|
||||
)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (s < best_s)
|
||||
{
|
||||
best_s = s;
|
||||
best_lev = lev;
|
||||
for (i = 0; i <= lev; i++)
|
||||
{
|
||||
best_p[i] = p[i];
|
||||
best_c[i] = c[i];
|
||||
best_t[i] = t[i];
|
||||
best_cluster[i] = clusters[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bt (
|
||||
int node_size
|
||||
)
|
||||
{
|
||||
long i, j, k, y, sbak;
|
||||
long key_bytes;
|
||||
|
||||
if (t[lev] == 1)
|
||||
{
|
||||
found ();
|
||||
return;
|
||||
}
|
||||
if (lev == max_depth)
|
||||
return;
|
||||
|
||||
for (i = 1 - t[lev] % 2; i <= nn + (t[lev] >> nn) % 2; i++)
|
||||
{
|
||||
nn -= (p[lev] = i);
|
||||
clusters[lev] = cluster = (i && nn >= 0) ? pow[i] : t[lev];
|
||||
cmpcluster = cluster + 1;
|
||||
|
||||
t[lev + 1] = (t[lev] - 1) / cluster + 1;
|
||||
for (j = 0; j < t[lev + 1]; j++)
|
||||
{
|
||||
memmove (temp + j * cmpcluster, tab[lev] + j * cluster,
|
||||
cluster * sizeof (tab[lev][0]));
|
||||
temp[j * cmpcluster + cluster] = j;
|
||||
}
|
||||
qsort (temp, t[lev + 1], cmpcluster * sizeof (temp[0]), compare);
|
||||
for (j = 0; j < t[lev + 1]; j++)
|
||||
{
|
||||
perm[j] = temp[j * cmpcluster + cluster];
|
||||
temp[j * cmpcluster + cluster] = 0;
|
||||
}
|
||||
k = 1;
|
||||
y = 0;
|
||||
tab[lev + 1][perm[0]] = perm[0];
|
||||
for (j = 1; j < t[lev + 1]; j++)
|
||||
{
|
||||
if (compare (temp + y, temp + y + cmpcluster))
|
||||
{
|
||||
k++;
|
||||
tab[lev + 1][perm[j]] = perm[j];
|
||||
}
|
||||
else
|
||||
tab[lev + 1][perm[j]] = tab[lev + 1][perm[j - 1]];
|
||||
y += cmpcluster;
|
||||
}
|
||||
sbak = s;
|
||||
s += k * node_size * cluster;
|
||||
c[lev] = k;
|
||||
|
||||
if (s >= best_s)
|
||||
{
|
||||
s = sbak;
|
||||
nn += i;
|
||||
return;
|
||||
}
|
||||
|
||||
key_bytes = k * cluster;
|
||||
key_bytes = key_bytes < 0xff ? 1 : key_bytes < 0xffff ? 2 : 4;
|
||||
lev++;
|
||||
bt (key_bytes);
|
||||
lev--;
|
||||
|
||||
s = sbak;
|
||||
nn += i;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
solve (
|
||||
void
|
||||
)
|
||||
{
|
||||
best_lev = max_depth + 2;
|
||||
best_s = N * a * 2;
|
||||
lev = 0;
|
||||
s = 0;
|
||||
nn = n;
|
||||
t[0] = N;
|
||||
bt (a);
|
||||
}
|
||||
|
||||
static void
|
||||
write_array (
|
||||
long max_key
|
||||
)
|
||||
{
|
||||
int i, j, k, y, ii, ofs;
|
||||
const char *key_type;
|
||||
|
||||
if (best_t[lev] == 1)
|
||||
return;
|
||||
|
||||
nn -= (i = best_p[lev]);
|
||||
cluster = best_cluster[lev];
|
||||
cmpcluster = cluster + 1;
|
||||
|
||||
t[lev + 1] = best_t[lev + 1];
|
||||
for (j = 0; j < t[lev + 1]; j++)
|
||||
{
|
||||
memmove (temp + j * cmpcluster, tab[lev] + j * cluster,
|
||||
cluster * sizeof (tab[lev][0]));
|
||||
temp[j * cmpcluster + cluster] = j;
|
||||
}
|
||||
qsort (temp, t[lev + 1], cmpcluster * sizeof (temp[0]), compare);
|
||||
for (j = 0; j < t[lev + 1]; j++)
|
||||
{
|
||||
perm[j] = temp[j * cmpcluster + cluster];
|
||||
temp[j * cmpcluster + cluster] = 0;
|
||||
}
|
||||
k = 1;
|
||||
y = 0;
|
||||
tab[lev + 1][perm[0]] = x[0] = perm[0];
|
||||
for (j = 1; j < t[lev + 1]; j++)
|
||||
{
|
||||
if (compare (temp + y, temp + y + cmpcluster))
|
||||
{
|
||||
x[k] = perm[j];
|
||||
tab[lev + 1][perm[j]] = x[k];
|
||||
k++;
|
||||
}
|
||||
else
|
||||
tab[lev + 1][perm[j]] = tab[lev + 1][perm[j - 1]];
|
||||
y += cmpcluster;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for (ii = 1; ii < k; ii++)
|
||||
if (x[ii] < x[i])
|
||||
i = ii;
|
||||
|
||||
key_type = !lev ? key_type_name :
|
||||
max_key <= 0xff ? "PACKTAB_UINT8" :
|
||||
max_key <= 0xffff ? "PACKTAB_UINT16" : "PACKTAB_UINT32";
|
||||
fprintf (f, "static const %s %sLev%d[%ld*%d] = {", key_type, table_name,
|
||||
best_lev - lev - 1, cluster, k);
|
||||
ofs = 0;
|
||||
for (ii = 0; ii < k; ii++)
|
||||
{
|
||||
int kk, jj;
|
||||
fprintf (f, "\n#define %sLev%d_%0*lX 0x%0X", table_name,
|
||||
best_lev - lev - 1, digits, x[i] * pow[n - nn], ofs);
|
||||
kk = x[i] * cluster;
|
||||
if (!lev)
|
||||
if (name)
|
||||
for (j = 0; j < cluster; j++)
|
||||
{
|
||||
if (!(j % per_row) && j != cluster - 1)
|
||||
fprintf (f, "\n ");
|
||||
fprintf (f, "%*s,", tab_width, name[tab[lev][kk++]]);
|
||||
}
|
||||
else
|
||||
for (j = 0; j < cluster; j++)
|
||||
{
|
||||
if (!(j % per_row) && j != cluster - 1)
|
||||
fprintf (f, "\n ");
|
||||
fprintf (f, "%*d,", tab_width, tab[lev][kk++]);
|
||||
}
|
||||
else
|
||||
for (j = 0; j < cluster; j++, kk++)
|
||||
fprintf (f, "\n %sLev%d_%0*lX, /* %0*lX..%0*lX */", table_name,
|
||||
best_lev - lev, digits,
|
||||
tab[lev][kk] * pow[n - nn - best_p[lev]], digits,
|
||||
x[i] * pow[n - nn] + j * pow[n - nn - best_p[lev]], digits,
|
||||
x[i] * pow[n - nn] + (j + 1) * pow[n - nn - best_p[lev]] -
|
||||
1);
|
||||
ofs += cluster;
|
||||
jj = i;
|
||||
for (j = 0; j < k; j++)
|
||||
if (x[j] > x[i] && (x[j] < x[jj] || jj == i))
|
||||
jj = j;
|
||||
i = jj;
|
||||
}
|
||||
fprintf (f, "\n};\n\n");
|
||||
lev++;
|
||||
write_array (cluster * k);
|
||||
lev--;
|
||||
}
|
||||
|
||||
static void
|
||||
write_source (
|
||||
void
|
||||
)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
lev = 0;
|
||||
s = 0;
|
||||
nn = n;
|
||||
t[0] = N;
|
||||
fprintf (f, "\n" "/* *IND" "ENT-OFF* */\n\n");
|
||||
write_array (0);
|
||||
fprintf (f, "/* *IND" "ENT-ON* */\n\n");
|
||||
|
||||
fprintf (f, "#define %s(x) \\\n", macro_name);
|
||||
fprintf (f, "\t((x) >= 0x%lx ? ", N);
|
||||
if (name)
|
||||
fprintf (f, "%s", name[def_key]);
|
||||
else
|
||||
fprintf (f, "%d", def_key);
|
||||
fprintf (f, " : ");
|
||||
j = 0;
|
||||
for (i = best_lev - 1; i >= 0; i--)
|
||||
{
|
||||
fprintf (f, " \\\n\t%sLev%d[((x)", table_name, i);
|
||||
if (j != 0)
|
||||
fprintf (f, " >> %d", j);
|
||||
if (i)
|
||||
fprintf (f, " & 0x%02lx) +", pow[best_p[best_lev - 1 - i]] - 1);
|
||||
j += best_p[best_lev - 1 - i];
|
||||
}
|
||||
fprintf (f, ")");
|
||||
for (i = 0; i < best_lev; i++)
|
||||
fprintf (f, "]");
|
||||
fprintf (f, ")\n\n");
|
||||
}
|
||||
|
||||
static void
|
||||
write_out (
|
||||
void
|
||||
)
|
||||
{
|
||||
int i;
|
||||
fprintf (f, "/*\n"
|
||||
" generated by packtab.c version %d\n\n"
|
||||
" use %s(key) to access your table\n\n"
|
||||
" assumed sizeof(%s): %d\n"
|
||||
" required memory: %ld\n"
|
||||
" lookups: %d\n"
|
||||
" partition shape: %s",
|
||||
packtab_version, macro_name, key_type_name, a, best_s, best_lev,
|
||||
table_name);
|
||||
for (i = best_lev - 1; i >= 0; i--)
|
||||
fprintf (f, "[%ld]", best_cluster[i]);
|
||||
fprintf (f, "\n" " different table entries:");
|
||||
for (i = best_lev - 1; i >= 0; i--)
|
||||
fprintf (f, " %ld", best_c[i]);
|
||||
fprintf (f, "\n*/\n");
|
||||
write_source ();
|
||||
}
|
||||
|
||||
int
|
||||
pack_table (
|
||||
const signed int *base,
|
||||
long key_num,
|
||||
int key_size,
|
||||
signed int default_key,
|
||||
int p_max_depth,
|
||||
int p_tab_width,
|
||||
const char *const *p_name,
|
||||
const char *p_key_type_name,
|
||||
const char *p_table_name,
|
||||
const char *p_macro_name,
|
||||
FILE *out
|
||||
)
|
||||
{
|
||||
N = key_num;
|
||||
a = key_size;
|
||||
def_key = default_key;
|
||||
max_depth = p_max_depth;
|
||||
tab_width = p_tab_width;
|
||||
name = p_name;
|
||||
key_type_name = p_key_type_name;
|
||||
table_name = p_table_name;
|
||||
macro_name = p_macro_name;
|
||||
f = out;
|
||||
init (base);
|
||||
if (!(tab = malloc ((n + 1) * sizeof (tab[0]))))
|
||||
return 0;
|
||||
memmove (tab[0], base, N * sizeof (base[0]));
|
||||
solve ();
|
||||
write_out ();
|
||||
free (tab);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* End of packtab.c */
|
||||
50
glib/glib/glib-mirroring-tab/packtab.h
Normal file
50
glib/glib/glib-mirroring-tab/packtab.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/* PackTab - Pack a static table
|
||||
* Copyright (C) 2001 Behdad Esfahbod.
|
||||
*
|
||||
* 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, in a file named COPYING; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA
|
||||
*
|
||||
* For licensing issues, contact <fwpg@sharif.edu>.
|
||||
*/
|
||||
|
||||
#ifndef PACKTAB_H
|
||||
#define PACKTAB_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define packtab_version 3
|
||||
|
||||
int pack_table (
|
||||
const signed int *base,
|
||||
long key_num,
|
||||
int key_size,
|
||||
signed int default_key,
|
||||
int max_depth,
|
||||
int tab_width,
|
||||
const char *const *name,
|
||||
const char *key_type_name,
|
||||
const char *table_name,
|
||||
const char *macro_name,
|
||||
FILE *out
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PACKTAB_H */
|
||||
42
glib/glib/glib-object.h
Normal file
42
glib/glib/glib-object.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/* GObject - GLib Type, Object, Parameter and Signal Library
|
||||
* Copyright (C) 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
|
||||
*
|
||||
* 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 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., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __GLIB_GOBJECT_H__
|
||||
#define __GLIB_GOBJECT_H__
|
||||
|
||||
#define __GLIB_GOBJECT_H_INSIDE__
|
||||
|
||||
/* topmost include file for GObject header files */
|
||||
#include <gobject/gbinding.h>
|
||||
#include <gobject/gboxed.h>
|
||||
#include <gobject/genums.h>
|
||||
#include <gobject/gobject.h>
|
||||
#include <gobject/gparam.h>
|
||||
#include <gobject/gparamspecs.h>
|
||||
#include <gobject/gsignal.h>
|
||||
#include <gobject/gsourceclosure.h>
|
||||
#include <gobject/gtype.h>
|
||||
#include <gobject/gtypemodule.h>
|
||||
#include <gobject/gtypeplugin.h>
|
||||
#include <gobject/gvalue.h>
|
||||
#include <gobject/gvaluearray.h>
|
||||
#include <gobject/gvaluetypes.h>
|
||||
|
||||
#undef __GLIB_GOBJECT_H_INSIDE__
|
||||
|
||||
#endif /* __GLIB_GOBJECT_H__ */
|
||||
46
glib/glib/glib-private.c
Normal file
46
glib/glib/glib-private.c
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Colin Walters <walters@verbum.org>
|
||||
*/
|
||||
|
||||
#include "glib-private.h"
|
||||
|
||||
/**
|
||||
* glib__private__:
|
||||
* @arg: Do not use this argument
|
||||
*
|
||||
* Do not call this function; it is used to share private
|
||||
* API between glib, gobject, and gio.
|
||||
*/
|
||||
GLibPrivateVTable *
|
||||
glib__private__ (void)
|
||||
{
|
||||
static GLibPrivateVTable table = {
|
||||
g_wakeup_new,
|
||||
g_wakeup_free,
|
||||
g_wakeup_get_pollfd,
|
||||
g_wakeup_signal,
|
||||
g_wakeup_acknowledge,
|
||||
|
||||
g_get_worker_context
|
||||
};
|
||||
|
||||
return &table;
|
||||
}
|
||||
|
||||
47
glib/glib/glib-private.h
Normal file
47
glib/glib/glib-private.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/* glib-private.h - GLib-internal private API, shared between glib, gobject, gio
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GLIB_PRIVATE_H__
|
||||
#define __GLIB_PRIVATE_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include "gwakeup.h"
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
GMainContext * g_get_worker_context (void);
|
||||
|
||||
#define GLIB_PRIVATE_CALL(symbol) (glib__private__()->symbol)
|
||||
|
||||
typedef struct {
|
||||
/* See gwakeup.c */
|
||||
GWakeup * (* g_wakeup_new) (void);
|
||||
void (* g_wakeup_free) (GWakeup *wakeup);
|
||||
void (* g_wakeup_get_pollfd) (GWakeup *wakeup,
|
||||
GPollFD *poll_fd);
|
||||
void (* g_wakeup_signal) (GWakeup *wakeup);
|
||||
void (* g_wakeup_acknowledge) (GWakeup *wakeup);
|
||||
|
||||
/* See gmain.c */
|
||||
GMainContext * (* g_get_worker_context) (void);
|
||||
/* Add other private functions here, initialize them in glib-private.c */
|
||||
} GLibPrivateVTable;
|
||||
|
||||
GLibPrivateVTable *glib__private__ (void);
|
||||
|
||||
#endif /* __G_MAIN_H__ */
|
||||
280
glib/glib/glib-unix.c
Normal file
280
glib/glib/glib-unix.c
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
*
|
||||
* glib-unix.c: UNIX specific API wrappers and convenience functions
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Authors: Colin Walters <walters@verbum.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "glib-unix.h"
|
||||
#include "gmain-internal.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* SECTION:gunix
|
||||
* @title: UNIX-specific utilities and integration
|
||||
* @short_description: pipes, signal handling
|
||||
* @include: glib-unix.h
|
||||
*
|
||||
* Most of GLib is intended to be portable; in contrast, this set of
|
||||
* functions is designed for programs which explicitly target UNIX,
|
||||
* or are using it to build higher level abstractions which would be
|
||||
* conditionally compiled if the platform matches G_OS_UNIX.
|
||||
*
|
||||
* To use these functions, you must explicitly include the
|
||||
* "glib-unix.h" header.
|
||||
*/
|
||||
|
||||
GQuark
|
||||
g_unix_error_quark (void)
|
||||
{
|
||||
return g_quark_from_static_string ("g-unix-error-quark");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_unix_set_error_from_errno (GError **error,
|
||||
gint saved_errno)
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
G_UNIX_ERROR,
|
||||
0,
|
||||
g_strerror (saved_errno));
|
||||
errno = saved_errno;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_unix_open_pipe:
|
||||
* @fds: Array of two integers
|
||||
* @flags: Bitfield of file descriptor flags, see "man 2 fcntl"
|
||||
* @error: a #GError
|
||||
*
|
||||
* Similar to the UNIX pipe() call, but on modern systems like Linux
|
||||
* uses the pipe2() system call, which atomically creates a pipe with
|
||||
* the configured flags. The only supported flag currently is
|
||||
* <literal>FD_CLOEXEC</literal>. If for example you want to configure
|
||||
* <literal>O_NONBLOCK</literal>, that must still be done separately with
|
||||
* fcntl().
|
||||
*
|
||||
* <note>This function does *not* take <literal>O_CLOEXEC</literal>, it takes
|
||||
* <literal>FD_CLOEXEC</literal> as if for fcntl(); these are
|
||||
* different on Linux/glibc.</note>
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE if not (and errno will be set).
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
gboolean
|
||||
g_unix_open_pipe (int *fds,
|
||||
int flags,
|
||||
GError **error)
|
||||
{
|
||||
int ecode;
|
||||
|
||||
/* We only support FD_CLOEXEC */
|
||||
g_return_val_if_fail ((flags & (FD_CLOEXEC)) == flags, FALSE);
|
||||
|
||||
#ifdef HAVE_PIPE2
|
||||
{
|
||||
int pipe2_flags = 0;
|
||||
if (flags & FD_CLOEXEC)
|
||||
pipe2_flags |= O_CLOEXEC;
|
||||
/* Atomic */
|
||||
ecode = pipe2 (fds, pipe2_flags);
|
||||
if (ecode == -1 && errno != ENOSYS)
|
||||
return g_unix_set_error_from_errno (error, errno);
|
||||
else if (ecode == 0)
|
||||
return TRUE;
|
||||
/* Fall through on -ENOSYS, we must be running on an old kernel */
|
||||
}
|
||||
#endif
|
||||
ecode = pipe (fds);
|
||||
if (ecode == -1)
|
||||
return g_unix_set_error_from_errno (error, errno);
|
||||
ecode = fcntl (fds[0], flags);
|
||||
if (ecode == -1)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
close (fds[0]);
|
||||
close (fds[1]);
|
||||
return g_unix_set_error_from_errno (error, saved_errno);
|
||||
}
|
||||
ecode = fcntl (fds[1], flags);
|
||||
if (ecode == -1)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
close (fds[0]);
|
||||
close (fds[1]);
|
||||
return g_unix_set_error_from_errno (error, saved_errno);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_unix_set_fd_nonblocking:
|
||||
* @fd: A file descriptor
|
||||
* @nonblock: If %TRUE, set the descriptor to be non-blocking
|
||||
* @error: a #GError
|
||||
*
|
||||
* Control the non-blocking state of the given file descriptor,
|
||||
* according to @nonblock. On most systems this uses <literal>O_NONBLOCK</literal>, but
|
||||
* on some older ones may use <literal>O_NDELAY</literal>.
|
||||
*
|
||||
* Returns: %TRUE if successful
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
gboolean
|
||||
g_unix_set_fd_nonblocking (gint fd,
|
||||
gboolean nonblock,
|
||||
GError **error)
|
||||
{
|
||||
#ifdef F_GETFL
|
||||
glong fcntl_flags;
|
||||
fcntl_flags = fcntl (fd, F_GETFL);
|
||||
|
||||
if (fcntl_flags == -1)
|
||||
return g_unix_set_error_from_errno (error, errno);
|
||||
|
||||
if (nonblock)
|
||||
{
|
||||
#ifdef O_NONBLOCK
|
||||
fcntl_flags |= O_NONBLOCK;
|
||||
#else
|
||||
fcntl_flags |= O_NDELAY;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef O_NONBLOCK
|
||||
fcntl_flags &= ~O_NONBLOCK;
|
||||
#else
|
||||
fcntl_flags &= ~O_NDELAY;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (fcntl (fd, F_SETFL, fcntl_flags) == -1)
|
||||
return g_unix_set_error_from_errno (error, errno);
|
||||
return TRUE;
|
||||
#else
|
||||
return g_unix_set_error_from_errno (error, EINVAL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* g_unix_signal_source_new:
|
||||
* @signum: A signal number
|
||||
*
|
||||
* Create a #GSource that will be dispatched upon delivery of the UNIX
|
||||
* signal @signum. Currently only <literal>SIGHUP</literal>,
|
||||
* <literal>SIGINT</literal>, and <literal>SIGTERM</literal> can
|
||||
* be monitored. Note that unlike the UNIX default, all sources which
|
||||
* have created a watch will be dispatched, regardless of which
|
||||
* underlying thread invoked g_unix_signal_source_new().
|
||||
*
|
||||
* For example, an effective use of this function is to handle <literal>SIGTERM</literal>
|
||||
* cleanly; flushing any outstanding files, and then calling
|
||||
* g_main_loop_quit (). It is not safe to do any of this a regular
|
||||
* UNIX signal handler; your handler may be invoked while malloc() or
|
||||
* another library function is running, causing reentrancy if you
|
||||
* attempt to use it from the handler. None of the GLib/GObject API
|
||||
* is safe against this kind of reentrancy.
|
||||
*
|
||||
* The interaction of this source when combined with native UNIX
|
||||
* functions like sigprocmask() is not defined.
|
||||
*
|
||||
* The source will not initially be associated with any #GMainContext
|
||||
* and must be added to one with g_source_attach() before it will be
|
||||
* executed.
|
||||
*
|
||||
* Returns: A newly created #GSource
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
GSource *
|
||||
g_unix_signal_source_new (int signum)
|
||||
{
|
||||
g_return_val_if_fail (signum == SIGHUP || signum == SIGINT || signum == SIGTERM, NULL);
|
||||
|
||||
return _g_main_create_unix_signal_watch (signum);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_unix_signal_add_full:
|
||||
* @priority: the priority of the signal source. Typically this will be in
|
||||
* the range between #G_PRIORITY_DEFAULT and #G_PRIORITY_HIGH.
|
||||
* @signum: Signal number
|
||||
* @handler: Callback
|
||||
* @user_data: Data for @handler
|
||||
* @notify: #GDestroyNotify for @handler
|
||||
*
|
||||
* A convenience function for g_unix_signal_source_new(), which
|
||||
* attaches to the default #GMainContext. You can remove the watch
|
||||
* using g_source_remove().
|
||||
*
|
||||
* Returns: An ID (greater than 0) for the event source
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
guint
|
||||
g_unix_signal_add_full (int priority,
|
||||
int signum,
|
||||
GSourceFunc handler,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify)
|
||||
{
|
||||
guint id;
|
||||
GSource *source;
|
||||
|
||||
source = g_unix_signal_source_new (signum);
|
||||
|
||||
if (priority != G_PRIORITY_DEFAULT)
|
||||
g_source_set_priority (source, priority);
|
||||
|
||||
g_source_set_callback (source, handler, user_data, notify);
|
||||
id = g_source_attach (source, NULL);
|
||||
g_source_unref (source);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_unix_signal_add:
|
||||
* @signum: Signal number
|
||||
* @handler: Callback
|
||||
* @user_data: Data for @handler
|
||||
*
|
||||
* A convenience function for g_unix_signal_source_new(), which
|
||||
* attaches to the default #GMainContext. You can remove the watch
|
||||
* using g_source_remove().
|
||||
*
|
||||
* Returns: An ID (greater than 0) for the event source
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
guint
|
||||
g_unix_signal_add (int signum,
|
||||
GSourceFunc handler,
|
||||
gpointer user_data)
|
||||
{
|
||||
return g_unix_signal_add_full (G_PRIORITY_DEFAULT, signum, handler, user_data, NULL);
|
||||
}
|
||||
84
glib/glib/glib-unix.h
Normal file
84
glib/glib/glib-unix.h
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/* glib-unix.h - Unix specific integration
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __G_UNIX_H__
|
||||
#define __G_UNIX_H__
|
||||
|
||||
/* We need to include the UNIX headers needed to use the APIs below,
|
||||
* but we also take this opportunity to include a wide selection of
|
||||
* other UNIX headers. If one of the headers below is broken on some
|
||||
* system, work around it here (or better, fix the system or tell
|
||||
* people to use a better one).
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#ifndef G_OS_UNIX
|
||||
#error "This header may only be used on UNIX"
|
||||
#endif
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* G_UNIX_ERROR:
|
||||
*
|
||||
* Error domain for API in the "g_unix_" namespace. Note that there is
|
||||
* no exported enumeration mapping %errno. Instead, all functions
|
||||
* ensure that %errno is relevant. The code for all #G_UNIX_ERROR is
|
||||
* always <literal>0</literal>, and the error message is always
|
||||
* generated via g_strerror().
|
||||
*
|
||||
* It is expected that most code will not look at %errno from these
|
||||
* APIs. Important cases where one would want to differentiate between
|
||||
* errors are already covered by existing cross-platform GLib API,
|
||||
* such as e.g. #GFile wrapping <literal>ENOENT</literal>. However, it is
|
||||
* provided for completeness, at least.
|
||||
*/
|
||||
#define G_UNIX_ERROR (g_unix_error_quark())
|
||||
|
||||
GQuark g_unix_error_quark (void);
|
||||
|
||||
gboolean g_unix_open_pipe (gint *fds,
|
||||
gint flags,
|
||||
GError **error);
|
||||
|
||||
gboolean g_unix_set_fd_nonblocking (gint fd,
|
||||
gboolean nonblock,
|
||||
GError **error);
|
||||
|
||||
GSource *g_unix_signal_source_new (gint signum);
|
||||
|
||||
guint g_unix_signal_add_full (gint priority,
|
||||
gint signum,
|
||||
GSourceFunc handler,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify);
|
||||
|
||||
guint g_unix_signal_add (gint signum,
|
||||
GSourceFunc handler,
|
||||
gpointer user_data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_UNIX_H__ */
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue