Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Postgres/src/backend/utils/adt/   (Postgres Database Version 18.4©)  Datei vom 11.4.2026 mit Größe 6 kB image not shown  

Quelle  arrayutils.c

  Sprache: C
 

/*-------------------------------------------------------------------------
 *
 * arrayutils.c
 *   This file contains some support routines required for array functions.
 *
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *   src/backend/utils/adt/arrayutils.c
 *
 *-------------------------------------------------------------------------
 */


#include "postgres.h"

#include "catalog/pg_type.h"
#include "common/int.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/memutils.h"


/*
 * Convert subscript list into linear element number (from 0)
 *
 * We assume caller has already range-checked the dimensions and subscripts,
 * so no overflow is possible.
 */

int
ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
{
 int   i,
    scale = 1,
    offset = 0;

 for (i = n - 1; i >= 0; i--)
 {
  offset += (indx[i] - lb[i]) * scale;
  scale *= dim[i];
 }
 return offset;
}

/*
 * Convert array dimensions into number of elements
 *
 * This must do overflow checking, since it is used to validate that a user
 * dimensionality request doesn't overflow what we can handle.
 *
 * The multiplication overflow check only works on machines that have int64
 * arithmetic, but that is nearly all platforms these days, and doing check
 * divides for those that don't seems way too expensive.
 */

int
ArrayGetNItems(int ndim, const int *dims)
{
 return ArrayGetNItemsSafe(ndim, dims, NULL);
}

/*
 * This entry point can return the error into an ErrorSaveContext
 * instead of throwing an exception.  -1 is returned after an error.
 */

int
ArrayGetNItemsSafe(int ndim, const int *dims, struct Node *escontext)
{
 int32  ret;
 int   i;

 if (ndim <= 0)
  return 0;
 ret = 1;
 for (i = 0; i < ndim; i++)
 {
  int64  prod;

  /* A negative dimension implies that UB-LB overflowed ... */
  if (dims[i] < 0)
   ereturn(escontext, -1,
     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
      errmsg("array size exceeds the maximum allowed (%d)",
       (int) MaxArraySize)));

  prod = (int64) ret * (int64) dims[i];

  ret = (int32) prod;
  if ((int64) ret != prod)
   ereturn(escontext, -1,
     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
      errmsg("array size exceeds the maximum allowed (%d)",
       (int) MaxArraySize)));
 }
 Assert(ret >= 0);
 if ((Size) ret > MaxArraySize)
  ereturn(escontext, -1,
    (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     errmsg("array size exceeds the maximum allowed (%d)",
      (int) MaxArraySize)));
 return (int) ret;
}

/*
 * Verify sanity of proposed lower-bound values for an array
 *
 * The lower-bound values must not be so large as to cause overflow when
 * calculating subscripts, e.g. lower bound 2147483640 with length 10
 * must be disallowed.  We actually insist that dims[i] + lb[i] be
 * computable without overflow, meaning that an array with last subscript
 * equal to INT_MAX will be disallowed.
 *
 * It is assumed that the caller already called ArrayGetNItems, so that
 * overflowed (negative) dims[] values have been eliminated.
 */

void
ArrayCheckBounds(int ndim, const int *dims, const int *lb)
{
 (void) ArrayCheckBoundsSafe(ndim, dims, lb, NULL);
}

/*
 * This entry point can return the error into an ErrorSaveContext
 * instead of throwing an exception.
 */

bool
ArrayCheckBoundsSafe(int ndim, const int *dims, const int *lb,
      struct Node *escontext)
{
 int   i;

 for (i = 0; i < ndim; i++)
 {
  /* PG_USED_FOR_ASSERTS_ONLY prevents variable-isn't-read warnings */
  int32  sum PG_USED_FOR_ASSERTS_ONLY;

  if (pg_add_s32_overflow(dims[i], lb[i], &sum))
   ereturn(escontext, false,
     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
      errmsg("array lower bound is too large: %d",
       lb[i])));
 }

 return true;
}

/*
 * Compute ranges (sub-array dimensions) for an array slice
 *
 * We assume caller has validated slice endpoints, so overflow is impossible
 */

void
mda_get_range(int n, int *span, const int *st, const int *endp)
{
 int   i;

 for (i = 0; i < n; i++)
  span[i] = endp[i] - st[i] + 1;
}

/*
 * Compute products of array dimensions, ie, scale factors for subscripts
 *
 * We assume caller has validated dimensions, so overflow is impossible
 */

void
mda_get_prod(int n, const int *range, int *prod)
{
 int   i;

 prod[n - 1] = 1;
 for (i = n - 2; i >= 0; i--)
  prod[i] = prod[i + 1] * range[i + 1];
}

/*
 * From products of whole-array dimensions and spans of a sub-array,
 * compute offset distances needed to step through subarray within array
 *
 * We assume caller has validated dimensions, so overflow is impossible
 */

void
mda_get_offset_values(int n, int *dist, const int *prod, const int *span)
{
 int   i,
    j;

 dist[n - 1] = 0;
 for (j = n - 2; j >= 0; j--)
 {
  dist[j] = prod[j] - 1;
  for (i = j + 1; i < n; i++)
   dist[j] -= (span[i] - 1) * prod[i];
 }
}

/*
 * Generates the tuple that is lexicographically one greater than the current
 * n-tuple in "curr", with the restriction that the i-th element of "curr" is
 * less than the i-th element of "span".
 *
 * Returns -1 if no next tuple exists, else the subscript position (0..n-1)
 * corresponding to the dimension to advance along.
 *
 * We assume caller has validated dimensions, so overflow is impossible
 */

int
mda_next_tuple(int n, int *curr, const int *span)
{
 int   i;

 if (n <= 0)
  return -1;

 curr[n - 1] = (curr[n - 1] + 1) % span[n - 1];
 for (i = n - 1; i && curr[i] == 0; i--)
  curr[i - 1] = (curr[i - 1] + 1) % span[i - 1];

 if (i)
  return i;
 if (curr[0])
  return 0;

 return -1;
}

/*
 * ArrayGetIntegerTypmods: verify that argument is a 1-D cstring array,
 * and get the contents converted to integers.  Returns a palloc'd array
 * and places the length at *n.
 */

int32 *
ArrayGetIntegerTypmods(ArrayType *arr, int *n)
{
 int32    *result;
 Datum    *elem_values;
 int   i;

 if (ARR_ELEMTYPE(arr) != CSTRINGOID)
  ereport(ERROR,
    (errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
     errmsg("typmod array must be type cstring[]")));

 if (ARR_NDIM(arr) != 1)
  ereport(ERROR,
    (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
     errmsg("typmod array must be one-dimensional")));

 if (array_contains_nulls(arr))
  ereport(ERROR,
    (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
     errmsg("typmod array must not contain nulls")));

 deconstruct_array_builtin(arr, CSTRINGOID, &elem_values, NULL, n);

 result = (int32 *) palloc(*n * sizeof(int32));

 for (i = 0; i < *n; i++)
  result[i] = pg_strtoint32(DatumGetCString(elem_values[i]));

 pfree(elem_values);

 return result;
}

Messung V0.5 in Prozent
C=94 H=93 G=93

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.