Skip to content

Commit

Permalink
Исправление ошибки чтения: agread
Browse files Browse the repository at this point in the history
  • Loading branch information
lintest committed Dec 19, 2020
1 parent 9afa1d6 commit 7c4e4ef
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 43 deletions.
132 changes: 89 additions & 43 deletions src/GraphViz1C.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,58 @@ extern "C" {
extern gvplugin_library_t gvplugin_neato_layout_LTX_library;
extern gvplugin_library_t gvplugin_core_LTX_library;
extern gvplugin_library_t gvplugin_gdiplus_LTX_library;
extern char *Gvfilepath; /* Per-process path of files allowed in image attributes (also ps libs) */
extern char *Gvimagepath; /* Per-graph path of files allowed in image attributes (also ps libs) */
extern char* Gvfilepath; /* Per-process path of files allowed in image attributes (also ps libs) */
extern char* Gvimagepath; /* Per-graph path of files allowed in image attributes (also ps libs) */
}

namespace AddIn1C {

static int error(char* errMsg)
{
GraphViz1C::errors << errMsg;
return 0;
}

lt_symlist_t lt_preloaded_symbols[] = {
{ "gvplugin_dot_layout_LTX_library", (void*)(&gvplugin_dot_layout_LTX_library) },
{ "gvplugin_neato_layout_LTX_library", (void*)(&gvplugin_neato_layout_LTX_library) },
{ "gvplugin_core_LTX_library", (void*)(&gvplugin_core_LTX_library) },
{ "gvplugin_gdiplus_LTX_library", (void*)(&gvplugin_gdiplus_LTX_library) },
{ 0, 0 }
};

typedef struct {
const char* data;
int len;
int cur;
} rdr_t;

static int memiofread(void* chan, char* buf, int bufsize)
{
if (bufsize == 0) return 0;
rdr_t* s = (rdr_t*)chan;
if (s->cur >= s->len)
return 0;
int l = 0;
const char* ptr = s->data + s->cur;
char* optr = buf;
char c = *ptr++;
do {
*optr++ = c;
l++;
} while ((c != '\n') && (l < bufsize) && (c = *ptr++));
s->cur += l;
return l;
}

static Agraph_t* read(const char* data, unsigned int size)
{
rdr_t rdr{ data, size, 0 };
Agiodisc_t memIoDisc = { memiofread, AgIoDisc.putstr, AgIoDisc.flush };
Agdisc_t disc{ &AgMemDisc, &AgIdDisc, &memIoDisc };
agsetfile(NULL);
return agread(&rdr, &disc);
}
}

#pragma comment(lib, "vcruntime.lib")
Expand All @@ -28,11 +78,16 @@ GraphViz1C::GraphViz1C()
AddProperty(
u"ImagePath", u"ПутиКартинок",
[&](VH var) { var = imagepath; },
[&](VH var) { imagepath = var;
[&](VH var) {
imagepath = var;
Gvfilepath = (char*)imagepath.c_str();
Gvimagepath = (char*)imagepath.c_str();
Gvimagepath = (char*)imagepath.c_str();
}
);
AddProperty(
u"Errors", u"Ошибки",
[&](VH var) { var = buffer.str(); }
);
AddFunction(u"Render", u"Сформировать",
[&](VH source, VH format, VH layout) { this->render(source, format, layout); },
{ { 1, u"svg"}, { 2, u"dot" } }
Expand All @@ -41,84 +96,75 @@ GraphViz1C::GraphViz1C()
[&](VH api) { this->formats(api); },
{ { 0, (int64_t)3 } }
);

gvc = gvContextPlugins(AddIn1C::lt_preloaded_symbols, 0);
}

GraphViz1C::~GraphViz1C()
{
if (gvc) gvFreeContext(gvc);
}

std::stringbuf GraphViz1C::buffer;

std::ostream GraphViz1C::errors(&buffer);

static int error(char* errMsg)
{
GraphViz1C::errors << errMsg;
return 0;
}

void GraphViz1C::render(VH source, const std::string& format, const std::string& layout)
{
buffer.str({});
agseterrf(::error);
agseterrf(AddIn1C::error);

std::string text;
std::vector<char> data;
const char* input = nullptr;
char* output = nullptr;
unsigned int size = 0;
switch (source.type()) {
case VTYPE_BLOB:
data.resize((size_t)source.size() + 1, 0);
memcpy(data.data(), source.data(), data.size());
input = data.data();
input = source.data();
size = source.size();
break;
case VTYPE_PWSTR:
text = source;
input = text.c_str();
size = text.size();
break;
default:
result = "Unsupported data type";
return;
}

auto gvc = gvContextPlugins(lt_preloaded_symbols, 0);
if (gvc) {
auto g = agmemread(input);
if (g) {
if (gvLayout(gvc, g, layout.c_str()) == 0) {
if (gvRenderData(gvc, g, format.c_str(), &output, &size) == 0) {
try {
result.AllocMemory(size);
memcpy(result.data(), output, size);
}
catch (...) {
result = "Memory allocation error";
}
gvFreeRenderData(output);
if (!gvc) {
result = "Failed to initialize context plugins";
return;
}

agmemread("\0");
auto g = AddIn1C::read(input, size);
if (g) {
if (gvLayout(gvc, g, layout.c_str()) == 0) {
if (gvRenderData(gvc, g, format.c_str(), &output, &size) == 0) {
try {
result.AllocMemory(size);
memcpy(result.data(), output, size);
}
catch (...) {
result = "Memory allocation error";
}
gvFreeRenderData(output);
}
gvFreeLayout(gvc, g);
agclose(g);
}
gvFreeContext(gvc);
gvFreeLayout(gvc, g);
agclose(g);
}
if (result.type() == VTYPE_EMPTY) {
result = buffer.str();
buffer.str({});
}
}

lt_symlist_t lt_preloaded_symbols[] = {
{ "gvplugin_dot_layout_LTX_library", (void*)(&gvplugin_dot_layout_LTX_library) },
{ "gvplugin_neato_layout_LTX_library", (void*)(&gvplugin_neato_layout_LTX_library) },
{ "gvplugin_core_LTX_library", (void*)(&gvplugin_core_LTX_library) },
{ "gvplugin_gdiplus_LTX_library", (void*)(&gvplugin_gdiplus_LTX_library) },
{ 0, 0 }
};

void GraphViz1C::formats(int64_t api)
{
auto gvc = gvContextPlugins(lt_preloaded_symbols, 0);
if (gvc) {
auto str = gvplugin_list(gvc, (api_t)api, "");
if (str) result = std::string(str);
gvFreeContext(gvc);
}
}
3 changes: 3 additions & 0 deletions src/GraphViz1C.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define __GRAPHVIZ1C_H__

#include "AddInNative.h"
#include <common/types.h>
#include <iostream>
#include <sstream>

Expand All @@ -11,7 +12,9 @@ class GraphViz1C:
private:
static std::stringbuf buffer;
static std::vector<std::u16string> names;
GVC_t* gvc = nullptr;
GraphViz1C();
~GraphViz1C();
private:
void render(VH source, const std::string& format, const std::string& layout);
void formats(int64_t api = 3);
Expand Down

0 comments on commit 7c4e4ef

Please # to comment.