gen_stri.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 812 行 · 第 1/3 页

C
812
字号
//
// Copyright (C) 1991 Texas Instruments Incorporated.
//
// Permission is granted to any individual or institution to use, copy, modify,
// and distribute this software, provided that this complete copyright and
// permission notice is maintained, intact, in all copies and supporting
// documentation.
//
// Texas Instruments Incorporated provides this software "as is" without
// express or implied warranty.
//
//
// Created: MBN 03/17/89 -- Initial design and implementation
// Updated: MBN 04/06/89 -- Performance enhancement by changing several
//                          methods and friends to inline, and addition
//                          of two private friend functions.
// Updated: LGO 06/03/89 -- Fix string growth algorithm.
// Updated: MBN 06/06/89 -- Performance enhancement by making reference count
//                          and memory check/adjustment inline, addition of a
//                          resize method and a growth ratio data slot, and
//                          change of constructors to set specific object size,
//                          not class as a whole
// Updated: DKM 06/23/89 -- To get around a bug in the Glockenspiel translator
//                          we had to explicitly typecast arguments for calls
//                          to the overloaded unix string functions, including
//                          strchr, strrchr, strcpy, strcmp, strncmp, strtod,
//                          and strtol.
// Updated: MNF 06/27/89 -- Added the insert, remove, replace, yank, and
//                          sub_string public member functions.
// Updated: MBN 06/30/89 -- Updated to include support for regular expressions
// Updated: DKM 07/07/89 -- To work around Xenix 31 char limit:
//                          Shortened is_less_than        to is_lt
//                                    is_greater_than     to is_gt
//                                    is_less_or_equal    to is_le
//                                    is_greater_or_equal to is_ge
//                          Removed is_equal_or_less and is_greater_or_less
// Updated: MBN 09/07/89 -- Added conditional exception handling
// Updated: MBN 09/26/89 -- Fixed bug to set size when growth size ratio given
// Updated: LGO 10/11/89 -- Removed operator>>
// Updated: LGO 10/28/89 -- Removed is_lt, is_gt, is_le, is_ge, is_equal
//                          and is_not_equal (use char* functions instead)
// Updated: MBN 12/15/89 -- Sprinkled "const" qualifier all over the place!
// Updated: MBN 01/02/90 -- Made find search for the first/next regexp match 
// Updated: LGO 01/03/90 -- Avoid use of strncat
// Updated: LGO 01/05/90 -- Partial re-write of most everything to simplify
//                          and speed-up the code
// Updated: MJF 03/12/90 -- Added group names to RAISE
// Updated: MJF 05/21/90 -- Moved delete from grow_memory to validate
// Updated: DLS 03/22/91 -- New lite version
// Updated: JAM 08/14/92 -- removed DOS specifics, stdized #includes
// Updated: JAM 08/14/92 -- added static alloc_size_s def and initialization
//
// This  file contains member and  friend function  implementation code for the
// CoolGen_String class defined  in  the  Gen_String.h and Regexp.h header   files.
// Where appropriate and  possible, interfaces to, and  us  of, existing system
// functions   has been incorporated.  An overview    of the structure   of the
// Edit_String class, along with a synopsis of each member and friend function,
// can be found in the String.h header file.
//

#ifndef GEN_STRINGH                             // If class not defined
#include <cool/Gen_String.h>            // Include class specification
#endif

#include <ctype.h>              // Include character processing macros

// alloc_size_s -- Memory allocation growth size
int CoolGen_String::alloc_size_s = MEM_BLK_SZ;  // Init allocation size

// update_ref_count -- Gives "this" it's own (unshared) copy of a string
// Input:          None
// Output:         None

void CoolGen_String::update_ref_count() {
  this->p->ref_count--;              // Decrement reference count
  this->p = new String_Layout;       // Allocate layout structure
  this->p->ref_count = 1;            // One object at the moment
  this->p->size = 0;                 // No memory allocated yet
  this->p->start = this->str;        // Pointer to start of string
}


