/* -*- mode: C -*- */
/*
IGraph library.
Copyright (C) 2003, 2004, 2005 Gabor Csardi <csardi@rmki.kfki.hu>
MTA RMKI, Konkoly-Thege Miklos st. 29-33, Budapest 1121, Hungary
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 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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "types.h"
#include "memory.h"
#include "random.h"
#include "error.h"
#include <assert.h>
#include <string.h> /* memcpy & co. */
#include <stdlib.h>
/**
* \ingroup strvector
* \brief Initializes a string vector (constructor).
*
* @return Error code:
* - <b>IGRAPH_ENOMEM</b>: out of memory
*/
int igraph_strvector_init(igraph_strvector_t *sv, long int len) {
long int i;
sv->data=Calloc(len, char*);
if (sv->data==0) {
IGRAPH_ERROR("strvector init failed", IGRAPH_ENOMEM);
}
for (i=0; i<len; i++) {
sv->data[i]=Calloc(1, char);
if (sv->data[i]==0) {
igraph_strvector_destroy(sv);
IGRAPH_ERROR("strvector init failed", IGRAPH_ENOMEM);
}
sv->data[i][0]='\0';
}
sv->len=len;
return 0;
}
/**
* \ingroup strvector
* \brief Frees memory allocated for a string vector.
*/
void igraph_strvector_destroy(igraph_strvector_t *sv) {
long int i;
assert(sv != 0);
if (sv->data != 0) {
for (i=0; i<sv->len; i++) {
if (sv->data[i] != 0) {
Free(sv->data[i]);
}
}
Free(sv->data);
}
}
/**
* \ingroup strvector
* \brief Returns an element of a string vector.
*/
void igraph_strvector_get(const igraph_strvector_t *sv, long int idx,
char **value) {
assert(sv != 0);
assert(sv->data != 0);
assert(sv->data[idx] != 0);
*value = sv->data[idx];
}
/**
* \ingroup strvector
* \brief Sets an element of a string vector.
*
* @return Error code:
* - <b>IGRAPH_ENOMEM</b>: out of memory
*/
int igraph_strvector_set(igraph_strvector_t *sv, long int idx,
const char *value) {
assert(sv != 0);
assert(sv->data != 0);
if (sv->data[idx] == 0) {
sv->data[idx] = Calloc(strlen(value)+1, char);
if (sv->data[idx]==0) {
IGRAPH_ERROR("strvector set failed", IGRAPH_ENOMEM);
}
} else {
char *tmp=Realloc(sv->data[idx], strlen(value)+1, char);
if (tmp==0) {
IGRAPH_ERROR("strvector set failed", IGRAPH_ENOMEM);
}
sv->data[idx]=tmp;
}
strcpy(sv->data[idx], value);
return 0;
}
int igraph_strvector_set2(igraph_strvector_t *sv, long int idx,
const char *value, int len) {
assert(sv != 0);
assert(sv->data != 0);
if (sv->data[idx] == 0) {
sv->data[idx] = Calloc(len+1, char);
if (sv->data[idx]==0) {
IGRAPH_ERROR("strvector set failed", IGRAPH_ENOMEM);
}
} else {
char *tmp=Realloc(sv->data[idx], len+1, char);
if (tmp==0) {
IGRAPH_ERROR("strvector set failed", IGRAPH_ENOMEM);
}
sv->data[idx]=tmp;
}
memcpy(sv->data[idx], value, len*sizeof(char));
sv->data[idx][len]='\0';
return 0;
}
/**
* \ingroup strvector
* \brief Removes a section from a string vector.
* \todo repair realloc
*/
void igraph_strvector_remove_section(igraph_strvector_t *v, long int from,
long int to) {
long int i;
/* char **tmp; */
assert(v != 0);
assert(v->data != 0);
for (i=from; i<to; i++) {
if (v->data[i] != 0) {
Free(v->data[i]);
}
}
for (i=0; i<v->len-to; i++) {
v->data[from+i]=v->data[to+i];
}
v->len -= (to-from);
/* try to make it smaller */
/* tmp=Realloc(v->data, v->len, char*); */
/* if (tmp!=0) { */
/* v->data=tmp; */
/* } */
}
/**
* \ingroup strvector
* \brief Removes a single element from a string vector.
*/
void igraph_strvector_remove(igraph_strvector_t *v, long int elem) {
assert(v != 0);
assert(v->data != 0);
igraph_strvector_remove_section(v, elem, elem+1);
}
/**
* \ingroup strvector
* \brief Copies an interval of a string vector.
*/
void igraph_strvector_move_interval(igraph_strvector_t *v, long int begin,
long int end, long int to) {
long int i;
assert(v != 0);
assert(v->data != 0);
for (i=to; i<to+end-begin; i++) {
if (v->data[i] != 0) {
Free(v->data[i]);
}
}
for (i=0; i<end-begin; i++) {
if (v->data[begin+i] != 0) {
long int len=strlen(v->data[begin+i])+1;
v->data[to+i]=Calloc(len, char);
memcpy(v->data[to+i], v->data[begin+i], sizeof(char)*len);
}
}
}
/**
* \ingroup strvector
* \brief Copies a string vector (constructor).
*
* @return Error code:
* - <b>IGRAPH_ENOMEM</b>: out of memory
* \todo why does the assert fail
*/
int igraph_strvector_copy(igraph_strvector_t *to,
const igraph_strvector_t *from) {
long int i;
char *str;
assert(from != 0);
/* assert(from->data != 0); */
to->data=Calloc(from->len, char*);
if (to->data==0) {
IGRAPH_ERROR("Cannot copy string vector", IGRAPH_ENOMEM);
}
to->len=from->len;
for (i=0; i<from->len; i++) {
int ret;
igraph_strvector_get(from, i, &str);
ret=igraph_strvector_set(to, i, str);
if (ret != 0) {
igraph_strvector_destroy(to);
IGRAPH_ERROR("cannot copy string vector", ret);
}
}
return 0;
}
/**
* \ingroup strvector
* \brief Resizes a string vector.
*
* @return Error code:
* - <b>IGRAPH_ENOMEM</b>: out of memory
*/
int igraph_strvector_resize(igraph_strvector_t* v, long int newsize) {
long int toadd=newsize-v->len, i, j;
char **tmp;
assert(v != 0);
assert(v->data != 0);
/* printf("resize %li to %li\n", v->len, newsize); */
if (newsize < v->len) {
long int i, reallocsize=newsize;
for (i=newsize; i<v->len; i++) {
Free(v->data[i]);
}
/* try to give back some space */
if (reallocsize==0) { reallocsize=1; }
tmp=Realloc(v->data, reallocsize, char*);
/* printf("resize %li to %li, %p\n", v->len, newsize, tmp); */
if (tmp != 0) {
v->data=tmp;
}
} else if (newsize > v->len) {
igraph_bool_t error=0;
tmp=Realloc(v->data, newsize, char*);
if (tmp==0) {
IGRAPH_ERROR("cannot resize string vector", IGRAPH_ENOMEM);
}
v->data = tmp;
for (i=0; i<toadd; i++) {
v->data[v->len+i] = Calloc(1, char);
if (v->data[v->len+i] == 0) {
error=1;
break;
}
v->data[v->len+i][0]='\0';
}
if (error) {
/* There was an error, free everything we've allocated so far */
for (j=0; j<i; j++) {
if (v->data[v->len+i] != 0) {
Free(v->data[v->len+i]);
}
}
/* Try to give back space */
tmp=Realloc(v->data, v->len, char*);
if (tmp != 0) {
v->data=tmp;
}
IGRAPH_ERROR("canot resize string vector", IGRAPH_ENOMEM);
}
}
v->len = newsize;
return 0;
}
/**
* \ingroup strvector
* \brief Gives the size of a string vector.
* \todo repair assert
*/
long int igraph_strvector_size(const igraph_strvector_t *sv) {
assert(sv != 0);
assert(sv->data != 0);
return sv->len;
}
/**
* \ingroup strvector
* \brief Adds an element to the back of a string vector.
*/
int igraph_strvector_add(igraph_strvector_t *v, const char *value) {
long int s=igraph_strvector_size(v);
char **tmp;
assert(v != 0);
assert(v->data != 0);
tmp=Realloc(v->data, s+1, char*);
if (tmp == 0) {
IGRAPH_ERROR("cannot add string to string vector", IGRAPH_ENOMEM);
}
v->data=tmp;
v->data[s]=Calloc(strlen(value)+1, char);
if (v->data[s]==0) {
IGRAPH_ERROR("cannot add string to string vector", IGRAPH_ENOMEM);
}
strcpy(v->data[s], value);
v->len += 1;
return 0;
}
/**
* \ingroup strvector
* \brief Removes elements from a string vector (for internal use)
*/
void igraph_strvector_permdelete(igraph_strvector_t *v, long int *index,
long int nremove) {
long int i;
char **tmp;
assert(v != 0);
assert(v->data != 0);
for (i=0; i<igraph_strvector_size(v); i++) {
if (index[i] != 0) {
v->data[ index[i]-1 ] = v->data[i];
} else {
Free(v->data[i]);
}
}
/* Try to make it shorter */
tmp=Realloc(v->data, v->len-nremove, char*);
if (tmp != 0) {
v->data=tmp;
}
v->len -= nremove;
}
/**
* \ingroup strvector
* \brief Removes elements from a string vector (for internal use)
*/
void igraph_strvector_remove_negidx(igraph_strvector_t *v, const igraph_vector_t *neg,
long int nremove) {
long int i, idx=0;
char **tmp;
assert(v != 0);
assert(v->data != 0);
for (i=0; i<igraph_strvector_size(v); i++) {
if (VECTOR(*neg)[i] >= 0) {
v->data[idx++] = v->data[i];
} else {
Free(v->data[i]);
}
}
/* Try to give back some memory */
tmp=Realloc(v->data, v->len-nremove, char*);
if (tmp != 0) {
v->data=tmp;
}
v->len -= nremove;
}
syntax highlighted by Code2HTML, v. 0.9.1