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:
Dan Nicholson 2010-06-05 12:32:36 -07:00
parent 9961b85d2a
commit c23f6a6ef3
255 changed files with 207331 additions and 0 deletions

43
glib/.gitignore vendored Normal file
View 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
View 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
View 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
View 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
View 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

6191
glib/NEWS Normal file

File diff suppressed because it is too large Load diff

288
glib/README.in Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

188
glib/glib-gettextize.in Normal file
View 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
View 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
View 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
View 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
View 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

View 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) { }

View 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__ */

View 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);
}

View 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__ */

View 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

View 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__ */

View 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
View 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
View 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__ */

File diff suppressed because it is too large Load diff

View 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

File diff suppressed because it is too large Load diff

110
glib/glib/galloca.h Normal file
View 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

File diff suppressed because it is too large Load diff

187
glib/glib/garray.h Normal file
View 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
View 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
View 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__ */

View 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
View 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
View 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
View 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.
*
* |[
* &num;include &lt;glib.h&gt;
*
* 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);
* /&ast; ... &ast;/
* ]|
*
* 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

215
glib/glib/gbookmarkfile.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

86
glib/glib/gchecksum.h Normal file
View 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
View 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

File diff suppressed because it is too large Load diff

164
glib/glib/gconvert.h Normal file
View 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

File diff suppressed because it is too large Load diff

122
glib/glib/gdataset.h Normal file
View 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__ */

View 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

File diff suppressed because it is too large Load diff

264
glib/glib/gdate.h Normal file
View 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

File diff suppressed because it is too large Load diff

217
glib/glib/gdatetime.h Normal file
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

697
glib/glib/genviron.c Normal file
View 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
View 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
View 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", &amp;contents, NULL, &amp;err);
* g_assert ((contents == NULL &amp;&amp; err != NULL) || (contents != NULL &amp;&amp; err == NULL));
* if (err != NULL)
* {
* /&ast; Report error to user, and free error &ast;/
* g_assert (contents == NULL);
* fprintf (stderr, "Unable to read file: &percnt;s\n", err->message);
* g_error_free (err);
* }
* else
* {
* /&ast; Use file contents &ast;/
* 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", &amp;contents, NULL, NULL)) /&ast; ignore errors &ast;/
* /&ast; no error occurred &ast;/ ;
* else
* /&ast; error &ast;/ ;
* ]|
*
* 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-&gt;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-&gt;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 &lt; 0)
* {
* g_set_error (error,
* FOO_ERROR, /&ast; error domain &ast;/
* FOO_ERROR_BLAH, /&ast; error code &ast;/
* "Failed to open file: &percnt;s", /&ast; error message format string &ast;/
* 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))
* {
* /&ast; assert that error was set by the sub-function &ast;/
* g_assert (err == NULL || *err != NULL);
* return FALSE;
* }
*
* /&ast; otherwise continue, no error occurred &ast;/
* 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 (&amp;tmp_error);
*
* if (tmp_error != NULL)
* {
* /&ast; store tmp_error in err, if err != NULL,
* &ast; otherwise call g_error_free() on tmp_error
* &ast;/
* g_propagate_error (err, tmp_error);
* return FALSE;
* }
*
* /&ast; otherwise continue, no error occurred &ast;/
* }
* ]|
*
* 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 (&amp;tmp_error);
* other_function_that_can_fail (&amp;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); /&ast; ignore errors &ast;/
*
* tmp_error = NULL;
* other_function_that_can_fail (&amp;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>&lt;NAMESPACE&gt;_&lt;MODULE&gt;_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>&lt;namespace&gt;_&lt;module&gt;_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>&lt;Namespace&gt;&lt;Module&gt;Error</literal>;
* for example,#GThreadError or #GSpawnError.
* </para></listitem>
* <listitem><para>
* Members of the error code enumeration are called
* <literal>&lt;NAMESPACE&gt;_&lt;MODULE&gt;_ERROR_&lt;CODE&gt;</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>&lt;NAMESPACE&gt;_&lt;MODULE&gt;_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
View 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

File diff suppressed because it is too large Load diff

176
glib/glib/gfileutils.h Normal file
View 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
View 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:
* |[
* &num;define GETTEXT_PACKAGE "gtk20"
* &num;include &lt;glib/gi18n-lib.h&gt;
* ]|
* 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 &gt; 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 &gt; 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
View 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

File diff suppressed because it is too large Load diff

146
glib/glib/ghash.h Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

181
glib/glib/ghook.h Normal file
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

374
glib/glib/giochannel.h Normal file
View 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
View 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

File diff suppressed because it is too large Load diff

4383
glib/glib/gkeyfile.c Normal file

File diff suppressed because it is too large Load diff

268
glib/glib/gkeyfile.h Normal file
View 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
View 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
View 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__ */

View 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

View 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;
}

View 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 */

View 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
View 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
View 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
View 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
View 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
View 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