2014-10-15 17:26:51 +04:00
/*
* String Vector functions modeled after glibc argv_ * functions
*
* Copyright Volker Lendecke < vl @ samba . org > 2014
*
* 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 3 of the License , 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 , see < http : //www.gnu.org/licenses/>.
*/
# include "replace.h"
# include "strv.h"
# include "talloc.h"
# include <string.h>
2016-02-29 11:49:39 +03:00
static int _strv_append ( TALLOC_CTX * mem_ctx , char * * dst , const char * src ,
size_t srclen )
2014-10-15 17:26:51 +04:00
{
size_t dstlen = talloc_array_length ( * dst ) ;
size_t newlen = dstlen + srclen ;
char * new_dst ;
if ( ( newlen < srclen ) | | ( newlen < dstlen ) ) {
return ERANGE ;
}
new_dst = talloc_realloc ( mem_ctx , * dst , char , newlen ) ;
if ( new_dst = = NULL ) {
return ENOMEM ;
}
memcpy ( & new_dst [ dstlen ] , src , srclen ) ;
* dst = new_dst ;
return 0 ;
}
int strv_add ( TALLOC_CTX * mem_ctx , char * * strv , const char * string )
{
2016-02-29 11:49:39 +03:00
return _strv_append ( mem_ctx , strv , string , strlen ( string ) + 1 ) ;
2014-10-15 17:26:51 +04:00
}
2016-02-29 07:15:04 +03:00
int strv_addn ( TALLOC_CTX * mem_ctx , char * * strv , const char * string , size_t n )
{
char t [ n + 1 ] ;
memcpy ( t , string , n ) ;
t [ n ] = ' \0 ' ;
return _strv_append ( mem_ctx , strv , t , n + 1 ) ;
}
2014-10-15 17:26:51 +04:00
int strv_append ( TALLOC_CTX * mem_ctx , char * * strv , const char * src )
{
2016-02-29 11:49:39 +03:00
return _strv_append ( mem_ctx , strv , src , talloc_array_length ( src ) ) ;
2014-10-15 17:26:51 +04:00
}
static bool strv_valid_entry ( const char * strv , const char * entry ,
size_t * strv_len , size_t * entry_len )
{
size_t len ;
len = talloc_array_length ( strv ) ;
if ( len = = 0 ) {
return false ;
}
if ( strv [ len - 1 ] ! = ' \0 ' ) {
return false ;
}
if ( entry < strv ) {
return false ;
}
if ( entry > = ( strv + len ) ) {
return false ;
}
* strv_len = len ;
* entry_len = strlen ( entry ) ;
return true ;
}
char * strv_next ( char * strv , const char * entry )
{
size_t len , entry_len ;
char * result ;
2015-04-28 11:28:52 +03:00
if ( entry = = NULL ) {
if ( strv_valid_entry ( strv , strv , & len , & entry_len ) ) {
return strv ;
}
return NULL ;
}
2014-10-15 17:26:51 +04:00
if ( ! strv_valid_entry ( strv , entry , & len , & entry_len ) ) {
return NULL ;
}
result = & strv [ entry - strv ] ; /* avoid const problems with this stmt */
result + = entry_len + 1 ;
if ( result > = ( strv + len ) ) {
return NULL ;
}
return result ;
}
size_t strv_count ( char * strv )
{
char * entry ;
size_t count = 0 ;
for ( entry = strv ; entry ! = NULL ; entry = strv_next ( strv , entry ) ) {
count + = 1 ;
}
return count ;
}
char * strv_find ( char * strv , const char * entry )
{
char * e = NULL ;
while ( ( e = strv_next ( strv , e ) ) ! = NULL ) {
if ( strcmp ( e , entry ) = = 0 ) {
return e ;
}
}
return NULL ;
}
void strv_delete ( char * * strv , char * entry )
{
size_t len , entry_len ;
if ( entry = = NULL ) {
return ;
}
if ( ! strv_valid_entry ( * strv , entry , & len , & entry_len ) ) {
return ;
}
entry_len + = 1 ;
memmove ( entry , entry + entry_len ,
len - entry_len - ( entry - * strv ) ) ;
* strv = talloc_realloc ( NULL , * strv , char , len - entry_len ) ;
}
2016-10-13 12:25:08 +03:00
char * const * strv_to_env ( TALLOC_CTX * mem_ctx , char * strv )
{
char * * data ;
char * next = NULL ;
size_t i ;
size_t count = strv_count ( strv ) ;
if ( strv = = NULL ) {
return NULL ;
}
data = talloc_array ( mem_ctx , char * , count + 1 ) ;
if ( data = = NULL ) {
return NULL ;
}
for ( i = 0 ; i < count ; i + + ) {
next = strv_next ( strv , next ) ;
data [ i ] = next ;
}
data [ count ] = NULL ;
return data ;
}