1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
* Ceph - scalable distributed file system
*
* Copyright (C) 2015 Red Hat Inc
*
* Author: John Spray <john.spray@redhat.com>
*
* This is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software
* Foundation. See file COPYING.
*
*/
#include "PyFormatter.h"
#define LARGE_SIZE 1024
void PyFormatter::open_array_section(const char *name)
{
PyObject *list = PyList_New(0);
dump_pyobject(name, list);
stack.push(cursor);
cursor = list;
}
void PyFormatter::open_object_section(const char *name)
{
PyObject *dict = PyDict_New();
dump_pyobject(name, dict);
stack.push(cursor);
cursor = dict;
}
void PyFormatter::dump_unsigned(const char *name, uint64_t u)
{
PyObject *p = PyLong_FromUnsignedLong(u);
ceph_assert(p);
dump_pyobject(name, p);
}
void PyFormatter::dump_int(const char *name, int64_t u)
{
PyObject *p = PyLong_FromLongLong(u);
ceph_assert(p);
dump_pyobject(name, p);
}
void PyFormatter::dump_float(const char *name, double d)
{
dump_pyobject(name, PyFloat_FromDouble(d));
}
void PyFormatter::dump_string(const char *name, std::string_view s)
{
dump_pyobject(name, PyString_FromString(s.data()));
}
void PyFormatter::dump_bool(const char *name, bool b)
{
if (b) {
Py_INCREF(Py_True);
dump_pyobject(name, Py_True);
} else {
Py_INCREF(Py_False);
dump_pyobject(name, Py_False);
}
}
std::ostream& PyFormatter::dump_stream(const char *name)
{
// Give the caller an ostream, construct a PyString,
// and remember the association between the two. On flush,
// we'll read from the ostream into the PyString
auto ps = std::make_shared<PendingStream>();
ps->cursor = cursor;
ps->name = name;
pending_streams.push_back(ps);
return ps->stream;
}
void PyFormatter::dump_format_va(const char *name, const char *ns, bool quoted, const char *fmt, va_list ap)
{
char buf[LARGE_SIZE];
vsnprintf(buf, LARGE_SIZE, fmt, ap);
dump_pyobject(name, PyString_FromString(buf));
}
/**
* Steals reference to `p`
*/
void PyFormatter::dump_pyobject(const char *name, PyObject *p)
{
if (PyList_Check(cursor)) {
PyList_Append(cursor, p);
Py_DECREF(p);
} else if (PyDict_Check(cursor)) {
PyObject *key = PyString_FromString(name);
PyDict_SetItem(cursor, key, p);
Py_DECREF(key);
Py_DECREF(p);
} else {
ceph_abort();
}
}
void PyFormatter::finish_pending_streams()
{
for (const auto &i : pending_streams) {
PyObject *tmp_cur = cursor;
cursor = i->cursor;
dump_pyobject(
i->name.c_str(),
PyString_FromString(i->stream.str().c_str()));
cursor = tmp_cur;
}
pending_streams.clear();
}
|