// file: scl.cpp // author: Steve Norman // scl (Simple Class Library) Version 1.2 (Sept. 10, 1997) // // This code has been carefully tested. // However, that is NOT a GUARANTEE that this code is completely // free of defects. // // If any defects are discovered that interfere with the development // of programs in ENGG 335 labs in Fall 1997, this code will be // replaced with a new version, and announcements will be made in // lectures and labs to tell students to make sure that they are using // the new version. // // No defects were discovered in Fall 1997. (That STILL does NOT // GUARANTEE that the code is defect-free.) Except for changes to // this comment, this code has not been changed. // // Copyright (C) 1997 by S. A. Norman of the University of Calgary // Dept of Electrical and Computer Engineering. Permission is // granted to use this code, modified or unmodified, for any // purpose you like. I request only that you maintain this // copyright notice in your code. #include #include #include #include "scl.h" void scl_range_fail(int index, int size, const char* type_str) { cerr << "*** An scl function has terminated your program, because" << endl; cerr << "*** your program tried to do something that doesn't make sense." << endl; cerr << "*** " << type_str << " index of " << index << " was not valid." << endl; if (size == 0) cerr << "*** The array or string was empty." << endl; else { cerr << "*** A valid index would be >= 0 and < "; cerr << size << '.' << endl; } abort(); } char * const sclString::empty_string = ""; sclString::sclString() : storage(empty_string), lengthM(0), capacityM(1) { } sclString::sclString(char c) { if (c != '\0') { lengthM = 1; alloc_buffer(2); storage[0] = c; storage[1] = '\0'; } else { lengthM = 0; capacityM = 1; storage = empty_string; } } sclString::sclString(const char *p) { lengthM = strlen(p); if (lengthM > 0) { alloc_buffer(lengthM + 1); strcpy(storage, p); } else { storage = empty_string; capacityM = 1; } } sclString::sclString(const sclString& s) { lengthM = s.lengthM; if (lengthM > 0) { alloc_buffer(lengthM + 1); strcpy(storage, s.storage); } else { storage = empty_string; capacityM = 1; } } sclString::~sclString() { dispose_of(storage); storage = 0; } sclString& sclString::operator =(char c) { if (c != '\0') { lengthM = 1; if (storage == empty_string) alloc_buffer(2); storage[0] = c; storage[1] = '\0'; } else { lengthM = 0; dispose_of(storage); storage = empty_string; capacityM = 1; } return *this; } sclString& sclString::operator =(const char *p) { lengthM = strlen(p); if (lengthM == 0) { storage = empty_string; capacityM = 1; } else { if (lengthM >= capacityM) { dispose_of(storage); alloc_buffer(lengthM + 1); } strcpy(storage, p); } return *this; } sclString& sclString::operator =(const sclString& s) { if (this != &s) { lengthM = s.lengthM; if (lengthM == 0) { storage = empty_string; capacityM = 1; } else { if (lengthM >= capacityM) { dispose_of(storage); alloc_buffer(lengthM + 1); } strcpy(storage, s.storage); } } return *this; } void sclString::append(char c) { if (c != '\0') { int old_length = lengthM; ++lengthM; prepare_for_append(lengthM); storage[old_length] = c; storage[lengthM] = '\0'; } } void sclString::append(const char *p) { int old_length = lengthM; lengthM += strlen(p); prepare_for_append(lengthM); strcpy(storage + old_length, p); } void sclString::append(const sclString& s) { int old_length = lengthM; lengthM += s.lengthM; prepare_for_append(lengthM); if (this == &s) // special case: s.append(s) memmove(storage + old_length, storage, old_length + 1); else strcpy(storage + old_length, s.storage); } void sclString::truncate(int new_length) { // defend against nonsense argument if (new_length < 0) new_length = 0; if (new_length < lengthM) { lengthM = new_length; if (lengthM == 0) { dispose_of(storage); storage = empty_string; capacityM = 1; } else storage[lengthM] = '\0'; } } void sclString::alloc_buffer(int min_cap) { capacityM = MEM_CHUNK_SIZE * ((min_cap - 1) / MEM_CHUNK_SIZE + 1); storage = new char[capacityM]; } void sclString::prepare_for_append(int new_length) { if (new_length + 1 > capacityM) { char * old_storage = storage; alloc_buffer(new_length + 1); strcpy(storage, old_storage); dispose_of(old_storage); } } void sclString::expand_for_input() { char * old_storage = storage; alloc_buffer(2 * capacityM); memcpy(storage, old_storage, lengthM); dispose_of(old_storage); } ostream& operator <<(ostream& ostr, const sclString& s) { ostr << s.storage; return ostr; } istream& operator >>(istream& istr, sclString& s) { // skip whitespace char char_read; while (istr.get(char_read) && isspace(char_read)) /* do nothing */ ; s.lengthM = 0; while (istr && !isspace(char_read)) { if (s.lengthM + 1 == s.capacityM) s.expand_for_input(); s.storage[s.lengthM] = char_read; s.lengthM++; istr.get(char_read); } if (s.lengthM > 0) s.storage[s.lengthM] = '\0'; else { sclString::dispose_of(s.storage); s.storage = sclString::empty_string; s.capacityM = 1; } if (istr) istr.putback(char_read); return istr; } istream& getline(istream& istr, sclString& s) { s.lengthM = 0; char char_read; while (istr.get(char_read) && char_read != '\n') { if (s.lengthM + 1 == s.capacityM) s.expand_for_input(); s.storage[s.lengthM] = char_read; s.lengthM++; } if (s.lengthM > 0) s.storage[s.lengthM] = '\0'; else { sclString::dispose_of(s.storage); s.storage = sclString::empty_string; s.capacityM = 1; } return istr; }