blob: fb6bcbc5cac618bae23a2bc8a9896583318d8e65 [file] [log] [blame]
Mark Slee9f0c6512007-02-28 23:58:26 +00001// Copyright (c) 2006- Facebook
2// Distributed under the Thrift Software License
3//
4// See accompanying file LICENSE or visit the Thrift site at:
5// http://developers.facebook.com/thrift/
6
Mark Sleef9831082007-02-20 20:59:21 +00007#include <Thrift.h>
David Reissa4d7eef2008-06-11 01:18:20 +00008#include <cstring>
David Reissa1771092008-04-11 22:36:31 +00009#include <boost/lexical_cast.hpp>
Mark Sleef9831082007-02-20 20:59:21 +000010#include <protocol/TProtocol.h>
David Reiss01e55c12008-07-13 22:18:51 +000011#include <stdarg.h>
12#include <stdio.h>
Mark Sleef9831082007-02-20 20:59:21 +000013
14namespace facebook { namespace thrift {
15
boz6ded7752007-06-05 22:41:18 +000016TOutput GlobalOutput;
17
David Reiss01e55c12008-07-13 22:18:51 +000018void TOutput::printf(const char *message, ...) {
19 // Try to reduce heap usage, even if printf is called rarely.
20 static const int STACK_BUF_SIZE = 256;
21 char stack_buf[STACK_BUF_SIZE];
22 va_list ap;
23
24 va_start(ap, message);
25 int need = vsnprintf(stack_buf, STACK_BUF_SIZE, message, ap);
26 va_end(ap);
27
28 if (need < STACK_BUF_SIZE) {
29 f_(stack_buf);
30 return;
31 }
32
33 char *heap_buf = (char*)malloc((need+1) * sizeof(char));
34 if (heap_buf == NULL) {
35 // Malloc failed. We might as well print the stack buffer.
36 f_(stack_buf);
37 return;
38 }
39
40 va_start(ap, message);
41 int rval = vsnprintf(heap_buf, need+1, message, ap);
42 va_end(ap);
43 // TODO(shigin): inform user
44 if (rval != -1) {
45 f_(heap_buf);
46 }
47 free(heap_buf);
48}
49
50void TOutput::perror(const char *message, int errno_copy) {
51 std::string out = message + strerror_s(errno_copy);
52 f_(out.c_str());
53}
54
David Reiss9b209552008-04-08 06:26:05 +000055std::string TOutput::strerror_s(int errno_copy) {
56#ifndef HAVE_STRERROR_R
David Reiss826e6482008-10-20 21:29:07 +000057 return "errno = " + boost::lexical_cast<std::string>(errno_copy);
David Reiss9b209552008-04-08 06:26:05 +000058#else // HAVE_STRERROR_R
59
60 char b_errbuf[1024] = { '\0' };
61#ifdef STRERROR_R_CHAR_P
62 char *b_error = strerror_r(errno_copy, b_errbuf, sizeof(b_errbuf));
63#else
64 char *b_error = b_errbuf;
65 int rv = strerror_r(errno_copy, b_errbuf, sizeof(b_errbuf));
66 if (rv == -1) {
67 // strerror_r failed. omgwtfbbq.
68 return "XSI-compliant strerror_r() failed with errno = " +
David Reissa1771092008-04-11 22:36:31 +000069 boost::lexical_cast<std::string>(errno_copy);
David Reiss9b209552008-04-08 06:26:05 +000070 }
71#endif
72 // Can anyone prove that explicit cast is probably not necessary
73 // to ensure that the string object is constructed before
74 // b_error becomes invalid?
75 return std::string(b_error);
76
77#endif // HAVE_STRERROR_R
78}
79
Mark Sleef9831082007-02-20 20:59:21 +000080uint32_t TApplicationException::read(facebook::thrift::protocol::TProtocol* iprot) {
81 uint32_t xfer = 0;
82 std::string fname;
83 facebook::thrift::protocol::TType ftype;
84 int16_t fid;
85
86 xfer += iprot->readStructBegin(fname);
87
88 while (true) {
89 xfer += iprot->readFieldBegin(fname, ftype, fid);
David Reiss0c90f6f2008-02-06 22:18:40 +000090 if (ftype == facebook::thrift::protocol::T_STOP) {
Mark Sleef9831082007-02-20 20:59:21 +000091 break;
92 }
93 switch (fid) {
94 case 1:
95 if (ftype == facebook::thrift::protocol::T_STRING) {
96 xfer += iprot->readString(message_);
97 } else {
98 xfer += iprot->skip(ftype);
99 }
100 break;
101 case 2:
102 if (ftype == facebook::thrift::protocol::T_I32) {
103 int32_t type;
104 xfer += iprot->readI32(type);
105 type_ = (TApplicationExceptionType)type;
106 } else {
107 xfer += iprot->skip(ftype);
108 }
109 break;
110 default:
111 xfer += iprot->skip(ftype);
112 break;
113 }
114 xfer += iprot->readFieldEnd();
115 }
116
117 xfer += iprot->readStructEnd();
118 return xfer;
119}
120
121uint32_t TApplicationException::write(facebook::thrift::protocol::TProtocol* oprot) const {
122 uint32_t xfer = 0;
123 xfer += oprot->writeStructBegin("TApplicationException");
124 xfer += oprot->writeFieldBegin("message", facebook::thrift::protocol::T_STRING, 1);
125 xfer += oprot->writeString(message_);
126 xfer += oprot->writeFieldEnd();
127 xfer += oprot->writeFieldBegin("type", facebook::thrift::protocol::T_I32, 2);
128 xfer += oprot->writeI32(type_);
129 xfer += oprot->writeFieldEnd();
130 xfer += oprot->writeFieldStop();
131 xfer += oprot->writeStructEnd();
132 return xfer;
133}
134
135}} // facebook::thrift