blob: e4e03256c10bb9d211690cf77e2eb954d491b4fc [file] [log] [blame]
/**********************************************************************
* File: strngs.h (Formerly strings.h)
* Description: STRING class definition.
* Author: Ray Smith
* Created: Fri Feb 15 09:15:01 GMT 1991
*
* (C) Copyright 1991, Hewlett-Packard Ltd.
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** http://www.apache.org/licenses/LICENSE-2.0
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*
**********************************************************************/
#ifndef STRNGS_H
#define STRNGS_H
#include <string.h>
#include "memry.h"
#include "serialis.h"
// STRING_IS_PROTECTED means that string[index] = X is invalid
// because you have to go through strings interface to modify it.
// This allows the string to ensure internal integrity and maintain
// its own string length. Unfortunately this is not possible because
// STRINGS are used as direct-manipulation data buffers for things
// like length arrays and many places cast away the const on string()
// to mutate the string. Turning this off means that internally we
// cannot assume we know the strlen.
#define STRING_IS_PROTECTED 0
class DLLSYM STRING
{
public:
STRING();
STRING(const STRING &string);
STRING(const char *string);
~STRING ();
BOOL8 contains(const char c) const;
inT32 length() const;
const char *string() const;
#if STRING_IS_PROTECTED
const char &operator[] (inT32 index) const;
// len is number of chars in s to insert starting at index in this string
void insert_range(inT32 index, const char*s, int len);
void erase_range(inT32 index, int len);
void truncate_at(inT32 index);
#else
char &operator[] (inT32 index) const;
#endif
BOOL8 operator== (const STRING & string) const;
BOOL8 operator!= (const STRING & string) const;
BOOL8 operator!= (const char *string) const;
STRING & operator= (const char *string);
STRING & operator= (const STRING & string);
STRING operator+ (const STRING & string) const;
STRING operator+ (const char ch) const;
STRING & operator+= (const char *string);
STRING & operator+= (const STRING & string);
STRING & operator+= (const char ch);
// WARNING
// This method leaks the underlying pointer,
// but that is what the original implementation did
void prep_serialise();
void dump(FILE *f);
void de_dump(FILE *f);
make_serialise (STRING)
// ensure capcaity but keep pointer encapsulated
inline void ensure(inT32 min_capacity) { ensure_cstr(min_capacity); }
private:
typedef struct STRING_HEADER {
// How much space was allocated in the string buffer for char data.
int capacity_;
// used_ is how much of the capacity is currently being used,
// including a '\0' terminator.
//
// If used_ is 0 then string is NULL (not even the '\0')
// else if used_ > 0 then it is strlen() + 1 (because it includes '\0')
// else strlen is >= 0 (not NULL) but needs to be computed.
// this condition is set when encapsulation is violated because
// an API returned a mutable string.
//
// capacity_ - used_ = excess capacity that the string can grow
// without reallocating
mutable int used_;
} STRING_HEADER;
// To preserve the behavior of the old serialization, we only have space
// for one pointer in this structure. So we are embedding a data structure
// at the start of the storage that will hold additional state variables,
// then storing the actual string contents immediately after.
STRING_HEADER* data_;
// returns the header part of the storage
inline STRING_HEADER* GetHeader() {
return data_;
}
inline const STRING_HEADER* GetHeader() const {
return data_;
}
// returns the string data part of storage
inline char* GetCStr() {
return ((char *)data_) + sizeof(STRING_HEADER);
};
inline const char* GetCStr() const {
return ((const char *)data_) + sizeof(STRING_HEADER);
};
// Ensure string has requested capacity as optimization
// to avoid unnecessary reallocations.
// The return value is a cstr buffer with at least requested capacity
char* ensure_cstr(inT32 min_capacity);
void FixHeader() const; // make used_ non-negative, even if const
char* AllocData(int used, int capacity);
void DiscardData();
};
#endif