1 /* Frobby: Software for monomial ideal computations.
2    Copyright (C) 2007 Bjarke Hammersholt Roune (www.broune.com)
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see http://www.gnu.org/licenses/.
16 */
17 #include "stdinc.h"
18 #include "FrobbyStringStream.h"
19 
20 #include <algorithm>
21 #include <exception>
22 
23 // This is a replacement for stringstream, which may seem weird since
24 // stringstream should work perfectly fine for any purpose where
25 // FrobbyStringStream could be used. Unfortunately this is not the
26 // case.
27 //
28 // The sad truth is that stringstream is unusable due to its behavior
29 // when running out of memory - it just stops what it is doing and
30 // then returns without propagating the bad_alloc exception. Setting
31 // exception flags with the exception() method does not change this
32 // behavior. This is for GCC v. 3.4.4 and on GCC 4.1.2 I have tested
33 // that at least without setting exception() it fails silently, though
34 // not whether that can be changed by using exception().
35 //
36 // The advantage of FrobbyStringStream is that it does not try to be
37 // clever in any way, and so it avoids these issues.
38 
operator <<(char character)39 FrobbyStringStream& FrobbyStringStream::operator<<(char character) {
40   _str += character;
41   return *this;
42 }
43 
operator <<(unsigned long long integer)44 FrobbyStringStream& FrobbyStringStream::operator<<(unsigned long long integer) {
45   appendIntegerToString(_str, integer);
46   return *this;
47 }
48 
operator <<(unsigned long integer)49 FrobbyStringStream& FrobbyStringStream::operator<<(unsigned long integer) {
50   appendIntegerToString(_str, integer);
51   return *this;
52 }
53 
operator <<(unsigned int integer)54 FrobbyStringStream& FrobbyStringStream::operator<<(unsigned int integer) {
55   appendIntegerToString(_str, integer);
56   return *this;
57 }
58 
operator <<(const mpz_class & integer)59 FrobbyStringStream& FrobbyStringStream::operator<<(const mpz_class& integer) {
60   appendIntegerToString(_str, integer);
61   return *this;
62 }
63 
operator <<(const string & text)64 FrobbyStringStream& FrobbyStringStream::operator<<(const string& text) {
65   _str += text;
66   return *this;
67 }
68 
operator <<(const char * text)69 FrobbyStringStream& FrobbyStringStream::operator<<(const char* text) {
70   _str += text;
71   return *this;
72 }
73 
str()74 string& FrobbyStringStream::str() {
75   return _str;
76 }
77 
str() const78 const string& FrobbyStringStream::str() const {
79   return _str;
80 }
81 
operator const string&() const82 FrobbyStringStream::operator const string&() const {
83   return _str;
84 }
85 
appendIntegerToString(string & str,unsigned long integer)86 void FrobbyStringStream::appendIntegerToString(string& str,
87                                                unsigned long integer) {
88   unsigned long initialLength = str.size();
89 
90   // Append string representation of integer with digits in reverse
91   // order.
92   do {
93     unsigned long quotient = integer / 10;
94     unsigned long remainder = integer - quotient * 10; // faster than %
95 
96     char digit = static_cast<char>(remainder + '0');
97     str += digit;
98 
99     integer = quotient;
100 
101     // condition at end so that zero maps to "0" rather than "".
102   } while (integer != 0);
103 
104   // Reverse the digits (and only the digits) to get the correct
105   // order.
106   reverse(str.begin() + initialLength, str.end());
107 }
108 
appendIntegerToString(string & str,const mpz_class & integer)109 void FrobbyStringStream::appendIntegerToString(string& str,
110                                                const mpz_class& integer) {
111   str += integer.get_str();
112 }
113 
parseInteger(mpz_class & integer,const string & str)114 void FrobbyStringStream::parseInteger(mpz_class& integer, const string& str) {
115   if (integer.set_str(str, 10) != 0)
116     throw NotAnIntegerException
117       ("Argument to FrobbyStringStream::parseInteger not a valid integer.");
118 }
119 
NotAnIntegerException(const string & str)120 FrobbyStringStream::NotAnIntegerException::NotAnIntegerException
121 (const string& str):
122   runtime_error(str) {
123 }
124