27 #include <cuda_runtime.h>
30 #include <torch/torch.h>
31 #include <unordered_map>
66 return torch::Tensor();
69 std::vector<int64_t> torch_shape;
70 torch_shape.reserve(
shape.size());
71 for (
auto dim :
shape) {
72 torch_shape.push_back(
static_cast<int64_t
>(dim));
76 auto options = torch::TensorOptions().device(
gpu_id >= 0 ?
77 torch::Device(torch::kCUDA,
gpu_id) : torch::Device(torch::kCPU));
82 float* data_ptr =
static_cast<float*
>(
buffer);
83 return torch::from_blob(data_ptr, torch_shape, torch::kFloat32).to(options.device());
86 int32_t* data_ptr =
static_cast<int32_t*
>(
buffer);
87 return torch::from_blob(data_ptr, torch_shape, torch::kInt32).to(options.device());
90 int8_t* data_ptr =
static_cast<int8_t*
>(
buffer);
91 return torch::from_blob(data_ptr, torch_shape, torch::kInt8).to(options.device());
94 uint8_t* data_ptr =
static_cast<uint8_t*
>(
buffer);
95 return torch::from_blob(data_ptr, torch_shape, torch::kUInt8).to(options.device());
98 int64_t* data_ptr =
static_cast<int64_t*
>(
buffer);
99 return torch::from_blob(data_ptr, torch_shape, torch::kInt64).to(options.device());
102 uint32_t* data_ptr =
static_cast<uint32_t*
>(
buffer);
103 return torch::from_blob(data_ptr, torch_shape, torch::kInt32).to(options.device());
106 uint64_t* data_ptr =
static_cast<uint64_t*
>(
buffer);
107 return torch::from_blob(data_ptr, torch_shape, torch::kInt64).to(options.device());
110 uint16_t* data_ptr =
static_cast<uint16_t*
>(
buffer);
111 return torch::from_blob(data_ptr, torch_shape, torch::kHalf).to(options.device());
115 std::cerr <<
"Unsupported data type for conversion to torch::Tensor" << std::endl;
116 return torch::Tensor();
131 bool memory_freed =
false;
138 cudaError_t err = cudaFree(
buffer);
139 memory_freed = (err == cudaSuccess);
140 if (err != cudaSuccess) {
141 std::cerr <<
"Error freeing GPU memory: " << cudaGetErrorString(err) << std::endl;
174 inline void display(
bool print_data =
false)
const {
175 bool is_gpu_tensor = (
gpu_id >= 0);
176 size_t total_elements = 1;
177 size_t max_elements = 100;
179 const int lineWidth = 100;
180 const std::string headerBorder =
"+" + std::string(lineWidth+1,
'-') +
"+";
182 std::cout <<
"\n" << headerBorder << std::endl;
185 std::string tensorName = !
name.empty() ?
name :
"Unnamed";
186 std::string headerText =
"Tensor Information - " + tensorName;
189 int padding = (lineWidth - headerText.length()) / 2;
190 std::cout <<
"| " << std::string(padding,
' ') << headerText
191 << std::string(lineWidth - padding - headerText.length(),
' ') <<
"|" << std::endl;
193 std::cout << headerBorder << std::endl;
196 const int labelWidth = 16;
197 const int valueWidth = lineWidth - labelWidth - 3;
200 std::string shapeStr =
"[";
202 if (
shape.size() > 0) {
203 shapeStr += std::to_string(
shape[
shape.size() - 1]);
205 shapeStr +=
"Unknown";
208 for (
size_t i = 0; i <
shape.size(); i++) {
209 shapeStr += std::to_string(
shape[i]);
210 if (i <
shape.size() - 1) shapeStr +=
", ";
215 std::string deviceStr = (is_gpu_tensor) ?
"GPU [" + std::to_string(
gpu_id) +
"]" :
"CPU";
226 default: typeStr =
"Unknown";
break;
228 size_t elements_to_display =
std::min(total_elements, max_elements);
231 std::cout <<
"| Shape | " << std::left << std::setw(valueWidth) << shapeStr <<
" |" << std::endl;
232 std::cout <<
"| Device | " << std::left << std::setw(valueWidth) << deviceStr <<
" |" << std::endl;
233 std::cout <<
"| Buffer Size | " << std::left << std::setw(valueWidth) << std::to_string(
size) +
" bytes" <<
" |" << std::endl;
234 std::cout <<
"| Elements | " << std::left << std::setw(valueWidth) << std::to_string(total_elements) <<
" |" << std::endl;
235 std::cout <<
"| Data Type | " << std::left << std::setw(valueWidth) << typeStr <<
" |" << std::endl;
237 std::cout <<
"| Buffer Pointer | " << std::left << std::setw(valueWidth) <<
buffer <<
" |" << std::endl;
239 std::cout <<
"| Buffer Pointer | " << std::left << std::setw(valueWidth) <<
"NULL" <<
" |" << std::endl;
243 std::cout <<
"| Frame Number | " << std::left << std::setw(valueWidth) <<
frame_num <<
" |" << std::endl;
249 std::cout <<
"|" << std::string(lineWidth+1,
'-') <<
"|" << std::endl;
250 std::cout <<
"| No data to display - buffer is null" << std::string(lineWidth - 34,
' ') <<
"|" << std::endl;
251 std::cout << headerBorder << std::endl;
256 std::cout <<
"|" << std::string(lineWidth+1,
'-') <<
"|" << std::endl;
257 void* host_buffer =
nullptr;
259 std::cout <<
"| Values [GPU --> CPU]:" << std::string(lineWidth - 21,
' ') <<
"|" << std::endl;
261 host_buffer = malloc(
size);
263 std::cerr <<
"| ERROR: Failed to allocate CPU memory for tensor display"
264 << std::string(lineWidth - 51,
' ') <<
"|" << std::endl;
265 std::cout << headerBorder << std::endl;
269 cudaError_t err = cudaMemcpy(host_buffer,
buffer,
size, cudaMemcpyDeviceToHost);
270 if (err != cudaSuccess) {
271 std::cerr <<
"| ERROR: Failed to copy tensor data from GPU to CPU: " << cudaGetErrorString(err)
272 << std::string(lineWidth - 59 - strlen(cudaGetErrorString(err)),
' ') <<
"|" << std::endl;
274 std::cout << headerBorder << std::endl;
279 std::cout <<
"| Values [CPU]:" << std::string(lineWidth - 13,
' ') <<
"|" << std::endl;
284 std::cout << std::fixed << std::setprecision(precision);
297 default: typeStr =
"Unknown";
break;
301 std::cout <<
"|" << std::string(lineWidth+1,
' ') <<
"|" << std::endl;
303 const int indent = 2;
304 const int valueWidth = lineWidth - 3;
305 std::stringstream line;
310 const float*
data =
static_cast<const float*
>(host_buffer);
311 for (
size_t i = 0; i < elements_to_display; i++) {
312 std::stringstream value_stream;
313 value_stream << std::fixed << std::setprecision(precision) <<
data[i];
314 std::string value = value_stream.str();
317 if (line_chars > 0 && line_chars + value.length() + 2 > valueWidth) {
318 std::cout <<
"| " << std::string(indent,
' ') << line.str() << std::string(valueWidth - line_chars,
' ') <<
" |" << std::endl;
324 if (line_chars > 0) {
329 line_chars += value.length();
334 const int32_t*
data =
static_cast<const int32_t*
>(host_buffer);
335 for (
size_t i = 0; i < elements_to_display; i++) {
336 std::string value = std::to_string(
data[i]);
339 if (line_chars > 0 && line_chars + value.length() + 2 > valueWidth) {
340 std::cout <<
"| " << std::string(indent,
' ') << line.str() << std::string(valueWidth - line_chars,
' ') <<
" |" << std::endl;
346 if (line_chars > 0) {
351 line_chars += value.length();
356 const uint32_t*
data =
static_cast<const uint32_t*
>(host_buffer);
357 for (
size_t i = 0; i < elements_to_display; i++) {
358 std::string value = std::to_string(
data[i]);
361 if (line_chars > 0 && line_chars + value.length() + 2 > valueWidth) {
362 std::cout <<
"| " << std::string(indent,
' ') << line.str() << std::string(valueWidth - line_chars,
' ') <<
" |" << std::endl;
368 if (line_chars > 0) {
373 line_chars += value.length();
378 const int8_t*
data =
static_cast<const int8_t*
>(host_buffer);
379 for (
size_t i = 0; i < elements_to_display; i++) {
380 std::string value = std::to_string(
static_cast<int>(
data[i]));
383 if (line_chars > 0 && line_chars + value.length() + 2 > valueWidth) {
384 std::cout <<
"| " << std::string(indent,
' ') << line.str() << std::string(valueWidth - line_chars,
' ') <<
" |" << std::endl;
390 if (line_chars > 0) {
395 line_chars += value.length();
400 const uint8_t*
data =
static_cast<const uint8_t*
>(host_buffer);
401 for (
size_t i = 0; i < elements_to_display; i++) {
402 std::string value = std::to_string(
static_cast<int>(
data[i]));
405 if (line_chars > 0 && line_chars + value.length() + 2 > valueWidth) {
406 std::cout <<
"| " << std::string(indent,
' ') << line.str() << std::string(valueWidth - line_chars,
' ') <<
" |" << std::endl;
412 if (line_chars > 0) {
417 line_chars += value.length();
423 std::cout <<
"| " << std::string(indent,
' ') <<
"FP16 data display not fully implemented"
424 << std::string(valueWidth - 37,
' ') <<
"|" << std::endl;
428 const int64_t*
data =
static_cast<const int64_t*
>(host_buffer);
429 for (
size_t i = 0; i < elements_to_display; i++) {
430 std::string value = std::to_string(
data[i]);
433 if (line_chars > 0 && line_chars + value.length() + 2 > valueWidth) {
434 std::cout <<
"| " << std::string(indent,
' ') << line.str() << std::string(valueWidth - line_chars,
' ') <<
" |" << std::endl;
440 if (line_chars > 0) {
445 line_chars += value.length();
450 const uint64_t*
data =
static_cast<const uint64_t*
>(host_buffer);
451 for (
size_t i = 0; i < elements_to_display; i++) {
452 std::string value = std::to_string(
data[i]);
455 if (line_chars > 0 && line_chars + value.length() + 2 > valueWidth) {
456 std::cout <<
"| " << std::string(indent,
' ') << line.str() << std::string(valueWidth - line_chars,
' ') <<
" |" << std::endl;
462 if (line_chars > 0) {
467 line_chars += value.length();
472 std::cout <<
"| " << std::string(indent,
' ') <<
"Unsupported data type for display"
473 << std::string(valueWidth - 32,
' ') <<
"|" << std::endl;
477 if (line_chars > 0) {
478 std::cout <<
"| " << std::string(indent,
' ') << line.str() << std::string(valueWidth - line_chars,
' ') <<
" |" << std::endl;
482 if (elements_to_display < total_elements) {
483 std::cout <<
"|" << std::string(lineWidth+1,
' ') <<
"|" << std::endl;
484 std::cout <<
"| " << std::string(indent,
' ') <<
"..." << std::string(valueWidth - 3,
' ') <<
" |" << std::endl;
488 std::cout <<
"|" << std::string(lineWidth+1,
' ') <<
"|" << std::endl;
491 std::cout << headerBorder << std::endl;
494 if (is_gpu_tensor && host_buffer) {
499 std::cout << headerBorder << std::endl;
513 std::unordered_map<std::string, Tensor*> m_tensors;
540 m_tensors[tensor->
name] = tensor;
554 auto it = m_tensors.find(name);
555 if (it != m_tensors.end()) {
568 auto it = m_tensors.find(name);
569 if (it != m_tensors.end() && it->second) {
570 return it->second->buffer;
582 auto it = m_tensors.find(name);
583 if (it != m_tensors.end() && it->second) {
584 return it->second->size;
596 auto it = m_tensors.find(name);
597 if (it != m_tensors.end() && it->second) {
598 return it->second->shape;
600 return std::vector<int>();
610 auto it = m_tensors.find(name);
611 if (it != m_tensors.end() && it->second) {
612 return it->second->gpu_id;
624 auto it = m_tensors.find(name);
625 if (it != m_tensors.end() && it->second) {
626 return it->second->frame_num;
640 if (tensor && tensor->
buffer) {
643 return torch::Tensor();
660 tensor->
buffer = newBuffer;
678 if (!srcTensor || !srcTensor->
buffer || srcTensor->
size == 0) {
682 std::string cpu_tensor_name = srcTensor->
name +
"_cpu";
683 Tensor* cpuTensor =
nullptr;
692 cpuTensor->
name = cpu_tensor_name;
702 std::cerr <<
"Failed to allocate CPU memory for tensor clone" << std::endl;
707 m_tensors[cpu_tensor_name] = cpuTensor;
714 if (srcTensor->
gpu_id >= 0) {
716 cudaError_t copyError = cudaMemcpy(
720 cudaMemcpyDeviceToHost
723 if (copyError != cudaSuccess) {
724 std::cerr <<
"Failed to copy tensor from GPU to CPU: "
725 << cudaGetErrorString(copyError) << std::endl;
753 return torch::Tensor();
767 return m_tensors.find(name) != m_tensors.end();
777 auto it = m_tensors.find(name);
778 if (it != m_tensors.end()) {
781 it->second->release();
794 for (
auto& pair : m_tensors) {
796 if (pair.first ==
"img") {
802 pair.second->release();
815 return m_tensors.size();
824 std::vector<std::string> names;
825 names.reserve(m_tensors.size());
826 for (
const auto& pair : m_tensors) {
827 names.push_back(pair.first);
837 const std::unordered_map<std::string, Tensor*>&
getTensors()
const {
847 for (
const auto& pair : m_tensors) {
849 pair.second->display(print_data);
851 std::cout <<
" [NULL TENSOR]" << std::endl;
862 void displayTensor(
const std::string& name,
bool print_data =
false)
const {
863 auto it = m_tensors.find(name);
864 if (it != m_tensors.end() && it->second) {
865 it->second->display(print_data);
867 std::cout <<
" [NULL TENSOR]" << std::endl;
883 if (!tensor.defined()) {
884 return "[undefined]";
887 std::stringstream ss;
889 for (
size_t i = 0; i < tensor.sizes().
size(); ++i) {
890 ss << tensor.sizes()[i];
891 if (i < tensor.sizes().size() - 1) {
911 if (!tensor.defined()) {
912 return "[undefined tensor]";
916 auto t = tensor.clone().contiguous().cpu();
918 std::stringstream ss;
922 int64_t num_to_print;
925 if (max_values == -1) {
927 num_to_print = t.numel();
928 show_ellipsis =
false;
931 num_to_print =
std::min(
static_cast<int64_t
>(max_values), t.numel());
932 show_ellipsis = num_to_print < t.numel();
936 if (t.numel() == 0) {
942 if (t.scalar_type() == torch::ScalarType::Float) {
943 auto a = t.data_ptr<
float>();
944 for (int64_t i = 0; i < num_to_print; i++) {
946 if (i < num_to_print - 1) {
950 }
else if (t.scalar_type() == torch::ScalarType::Int) {
951 auto a = t.data_ptr<int32_t>();
952 for (int64_t i = 0; i < num_to_print; i++) {
954 if (i < num_to_print - 1) {
958 }
else if (t.scalar_type() == torch::ScalarType::Long) {
959 auto a = t.data_ptr<int64_t>();
960 for (int64_t i = 0; i < num_to_print; i++) {
962 if (i < num_to_print - 1) {
968 ss <<
"tensor(" << t.sizes() <<
")";
969 show_ellipsis =
false;
998 const std::string& dtype,
999 int64_t num_elements,
1000 const std::vector<int64_t>& shape_int64,
1001 const std::string& file_path,
1004 cudaError_t cuda_status;
1007 if (dtype.find(
"float32") != std::string::npos) {
1009 size_t element_size =
sizeof(float);
1012 std::vector<float> cpu_data(num_elements);
1013 file.read(
reinterpret_cast<char*
>(cpu_data.data()), num_elements * element_size);
1016 result->
size = num_elements * element_size;
1017 cuda_status = cudaMalloc(&result->
buffer, result->
size);
1018 if (cuda_status != cudaSuccess) {
1019 std::cerr <<
"Error allocating GPU memory: "
1020 << cudaGetErrorString(cuda_status) << std::endl;
1025 cuda_status = cudaMemcpy(result->
buffer, cpu_data.data(), result->
size, cudaMemcpyHostToDevice);
1026 if (cuda_status != cudaSuccess) {
1027 std::cerr <<
"Error copying data to GPU: "
1028 << cudaGetErrorString(cuda_status) << std::endl;
1029 cudaFree(result->
buffer);
1030 result->
buffer =
nullptr;
1060 result->
name =
"tensor_from_file";
1065 if (!file.is_open()) {
1066 std::cerr <<
"Error: Could not open file: " << file_path << std::endl;
1074 file.read(
reinterpret_cast<char*
>(&num_dims),
sizeof(int64_t));
1077 std::vector<int64_t> shape_int64(num_dims);
1078 file.read(
reinterpret_cast<char*
>(shape_int64.data()), num_dims *
sizeof(int64_t));
1081 result->
shape.resize(num_dims);
1082 for (int64_t i = 0; i < num_dims; ++i) {
1083 result->
shape[i] =
static_cast<int>(shape_int64[i]);
1087 int64_t dtype_str_len;
1088 file.read(
reinterpret_cast<char*
>(&dtype_str_len),
sizeof(int64_t));
1091 std::vector<char> dtype_str(dtype_str_len + 1, 0);
1092 file.read(dtype_str.data(), dtype_str_len);
1093 std::string dtype(dtype_str.data());
1096 int64_t num_elements = 1;
1097 for (int64_t dim : shape_int64) {
1098 num_elements *= dim;
1102 cudaError_t cuda_status = cudaSetDevice(gpu_id);
1103 if (cuda_status != cudaSuccess) {
1104 std::cerr <<
"Error setting CUDA device " << gpu_id <<
": "
1105 << cudaGetErrorString(cuda_status) << std::endl;
1110 processDataType(file, result, dtype, num_elements, shape_int64, file_path, gpu_id);
1114 catch (
const std::exception& e) {
1115 std::cerr <<
"Error reading tensor from file: " << e.what() << std::endl;
1117 cudaFree(result->
buffer);
1118 result->
buffer =
nullptr;
1137 const std::string& name =
"Tensor",
1138 bool print_data =
false,
1139 size_t max_elements = 100,
1140 int precision = 4) {
1141 if (!tensor.defined()) {
1142 std::cout <<
"Undefined tensor" << std::endl;
1147 const int lineWidth = 100;
1148 const std::string headerBorder =
"+" + std::string(lineWidth+1,
'-') +
"+";
1149 const int labelWidth = 16;
1150 const int valueWidth = lineWidth - labelWidth - 3;
1151 const int indent = 2;
1153 std::cout <<
"\n" << headerBorder << std::endl;
1156 std::string headerText =
"Tensor Information - " + name;
1157 int padding = (lineWidth - headerText.length()) / 2;
1158 std::cout <<
"| " << std::string(padding,
' ') << headerText
1159 << std::string(lineWidth - padding - headerText.length(),
' ') <<
"|" << std::endl;
1161 std::cout << headerBorder << std::endl;
1164 auto sizes = tensor.sizes();
1165 auto dtype = tensor.scalar_type();
1166 auto device = tensor.device();
1167 size_t numel = tensor.numel();
1168 size_t elements_to_display =
std::min(numel, max_elements);
1171 std::string shapeStr =
"[";
1172 for (
size_t i = 0; i < sizes.size(); i++) {
1173 shapeStr += std::to_string(sizes[i]);
1174 if (i < sizes.size() - 1) shapeStr +=
", ";
1179 std::string dtypeStr;
1181 case torch::kFloat32: dtypeStr =
"Float32";
break;
1182 case torch::kFloat16: dtypeStr =
"Float16";
break;
1183 case torch::kFloat64: dtypeStr =
"Float64";
break;
1184 case torch::kInt32: dtypeStr =
"Int32";
break;
1185 case torch::kInt64: dtypeStr =
"Int64";
break;
1186 case torch::kInt16: dtypeStr =
"Int16";
break;
1187 case torch::kInt8: dtypeStr =
"Int8";
break;
1188 case torch::kUInt8: dtypeStr =
"UInt8";
break;
1189 case torch::kBool: dtypeStr =
"Bool";
break;
1190 default: dtypeStr =
"Unknown";
break;
1194 std::string deviceStr;
1195 if (device.is_cuda()) {
1196 deviceStr =
"GPU [" + std::to_string(device.index()) +
"]";
1202 size_t element_size = 0;
1204 case torch::kFloat32: element_size = 4;
break;
1205 case torch::kFloat16: element_size = 2;
break;
1206 case torch::kFloat64: element_size = 8;
break;
1207 case torch::kInt32: element_size = 4;
break;
1208 case torch::kInt64: element_size = 8;
break;
1209 case torch::kInt16: element_size = 2;
break;
1210 case torch::kInt8: element_size = 1;
break;
1211 case torch::kUInt8: element_size = 1;
break;
1212 case torch::kBool: element_size = 1;
break;
1213 default: element_size = 4;
break;
1215 size_t memory_size = numel * element_size;
1218 std::cout <<
"| Shape | " << std::left << std::setw(valueWidth) << shapeStr <<
" |" << std::endl;
1219 std::cout <<
"| Device | " << std::left << std::setw(valueWidth) << deviceStr <<
" |" << std::endl;
1220 std::cout <<
"| Memory Size | " << std::left << std::setw(valueWidth) << std::to_string(memory_size) +
" bytes" <<
" |" << std::endl;
1221 std::cout <<
"| Elements | " << std::left << std::setw(valueWidth) << std::to_string(numel) <<
" |" << std::endl;
1222 std::cout <<
"| Data Type | " << std::left << std::setw(valueWidth) << dtypeStr <<
" |" << std::endl;
1223 std::cout <<
"| Requires Grad | " << std::left << std::setw(valueWidth) << (tensor.requires_grad() ?
"True" :
"False") <<
" |" << std::endl;
1226 if (print_data && numel > 0) {
1228 torch::Tensor cpu_tensor = tensor.device().is_cuda() ? tensor.to(torch::kCPU) : tensor;
1231 cpu_tensor = cpu_tensor.contiguous();
1234 std::cout <<
"|" << std::string(lineWidth+1,
'-') <<
"|" << std::endl;
1236 if (tensor.device().is_cuda()) {
1237 std::cout <<
"| Values [GPU --> CPU]:" << std::string(lineWidth - 21,
' ') <<
"|" << std::endl;
1239 std::cout <<
"| Values [CPU]:" << std::string(lineWidth - 13,
' ') <<
"|" << std::endl;
1243 std::cout <<
"|" << std::string(lineWidth+1,
' ') <<
"|" << std::endl;
1246 std::cout << std::fixed << std::setprecision(precision);
1249 std::vector<std::string> value_strings;
1250 value_strings.reserve(elements_to_display);
1253 if (dtype == torch::kFloat32) {
1254 auto data_ptr = cpu_tensor.data_ptr<
float>();
1255 for (
size_t i = 0; i < elements_to_display; i++) {
1256 std::stringstream ss;
1257 ss << std::fixed << std::setprecision(precision) << data_ptr[i];
1258 value_strings.push_back(ss.str());
1260 }
else if (dtype == torch::kInt32) {
1261 auto data_ptr = cpu_tensor.data_ptr<int32_t>();
1262 for (
size_t i = 0; i < elements_to_display; i++) {
1263 value_strings.push_back(std::to_string(data_ptr[i]));
1265 }
else if (dtype == torch::kInt64) {
1266 auto data_ptr = cpu_tensor.data_ptr<int64_t>();
1267 for (
size_t i = 0; i < elements_to_display; i++) {
1268 value_strings.push_back(std::to_string(data_ptr[i]));
1270 }
else if (dtype == torch::kUInt8 || dtype == torch::kInt8) {
1271 auto data_ptr = cpu_tensor.data_ptr<uint8_t>();
1272 for (
size_t i = 0; i < elements_to_display; i++) {
1273 value_strings.push_back(std::to_string(
static_cast<int>(data_ptr[i])));
1275 }
else if (dtype == torch::kBool) {
1276 auto data_ptr = cpu_tensor.data_ptr<
bool>();
1277 for (
size_t i = 0; i < elements_to_display; i++) {
1278 value_strings.push_back(data_ptr[i] ?
"true" :
"false");
1280 }
else if (dtype == torch::kFloat16) {
1281 std::cout <<
"| " << std::string(indent,
' ') <<
"Float16 data display not fully implemented"
1282 << std::string(valueWidth - 37,
' ') <<
"|" << std::endl;
1283 std::cout <<
"|" << std::string(lineWidth+1,
' ') <<
"|" << std::endl;
1284 std::cout << headerBorder << std::endl;
1287 std::cout <<
"| " << std::string(indent,
' ') <<
"Unsupported data type for display"
1288 << std::string(valueWidth - 32,
' ') <<
"|" << std::endl;
1289 std::cout <<
"|" << std::string(lineWidth+1,
' ') <<
"|" << std::endl;
1290 std::cout << headerBorder << std::endl;
1295 const int max_line_width = lineWidth - 2 * indent - 4;
1296 std::string current_line;
1297 int current_line_width = 0;
1299 for (
size_t i = 0; i < value_strings.size(); i++) {
1300 std::string value = value_strings[i];
1301 std::string entry = value;
1304 if (i < value_strings.size() - 1) {
1308 int entry_width = entry.length();
1311 if (current_line_width > 0 && current_line_width + entry_width > max_line_width) {
1313 std::cout <<
"| " << std::string(indent,
' ') << std::left
1314 << std::setw(lineWidth - 3) << current_line <<
" |" << std::endl;
1315 current_line = entry;
1316 current_line_width = entry_width;
1319 current_line += entry;
1320 current_line_width += entry_width;
1325 if (current_line_width > 0) {
1326 std::cout <<
"| " << std::string(indent,
' ') << std::left
1327 << std::setw(lineWidth - 3) << current_line <<
" |" << std::endl;
1331 if (elements_to_display < numel) {
1332 std::cout <<
"|" << std::string(lineWidth+1,
' ') <<
"|" << std::endl;
1333 std::cout <<
"| " << std::string(indent,
' ') <<
"..."
1334 << std::string(lineWidth - indent - 5,
' ') <<
" |" << std::endl;
1338 std::cout <<
"|" << std::string(lineWidth+1,
' ') <<
"|" << std::endl;
1342 std::cout << headerBorder << std::endl;