// validate -- protected method called when a string is modified
// Input:        before calling, set this->length to new length.
//               dont_copy - set to TRUE If you don't want the old string
//               copied on a grow, or ref-count copy
// Output:       None
void CoolGen_String::validate(Boolean dont_copy) {
  if (this->p->ref_count > 1) {   // If sharing memory with another CoolGen_String
    this->update_ref_count();     // decrement reference count and 
    this->grow_memory(dont_copy); // allocate memory for own copy
  }
  else if (this->length >= this->p->size) { // If not long enough,
    char* ostr = this->str;                 // save old string to delete later
    this->grow_memory(dont_copy);           // allocate memory,
    if (ostr != NULL) delete ostr;          // and free old memory block
  }
}

// grow_memory -- Called when string isn't long enough, or to allocate memory
//                after update_ref_count inside validate.
// Input:         dont_copy - TRUE If you don't want the old string copied.
// Output:        None

void CoolGen_String::grow_memory (Boolean dont_copy) {
  char* old_chars = this->str;
  long size = this->p->size;
  if (this->length >= size) { // Called from validate just to allocate memory
    if (this->growth_ratio != 0.0)     // If a growth ratio is set
      size += long(size * this->growth_ratio);
    else
      size += this->alloc_size_s;    // Increment by allocation size
    if (size < this->length)         // But if still not big enough
      size = this->length+1;         // Grow to big enough size
    this->p->size = size;
  }
  this->str = new char[size];        // Allocate memory for string
  this->p->start = this->str;        // Pointer to start of string
  if (old_chars != NULL) {
    if (!dont_copy)
      strcpy ((char *)this->str, old_chars);   // Copy initial string
  }
  else
    *this->str = END_OF_STRING;
}


// CoolGen_String() -- Simple constructor for a CoolGen_String object. Memory is
//                 allocated for the layout structure and char* pointers are
//                 set to the "alloc_size_s" value.
// Input:          None
// Output:         CoolGen_String reference


CoolGen_String::CoolGen_String () {             
  this->growth_ratio = 0.0;             // Initialize growth ratio
  this->str = new char[alloc_size_s];   // Allocate block of memory
  this->length = 0;                     // Zero characters in string
  this->p = new String_Layout;          // Allocate layout structure
  this->p->ref_count = 1;               // One String object at the moment
  this->p->size = alloc_size_s;         // Size of allocated block 
  this->p->start = str;                 // Pointer to start of string 
  *this->str = END_OF_STRING;           // END_OF_STRING terminate for safety
  this->rgexp = NULL;                   // No regular expression yet
}


// CoolGen_String(char) -- Constructor to initialize object with a char
// Input:              character
// Output:             CoolGen_String reference to new object

CoolGen_String::CoolGen_String (char c) {               
  this->growth_ratio = 0.0;             // Initialize growth ratio
  this->length = 1;                     // Length of character is 1
  this->str = new char[length+1];       // Allocate memory for string
  this->p = new String_Layout;          // Allocate layout structure
  this->p->ref_count = 1;               // One String object at the moment
  this->p->size = this->length+1;       // Size of allocated block
  this->p->start = this->str;           // Pointer to start of string
  *this->str = c;                       // Assign character
  *(this->str+1) = END_OF_STRING;       // END_OF_STRING terminator for string
  this->rgexp = NULL;                   // No regular expression yet
}


// CoolGen_String(char*) -- Constructor to initialize object with a char*.
// Input:               char* pointer
// Output:              CoolGen_String reference to new object

