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