#include "src/include/pmix_config.h"
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <ctype.h>
#include "include/pmix.h"
#include "pmix_common.h"
#include "src/class/pmix_list.h"
#include "src/client/pmix_client_ops.h"
#include "src/include/pmix_globals.h"
#include "src/include/pmix_socket_errno.h"
#include "src/mca/bfrops/base/base.h"
#include "src/mca/gds/gds.h"
#include "src/util/pmix_argv.h"
#include "src/util/pmix_error.h"
#include "src/util/pmix_output.h"
#include "preg_compress.h"
#include "src/mca/pcompress/pcompress.h"
#include "src/mca/preg/base/base.h"
static pmix_status_t generate_node_regex(const char *input, char **regex);
static pmix_status_t generate_ppn(const char *input, char **ppn);
static pmix_status_t parse_nodes(const char *regexp, char ***names);
static pmix_status_t parse_procs(const char *regexp, char ***procs);
static pmix_status_t copy(char **dest, size_t *len, const char *input);
static pmix_status_t pack(pmix_buffer_t *buffer, const char *input);
static pmix_status_t unpack(pmix_buffer_t *buffer, char **regex);
static pmix_status_t release(char *regexp);
pmix_preg_module_t pmix_preg_compress_module = {
.name = "compress",
.generate_node_regex = generate_node_regex,
.generate_ppn = generate_ppn,
.parse_nodes = parse_nodes,
.parse_procs = parse_procs,
.copy = copy,
.pack = pack,
.unpack = unpack,
.release = release
};
#define PREG_COMPRESS_PREFIX "blob: component=zlib: size="
static pmix_status_t pack_blob(const uint8_t *tmp, size_t len, char **regexp)
{
char *result, *slen;
int idx;
if (0 > asprintf(&slen, "%lu", (unsigned long) len)) {
return PMIX_ERR_NOMEM;
}
result = calloc(len + strlen(PREG_COMPRESS_PREFIX) + strlen(slen) + strlen(":") + 1,
sizeof(char));
idx = 0;
strcpy(result, "blob:");
idx += strlen("blob:") + 1; strcpy(&result[idx], "component=zlib:");
idx += strlen("component=zlib:") + 1; strcpy(&result[idx], "size=");
idx += strlen("size=");
strcpy(&result[idx], slen);
idx += strlen(slen);
strcpy(&result[idx], ":");
idx += strlen(":") + 1; memcpy(&result[idx], tmp, len);
free(slen);
*regexp = result;
return PMIX_SUCCESS;
}
static pmix_status_t generate_node_regex(const char *input, char **regexp)
{
size_t len;
uint8_t *tmp;
pmix_status_t rc;
if (!pmix_compress.compress_string((char *) input, &tmp, &len)) {
return PMIX_ERR_TAKE_NEXT_OPTION;
}
if (NULL == tmp) {
return PMIX_ERR_NOMEM;
}
rc = pack_blob(tmp, len, regexp);
free(tmp);
return rc;
}
static pmix_status_t generate_ppn(const char *input, char **regexp)
{
size_t len;
uint8_t *tmp;
pmix_status_t rc;
if (!pmix_compress.compress_string((char *) input, &tmp, &len)) {
return PMIX_ERR_TAKE_NEXT_OPTION;
}
if (NULL == tmp) {
return PMIX_ERR_NOMEM;
}
rc = pack_blob(tmp, len, regexp);
free(tmp);
return rc;
}
static pmix_status_t parse_nodes(const char *regexp, char ***names)
{
char *tmp, *ptr, **argv;
size_t len;
int idx;
if (0 != strncmp(regexp, "blob", 4)) {
return PMIX_ERR_TAKE_NEXT_OPTION;
}
idx = strlen(regexp) + 1;
if (0 != strncmp(®exp[idx], "component=zlib:", strlen("component=zlib:"))) {
return PMIX_ERR_TAKE_NEXT_OPTION;
}
idx += strlen("component=zlib:") + 1;
len = strtoul(®exp[idx], &ptr, 10);
ptr += 2;
tmp = malloc(len);
if (NULL == tmp) {
return PMIX_ERR_NOMEM;
}
if (!pmix_compress.decompress_string(&tmp, (uint8_t *) ptr, len)) {
free(tmp);
return PMIX_ERR_TAKE_NEXT_OPTION;
}
argv = PMIx_Argv_split(tmp, ',');
free(tmp);
*names = argv;
return PMIX_SUCCESS;
}
static pmix_status_t parse_procs(const char *regexp, char ***procs)
{
char *tmp, *ptr, **argv;
size_t len;
int idx;
if (0 != strncmp(regexp, "blob", 4)) {
return PMIX_ERR_TAKE_NEXT_OPTION;
}
idx = strlen(regexp) + 1;
if (0 != strncmp(®exp[idx], "component=zlib:", strlen("component=zlib:"))) {
return PMIX_ERR_TAKE_NEXT_OPTION;
}
idx += strlen("component=zlib:") + 1;
len = strtoul(®exp[idx], &ptr, 10);
ptr += 2;
tmp = malloc(len);
if (NULL == tmp) {
return PMIX_ERR_NOMEM;
}
if (!pmix_compress.decompress_string(&tmp, (uint8_t *) ptr, len)) {
free(tmp);
return PMIX_ERR_TAKE_NEXT_OPTION;
}
argv = PMIx_Argv_split(tmp, ';');
free(tmp);
*procs = argv;
return PMIX_SUCCESS;
}
static pmix_status_t copy(char **dest, size_t *len, const char *input)
{
size_t slen;
char *tmp;
int idx;
if (0 != strncmp(input, "blob", 4)) {
return PMIX_ERR_TAKE_NEXT_OPTION;
}
idx = strlen(input) + 1;
if (0 != strncmp(&input[idx], "component=zlib:", strlen("component=zlib:"))) {
return PMIX_ERR_TAKE_NEXT_OPTION;
}
idx += strlen("component=zlib:") + 1;
slen = strtoul(&input[idx], NULL, 10) + strlen(PREG_COMPRESS_PREFIX) + strlen(&input[idx]) + 1;
tmp = calloc(slen, sizeof(char));
if (NULL == tmp) {
return PMIX_ERR_NOMEM;
}
memcpy(tmp, input, slen);
*dest = tmp;
*len = slen;
return PMIX_SUCCESS;
}
static pmix_status_t pack(pmix_buffer_t *buffer, const char *input)
{
size_t slen;
char *ptr;
int idx;
if (0 != strncmp(input, "blob", 4)) {
return PMIX_ERR_TAKE_NEXT_OPTION;
}
idx = strlen(input) + 1;
if (0 != strncmp(&input[idx], "component=zlib:", strlen("component=zlib:"))) {
return PMIX_ERR_TAKE_NEXT_OPTION;
}
idx += strlen("component=zlib:") + 1;
slen = strtoul(&input[idx], NULL, 10) + strlen(PREG_COMPRESS_PREFIX) + strlen(&input[idx]) + 1;
ptr = pmix_bfrop_buffer_extend(buffer, slen);
if (NULL == ptr) {
return PMIX_ERR_NOMEM;
}
memcpy(ptr, input, slen);
buffer->bytes_used += slen;
buffer->pack_ptr += slen;
return PMIX_SUCCESS;
}
static pmix_status_t unpack(pmix_buffer_t *buffer, char **regex)
{
size_t slen;
char *ptr, *output;
int idx;
ptr = buffer->unpack_ptr;
if (0 != strncmp(ptr, "blob", 4)) {
return PMIX_ERR_TAKE_NEXT_OPTION;
}
idx = strlen(ptr) + 1;
if (0 != strncmp(&ptr[idx], "component=zlib:", strlen("component=zlib:"))) {
return PMIX_ERR_TAKE_NEXT_OPTION;
}
idx += strlen("component=zlib:") + 1;
slen = strtoul(&ptr[idx], NULL, 10) + strlen(PREG_COMPRESS_PREFIX) + strlen(&ptr[idx]) + 1;
output = (char *) malloc(slen);
if (NULL == output) {
*regex = NULL;
return PMIX_ERR_NOMEM;
}
memcpy(output, ptr, slen);
buffer->unpack_ptr += slen;
*regex = output;
return PMIX_SUCCESS;
}
static pmix_status_t release(char *regexp)
{
int idx;
if (NULL == regexp) {
return PMIX_SUCCESS;
}
if (0 != strncmp(regexp, "blob", 4)) {
return PMIX_ERR_TAKE_NEXT_OPTION;
}
idx = strlen(regexp) + 1;
if (0 != strncmp(®exp[idx], "component=zlib:", strlen("component=zlib:"))) {
return PMIX_ERR_TAKE_NEXT_OPTION;
}
free(regexp);
return PMIX_SUCCESS;
}