CoolGen_String::CoolGen_String (const char* c) {                
  this->growth_ratio = 0.0;             // Initialize growth ratio
  this->length = strlen (c);            // Determine length of character string
  this->str = new char[length+1];       // Allocate memory for string
  this->p = new String_Layout;          // Allocate layout structure
  this->p->ref_count = 1;               // One String object at the moment
  this->p->size = this->length+1;       // Size of allocated block
  this->p->start = this->str;           // Pointer to start of string
  strcpy ((char *)this->str, c);        // Copy characters
  this->rgexp = NULL;                   // No regular expression yet
}


// CoolGen_String(CoolGen_String&) -- Constructor to initialize object to CoolGen_String
//                            Note that this involves use of delayed copy via 
//                            the reference count mechanism.
// Input:                     CoolGen_String reference
// Output:                    CoolGen_String reference to new object

CoolGen_String::CoolGen_String (const CoolGen_String& s) {
  this->growth_ratio = s.growth_ratio;  // Initialize growth ratio
  this->length = s.length;              // Determine length of character string
  this->str = s.str;                    // Point to same string memory block
  this->p = s.p;                        // Point to same layout structure
  this->p->ref_count++;                 // Increment reference count
  this->rgexp = NULL;                   // No regular expression yet
}


// CoolGen_String(char*, size) -- Constructor to initialize object with a char*
//                            and control initial allocation size
// Input:                     char* pointer and size value
// Output:                    CoolGen_String reference to new object

CoolGen_String::CoolGen_String (const char* c, long sz) {
  this->length = strlen (c);            // Determine length of character string
  this->p = new String_Layout;          // Allocate layout structure
  if (this->length > sz) {              // If initial string is larger
    this->str = new char[length+1];     // Allocate memory for string
    this->p->size = length+1;           // Size of allocated block
  }
  else {
    this->str = new char[sz+1];         // Allocate memory for string 
    this->p->size = sz+1;               // Size of allocated block
  }
  this->p->ref_count = 1;               // One String object at the moment
  this->p->start = this->str;           // Pointer to start of string
  strcpy ((char *)this->str, c);        // Copy characters
  this->rgexp = NULL;                   // No regular expression yet
}


// CoolGen_String(CoolGen_String&, long) -- Constructor to initialize object to a
//                                  CoolGen_String and control initial alloc size
// Input:                           CoolGen_String reference and size value
// Output:                          CoolGen_String reference to new object

CoolGen_String::CoolGen_String (const CoolGen_String& s, long sz) { 
  this->length = s.length;              // Determine length of character string
  this->p = new String_Layout;          // Allocate layout structure
  if (this->length > sz) {              // If initial string is larger
    this->str = new char[length+1];     // Allocate memory for string
    this->p->size = length+1;           // Size of allocated block
  }
  else {
    this->str = new char[sz+1];         // Allocate memory for string 
    this->p->size = sz+1;               // Size of allocated block
  }
  this->p->ref_count = 1;               // One String object at the moment
  this->p->start = this->str;           // Pointer to start of string
  strcpy ((char *)this->str, s.str);    // Copy characters over
  this->rgexp = NULL;                   // No regular expression yet
}


// ~CoolGen_String() -- CoolGen_String object destructor frees up allocated memory and
//                  decrements reference count if necessary
// Input:           CoolGen_String object
// Output:          None

CoolGen_String::~CoolGen_String () {                    
  if (this->p->ref_count == 1) {      // If not sharing mem with other String
    delete this->str;                 // then delete String object
    delete this->p;                   // Delete layout structure
  } else 
    this->p->ref_count--;               // Else decrement reference counter
  delete this->rgexp;                   // Delete regular expression object
}


// clear -- Flush the character string from the string object by setting
//          the char* pointer to NULL and the length to zero.
// Input:   this*
    // Output:  None

void CoolGen_String::clear() {
  this->length = 0;                     // Set new string length
  if (this->rgexp)                      // If there is a Regexp object
    this->rgexp->set_invalid();         // Invalidate compiled expression
  if (this->p->ref_count == 1)          // If not sharing mem with other String
    *(this->str) = NULL;                // Clear this String by using NULL
  else {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?