Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
#include <string.h>
#include "json.hpp" // https://github.com/nlohmann/json/tree/develop/src
using json = nlohmann::json;
json parseLsof(std::string str) {
json rez = json::array();
json headers{ json::array() };
// [ {name:'BLAH', min:0, max:0} ] // min max are indexes (1 col padding exclusive) (pad can be on both sides if in middle, or if first entry one on right, or if last entry then one on left)
bool hdone = false; // header_done
std::string word{ "" }; // current_word
std::string::size_type lnstix{ 0 }; // line_start_index
std::string::size_type ix{ 0 }; // ix throughout the whole string. its `i`
std::string::size_type lnix{ 0 }; // ix on line offset by line start ix
const char CHAR_N{ '\n' };
const char CHAR_B{ ' ' };
bool loopstarted = false;
json entry = json::object();
std::string::size_type hix{ 0 }; // header_index_currently_filling
std::string::size_type LAST_CHAR_N{ str.find_last_of(CHAR_N) }; // line_index
if (LAST_CHAR_N == std::string::npos) {
// no new line char
return rez;
} else {
LAST_CHAR_N += 1;
}
for(char& c : str) {
if (loopstarted) ix++;
if (!loopstarted) loopstarted = true;
if (ix == LAST_CHAR_N) break; // as the lsof output ends in "\n0\u000b\u0001". I'm not sure about the final 3 chars, but at least the final "\n" sounds right
// debug_log(ix, c);
if (!hdone) {
// space or \n means end of name
if (c == CHAR_N || c == CHAR_B) {
if (word.length()) {
std::string::size_type min;
std::string::size_type max;
if (headers.size() == 0) {
min = 0;
} else {
min = ix - word.length();
}
max = ix - 1;
headers.push_back({
{"name", word},
{"min", min},
{"max", max}
});
word = "";
}
} else {
word += c;
}
if (c == CHAR_N) {
hdone = true;
lnstix = ix + 1;
headers[headers.size()-1]["max"] = ix - 1;
}
} else {
lnix = ix - lnstix;
// debug_log( headers[hix]["name"], static_cast<int>(headers[hix]["min"]) );
if (c == CHAR_N) {
// start of block-link29393
if (word.length()) {
std::string cname = (headers[hix]["name"]);
trim(word);
entry[cname] = word;
word = "";
if (hix < headers.size()) hix++;
}
// end block-link29393
for (int a_hix=hix; a_hix<headers.size(); a_hix++) {
// hix is definitely NEXT, because if word had length then it was incremented ELSE word was blank so no work field added to entry for this
std::string cname = (headers[a_hix]["name"]);
entry[cname] = "";
}
rez.push_back(entry);
entry.clear();
hix = 0;
lnstix = ix + 1;
} else {
std::string::size_type cmin = static_cast<int>(headers[hix]["min"]);
std::string::size_type cmax = static_cast<int>(headers[hix]["max"]);
if (lnix >= cmin && lnix <= cmax) {
word += c;
} else if (lnix > cmax) {
char end_char = (hix == headers.size() - 1) ? CHAR_N : CHAR_B;
if (c != end_char) {
word += c;
headers[hix]["max"] = lnix;
} else {
// copy of block-link29393
if (word.length()) {
std::string cname = (headers[hix]["name"]);
trim(word);
entry[cname] = word;
word = "";
if (hix < headers.size()) hix++;
}
// end block-link29393
}
} else if (lnix < cmin) {
if (c != CHAR_B) {
word += c;
headers[hix]["min"] = lnix;
}
}
}
}
}
debug_log("headers:", headers.dump());
debug_log("rez:", rez.dump());
return rez;
}
std::string outstr = "COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\nbash 252 noida cwd DIR 1,2 1088 410828 /Users/noida ion/Desktop\nbash 252 noida txt REG 1,2 628736 11647 /bin/bash\nbash 252 noida txt REG 1,2 622896 11866 /usr/lib/dyld\nbash 252 noida txt REG 1,2 382100934 418209 /private/var/db/dyld/dyld_shared_cache_x86_64\nbash 252 noida 0u CHR 16,0 0t401079 601 /dev/ttys000\nbash 252 noida 1u CHR 16,0 0t401079 601 /dev/ttys000\nbash 252 noida 2u CHR 16,0 0t401079 601 /dev/ttys000\nbash 252 noida 255u CHR 16,0 0t401079 601 /dev/ttys000\n0\u000b\u0001";
json entries = parseLsof(outstr);
debug_log("entries:", entries.dump());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment