contrib/python-zstandard/c-ext/frameparams.c
author Martin von Zweigbergk <martinvonz@google.com>
Fri, 08 Feb 2019 10:19:30 -0800
changeset 41648 d8cdd5320f75
parent 37495 b1fb341d8a61
child 46374 e92ca942ddca
permissions -rw-r--r--
subrepo: use relative path for "already tracked" message From 932de135041f (subrepo: warn when adding already tracked files in gitsubrepo, 2015-02-27): The file is printed with abs() to be consistent with how it is printed in workingctx, even though that is inconsistent with how added files are printed in verbose mode. However, a few year later, the same author wrote 7008f6819002 (context: name files relative to cwd in warning messages, 2017-07-11) and now it's inconsistent. This fixes that inconsistency. Differential Revision: https://phab.mercurial-scm.org/D5899

/**
* Copyright (c) 2017-present, Gregory Szorc
* All rights reserved.
*
* This software may be modified and distributed under the terms
* of the BSD license. See the LICENSE file for details.
*/

#include "python-zstandard.h"

extern PyObject* ZstdError;

PyDoc_STRVAR(FrameParameters__doc__,
	"FrameParameters: information about a zstd frame");

FrameParametersObject* get_frame_parameters(PyObject* self, PyObject* args, PyObject* kwargs) {
	static char* kwlist[] = {
		"data",
		NULL
	};

	Py_buffer source;
	ZSTD_frameHeader header;
	FrameParametersObject* result = NULL;
	size_t zresult;

#if PY_MAJOR_VERSION >= 3
	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*:get_frame_parameters",
#else
	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*:get_frame_parameters",
#endif
		kwlist, &source)) {
		return NULL;
	}

	if (!PyBuffer_IsContiguous(&source, 'C') || source.ndim > 1) {
		PyErr_SetString(PyExc_ValueError,
			"data buffer should be contiguous and have at most one dimension");
		goto finally;
	}

	zresult = ZSTD_getFrameHeader(&header, source.buf, source.len);

	if (ZSTD_isError(zresult)) {
		PyErr_Format(ZstdError, "cannot get frame parameters: %s", ZSTD_getErrorName(zresult));
		goto finally;
	}

	if (zresult) {
		PyErr_Format(ZstdError, "not enough data for frame parameters; need %zu bytes", zresult);
		goto finally;
	}

	result = PyObject_New(FrameParametersObject, &FrameParametersType);
	if (!result) {
		goto finally;
	}

	result->frameContentSize = header.frameContentSize;
	result->windowSize = header.windowSize;
	result->dictID = header.dictID;
	result->checksumFlag = header.checksumFlag ? 1 : 0;

finally:
	PyBuffer_Release(&source);
	return result;
}

static void FrameParameters_dealloc(PyObject* self) {
	PyObject_Del(self);
}

static PyMemberDef FrameParameters_members[] = {
	{ "content_size", T_ULONGLONG,
	  offsetof(FrameParametersObject, frameContentSize), READONLY,
	  "frame content size" },
	{ "window_size", T_ULONGLONG,
	  offsetof(FrameParametersObject, windowSize), READONLY,
	  "window size" },
	{ "dict_id", T_UINT,
	  offsetof(FrameParametersObject, dictID), READONLY,
	  "dictionary ID" },
	{ "has_checksum", T_BOOL,
	  offsetof(FrameParametersObject, checksumFlag), READONLY,
	  "checksum flag" },
	{ NULL }
};

PyTypeObject FrameParametersType = {
	PyVarObject_HEAD_INIT(NULL, 0)
	"FrameParameters",          /* tp_name */
	sizeof(FrameParametersObject), /* tp_basicsize */
	0,                         /* tp_itemsize */
	(destructor)FrameParameters_dealloc, /* tp_dealloc */
	0,                         /* tp_print */
	0,                         /* tp_getattr */
	0,                         /* tp_setattr */
	0,                         /* tp_compare */
	0,                         /* tp_repr */
	0,                         /* tp_as_number */
	0,                         /* tp_as_sequence */
	0,                         /* tp_as_mapping */
	0,                         /* tp_hash  */
	0,                         /* tp_call */
	0,                         /* tp_str */
	0,                         /* tp_getattro */
	0,                         /* tp_setattro */
	0,                         /* tp_as_buffer */
	Py_TPFLAGS_DEFAULT,        /* tp_flags */
	FrameParameters__doc__,    /* tp_doc */
	0,                         /* tp_traverse */
	0,                         /* tp_clear */
	0,                         /* tp_richcompare */
	0,                         /* tp_weaklistoffset */
	0,                         /* tp_iter */
	0,                         /* tp_iternext */
	0,                         /* tp_methods */
	FrameParameters_members,   /* tp_members */
	0,                         /* tp_getset */
	0,                         /* tp_base */
	0,                         /* tp_dict */
	0,                         /* tp_descr_get */
	0,                         /* tp_descr_set */
	0,                         /* tp_dictoffset */
	0,                         /* tp_init */
	0,                         /* tp_alloc */
	0,                         /* tp_new */
};

void frameparams_module_init(PyObject* mod) {
	Py_TYPE(&FrameParametersType) = &PyType_Type;
	if (PyType_Ready(&FrameParametersType) < 0) {
		return;
	}

	Py_INCREF(&FrameParametersType);
	PyModule_AddObject(mod, "FrameParameters", (PyObject*)&FrameParametersType);
}