source: trunk/src/core/RpOutcome.cc @ 1366

Last change on this file since 1366 was 1366, checked in by gah, 16 years ago

Begin reorganizing Rappture C++ API, starting with the use of
Rappture::Outcome.

Instead of returning an Outcome and expecting every routine to
save it, pass it as a reference. Let's strip it down to what's
needed right now and add back functionality as required.

Right now too many return values are ignored in the rappture library.
We need to check all results and return the error messages via
the Outcome. At the topmost level where is touches the developer
API we can drop the error checking or turn it on via an environment
variable.

Example. Not enough checks are made for memory allocation failure.
If the application is running on an over-committed server memory
allocation errors will be silently passed on. It's okay to be
fault tolerant where possible, but if we fail to check in the internal
library functions, it's too late.

--gah

File size: 3.7 KB
Line 
1/*
2 * ======================================================================
3 *  Rappture::Outcome
4 *
5 *  AUTHOR:  Michael McLennan, Purdue University
6 *  Copyright (c) 2004-2007  Purdue Research Foundation
7 * ----------------------------------------------------------------------
8 *  See the file "license.terms" for information on usage and
9 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10 * ======================================================================
11 */
12#include "RpOutcome.h"
13#include <stdarg.h>
14#include <stdlib.h>
15using namespace Rappture;
16
17/**
18 *  Create a negative outcome, with the given error message.
19 */
20Outcome::Outcome(const char *errmsg) :
21    _status(0)
22{
23    if (errmsg) {
24        error(errmsg);
25    }
26}
27
28/// Copy constructor
29Outcome::Outcome(const Outcome& oc) :
30    _status(oc._status),
31    _remark(oc._remark),
32    _context(oc._context)
33{
34}
35
36/// Assignment operator
37Outcome&
38Outcome::operator=(const Outcome& oc)
39{
40    _status = oc._status;
41    _remark = oc._remark;
42    _context = oc._context;
43    return *this;
44}
45
46/// Destructor
47Outcome::~Outcome()
48{}
49
50/**
51 *  Assign an error condition to the outcome.
52 */
53Outcome&
54Outcome::error(const char* errmsg, int status)
55{
56    _status = status;
57    _remark = errmsg;
58    return *this;
59}
60
61Outcome&
62Outcome::addError(const char* format, ...)
63{
64    char stackSpace[1024];
65    va_list lst;
66    size_t n;
67    char *bufPtr;
68
69    va_start(lst, format);
70    bufPtr = stackSpace;
71    n = vsnprintf(bufPtr, 1024, format, lst);
72    if (n >= 1024) {
73        bufPtr = (char *)malloc(n);
74        vsnprintf(bufPtr, n, format, lst);
75    }
76    if (_remark == "") {
77        _remark = _context;
78        _remark.append(":\n");
79        _remark.append(bufPtr);
80    } else {
81        _remark.append("\n");
82        _remark.append(bufPtr);
83    }
84    _status = 1;                /* Set to error */
85    if (bufPtr != stackSpace) {
86        free(bufPtr);
87    }
88    return *this;
89}
90
91/**
92 *  Clear the status of this outcome.
93 */
94Outcome&
95Outcome::clear()
96{
97    _status = 0;
98    _remark.clear();
99    _context.clear();
100    return *this;
101}
102
103/**
104 *  Returns the status of this outcome as an integer.
105 *  As in Unix systems, 0 = okay.
106 */
107Outcome::operator int() const
108{
109    return _status;
110}
111
112/**
113 *  For !error tests.
114 */
115int
116Outcome::operator!() const
117{
118    return (_status == 0);
119}
120
121/**
122 *  Use this to concatenate many different outcomes.
123 */
124Outcome&
125Outcome::operator&=(Outcome oc)
126{
127    _status &= oc._status;
128    _remark = oc._remark;
129    _context = oc._context;
130    return *this;
131}
132
133/**
134 *  Query the error remark from an outcome.
135 */
136const char *
137Outcome::remark() const
138{
139    return _remark.c_str();
140}
141
142/**
143 *  Add information to the context stack for an outcome.
144 */
145Outcome&
146Outcome::addContext(const char *rem)
147{
148    // FIXME: There should be a stack of contexts
149    _context = rem;
150    _context.append("\n");
151    return *this;
152}
153
154#ifdef soon
155/**
156 *  Push context information on to the context stack for an outcome.
157 */
158void
159Outcome::pushContext(const char* format, ...)
160{
161    char stackSpace[1024];
162    va_list lst;
163    size_t n;
164    char *bufPtr;
165
166    va_start(lst, format);
167    bufPtr = stackSpace;
168    n = vsnprintf(bufPtr, 1024, format, lst);
169    if (n >= 1024) {
170        bufPtr = (char *)malloc(n);
171        vsnprintf(bufPtr, n, format, lst);
172    }
173    _contexts.push_front(bufPtr);
174}
175
176/**
177 *  Pop the last context from the stack.
178 */
179void
180Outcome::popContext(void)
181{
182    _contexts.pop_front();
183}
184
185void
186Outcome::printContext(void)
187{
188    list<const char *>::interator iter;
189   
190    for (iter = _contexts.begin(); iter != _contexts.end(); iter++) {
191        fprintf(stderr, "Called from %s\n", *iter);
192    }
193}
194
195#endif /*soon*/
196
197/**
198 *  Query the context stack from an outcome.
199 */
200
201const char *
202Outcome::context() const
203{
204    return _context.c_str();
205}
Note: See TracBrowser for help on using the repository browser.