2006-10-19 23:00:14 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
* vlc_arrays.h : Arrays and data structures handling
|
|
|
|
*****************************************************************************
|
LGPL
Re-license almost all of libVLC and libVLCcore to LGPLv2.1+
This move was authorized by the developers, either:
- by e-mail,
- by vote at the VideoLAN Dev Days 2011,
- on the license website,
- in a contract, oral or written.
No objection was raised, so far.
The developers agreeing are:
Justus Piater
Alexis Ballier
Alexander Bethke
Mohammed Adnène Trojette
Alex Converse
Alexey Sokolov
Alexis de Lattre
Andre Pang
Anthony Loiseau
Cyril Deguet
André Weber
Boris Dorès
Brieuc Jeunhomme
Benjamin Drung
Hugo Beauzée-Luyssen
Benoit Steiner
Benjamin Pracht
Bernie Purcell
Przemyslaw Fiala
Arnaud de Bossoreille de Ribou
Brad Smith
Nick Briggs
Christopher Rath
Christophe Courtaut
Christopher Mueller
Clement Chesnin
Andres Krapf
Damien Fouilleul
David Flynn
Sebastien Zwickert
Antoine Cellerier
Jérôme Decoodt
Jérome Decoodt
Dylan Yudaken
Eduard Babayan
Eugenio Jarosiewicz
Elliot Murphy
Eric Petit
Erwan Tulou
Etienne Membrives
Ludovic Fauvet
Fabio Ritrovato
Tobias Güntner
Jakub Wieczorek
Frédéric Crozat
Francois Cartegnie
Laurent Aimar
Florian G. Pflug
Felix Paul Kühne
Frank Enderle
Rafaël Carré
Simon Latapie
Gildas Bazin
Geoffroy Couprie
Julien / Gellule
Gildas Bazin
Arnaud Schauly
Toralf Niebuhr
Vicente Jimenez Aguilar
Derk-Jan Hartman
Henri Fallon
Ilkka Ollakka
Olivier Teulière
Rémi Duraffort
Jakob Leben
Jean-Baptiste Kempf
Jean-Paul Saman
Jean-Philippe Grimaldi
Jean-François Massol
Gaël Hendryckx
Jakob Leben
Jean-Marc Dressler
Jai Menon
Johan Bilien
Johann Ransay
Joris van Rooij
JP Dinger
Jean-Philippe André
Adrien Grand
Juha Jeronen
Juho Vähä-Herttua
Kaarlo Raiha
Kaarlo Raiha
Kamil Baldyga
Keary Griffin
Ken Self
KO Myung-Hun
Pierre Ynard
Filippo Carone
Loïc Minier
Luca Barbato
Lucas C. Villa Real
Lukas Durfina
Adrien Maglo
Marc Ariberti
Mark Lee
Mark Moriarty
Martin Storsjö
Christophe Massiot
Michel Kaempf
Marian Ďurkovič
Mirsal Ennaime
Carlo Calabrò
Damien Lucas
Naohiro Koriyama
Basos G
Pierre Baillet
Vincent Penquerc'h
Olivier Aubert
Pankaj Yadav
Paul Corke
Pierre d'Herbemont
Philippe Morin
Antoine Lejeune
Michael Ploujnikov
Jean-Marc Dressler
Michael Hanselmann
Rafaël Carré
Ramiro Polla
Rémi Denis-Courmont
Renaud Dartus
Richard Shepherd
Faustino Osuna
Arnaud Vallat
Rob Jonson
Robert Jedrzejczyk
Steve Lhomme
Rocky Bernstein
Romain Goyet
Rov Juvano
Sam Hocevar
Martin T. H. Sandsmark
Sebastian Birk
Sébastien Escudier
Vincent Seguin
Fabio Ritrovato
Sigmund Augdal Helberg
Casian Andrei
Srikanth Raju
Hannes Domani
Stéphane Borel
Stephan Krempel
Stephan Assmus
Tony Castley
Pavlov Konstantin
Eric Petit
Tanguy Krotoff
Dennis van Amerongen
Michel Lespinasse
Can Wu
Xavier Marchesini
Sébastien Toque
Christophe Mutricy
Yoann Peronneau
Yohann Martineau
Yuval Tze
Scott Caudle
Clément Stenac
It is possible, that some minor piece of code was badly tracked, for
some reasons (SVN, mainly) or that some small developers did not answer.
However, as an "œuvre collective", defined as in "CPI 113-2 alinéa 3",
and seeing "Cour. Cass. 17 Mai 1978", and seeing that the editor and
the very vast majority of developers have agreed (> 99.99% of the code,
> 99% of developers), we are fine here.
2011-11-27 21:44:15 +01:00
|
|
|
* Copyright (C) 1999-2004 VLC authors and VideoLAN
|
2006-10-19 23:00:14 +02:00
|
|
|
*
|
|
|
|
* Authors: Samuel Hocevar <sam@zoy.org>
|
|
|
|
* Clément Stenac <zorglub@videolan.org>
|
|
|
|
*
|
LGPL
Re-license almost all of libVLC and libVLCcore to LGPLv2.1+
This move was authorized by the developers, either:
- by e-mail,
- by vote at the VideoLAN Dev Days 2011,
- on the license website,
- in a contract, oral or written.
No objection was raised, so far.
The developers agreeing are:
Justus Piater
Alexis Ballier
Alexander Bethke
Mohammed Adnène Trojette
Alex Converse
Alexey Sokolov
Alexis de Lattre
Andre Pang
Anthony Loiseau
Cyril Deguet
André Weber
Boris Dorès
Brieuc Jeunhomme
Benjamin Drung
Hugo Beauzée-Luyssen
Benoit Steiner
Benjamin Pracht
Bernie Purcell
Przemyslaw Fiala
Arnaud de Bossoreille de Ribou
Brad Smith
Nick Briggs
Christopher Rath
Christophe Courtaut
Christopher Mueller
Clement Chesnin
Andres Krapf
Damien Fouilleul
David Flynn
Sebastien Zwickert
Antoine Cellerier
Jérôme Decoodt
Jérome Decoodt
Dylan Yudaken
Eduard Babayan
Eugenio Jarosiewicz
Elliot Murphy
Eric Petit
Erwan Tulou
Etienne Membrives
Ludovic Fauvet
Fabio Ritrovato
Tobias Güntner
Jakub Wieczorek
Frédéric Crozat
Francois Cartegnie
Laurent Aimar
Florian G. Pflug
Felix Paul Kühne
Frank Enderle
Rafaël Carré
Simon Latapie
Gildas Bazin
Geoffroy Couprie
Julien / Gellule
Gildas Bazin
Arnaud Schauly
Toralf Niebuhr
Vicente Jimenez Aguilar
Derk-Jan Hartman
Henri Fallon
Ilkka Ollakka
Olivier Teulière
Rémi Duraffort
Jakob Leben
Jean-Baptiste Kempf
Jean-Paul Saman
Jean-Philippe Grimaldi
Jean-François Massol
Gaël Hendryckx
Jakob Leben
Jean-Marc Dressler
Jai Menon
Johan Bilien
Johann Ransay
Joris van Rooij
JP Dinger
Jean-Philippe André
Adrien Grand
Juha Jeronen
Juho Vähä-Herttua
Kaarlo Raiha
Kaarlo Raiha
Kamil Baldyga
Keary Griffin
Ken Self
KO Myung-Hun
Pierre Ynard
Filippo Carone
Loïc Minier
Luca Barbato
Lucas C. Villa Real
Lukas Durfina
Adrien Maglo
Marc Ariberti
Mark Lee
Mark Moriarty
Martin Storsjö
Christophe Massiot
Michel Kaempf
Marian Ďurkovič
Mirsal Ennaime
Carlo Calabrò
Damien Lucas
Naohiro Koriyama
Basos G
Pierre Baillet
Vincent Penquerc'h
Olivier Aubert
Pankaj Yadav
Paul Corke
Pierre d'Herbemont
Philippe Morin
Antoine Lejeune
Michael Ploujnikov
Jean-Marc Dressler
Michael Hanselmann
Rafaël Carré
Ramiro Polla
Rémi Denis-Courmont
Renaud Dartus
Richard Shepherd
Faustino Osuna
Arnaud Vallat
Rob Jonson
Robert Jedrzejczyk
Steve Lhomme
Rocky Bernstein
Romain Goyet
Rov Juvano
Sam Hocevar
Martin T. H. Sandsmark
Sebastian Birk
Sébastien Escudier
Vincent Seguin
Fabio Ritrovato
Sigmund Augdal Helberg
Casian Andrei
Srikanth Raju
Hannes Domani
Stéphane Borel
Stephan Krempel
Stephan Assmus
Tony Castley
Pavlov Konstantin
Eric Petit
Tanguy Krotoff
Dennis van Amerongen
Michel Lespinasse
Can Wu
Xavier Marchesini
Sébastien Toque
Christophe Mutricy
Yoann Peronneau
Yohann Martineau
Yuval Tze
Scott Caudle
Clément Stenac
It is possible, that some minor piece of code was badly tracked, for
some reasons (SVN, mainly) or that some small developers did not answer.
However, as an "œuvre collective", defined as in "CPI 113-2 alinéa 3",
and seeing "Cour. Cass. 17 Mai 1978", and seeing that the editor and
the very vast majority of developers have agreed (> 99.99% of the code,
> 99% of developers), we are fine here.
2011-11-27 21:44:15 +01:00
|
|
|
* This program 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
|
2006-10-19 23:00:14 +02:00
|
|
|
* (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
|
LGPL
Re-license almost all of libVLC and libVLCcore to LGPLv2.1+
This move was authorized by the developers, either:
- by e-mail,
- by vote at the VideoLAN Dev Days 2011,
- on the license website,
- in a contract, oral or written.
No objection was raised, so far.
The developers agreeing are:
Justus Piater
Alexis Ballier
Alexander Bethke
Mohammed Adnène Trojette
Alex Converse
Alexey Sokolov
Alexis de Lattre
Andre Pang
Anthony Loiseau
Cyril Deguet
André Weber
Boris Dorès
Brieuc Jeunhomme
Benjamin Drung
Hugo Beauzée-Luyssen
Benoit Steiner
Benjamin Pracht
Bernie Purcell
Przemyslaw Fiala
Arnaud de Bossoreille de Ribou
Brad Smith
Nick Briggs
Christopher Rath
Christophe Courtaut
Christopher Mueller
Clement Chesnin
Andres Krapf
Damien Fouilleul
David Flynn
Sebastien Zwickert
Antoine Cellerier
Jérôme Decoodt
Jérome Decoodt
Dylan Yudaken
Eduard Babayan
Eugenio Jarosiewicz
Elliot Murphy
Eric Petit
Erwan Tulou
Etienne Membrives
Ludovic Fauvet
Fabio Ritrovato
Tobias Güntner
Jakub Wieczorek
Frédéric Crozat
Francois Cartegnie
Laurent Aimar
Florian G. Pflug
Felix Paul Kühne
Frank Enderle
Rafaël Carré
Simon Latapie
Gildas Bazin
Geoffroy Couprie
Julien / Gellule
Gildas Bazin
Arnaud Schauly
Toralf Niebuhr
Vicente Jimenez Aguilar
Derk-Jan Hartman
Henri Fallon
Ilkka Ollakka
Olivier Teulière
Rémi Duraffort
Jakob Leben
Jean-Baptiste Kempf
Jean-Paul Saman
Jean-Philippe Grimaldi
Jean-François Massol
Gaël Hendryckx
Jakob Leben
Jean-Marc Dressler
Jai Menon
Johan Bilien
Johann Ransay
Joris van Rooij
JP Dinger
Jean-Philippe André
Adrien Grand
Juha Jeronen
Juho Vähä-Herttua
Kaarlo Raiha
Kaarlo Raiha
Kamil Baldyga
Keary Griffin
Ken Self
KO Myung-Hun
Pierre Ynard
Filippo Carone
Loïc Minier
Luca Barbato
Lucas C. Villa Real
Lukas Durfina
Adrien Maglo
Marc Ariberti
Mark Lee
Mark Moriarty
Martin Storsjö
Christophe Massiot
Michel Kaempf
Marian Ďurkovič
Mirsal Ennaime
Carlo Calabrò
Damien Lucas
Naohiro Koriyama
Basos G
Pierre Baillet
Vincent Penquerc'h
Olivier Aubert
Pankaj Yadav
Paul Corke
Pierre d'Herbemont
Philippe Morin
Antoine Lejeune
Michael Ploujnikov
Jean-Marc Dressler
Michael Hanselmann
Rafaël Carré
Ramiro Polla
Rémi Denis-Courmont
Renaud Dartus
Richard Shepherd
Faustino Osuna
Arnaud Vallat
Rob Jonson
Robert Jedrzejczyk
Steve Lhomme
Rocky Bernstein
Romain Goyet
Rov Juvano
Sam Hocevar
Martin T. H. Sandsmark
Sebastian Birk
Sébastien Escudier
Vincent Seguin
Fabio Ritrovato
Sigmund Augdal Helberg
Casian Andrei
Srikanth Raju
Hannes Domani
Stéphane Borel
Stephan Krempel
Stephan Assmus
Tony Castley
Pavlov Konstantin
Eric Petit
Tanguy Krotoff
Dennis van Amerongen
Michel Lespinasse
Can Wu
Xavier Marchesini
Sébastien Toque
Christophe Mutricy
Yoann Peronneau
Yohann Martineau
Yuval Tze
Scott Caudle
Clément Stenac
It is possible, that some minor piece of code was badly tracked, for
some reasons (SVN, mainly) or that some small developers did not answer.
However, as an "œuvre collective", defined as in "CPI 113-2 alinéa 3",
and seeing "Cour. Cass. 17 Mai 1978", and seeing that the editor and
the very vast majority of developers have agreed (> 99.99% of the code,
> 99% of developers), we are fine here.
2011-11-27 21:44:15 +01:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Lesser General Public License for more details.
|
2006-10-19 23:00:14 +02:00
|
|
|
*
|
LGPL
Re-license almost all of libVLC and libVLCcore to LGPLv2.1+
This move was authorized by the developers, either:
- by e-mail,
- by vote at the VideoLAN Dev Days 2011,
- on the license website,
- in a contract, oral or written.
No objection was raised, so far.
The developers agreeing are:
Justus Piater
Alexis Ballier
Alexander Bethke
Mohammed Adnène Trojette
Alex Converse
Alexey Sokolov
Alexis de Lattre
Andre Pang
Anthony Loiseau
Cyril Deguet
André Weber
Boris Dorès
Brieuc Jeunhomme
Benjamin Drung
Hugo Beauzée-Luyssen
Benoit Steiner
Benjamin Pracht
Bernie Purcell
Przemyslaw Fiala
Arnaud de Bossoreille de Ribou
Brad Smith
Nick Briggs
Christopher Rath
Christophe Courtaut
Christopher Mueller
Clement Chesnin
Andres Krapf
Damien Fouilleul
David Flynn
Sebastien Zwickert
Antoine Cellerier
Jérôme Decoodt
Jérome Decoodt
Dylan Yudaken
Eduard Babayan
Eugenio Jarosiewicz
Elliot Murphy
Eric Petit
Erwan Tulou
Etienne Membrives
Ludovic Fauvet
Fabio Ritrovato
Tobias Güntner
Jakub Wieczorek
Frédéric Crozat
Francois Cartegnie
Laurent Aimar
Florian G. Pflug
Felix Paul Kühne
Frank Enderle
Rafaël Carré
Simon Latapie
Gildas Bazin
Geoffroy Couprie
Julien / Gellule
Gildas Bazin
Arnaud Schauly
Toralf Niebuhr
Vicente Jimenez Aguilar
Derk-Jan Hartman
Henri Fallon
Ilkka Ollakka
Olivier Teulière
Rémi Duraffort
Jakob Leben
Jean-Baptiste Kempf
Jean-Paul Saman
Jean-Philippe Grimaldi
Jean-François Massol
Gaël Hendryckx
Jakob Leben
Jean-Marc Dressler
Jai Menon
Johan Bilien
Johann Ransay
Joris van Rooij
JP Dinger
Jean-Philippe André
Adrien Grand
Juha Jeronen
Juho Vähä-Herttua
Kaarlo Raiha
Kaarlo Raiha
Kamil Baldyga
Keary Griffin
Ken Self
KO Myung-Hun
Pierre Ynard
Filippo Carone
Loïc Minier
Luca Barbato
Lucas C. Villa Real
Lukas Durfina
Adrien Maglo
Marc Ariberti
Mark Lee
Mark Moriarty
Martin Storsjö
Christophe Massiot
Michel Kaempf
Marian Ďurkovič
Mirsal Ennaime
Carlo Calabrò
Damien Lucas
Naohiro Koriyama
Basos G
Pierre Baillet
Vincent Penquerc'h
Olivier Aubert
Pankaj Yadav
Paul Corke
Pierre d'Herbemont
Philippe Morin
Antoine Lejeune
Michael Ploujnikov
Jean-Marc Dressler
Michael Hanselmann
Rafaël Carré
Ramiro Polla
Rémi Denis-Courmont
Renaud Dartus
Richard Shepherd
Faustino Osuna
Arnaud Vallat
Rob Jonson
Robert Jedrzejczyk
Steve Lhomme
Rocky Bernstein
Romain Goyet
Rov Juvano
Sam Hocevar
Martin T. H. Sandsmark
Sebastian Birk
Sébastien Escudier
Vincent Seguin
Fabio Ritrovato
Sigmund Augdal Helberg
Casian Andrei
Srikanth Raju
Hannes Domani
Stéphane Borel
Stephan Krempel
Stephan Assmus
Tony Castley
Pavlov Konstantin
Eric Petit
Tanguy Krotoff
Dennis van Amerongen
Michel Lespinasse
Can Wu
Xavier Marchesini
Sébastien Toque
Christophe Mutricy
Yoann Peronneau
Yohann Martineau
Yuval Tze
Scott Caudle
Clément Stenac
It is possible, that some minor piece of code was badly tracked, for
some reasons (SVN, mainly) or that some small developers did not answer.
However, as an "œuvre collective", defined as in "CPI 113-2 alinéa 3",
and seeing "Cour. Cass. 17 Mai 1978", and seeing that the editor and
the very vast majority of developers have agreed (> 99.99% of the code,
> 99% of developers), we are fine here.
2011-11-27 21:44:15 +01:00
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
2008-09-26 22:59:23 +02:00
|
|
|
*****************************************************************************/
|
2006-10-19 23:00:14 +02:00
|
|
|
|
2008-08-11 18:13:10 +02:00
|
|
|
#ifndef VLC_ARRAYS_H_
|
|
|
|
#define VLC_ARRAYS_H_
|
2006-10-19 23:00:14 +02:00
|
|
|
|
2023-12-21 09:55:20 +01:00
|
|
|
#include <vlc_common.h>
|
|
|
|
|
2008-08-11 17:31:57 +02:00
|
|
|
/**
|
|
|
|
* \file
|
|
|
|
* This file defines functions, structures and macros for handling arrays in vlc
|
|
|
|
*/
|
|
|
|
|
2009-05-24 19:52:40 +02:00
|
|
|
/* realloc() that never fails *if* downsizing */
|
|
|
|
static inline void *realloc_down( void *ptr, size_t size )
|
|
|
|
{
|
|
|
|
void *ret = realloc( ptr, size );
|
|
|
|
return ret ? ret : ptr;
|
|
|
|
}
|
|
|
|
|
2018-02-11 20:35:16 +01:00
|
|
|
/**
|
|
|
|
* This wrapper around realloc() will free the input pointer when
|
|
|
|
* realloc() returns NULL. The use case ptr = realloc(ptr, newsize) will
|
|
|
|
* cause a memory leak when ptr pointed to a heap allocation before,
|
|
|
|
* leaving the buffer allocated but unreferenced. vlc_realloc() is a
|
|
|
|
* drop-in replacement for that use case (and only that use case).
|
|
|
|
*/
|
|
|
|
static inline void *realloc_or_free( void *p, size_t sz )
|
|
|
|
{
|
|
|
|
void *n = realloc(p,sz);
|
|
|
|
if( !n )
|
|
|
|
free(p);
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2007-02-26 20:19:18 +01:00
|
|
|
#define TAB_INIT( count, tab ) \
|
|
|
|
do { \
|
|
|
|
(count) = 0; \
|
|
|
|
(tab) = NULL; \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
#define TAB_CLEAN( count, tab ) \
|
|
|
|
do { \
|
2008-03-11 22:18:20 +01:00
|
|
|
free( tab ); \
|
2007-02-26 20:19:18 +01:00
|
|
|
(count)= 0; \
|
|
|
|
(tab)= NULL; \
|
|
|
|
} while(0)
|
2006-10-19 23:00:14 +02:00
|
|
|
|
2007-03-23 20:49:21 +01:00
|
|
|
#define TAB_APPEND_CAST( cast, count, tab, p ) \
|
2007-02-26 20:19:18 +01:00
|
|
|
do { \
|
2006-10-19 23:00:14 +02:00
|
|
|
if( (count) > 0 ) \
|
2013-07-22 17:42:52 +02:00
|
|
|
(tab) = cast realloc( tab, sizeof( *(tab) ) * ( (count) + 1 ) ); \
|
2006-10-19 23:00:14 +02:00
|
|
|
else \
|
2013-07-22 17:42:52 +02:00
|
|
|
(tab) = cast malloc( sizeof( *(tab) ) ); \
|
2009-05-31 21:25:54 +02:00
|
|
|
if( !(tab) ) abort(); \
|
2007-02-26 20:19:18 +01:00
|
|
|
(tab)[count] = (p); \
|
|
|
|
(count)++; \
|
|
|
|
} while(0)
|
2006-10-19 23:00:14 +02:00
|
|
|
|
2007-03-23 20:49:21 +01:00
|
|
|
#define TAB_APPEND( count, tab, p ) \
|
|
|
|
TAB_APPEND_CAST( , count, tab, p )
|
|
|
|
|
2013-02-06 19:56:02 +01:00
|
|
|
#define TAB_FIND( count, tab, p, idx ) \
|
2007-02-26 20:19:18 +01:00
|
|
|
do { \
|
2013-02-06 19:56:02 +01:00
|
|
|
for( (idx) = 0; (idx) < (count); (idx)++ ) \
|
|
|
|
if( (tab)[(idx)] == (p) ) \
|
2011-08-21 01:56:50 +02:00
|
|
|
break; \
|
2013-02-06 19:56:02 +01:00
|
|
|
if( (idx) >= (count) ) \
|
|
|
|
(idx) = -1; \
|
2007-02-26 20:19:18 +01:00
|
|
|
} while(0)
|
2006-10-19 23:00:14 +02:00
|
|
|
|
2007-10-11 14:02:06 +02:00
|
|
|
|
2016-02-12 16:17:55 +01:00
|
|
|
#define TAB_ERASE( count, tab, index ) \
|
|
|
|
do { \
|
|
|
|
if( (count) > 1 ) \
|
2017-02-21 20:53:15 +01:00
|
|
|
memmove( (tab) + (index), \
|
|
|
|
(tab) + (index) + 1, \
|
|
|
|
((count) - (index) - 1 ) * sizeof( *(tab) ) );\
|
2016-02-12 16:17:55 +01:00
|
|
|
(count)--; \
|
|
|
|
if( (count) == 0 ) \
|
|
|
|
{ \
|
|
|
|
free( tab ); \
|
|
|
|
(tab) = NULL; \
|
|
|
|
} \
|
|
|
|
} while(0)
|
|
|
|
|
2006-10-19 23:00:14 +02:00
|
|
|
#define TAB_REMOVE( count, tab, p ) \
|
2007-02-26 20:19:18 +01:00
|
|
|
do { \
|
2011-08-21 01:56:50 +02:00
|
|
|
int i_index; \
|
|
|
|
TAB_FIND( count, tab, p, i_index ); \
|
|
|
|
if( i_index >= 0 ) \
|
2016-02-12 16:17:55 +01:00
|
|
|
TAB_ERASE( count, tab, i_index ); \
|
2007-02-26 20:19:18 +01:00
|
|
|
} while(0)
|
2006-10-19 23:00:14 +02:00
|
|
|
|
2007-06-04 00:19:50 +02:00
|
|
|
#define TAB_INSERT_CAST( cast, count, tab, p, index ) do { \
|
|
|
|
if( (count) > 0 ) \
|
2013-07-22 17:42:52 +02:00
|
|
|
(tab) = cast realloc( tab, sizeof( *(tab) ) * ( (count) + 1 ) ); \
|
2007-06-04 00:19:50 +02:00
|
|
|
else \
|
2013-07-22 17:42:52 +02:00
|
|
|
(tab) = cast malloc( sizeof( *(tab) ) ); \
|
2009-05-31 21:25:54 +02:00
|
|
|
if( !(tab) ) abort(); \
|
2007-06-04 00:19:50 +02:00
|
|
|
if( (count) - (index) > 0 ) \
|
2017-02-21 20:53:15 +01:00
|
|
|
memmove( (tab) + (index) + 1, \
|
|
|
|
(tab) + (index), \
|
|
|
|
((count) - (index)) * sizeof( *(tab) ) );\
|
2007-06-04 00:19:50 +02:00
|
|
|
(tab)[(index)] = (p); \
|
|
|
|
(count)++; \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
#define TAB_INSERT( count, tab, p, index ) \
|
|
|
|
TAB_INSERT_CAST( , count, tab, p, index )
|
|
|
|
|
2006-10-19 23:00:14 +02:00
|
|
|
/**
|
2006-10-21 13:09:51 +02:00
|
|
|
* Binary search in a sorted array. The key must be comparable by < and >
|
2006-10-19 23:00:14 +02:00
|
|
|
* \param entries array of entries
|
|
|
|
* \param count number of entries
|
|
|
|
* \param elem key to check within an entry (like .id, or ->i_id)
|
|
|
|
* \param zetype type of the key
|
|
|
|
* \param key value of the key
|
|
|
|
* \param answer index of answer within the array. -1 if not found
|
|
|
|
*/
|
2007-02-26 20:19:18 +01:00
|
|
|
#define BSEARCH( entries, count, elem, zetype, key, answer ) \
|
|
|
|
do { \
|
2006-10-19 23:00:14 +02:00
|
|
|
int low = 0, high = count - 1; \
|
|
|
|
answer = -1; \
|
|
|
|
while( low <= high ) {\
|
2016-09-14 18:16:12 +02:00
|
|
|
int mid = ((unsigned int)low + (unsigned int)high) >> 1;\
|
2006-10-19 23:00:14 +02:00
|
|
|
zetype mid_val = entries[mid] elem;\
|
|
|
|
if( mid_val < key ) \
|
|
|
|
low = mid + 1; \
|
|
|
|
else if ( mid_val > key ) \
|
|
|
|
high = mid -1; \
|
|
|
|
else \
|
|
|
|
{ \
|
|
|
|
answer = mid; break; \
|
|
|
|
}\
|
|
|
|
} \
|
2007-02-26 20:19:18 +01:00
|
|
|
} while(0)
|
2006-10-19 23:00:14 +02:00
|
|
|
|
2007-08-09 21:54:43 +02:00
|
|
|
|
2006-10-19 23:00:14 +02:00
|
|
|
/************************************************************************
|
|
|
|
* Dynamic arrays with progressive allocation
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
/* Internal functions */
|
|
|
|
#define _ARRAY_ALLOC(array, newsize) { \
|
2008-09-26 21:35:46 +02:00
|
|
|
(array).i_alloc = newsize; \
|
2023-07-12 08:31:07 +02:00
|
|
|
(array).p_elems = vlc_reallocarray( (array).p_elems, (array).i_alloc, \
|
2012-09-03 11:44:38 +02:00
|
|
|
sizeof(*(array).p_elems) ); \
|
2009-05-31 21:25:54 +02:00
|
|
|
if( !(array).p_elems ) abort(); \
|
2006-10-19 23:00:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#define _ARRAY_GROW1(array) { \
|
2008-09-26 21:35:46 +02:00
|
|
|
if( (array).i_alloc < 10 ) \
|
2006-10-19 23:00:14 +02:00
|
|
|
_ARRAY_ALLOC(array, 10 ) \
|
2008-09-26 21:35:46 +02:00
|
|
|
else if( (array).i_alloc == (array).i_size ) \
|
2017-05-30 10:55:36 +02:00
|
|
|
_ARRAY_ALLOC(array, (int)((array).i_alloc * 1.5) ) \
|
2006-10-19 23:00:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* API */
|
|
|
|
#define DECL_ARRAY(type) struct { \
|
|
|
|
int i_alloc; \
|
|
|
|
int i_size; \
|
|
|
|
type *p_elems; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define TYPEDEF_ARRAY(type, name) typedef DECL_ARRAY(type) name;
|
|
|
|
|
|
|
|
#define ARRAY_INIT(array) \
|
2008-09-26 22:59:23 +02:00
|
|
|
do { \
|
2008-09-26 21:35:46 +02:00
|
|
|
(array).i_alloc = 0; \
|
|
|
|
(array).i_size = 0; \
|
2008-09-26 22:59:23 +02:00
|
|
|
(array).p_elems = NULL; \
|
|
|
|
} while(0)
|
2006-10-19 23:00:14 +02:00
|
|
|
|
2006-10-21 13:09:51 +02:00
|
|
|
#define ARRAY_RESET(array) \
|
2008-09-26 22:59:23 +02:00
|
|
|
do { \
|
2008-09-26 21:35:46 +02:00
|
|
|
(array).i_alloc = 0; \
|
|
|
|
(array).i_size = 0; \
|
2008-09-26 22:59:23 +02:00
|
|
|
free( (array).p_elems ); (array).p_elems = NULL; \
|
|
|
|
} while(0)
|
2006-10-21 13:09:51 +02:00
|
|
|
|
2008-09-26 22:59:23 +02:00
|
|
|
#define ARRAY_APPEND(array, elem) \
|
|
|
|
do { \
|
2006-10-19 23:00:14 +02:00
|
|
|
_ARRAY_GROW1(array); \
|
2008-09-26 21:35:46 +02:00
|
|
|
(array).p_elems[(array).i_size] = elem; \
|
|
|
|
(array).i_size++; \
|
2008-09-26 22:59:23 +02:00
|
|
|
} while(0)
|
2006-10-19 23:00:14 +02:00
|
|
|
|
2008-09-26 22:59:23 +02:00
|
|
|
#define ARRAY_INSERT(array,elem,pos) \
|
|
|
|
do { \
|
2006-10-19 23:00:14 +02:00
|
|
|
_ARRAY_GROW1(array); \
|
2018-08-28 10:52:21 +02:00
|
|
|
if( (array).i_size - (pos) ) { \
|
|
|
|
memmove( (array).p_elems + (pos) + 1, (array).p_elems + (pos), \
|
|
|
|
((array).i_size-(pos)) * sizeof(*(array).p_elems) ); \
|
2006-10-19 23:00:14 +02:00
|
|
|
} \
|
2008-09-26 21:35:46 +02:00
|
|
|
(array).p_elems[pos] = elem; \
|
|
|
|
(array).i_size++; \
|
2008-09-26 22:59:23 +02:00
|
|
|
} while(0)
|
2006-10-19 23:00:14 +02:00
|
|
|
|
2011-08-21 01:56:50 +02:00
|
|
|
#define _ARRAY_SHRINK(array) { \
|
|
|
|
if( (array).i_size > 10 && (array).i_size < (int)((array).i_alloc / 1.5) ) { \
|
|
|
|
_ARRAY_ALLOC(array, (array).i_size + 5); \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
2018-07-18 15:51:56 +02:00
|
|
|
#define ARRAY_FIND(array, p, idx) \
|
|
|
|
TAB_FIND((array).i_size, (array).p_elems, p, idx)
|
|
|
|
|
2008-09-26 22:59:23 +02:00
|
|
|
#define ARRAY_REMOVE(array,pos) \
|
|
|
|
do { \
|
2008-09-26 21:35:46 +02:00
|
|
|
if( (array).i_size - (pos) - 1 ) \
|
2006-10-19 23:00:14 +02:00
|
|
|
{ \
|
2018-08-28 10:52:21 +02:00
|
|
|
memmove( (array).p_elems + (pos), (array).p_elems + (pos) + 1, \
|
|
|
|
( (array).i_size - (pos) - 1 ) *sizeof(*(array).p_elems) );\
|
2006-10-19 23:00:14 +02:00
|
|
|
} \
|
2008-09-26 21:35:46 +02:00
|
|
|
(array).i_size--; \
|
2006-10-19 23:00:14 +02:00
|
|
|
_ARRAY_SHRINK(array); \
|
2008-09-26 22:59:23 +02:00
|
|
|
} while(0)
|
2006-10-19 23:00:14 +02:00
|
|
|
|
2006-10-21 13:09:51 +02:00
|
|
|
#define ARRAY_VAL(array, pos) array.p_elems[pos]
|
|
|
|
|
|
|
|
#define ARRAY_BSEARCH(array, elem, zetype, key, answer) \
|
2008-09-26 21:35:46 +02:00
|
|
|
BSEARCH( (array).p_elems, (array).i_size, elem, zetype, key, answer)
|
2006-10-21 13:09:51 +02:00
|
|
|
|
2018-08-28 15:13:53 +02:00
|
|
|
/* append ##item to index variable name to avoid variable shadowing warnings for
|
|
|
|
* nested loops */
|
2018-08-28 15:13:52 +02:00
|
|
|
#define ARRAY_FOREACH(item, array) \
|
2018-08-28 15:13:53 +02:00
|
|
|
for (int array_index_##item = 0; \
|
|
|
|
array_index_##item < (array).i_size && \
|
|
|
|
((item) = (array).p_elems[array_index_##item], 1); \
|
|
|
|
++array_index_##item)
|
2006-10-21 13:09:51 +02:00
|
|
|
|
2007-10-11 14:02:06 +02:00
|
|
|
|
|
|
|
/************************************************************************
|
2008-03-21 22:25:30 +01:00
|
|
|
* Dynamic arrays with progressive allocation (Preferred API)
|
2007-10-11 14:02:06 +02:00
|
|
|
************************************************************************/
|
|
|
|
typedef struct vlc_array_t
|
|
|
|
{
|
2017-02-18 15:10:02 +01:00
|
|
|
size_t i_count;
|
2007-10-11 14:02:06 +02:00
|
|
|
void ** pp_elems;
|
|
|
|
} vlc_array_t;
|
|
|
|
|
|
|
|
static inline void vlc_array_init( vlc_array_t * p_array )
|
|
|
|
{
|
2017-02-18 15:10:02 +01:00
|
|
|
p_array->i_count = 0;
|
|
|
|
p_array->pp_elems = NULL;
|
2007-10-11 14:02:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void vlc_array_clear( vlc_array_t * p_array )
|
|
|
|
{
|
|
|
|
free( p_array->pp_elems );
|
2017-02-18 15:10:02 +01:00
|
|
|
vlc_array_init( p_array );
|
2007-10-11 14:02:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Read */
|
2023-08-31 10:13:52 +02:00
|
|
|
static inline size_t vlc_array_count( const vlc_array_t * p_array )
|
2007-10-11 14:02:06 +02:00
|
|
|
{
|
|
|
|
return p_array->i_count;
|
|
|
|
}
|
|
|
|
|
2017-11-14 17:22:01 +01:00
|
|
|
#ifndef __cplusplus
|
2017-02-18 15:10:02 +01:00
|
|
|
# define vlc_array_item_at_index(ar, idx) \
|
|
|
|
_Generic((ar), \
|
|
|
|
const vlc_array_t *: ((ar)->pp_elems[idx]), \
|
|
|
|
vlc_array_t *: ((ar)->pp_elems[idx]))
|
2017-11-14 17:22:01 +01:00
|
|
|
#else
|
2017-02-18 15:10:02 +01:00
|
|
|
static inline void *vlc_array_item_at_index( vlc_array_t *ar, size_t idx )
|
2007-10-11 14:02:06 +02:00
|
|
|
{
|
2017-02-18 15:10:02 +01:00
|
|
|
return ar->pp_elems[idx];
|
2007-10-11 14:02:06 +02:00
|
|
|
}
|
|
|
|
|
2017-02-18 15:10:02 +01:00
|
|
|
static inline const void *vlc_array_item_at_index( const vlc_array_t *ar,
|
|
|
|
size_t idx )
|
2007-11-19 14:58:52 +01:00
|
|
|
{
|
2017-02-18 15:10:02 +01:00
|
|
|
return ar->pp_elems[idx];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static inline ssize_t vlc_array_index_of_item( const vlc_array_t *ar,
|
|
|
|
const void *elem )
|
|
|
|
{
|
|
|
|
for( size_t i = 0; i < ar->i_count; i++ )
|
2007-11-19 14:58:52 +01:00
|
|
|
{
|
2017-02-18 15:10:02 +01:00
|
|
|
if( ar->pp_elems[i] == elem )
|
2007-11-19 14:58:52 +01:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-10-11 14:02:06 +02:00
|
|
|
/* Write */
|
2017-10-25 12:02:28 +02:00
|
|
|
static inline int vlc_array_insert( vlc_array_t *ar, void *elem, int idx )
|
2007-10-11 14:02:06 +02:00
|
|
|
{
|
2017-02-18 15:10:02 +01:00
|
|
|
void **pp = (void **)realloc( ar->pp_elems,
|
|
|
|
sizeof( void * ) * (ar->i_count + 1) );
|
|
|
|
if( unlikely(pp == NULL) )
|
2017-10-25 12:02:28 +02:00
|
|
|
return -1;
|
2017-02-18 15:10:02 +01:00
|
|
|
|
|
|
|
size_t tail = ar->i_count - idx;
|
|
|
|
if( tail > 0 )
|
|
|
|
memmove( pp + idx + 1, pp + idx, sizeof( void * ) * tail );
|
|
|
|
|
|
|
|
pp[idx] = elem;
|
|
|
|
ar->i_count++;
|
|
|
|
ar->pp_elems = pp;
|
2017-10-25 12:02:28 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void vlc_array_insert_or_abort( vlc_array_t *ar, void *elem, int idx )
|
|
|
|
{
|
|
|
|
if( vlc_array_insert( ar, elem, idx ) )
|
|
|
|
abort();
|
2007-10-11 14:02:06 +02:00
|
|
|
}
|
|
|
|
|
2017-10-25 12:00:05 +02:00
|
|
|
static inline int vlc_array_append( vlc_array_t *ar, void *elem )
|
2007-10-11 14:02:06 +02:00
|
|
|
{
|
2017-02-18 15:10:02 +01:00
|
|
|
void **pp = (void **)realloc( ar->pp_elems,
|
|
|
|
sizeof( void * ) * (ar->i_count + 1) );
|
|
|
|
if( unlikely(pp == NULL) )
|
2017-10-25 12:00:05 +02:00
|
|
|
return -1;
|
2017-02-18 15:10:02 +01:00
|
|
|
|
|
|
|
pp[ar->i_count++] = elem;
|
|
|
|
ar->pp_elems = pp;
|
2017-10-25 12:00:05 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void vlc_array_append_or_abort( vlc_array_t *ar, void *elem )
|
|
|
|
{
|
|
|
|
if( vlc_array_append( ar, elem ) != 0 )
|
|
|
|
abort();
|
2007-10-11 14:02:06 +02:00
|
|
|
}
|
|
|
|
|
2017-02-18 15:10:02 +01:00
|
|
|
static inline void vlc_array_remove( vlc_array_t *ar, size_t idx )
|
2007-10-11 14:02:06 +02:00
|
|
|
{
|
2017-02-18 15:10:02 +01:00
|
|
|
void **pp = ar->pp_elems;
|
|
|
|
size_t tail = ar->i_count - idx - 1;
|
|
|
|
|
|
|
|
if( tail > 0 )
|
|
|
|
memmove( pp + idx, pp + idx + 1, sizeof( void * ) * tail );
|
|
|
|
|
|
|
|
ar->i_count--;
|
|
|
|
|
|
|
|
if( ar->i_count > 0 )
|
|
|
|
{
|
|
|
|
pp = (void **)realloc( pp, sizeof( void * ) * ar->i_count );
|
|
|
|
if( likely(pp != NULL) )
|
|
|
|
ar->pp_elems = pp;
|
|
|
|
}
|
|
|
|
else
|
2007-10-11 14:02:06 +02:00
|
|
|
{
|
2017-02-18 15:10:02 +01:00
|
|
|
free( pp );
|
|
|
|
ar->pp_elems = NULL;
|
2007-10-11 14:02:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-08-10 02:35:57 +02:00
|
|
|
/************************************************************************
|
|
|
|
* Dictionaries
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
/* This function is not intended to be crypto-secure, we only want it to be
|
|
|
|
* fast and not suck too much. This one is pretty fast and did 0 collisions
|
|
|
|
* in wenglish's dictionary.
|
|
|
|
*/
|
|
|
|
static inline uint64_t DictHash( const char *psz_string, int hashsize )
|
|
|
|
{
|
|
|
|
uint64_t i_hash = 0;
|
|
|
|
if( psz_string )
|
|
|
|
{
|
|
|
|
while( *psz_string )
|
|
|
|
{
|
|
|
|
i_hash += *psz_string++;
|
|
|
|
i_hash += i_hash << 10;
|
|
|
|
i_hash ^= i_hash >> 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return i_hash % hashsize;
|
|
|
|
}
|
|
|
|
|
2008-10-09 01:22:02 +02:00
|
|
|
typedef struct vlc_dictionary_entry_t
|
2007-08-10 02:35:57 +02:00
|
|
|
{
|
|
|
|
char * psz_key;
|
|
|
|
void * p_value;
|
|
|
|
struct vlc_dictionary_entry_t * p_next;
|
2008-10-09 01:22:02 +02:00
|
|
|
} vlc_dictionary_entry_t;
|
2007-08-10 02:35:57 +02:00
|
|
|
|
|
|
|
typedef struct vlc_dictionary_t
|
|
|
|
{
|
|
|
|
int i_size;
|
2008-10-09 01:22:02 +02:00
|
|
|
vlc_dictionary_entry_t ** p_entries;
|
2007-08-10 02:35:57 +02:00
|
|
|
} vlc_dictionary_t;
|
|
|
|
|
|
|
|
static void * const kVLCDictionaryNotFound = NULL;
|
|
|
|
|
|
|
|
static inline void vlc_dictionary_init( vlc_dictionary_t * p_dict, int i_size )
|
|
|
|
{
|
2008-10-09 01:22:02 +02:00
|
|
|
p_dict->p_entries = NULL;
|
|
|
|
|
2007-08-13 16:05:34 +02:00
|
|
|
if( i_size > 0 )
|
|
|
|
{
|
2008-10-09 01:22:02 +02:00
|
|
|
p_dict->p_entries = (vlc_dictionary_entry_t **)calloc( i_size, sizeof(*p_dict->p_entries) );
|
|
|
|
if( !p_dict->p_entries )
|
|
|
|
i_size = 0;
|
2007-08-13 16:05:34 +02:00
|
|
|
}
|
2007-08-10 02:35:57 +02:00
|
|
|
p_dict->i_size = i_size;
|
|
|
|
}
|
|
|
|
|
2008-09-30 09:10:25 +02:00
|
|
|
static inline void vlc_dictionary_clear( vlc_dictionary_t * p_dict,
|
|
|
|
void ( * pf_free )( void * p_data, void * p_obj ),
|
|
|
|
void * p_obj )
|
2007-08-10 02:35:57 +02:00
|
|
|
{
|
2008-02-13 23:09:00 +01:00
|
|
|
if( p_dict->p_entries )
|
2007-08-10 02:35:57 +02:00
|
|
|
{
|
2008-10-09 01:22:02 +02:00
|
|
|
for( int i = 0; i < p_dict->i_size; i++ )
|
2007-08-10 02:35:57 +02:00
|
|
|
{
|
2008-10-09 01:22:02 +02:00
|
|
|
vlc_dictionary_entry_t * p_current, * p_next;
|
2008-02-13 23:09:00 +01:00
|
|
|
p_current = p_dict->p_entries[i];
|
|
|
|
while( p_current )
|
|
|
|
{
|
2008-02-15 23:04:18 +01:00
|
|
|
p_next = p_current->p_next;
|
2008-09-30 09:10:25 +02:00
|
|
|
if( pf_free != NULL )
|
|
|
|
( * pf_free )( p_current->p_value, p_obj );
|
2008-02-15 23:04:18 +01:00
|
|
|
free( p_current->psz_key );
|
2008-02-13 23:09:00 +01:00
|
|
|
free( p_current );
|
|
|
|
p_current = p_next;
|
|
|
|
}
|
2007-08-10 02:35:57 +02:00
|
|
|
}
|
2008-02-13 23:09:00 +01:00
|
|
|
free( p_dict->p_entries );
|
2008-09-28 15:56:21 +02:00
|
|
|
p_dict->p_entries = NULL;
|
2007-08-10 02:35:57 +02:00
|
|
|
}
|
|
|
|
p_dict->i_size = 0;
|
|
|
|
}
|
|
|
|
|
2012-02-22 09:27:38 +01:00
|
|
|
static inline int
|
|
|
|
vlc_dictionary_has_key( const vlc_dictionary_t * p_dict, const char * psz_key )
|
|
|
|
{
|
|
|
|
if( !p_dict->p_entries )
|
|
|
|
return 0;
|
2007-08-10 02:35:57 +02:00
|
|
|
|
2012-02-22 09:27:38 +01:00
|
|
|
int i_pos = DictHash( psz_key, p_dict->i_size );
|
2017-04-23 15:39:37 +02:00
|
|
|
const vlc_dictionary_entry_t * p_entry = p_dict->p_entries[i_pos];
|
|
|
|
for( ; p_entry != NULL; p_entry = p_entry->p_next )
|
|
|
|
{
|
|
|
|
if( !strcmp( psz_key, p_entry->psz_key ) )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return p_entry != NULL;
|
2012-02-22 09:27:38 +01:00
|
|
|
}
|
2007-08-10 02:35:57 +02:00
|
|
|
|
|
|
|
static inline void *
|
|
|
|
vlc_dictionary_value_for_key( const vlc_dictionary_t * p_dict, const char * psz_key )
|
|
|
|
{
|
2007-08-13 16:05:34 +02:00
|
|
|
if( !p_dict->p_entries )
|
|
|
|
return kVLCDictionaryNotFound;
|
|
|
|
|
2007-08-10 02:35:57 +02:00
|
|
|
int i_pos = DictHash( psz_key, p_dict->i_size );
|
2008-10-09 01:22:02 +02:00
|
|
|
vlc_dictionary_entry_t * p_entry = p_dict->p_entries[i_pos];
|
2007-08-10 02:35:57 +02:00
|
|
|
|
|
|
|
if( !p_entry )
|
|
|
|
return kVLCDictionaryNotFound;
|
|
|
|
|
2008-02-13 23:09:00 +01:00
|
|
|
/* Make sure we return the right item. (Hash collision) */
|
2007-08-10 02:35:57 +02:00
|
|
|
do {
|
|
|
|
if( !strcmp( psz_key, p_entry->psz_key ) )
|
|
|
|
return p_entry->p_value;
|
|
|
|
p_entry = p_entry->p_next;
|
|
|
|
} while( p_entry );
|
|
|
|
|
2007-08-10 15:18:46 +02:00
|
|
|
return kVLCDictionaryNotFound;
|
2007-08-10 02:35:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
vlc_dictionary_keys_count( const vlc_dictionary_t * p_dict )
|
|
|
|
{
|
2008-10-09 01:22:02 +02:00
|
|
|
vlc_dictionary_entry_t * p_entry;
|
2007-08-10 02:35:57 +02:00
|
|
|
int i, count = 0;
|
2008-02-13 23:09:00 +01:00
|
|
|
|
|
|
|
if( !p_dict->p_entries )
|
|
|
|
return 0;
|
|
|
|
|
2007-08-10 02:35:57 +02:00
|
|
|
for( i = 0; i < p_dict->i_size; i++ )
|
|
|
|
{
|
|
|
|
for( p_entry = p_dict->p_entries[i]; p_entry; p_entry = p_entry->p_next ) count++;
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2017-06-21 18:18:27 +02:00
|
|
|
static inline bool
|
|
|
|
vlc_dictionary_is_empty( const vlc_dictionary_t * p_dict )
|
|
|
|
{
|
|
|
|
if( p_dict->p_entries )
|
|
|
|
for( int i = 0; i < p_dict->i_size; i++ )
|
|
|
|
if( p_dict->p_entries[i] )
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-08-10 02:35:57 +02:00
|
|
|
static inline char **
|
|
|
|
vlc_dictionary_all_keys( const vlc_dictionary_t * p_dict )
|
|
|
|
{
|
2008-10-09 01:22:02 +02:00
|
|
|
vlc_dictionary_entry_t * p_entry;
|
2007-08-10 02:35:57 +02:00
|
|
|
char ** ppsz_ret;
|
|
|
|
int i, count = vlc_dictionary_keys_count( p_dict );
|
|
|
|
|
2007-08-10 02:56:04 +02:00
|
|
|
ppsz_ret = (char**)malloc(sizeof(char *) * (count + 1));
|
2012-05-03 13:16:00 +02:00
|
|
|
if( unlikely(!ppsz_ret) )
|
2012-05-02 11:05:16 +02:00
|
|
|
return NULL;
|
2008-01-17 23:16:11 +01:00
|
|
|
|
2007-08-10 02:35:57 +02:00
|
|
|
count = 0;
|
|
|
|
for( i = 0; i < p_dict->i_size; i++ )
|
|
|
|
{
|
|
|
|
for( p_entry = p_dict->p_entries[i]; p_entry; p_entry = p_entry->p_next )
|
|
|
|
ppsz_ret[count++] = strdup( p_entry->psz_key );
|
|
|
|
}
|
|
|
|
ppsz_ret[count] = NULL;
|
|
|
|
return ppsz_ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2017-05-18 12:59:19 +02:00
|
|
|
vlc_dictionary_insert_impl_( vlc_dictionary_t * p_dict, const char * psz_key,
|
|
|
|
void * p_value, bool rebuild )
|
2007-08-10 02:35:57 +02:00
|
|
|
{
|
2007-08-13 16:05:34 +02:00
|
|
|
if( !p_dict->p_entries )
|
|
|
|
vlc_dictionary_init( p_dict, 1 );
|
|
|
|
|
2007-08-10 02:35:57 +02:00
|
|
|
int i_pos = DictHash( psz_key, p_dict->i_size );
|
2008-10-09 01:22:02 +02:00
|
|
|
vlc_dictionary_entry_t * p_entry;
|
2007-08-10 02:35:57 +02:00
|
|
|
|
2008-10-09 01:22:02 +02:00
|
|
|
p_entry = (vlc_dictionary_entry_t *)malloc(sizeof(*p_entry));
|
2007-08-10 02:35:57 +02:00
|
|
|
p_entry->psz_key = strdup( psz_key );
|
|
|
|
p_entry->p_value = p_value;
|
|
|
|
p_entry->p_next = p_dict->p_entries[i_pos];
|
|
|
|
p_dict->p_entries[i_pos] = p_entry;
|
|
|
|
if( rebuild )
|
|
|
|
{
|
|
|
|
/* Count how many items there was */
|
|
|
|
int count;
|
2008-10-09 01:22:02 +02:00
|
|
|
for( count = 1; p_entry->p_next; count++ )
|
|
|
|
p_entry = p_entry->p_next;
|
2007-08-10 02:35:57 +02:00
|
|
|
if( count > 3 ) /* XXX: this need tuning */
|
|
|
|
{
|
|
|
|
/* Here it starts to be not good, rebuild a bigger dictionary */
|
|
|
|
struct vlc_dictionary_t new_dict;
|
2007-08-13 16:05:34 +02:00
|
|
|
int i_new_size = ( (p_dict->i_size+2) * 3) / 2; /* XXX: this need tuning */
|
2007-08-10 02:35:57 +02:00
|
|
|
int i;
|
|
|
|
vlc_dictionary_init( &new_dict, i_new_size );
|
|
|
|
for( i = 0; i < p_dict->i_size; i++ )
|
|
|
|
{
|
|
|
|
p_entry = p_dict->p_entries[i];
|
2008-02-15 23:04:18 +01:00
|
|
|
while( p_entry )
|
2007-08-10 02:35:57 +02:00
|
|
|
{
|
2017-05-18 12:59:19 +02:00
|
|
|
vlc_dictionary_insert_impl_( &new_dict, p_entry->psz_key,
|
2007-08-10 02:35:57 +02:00
|
|
|
p_entry->p_value,
|
2008-10-09 01:22:02 +02:00
|
|
|
false /* To avoid multiple rebuild loop */);
|
2007-08-10 02:35:57 +02:00
|
|
|
p_entry = p_entry->p_next;
|
2007-09-10 20:56:52 +02:00
|
|
|
}
|
2007-08-10 02:35:57 +02:00
|
|
|
}
|
2008-02-15 23:04:18 +01:00
|
|
|
|
2008-09-30 09:10:25 +02:00
|
|
|
vlc_dictionary_clear( p_dict, NULL, NULL );
|
2007-08-10 02:35:57 +02:00
|
|
|
p_dict->i_size = new_dict.i_size;
|
2008-02-13 23:09:00 +01:00
|
|
|
p_dict->p_entries = new_dict.p_entries;
|
2007-08-10 02:35:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
vlc_dictionary_insert( vlc_dictionary_t * p_dict, const char * psz_key, void * p_value )
|
|
|
|
{
|
2017-05-18 12:59:19 +02:00
|
|
|
vlc_dictionary_insert_impl_( p_dict, psz_key, p_value, true );
|
2007-08-10 02:35:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2008-09-30 09:10:25 +02:00
|
|
|
vlc_dictionary_remove_value_for_key( const vlc_dictionary_t * p_dict, const char * psz_key,
|
|
|
|
void ( * pf_free )( void * p_data, void * p_obj ),
|
|
|
|
void * p_obj )
|
2007-08-10 02:35:57 +02:00
|
|
|
{
|
2007-08-13 16:05:34 +02:00
|
|
|
if( !p_dict->p_entries )
|
|
|
|
return;
|
|
|
|
|
2007-08-10 02:35:57 +02:00
|
|
|
int i_pos = DictHash( psz_key, p_dict->i_size );
|
2008-10-09 01:22:02 +02:00
|
|
|
vlc_dictionary_entry_t * p_entry = p_dict->p_entries[i_pos];
|
|
|
|
vlc_dictionary_entry_t * p_prev;
|
2007-08-10 02:35:57 +02:00
|
|
|
|
|
|
|
if( !p_entry )
|
|
|
|
return; /* Not found, nothing to do */
|
|
|
|
|
|
|
|
/* Hash collision */
|
|
|
|
p_prev = NULL;
|
|
|
|
do {
|
|
|
|
if( !strcmp( psz_key, p_entry->psz_key ) )
|
|
|
|
{
|
2008-09-30 09:10:25 +02:00
|
|
|
if( pf_free != NULL )
|
|
|
|
( * pf_free )( p_entry->p_value, p_obj );
|
2007-08-10 02:35:57 +02:00
|
|
|
if( !p_prev )
|
|
|
|
p_dict->p_entries[i_pos] = p_entry->p_next;
|
|
|
|
else
|
|
|
|
p_prev->p_next = p_entry->p_next;
|
|
|
|
free( p_entry->psz_key );
|
|
|
|
free( p_entry );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
p_prev = p_entry;
|
|
|
|
p_entry = p_entry->p_next;
|
|
|
|
} while( p_entry );
|
|
|
|
|
|
|
|
/* No key was found */
|
|
|
|
}
|
|
|
|
|
2010-11-18 13:10:37 +01:00
|
|
|
#ifdef __cplusplus
|
|
|
|
// C++ helpers
|
|
|
|
template <typename T>
|
|
|
|
void vlc_delete_all( T &container )
|
|
|
|
{
|
|
|
|
typename T::iterator it = container.begin();
|
|
|
|
while ( it != container.end() )
|
|
|
|
{
|
|
|
|
delete *it;
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
container.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2006-10-19 23:00:14 +02:00
|
|
|
#endif
|