thalassa/lib/scriptpp/scrvect.cpp
2026-03-19 06:23:52 +05:00

236 lines
5.8 KiB
C++

// +-------------------------------------------------------------------------+
// | Script Plus Plus vers. 0.3.72 |
// | Copyright (c) Andrey V. Stolyarov <croco at croco dot net> 2003--2023 |
// | ----------------------------------------------------------------------- |
// | This is free software. Permission is granted to everyone to use, copy |
// | or modify this software under the terms and conditions of |
// | GNU LESSER GENERAL PUBLIC LICENSE, v. 2.1 |
// | as published by Free Software Foundation (see the file LGPL.txt) |
// | |
// | Please visit http://www.croco.net/software/scriptpp to get a fresh copy |
// | ----------------------------------------------------------------------- |
// | This code is provided strictly and exclusively on the "AS IS" basis. |
// | !!! THERE IS NO WARRANTY OF ANY KIND, NEITHER EXPRESSED NOR IMPLIED !!! |
// +-------------------------------------------------------------------------+
#include <string.h> // for strlen()
#include <stdlib.h> // for free()
#include "scrvar.hpp"
#include "scrvect.hpp"
enum { scriptvector_default_size = 16 };
ScriptVector::ScriptVector()
: vec(0), len(0), maxlen(0)
{
}
ScriptVector::ScriptVector(const ScriptVariable &sv,
const char *delims,
const char *trimspaces)
{
vec = new ScriptVariable[scriptvector_default_size];
len = 0;
maxlen = scriptvector_default_size;
if(!delims) {
vec[0] = sv;
len = 0;
return;
}
ScriptVariable sv1(sv); // to avoid const problem
ScriptVariable::Substring iter(sv1);
ScriptVariable::Substring word;
while(trimspaces ? iter.FetchToken(word, delims, trimspaces) :
iter.FetchWord(word, delims))
{
AddItem(word.Get());
}
}
ScriptVector::ScriptVector(const char * const *v)
{
vec = new ScriptVariable[scriptvector_default_size];
len = 0;
maxlen = scriptvector_default_size;
while(*v) {
AddItem(*v);
v++;
}
}
ScriptVector::ScriptVector(const ScriptVector &other, int aidx, int alen)
{
if(aidx < 0)
aidx = 0;
else if(aidx > other.len)
aidx = other.len;
if(alen == -1 || alen > other.len - aidx)
alen = other.len - aidx;
len = alen;
maxlen = scriptvector_default_size;
while(maxlen<len) maxlen*=2;
vec = new ScriptVariable[maxlen];
for(int i = 0; i<len; i++)
vec[i] = other.vec[i+aidx];
}
ScriptVector::~ScriptVector()
{
if(vec)
delete[] vec;
}
ScriptVariable& ScriptVector::operator[](int i)
{
if(i<0)
return vec[0]; // should be exception in fact... let it be.
if(i>=maxlen)
ProvideVectorLength(i+1);
if(i>=len)
len = i+1;
return vec[i];
}
const ScriptVector& ScriptVector::operator=(const ScriptVector &other)
{
ProvideVectorLength(other.len);
if(len < other.len)
len = other.len;
while(len>other.len) {
vec[len-1] = "";
len--;
}
for(int i = 0; i<other.len; i++)
vec[i] = other.vec[i];
return *this;
}
ScriptVariable ScriptVector::operator[](int i) const
{
return (i>=0 && i<len) ? vec[i] : ScriptVariable();
}
void ScriptVector::Insert(int idx, const ScriptVariable& sv)
{
DoInsert(idx, &sv, 1);
}
void ScriptVector::Insert(int idx, const ScriptVector& svec)
{
DoInsert(idx, svec.vec, svec.len);
}
void ScriptVector::Remove(int idx, int amount)
{
if(idx>=len)
return;
if(idx+amount>len)
amount = len-idx;
int i;
for(i=idx; i<len-amount; i++)
vec[i] = vec[i+amount];
for(;i<len;i++)
vec[i] = "";
len -= amount;
}
void ScriptVector::AddItem(const ScriptVariable& sv)
{
ProvideVectorLength(len+1);
vec[len++] = sv;
}
void ScriptVector::Clear()
{
for(int i=0;i<len;i++)
vec[i] = "";
len = 0;
}
ScriptVariable ScriptVector::Join(const char *sep, int start, int cnt) const
{
int totallen, i, j, k;
int seplen = sep ? strlen(sep) : 0;
int last = (cnt == -1) ? len-1 : start+cnt-1;
if(last >= len)
last = len-1;
if(start > last)
return "";
totallen = 0;
for(i=start; i<=last; i++)
totallen += vec[i].length();
if(sep)
totallen += seplen * (last-start);
ScriptVariableInv res;
res.MakeRoom(totallen);
int idx = 0;
for(i=start; i<=last; i++) {
for(k = 0; vec[i][k]; k++) {
res[idx++] = vec[i][k];
}
if(sep && i<last) {
for(j = 0; j<seplen; j++) {
res[idx++] = sep[j];
}
}
}
res[idx] = 0;
return res;
}
ScriptVariable
ScriptVector::Join(const ScriptVariable &sep, int start, int cnt) const
{
return Join(sep.c_str(), start, len);
}
char** ScriptVector::MakeArgv() const
{
char ** ret = new char*[len+1];
for(int i=0; i<len; i++)
ret[i] = strdup((*this)[i].c_str());
ret[len] = 0;
return ret;
}
void ScriptVector::DeleteArgv(char** argv)
{
for(int i=0; argv[i]; i++)
free((void*)(argv[i]));
delete[] argv;
}
void ScriptVector::DoInsert(int idx, const ScriptVariable *vars, int n)
{
ProvideVectorLength(len+n);
int i;
for(i=len+n-1; i>=idx+n; i--)
vec[i] = vec[i-n];
for(i=0; i<n; i++)
vec[idx+i] = vars[i];
len+=n;
}
void ScriptVector::ProvideVectorLength(int i)
{
if(i<=maxlen)
return;
int newlen = maxlen ? maxlen * 2 : scriptvector_default_size;
while(newlen<i)
newlen *= 2;
ScriptVariable *newvec = new ScriptVariable[newlen];
for(int i=0; i<len; i++)
newvec[i] = vec[i];
if(vec)
delete[] vec;
vec = newvec;
maxlen = newlen;
}