2013-01-18 09:00:23 +01:00
/*
2019-05-07 07:15:25 +02:00
Copyright (C) 2011 Equinor ASA, Norway.
2015-10-30 09:43:10 +01:00
The file 'stringlist.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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 3 of the License, or
(at your option) any later version.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
2013-01-18 09:00:23 +01:00
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
2018-08-13 10:20:34 +02:00
#include <ert/util/ert_api_config.hpp>
2018-04-09 08:48:36 +02:00
#ifdef ERT_HAVE_OPENDIR
#include <sys/types.h>
#include <dirent.h>
#endif
2016-04-19 14:48:14 +02:00
#ifdef ERT_HAVE_GLOB
2013-01-18 09:00:23 +01:00
#include <glob.h>
#else
#include <Windows.h>
#endif
2018-08-13 10:20:34 +02:00
#include <ert/util/util.h>
2018-05-04 14:06:42 +02:00
#include <ert/util/stringlist.hpp>
#include <ert/util/vector.hpp>
2013-01-18 09:00:23 +01:00
#define STRINGLIST_TYPE_ID 671855
/**
This file implements a very thin wrapper around a list (vector) of
strings, and the total number of strings. It is mostly to avoid
sending both argc and argv.
2015-10-30 09:43:10 +01:00
2013-01-18 09:00:23 +01:00
Most of the functionality is implemented through vector.c and
stateless functions in util.c
*/
#ifdef __cplusplus
extern "C" {
#endif
struct stringlist_struct {
UTIL_TYPE_ID_DECLARATION ;
vector_type * strings ;
};
static void stringlist_fprintf__ ( const stringlist_type * stringlist , const char * sep , FILE * stream ) {
int length = vector_get_size ( stringlist -> strings );
2013-04-04 08:24:40 +02:00
if ( length > 0 ) {
int i ;
for ( i = 0 ; i < length - 1 ; i ++ ) {
const char * s = stringlist_iget ( stringlist , i );
fprintf ( stream , "%s%s" , s , sep );
}
2015-10-30 09:43:10 +01:00
2013-04-04 08:24:40 +02:00
fprintf ( stream , "%s" , stringlist_iget ( stringlist , length - 1 ));
2013-01-18 09:00:23 +01:00
}
}
void stringlist_fprintf ( const stringlist_type * stringlist , const char * sep , FILE * stream ) {
stringlist_fprintf__ ( stringlist , sep , stream );
}
void stringlist_fprintf_fmt ( const stringlist_type * stringlist , const stringlist_type * fmt_list , FILE * stream ) {
if ( stringlist_get_size ( stringlist ) == stringlist_get_size ( fmt_list )) {
int i ;
for ( i = 0 ; i < stringlist_get_size ( stringlist ); i ++ )
fprintf ( stream , stringlist_iget ( fmt_list , i ) , stringlist_iget ( stringlist , i ));
} util_abort ( "%s: length of stringlist:%d length of fmt_list:%d - must be equal \n " , __func__ , stringlist_get_size ( stringlist ) , stringlist_get_size ( fmt_list ));
}
/**
This function appends a copy of s into the stringlist.
*/
void stringlist_append_copy ( stringlist_type * stringlist , const char * s ) {
2018-10-30 13:21:11 +01:00
if ( s )
vector_append_buffer ( stringlist -> strings , s , strlen ( s ) + 1 );
else
vector_append_ref ( stringlist -> strings , NULL );
2013-01-18 09:00:23 +01:00
}
/*****************************************************************/
void stringlist_iset_copy ( stringlist_type * stringlist , int index , const char * s ) {
vector_iset_buffer ( stringlist -> strings , index , s , strlen ( s ) + 1 );
}
void stringlist_iset_ref ( stringlist_type * stringlist , int index , const char * s ) {
vector_iset_ref ( stringlist -> strings , index , s );
}
void stringlist_iset_owned_ref ( stringlist_type * stringlist , int index , const char * s ) {
vector_iset_owned_ref ( stringlist -> strings , index , s , free );
}
/*****************************************************************/
void stringlist_insert_copy ( stringlist_type * stringlist , int index , const char * s ) {
vector_insert_buffer ( stringlist -> strings , index , s , strlen ( s ) + 1 );
}
void stringlist_insert_ref ( stringlist_type * stringlist , int index , const char * s ) {
vector_insert_ref ( stringlist -> strings , index , s );
}
void stringlist_insert_owned_ref ( stringlist_type * stringlist , int index , const char * s ) {
vector_insert_owned_ref ( stringlist -> strings , index , s , free );
}
static stringlist_type * stringlist_alloc_empty ( bool alloc_vector ) {
2017-08-29 07:48:38 +02:00
stringlist_type * stringlist = ( stringlist_type * ) util_malloc ( sizeof * stringlist );
2013-01-18 09:00:23 +01:00
UTIL_TYPE_ID_INIT ( stringlist , STRINGLIST_TYPE_ID );
if ( alloc_vector )
stringlist -> strings = vector_alloc_new ();
else
stringlist -> strings = NULL ;
2015-10-30 09:43:10 +01:00
2013-01-18 09:00:23 +01:00
return stringlist ;
}
stringlist_type * stringlist_alloc_new () {
return stringlist_alloc_empty ( true );
}
stringlist_type * stringlist_alloc_argv_copy ( const char ** argv , int argc ) {
int iarg ;
stringlist_type * stringlist = stringlist_alloc_empty ( true );
2015-10-30 09:43:10 +01:00
for ( iarg = 0 ; iarg < argc ; iarg ++ )
2013-01-18 09:00:23 +01:00
stringlist_append_copy ( stringlist , argv [ iarg ]);
2015-10-30 09:43:10 +01:00
2013-01-18 09:00:23 +01:00
return stringlist ;
}
/*
Can not use vector_deep copy - because we might not have the
constructor registered, in the node_data instance; but in this case
we know the copy constructor.
*/
stringlist_type * stringlist_alloc_deep_copy_with_limits ( const stringlist_type * src , int offset , int num_strings ) {
stringlist_type * copy = stringlist_alloc_empty ( true );
int i ;
2015-10-30 09:43:10 +01:00
for ( i = 0 ; i < num_strings ; i ++ )
2013-01-18 09:00:23 +01:00
stringlist_append_copy ( copy , stringlist_iget ( src , i + offset ));
return copy ;
}
stringlist_type * stringlist_alloc_deep_copy_with_offset ( const stringlist_type * src , int offset ) {
return stringlist_alloc_deep_copy_with_limits ( src , offset , stringlist_get_size ( src ) - offset );
}
stringlist_type * stringlist_alloc_deep_copy ( const stringlist_type * src ) {
return stringlist_alloc_deep_copy_with_offset ( src , 0 );
}
void stringlist_append_stringlist_copy ( stringlist_type * stringlist , const stringlist_type * src ) {
int i ;
for ( i = 0 ; i < stringlist_get_size ( src ); i ++ )
stringlist_append_copy ( stringlist , stringlist_iget ( src , i ));
}
/**
Insert a copy of a stringlist in some position.
2015-10-30 09:43:10 +01:00
2013-01-18 09:00:23 +01:00
Can probably be made more efficient.
*/
void stringlist_insert_stringlist_copy ( stringlist_type * stringlist , const stringlist_type * src , int pos ) {
int size_old = stringlist_get_size ( stringlist );
/** Cannot use assert_index here. */
if ( pos < 0 || pos > size_old )
util_abort ( "%s: Position %d is out of bounds. Min: 0 Max: %d \n " , pos , size_old );
{
stringlist_type * start = stringlist_alloc_new ();
stringlist_type * end = stringlist_alloc_new ();
stringlist_type * newList = stringlist_alloc_new ();
int i ;
for ( i = 0 ; i < pos ; i ++ )
2018-10-30 13:21:11 +01:00
stringlist_append_copy ( start , stringlist_iget ( stringlist , i ));
2013-01-18 09:00:23 +01:00
for ( i = pos ; i < size_old ; i ++ )
2018-10-30 13:21:11 +01:00
stringlist_append_copy ( end , stringlist_iget ( stringlist , i ));
2013-01-18 09:00:23 +01:00
stringlist_append_stringlist_copy ( newList , start );
stringlist_append_stringlist_copy ( newList , src );
stringlist_append_stringlist_copy ( newList , end );
stringlist_clear ( stringlist );
stringlist_append_stringlist_copy ( stringlist , newList );
stringlist_free ( newList );
stringlist_free ( start );
stringlist_free ( end );
}
}
void stringlist_deep_copy ( stringlist_type * target , const stringlist_type * src ) {
stringlist_clear ( target );
{
int i ;
for ( i = 0 ; i < stringlist_get_size ( src ); i ++ )
stringlist_append_copy ( target , stringlist_iget ( src , i ));
}
}
2015-10-30 09:43:10 +01:00
/**
2013-01-18 09:00:23 +01:00
Frees all the memory contained by the stringlist.
*/
void stringlist_clear ( stringlist_type * stringlist ) {
vector_clear ( stringlist -> strings );
}
void stringlist_free ( stringlist_type * stringlist ) {
stringlist_clear ( stringlist );
vector_free ( stringlist -> strings );
free ( stringlist );
}
static UTIL_SAFE_CAST_FUNCTION ( stringlist , STRINGLIST_TYPE_ID );
UTIL_IS_INSTANCE_FUNCTION ( stringlist , STRINGLIST_TYPE_ID )
void stringlist_free__ ( void * __stringlist ) {
stringlist_type * stringlist = stringlist_safe_cast ( __stringlist );
stringlist_free ( stringlist );
}
void stringlist_idel ( stringlist_type * stringlist , int index ) {
vector_idel ( stringlist -> strings , index );
}
2013-04-04 08:24:40 +02:00
char * stringlist_pop ( stringlist_type * stringlist ) {
2017-08-29 07:48:38 +02:00
return ( char * ) vector_pop_back ( stringlist -> strings );
2013-04-04 08:24:40 +02:00
}
2013-01-18 09:00:23 +01:00
const char * stringlist_iget ( const stringlist_type * stringlist , int index ) {
2017-08-29 07:48:38 +02:00
return ( const char * ) vector_iget ( stringlist -> strings , index );
2013-01-18 09:00:23 +01:00
}
2013-12-09 15:19:06 +01:00
const char * stringlist_front ( const stringlist_type * stringlist ) {
2017-08-29 07:48:38 +02:00
return ( const char * ) vector_iget ( stringlist -> strings , 0 );
2013-12-09 15:19:06 +01:00
}
const char * stringlist_back ( const stringlist_type * stringlist ) {
2017-08-29 07:48:38 +02:00
return ( const char * ) vector_iget ( stringlist -> strings , vector_get_size ( stringlist -> strings ) - 1 );
2013-12-09 15:19:06 +01:00
}
2013-04-04 08:24:40 +02:00
int stringlist_iget_as_int ( const stringlist_type * stringlist , int index , bool * valid ) {
const char * string_value = stringlist_iget ( stringlist , index );
int value = - 1 ;
2015-10-30 09:43:10 +01:00
2013-04-04 08:24:40 +02:00
if ( valid != NULL )
* valid = false ;
2015-10-30 09:43:10 +01:00
if ( util_sscanf_int ( string_value , & value ))
2013-04-04 08:24:40 +02:00
if ( valid != NULL )
* valid = true ;
return value ;
}
2015-04-14 15:47:22 +02:00
double stringlist_iget_as_double ( const stringlist_type * stringlist , int index , bool * valid ) {
const char * string_value = stringlist_iget ( stringlist , index );
double value = - 1.0 ;
if ( valid != NULL )
* valid = false ;
if ( util_sscanf_double ( string_value , & value ))
if ( valid != NULL )
* valid = true ;
return value ;
}
2014-10-09 20:13:04 +02:00
bool stringlist_iget_as_bool ( const stringlist_type * stringlist , int index , bool * valid ) {
const char * string_value = stringlist_iget ( stringlist , index );
bool value = false ;
if ( valid != NULL )
* valid = false ;
if ( util_sscanf_bool ( string_value , & value ))
if ( valid != NULL )
* valid = true ;
return value ;
}
2013-04-04 08:24:40 +02:00
const char * stringlist_get_last ( const stringlist_type * stringlist ) {
2017-08-29 07:48:38 +02:00
return ( const char * ) vector_get_last ( stringlist -> strings );
2013-04-04 08:24:40 +02:00
}
2013-01-18 09:00:23 +01:00
bool stringlist_iequal ( const stringlist_type * stringlist , int index , const char * s ) {
return util_string_equal ( stringlist_iget ( stringlist , index ) , s );
}
/**
Will return NULL if you ask for something beyond the limits of the
stringlist (will die on negative index - that is NEVER OK).
*/
const char * stringlist_safe_iget ( const stringlist_type * stringlist , int index ) {
if ( index < 0 )
util_abort ( "%s: negative index:%d is NOT allowed \n " , __func__ , index );
if ( index < stringlist_get_size ( stringlist ))
return stringlist_iget ( stringlist , index );
else
return NULL ;
}
char * stringlist_iget_copy ( const stringlist_type * stringlist , int index ) {
return util_alloc_string_copy ( stringlist_iget ( stringlist , index ));
}
int stringlist_get_size ( const stringlist_type * stringlist ) {
return vector_get_size ( stringlist -> strings );
}
/*
2015-10-30 09:43:10 +01:00
Return NULL if the list has zero entries.
2013-01-18 09:00:23 +01:00
*/
static char ** stringlist_alloc_char__ ( const stringlist_type * stringlist , bool deep_copy ) {
char ** strings = NULL ;
int size = stringlist_get_size ( stringlist );
if ( size > 0 ) {
int i ;
2017-08-29 07:48:38 +02:00
strings = ( char ** ) util_calloc ( size , sizeof * strings );
2013-01-18 09:00:23 +01:00
for ( i = 0 ; i < size ; i ++ ) {
if ( deep_copy )
strings [ i ] = stringlist_iget_copy ( stringlist , i );
else
strings [ i ] = ( char * ) stringlist_iget ( stringlist , i );
}
}
return strings ;
}
char ** stringlist_alloc_char_copy ( const stringlist_type * stringlist ) {
return stringlist_alloc_char__ ( stringlist , true );
}
char ** stringlist_alloc_char_ref ( const stringlist_type * stringlist ) {
return stringlist_alloc_char__ ( stringlist , false );
}
2015-10-30 09:43:10 +01:00
/**
2013-01-18 09:00:23 +01:00
Scans the stringlist (linear scan) to see if it contains (at
least) one occurence of 's'. Will never return true if the input
string @s equals NULL, altough the stringlist itself can contain
NULL elements.
*/
bool stringlist_contains ( const stringlist_type * stringlist , const char * s ) {
int size = stringlist_get_size ( stringlist );
int index = 0 ;
bool contains = false ;
2015-10-30 09:43:10 +01:00
2013-01-18 09:00:23 +01:00
while (( index < size ) && ( ! contains )) {
const char * istring = stringlist_iget ( stringlist , index );
if ( istring != NULL )
if ( strcmp ( istring , s ) == 0 ) contains = true ;
index ++ ;
}
return contains ;
}
/**
Finds the indicies of the entries matching 's'.
*/
int_vector_type * stringlist_find ( const stringlist_type * stringlist , const char * s ) {
int_vector_type * indicies = int_vector_alloc ( 0 , - 1 );
int size = stringlist_get_size ( stringlist );
int index = 0 ;
2015-10-30 09:43:10 +01:00
2013-01-18 09:00:23 +01:00
while ( index < size ) {
const char * istring = stringlist_iget ( stringlist , index );
if ( istring != NULL )
if ( strcmp ( istring , s ) == 0 )
int_vector_append ( indicies , index );
index ++ ;
}
return indicies ;
}
/**
Find the index of the first index matching 's'.
Returns -1 if 's' cannot be found.
*/
int stringlist_find_first ( const stringlist_type * stringlist , const char * s ) {
bool found = false ;
int size = stringlist_get_size ( stringlist );
int index = 0 ;
while ( index < size && ! found )
{
const char * istring = stringlist_iget ( stringlist , index );
if ( istring != NULL )
if ( strcmp ( istring , s ) == 0 )
{
found = true ;
break ;
}
index ++ ;
}
if ( found )
return index ;
else
return - 1 ;
}
bool stringlist_equal ( const stringlist_type * s1 , const stringlist_type * s2 ) {
int size1 = stringlist_get_size ( s1 );
int size2 = stringlist_get_size ( s2 );
if ( size1 == size2 ) {
bool equal = true ;
int i ;
for ( i = 0 ; i < size1 ; i ++ ) {
if ( strcmp ( stringlist_iget ( s1 , i ) , stringlist_iget ( s2 , i )) != 0 ) {
equal = false ;
break ;
}
}
return equal ;
} else
return false ;
}
/**
The interval is halfopen: [start_index , end_index).
*/
/* Based on buffer?? */
char * stringlist_alloc_joined_substring ( const stringlist_type * s , int start_index , int end_index , const char * sep ) {
if ( start_index >= stringlist_get_size ( s ))
2016-11-22 12:50:28 +01:00
return util_alloc_string_copy ( "" );
2013-01-18 09:00:23 +01:00
{
char * string = NULL ;
int i ;
2015-10-30 09:43:10 +01:00
2013-01-18 09:00:23 +01:00
/* Start with allocating a string long enough to hold all the substrings. */
{
int sep_length = strlen ( sep );
int total_length = 0 ;
for ( i = start_index ; i < end_index ; i ++ )
total_length += ( strlen ( stringlist_iget ( s , i )) + sep_length );
2015-10-30 09:43:10 +01:00
2013-01-18 09:00:23 +01:00
total_length += ( 1 - sep_length );
2017-08-29 07:48:38 +02:00
string = ( char * ) util_malloc ( total_length * sizeof * string );
2013-01-18 09:00:23 +01:00
string [ 0 ] = '\0' ;
}
2015-10-30 09:43:10 +01:00
2013-01-18 09:00:23 +01:00
for ( i = start_index ; i < end_index ; i ++ ) {
strcat ( string , stringlist_iget ( s , i ));
if ( i < ( end_index - 1 ))
strcat ( string , sep );
}
2015-10-30 09:43:10 +01:00
2013-01-18 09:00:23 +01:00
return string ;
}
}
char * stringlist_alloc_joined_string ( const stringlist_type * s , const char * sep ) {
return stringlist_alloc_joined_substring ( s , 0 , stringlist_get_size ( s ) , sep );
}
/**
This function will allocate a stringlist instance based on
splitting the input string. If the input string is NULL the
function will return a stringlist instance with zero elements.
Observe that the splitting is based on __ANY__ character in @sep;
NOT the full exact string @sep.
The newly allocated stringlist will take ownership of the strings
in the list. The actual functionality is in the util_split_string()
function.
*/
2015-10-30 09:43:10 +01:00
2013-01-18 09:00:23 +01:00
stringlist_type * stringlist_alloc_from_split ( const char * input_string , const char * sep ) {
stringlist_type * slist = stringlist_alloc_new ();
if ( input_string != NULL ) {
char ** items ;
int num_items , i ;
util_split_string ( input_string , sep , & num_items , & items );
for ( i = 0 ; i < num_items ; i ++ )
stringlist_append_copy ( slist , items [ i ] );
util_free_stringlist ( items , num_items );
}
return slist ;
}
/*****************************************************************/
void stringlist_fwrite ( const stringlist_type * s , FILE * stream ) {
int i ;
int size = stringlist_get_size ( s );
util_fwrite_int ( size , stream );
2015-10-30 09:43:10 +01:00
for ( i = 0 ; i < size ; i ++ )
2013-01-18 09:00:23 +01:00
util_fwrite_string ( stringlist_iget ( s , i ) , stream );
}
2015-10-30 09:43:10 +01:00
/*
2013-01-18 09:00:23 +01:00
When a stringlist is loaded from file the current content of the
stringlist is discarded; and the stringlist becomes the owner of
all the data read in.
*/
void stringlist_fread ( stringlist_type * s , FILE * stream ) {
int size = util_fread_int ( stream );
int i ;
stringlist_clear ( s );
2018-10-30 13:21:11 +01:00
for ( i = 0 ; i < size ; i ++ ) {
char * tmp = util_fread_alloc_string ( stream );
stringlist_append_copy ( s , tmp );
free ( tmp );
}
2013-01-18 09:00:23 +01:00
}
stringlist_type * stringlist_fread_alloc ( FILE * stream ) {
stringlist_type * s = stringlist_alloc_empty ( true );
stringlist_fread ( s , stream );
return s ;
}
static int strcmp__ ( const void * __s1 , const void * __s2 ) {
const char * s1 = ( const char * ) __s1 ;
const char * s2 = ( const char * ) __s2 ;
return strcmp ( s1 , s2 );
}
/**
Will sort the stringlist inplace. The prototype of the comparison
function is
int (cmp) (const void * , const void *);
i.e. ths strings are implemented as (void *). If string_cmp == NULL
the sort function will use the ordinary strcmp() function for
comparison.
*/
void stringlist_sort ( stringlist_type * s , string_cmp_ftype * string_cmp )
{
if ( string_cmp == NULL )
vector_sort ( s -> strings , strcmp__ );
else
vector_sort ( s -> strings , string_cmp );
}
void stringlist_python_sort ( stringlist_type * s , int cmp_flag ) {
if ( cmp_flag == 0 )
stringlist_sort ( s , NULL );
else if ( cmp_flag == 1 )
stringlist_sort ( s , ( string_cmp_ftype * ) util_strcmp_int );
else if ( cmp_flag == 2 )
stringlist_sort ( s , ( string_cmp_ftype * ) util_strcmp_float );
else
util_abort ( "%s: unrecognized cmp_flag:%d \n " , __func__ , cmp_flag );
}
2013-04-04 08:24:40 +02:00
void stringlist_reverse ( stringlist_type * s ) {
vector_inplace_reverse ( s -> strings );
}
2013-01-18 09:00:23 +01:00
/*****************************************************************/
/*
This function uses the stdlib function glob() to select file/path
names matching a pattern. The stringlist is cleared when the
function starts.
*/
2016-04-19 14:48:14 +02:00
#ifdef ERT_HAVE_GLOB
2013-01-18 09:00:23 +01:00
int stringlist_select_matching ( stringlist_type * names , const char * pattern ) {
int match_count = 0 ;
stringlist_clear ( names );
{
2018-05-04 14:06:42 +02:00
size_t i ;
2017-08-29 07:48:38 +02:00
glob_t * pglob = ( glob_t * ) util_malloc ( sizeof * pglob );
2013-01-18 09:00:23 +01:00
int glob_flags = 0 ;
glob ( pattern , glob_flags , NULL , pglob );
match_count = pglob -> gl_pathc ;
for ( i = 0 ; i < pglob -> gl_pathc ; i ++ )
stringlist_append_copy ( names , pglob -> gl_pathv [ i ] );
globfree ( pglob ); /* Only frees the _internal_ data structures of the pglob object. */
free ( pglob );
}
return match_count ;
}
#endif
int stringlist_select_matching_files ( stringlist_type * names , const char * path , const char * file_pattern ) {
2016-04-19 14:48:14 +02:00
#ifdef ERT_HAVE_GLOB
2013-01-18 09:00:23 +01:00
char * pattern = util_alloc_filename ( path , file_pattern , NULL );
int match_count = stringlist_select_matching ( names , pattern );
free ( pattern );
return match_count ;
#else
{
WIN32_FIND_DATA file_data ;
HANDLE file_handle ;
char * pattern = util_alloc_filename ( path , file_pattern , NULL );
2015-10-30 09:43:10 +01:00
2013-01-18 09:00:23 +01:00
stringlist_clear ( names );
file_handle = FindFirstFile ( pattern , & file_data );
if ( file_handle != INVALID_HANDLE_VALUE ) {
do {
char * full_path = util_alloc_filename ( path , file_data . cFileName , NULL );
2018-10-30 13:21:11 +01:00
stringlist_append_copy ( names , full_path );
free ( full_path );
2013-01-18 09:00:23 +01:00
} while ( FindNextFile ( file_handle , & file_data ) != 0 );
}
FindClose ( file_handle );
free ( pattern );
2015-10-30 09:43:10 +01:00
2013-01-18 09:00:23 +01:00
return stringlist_get_size ( names );
}
#endif
}
2018-04-09 08:48:36 +02:00
int stringlist_select_files ( stringlist_type * names , const char * path , file_pred_ftype * predicate , const void * pred_arg ) {
stringlist_clear ( names );
char * path_arg = path ? util_alloc_string_copy ( path ) : util_alloc_cwd ();
#ifdef ERT_HAVE_OPENDIR
DIR * dir = opendir ( path_arg );
if ( ! dir ) {
free ( path_arg );
return 0 ;
}
while ( true ) {
struct dirent * entry = readdir ( dir );
if ( ! entry )
break ;
if ( util_string_equal ( entry -> d_name , "." ))
continue ;
if ( util_string_equal ( entry -> d_name , ".." ))
continue ;
if ( predicate && ! predicate ( entry -> d_name , pred_arg ))
continue ;
2018-10-30 13:21:11 +01:00
{
char * fname = util_alloc_filename ( path , entry -> d_name , NULL );
stringlist_append_copy ( names , fname );
free ( fname );
}
2018-04-09 08:48:36 +02:00
}
closedir ( dir );
#else
WIN32_FIND_DATA file_data ;
HANDLE file_handle ;
char * pattern = util_alloc_filename ( path_arg , "*" , NULL );
file_handle = FindFirstFile ( pattern , & file_data );
if ( file_handle != INVALID_HANDLE_VALUE ) {
do {
if ( util_string_equal ( file_data . cFileName , "." ))
continue ;
if ( util_string_equal ( file_data . cFileName , ".." ))
continue ;
if ( predicate && ! predicate ( file_data . cFileName , pred_arg ))
continue ;
2018-10-30 13:21:11 +01:00
{
char * tmp_fname = util_alloc_filename ( path , file_data . cFileName , NULL );
stringlist_append_copy ( names , tmp_fname );
free ( tmp_fname );
}
2018-04-09 08:48:36 +02:00
} while ( FindNextFile ( file_handle , & file_data ) != 0 );
FindClose ( file_handle );
}
free ( pattern );
#endif
free ( path_arg );
return stringlist_get_size ( names );
}
2013-10-07 13:31:13 +02:00
int stringlist_append_matching_elements ( stringlist_type * target , const stringlist_type * src , const char * pattern ) {
int ielm ;
int match_count = 0 ;
for ( ielm = 0 ; ielm < stringlist_get_size ( src ); ielm ++ ) {
const char * item = stringlist_iget ( src , ielm );
if ( util_fnmatch ( pattern , item ) == 0 ) {
stringlist_append_copy ( target , item );
match_count ++ ;
}
}
return match_count ;
}
2015-10-30 09:43:10 +01:00
2018-10-30 13:21:11 +01:00
int stringlist_select_matching_elements ( stringlist_type * target , const stringlist_type * src , const char * pattern ) {
2013-10-07 13:31:13 +02:00
stringlist_clear ( target );
return stringlist_append_matching_elements ( target , src , pattern );
}
2013-01-18 09:00:23 +01:00
2018-04-09 08:48:36 +02:00
static int void_strcmp ( const void * s1 , const void * s2 ) {
2018-05-04 14:06:42 +02:00
return strcmp (( char * ) s1 , ( char * ) s2 );
2018-04-09 08:48:36 +02:00
}
2017-10-02 17:11:36 +02:00
bool stringlist_unique ( const stringlist_type * stringlist )
{
bool unique = true ;
2018-10-30 13:21:11 +01:00
stringlist_type * cpy = stringlist_alloc_deep_copy ( stringlist );
2017-10-02 17:11:36 +02:00
2018-04-09 08:48:36 +02:00
stringlist_sort ( cpy , void_strcmp );
2017-10-02 17:11:36 +02:00
for ( int i = 0 ; i < stringlist_get_size ( cpy ) - 1 ; i ++ ) {
const char * s1 = stringlist_iget ( cpy , i );
const char * s2 = stringlist_iget ( cpy , i + 1 );
if ( strcmp ( s1 , s2 ) == 0 ) {
unique = false ;
break ;
}
}
stringlist_free ( cpy );
return unique ;
}
2013-01-18 09:00:23 +01:00
#ifdef __cplusplus
}
#endif