// 从pg获取参数，调用udfDispatch，选择TEE还是纯软件
#include "stdio.h"
#include "Interface.h"
#include <string.h>
#include "postgres.h"
#include "fmgr.h"
#include "utils/geo_decls.h"
#include "ORE_STR22STRUCT.h"
#include <unistd.h>
#include <assert.h>
#include "stdlib.h"
#include "udfDispatch.h"
#include "t.h"
#include "Timer.h"
#include "lib/stringinfo.h"

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
typedef struct varlena ore_en;
#define TextDatumGetCString(d) ore_text_to_cstring((ore_en *) DatumGetPointer(d))
#define PG_RETURN_CSTRING(x) return CStringGetDatum(x)
#define PG_RETURN_ORE_EN_P(x)    PG_RETURN_POINTER(x)
typedef StringInfoData *StringInfo;

extern const char *getFloatScaleCiphertext(); //config.h
extern void c_count(const char* name, double time); //TimeCounter.h
// 两个text以\0分割
text *
concat_text(text *arg1, text *arg2)
{
   int32 arg1_size = VARSIZE(arg1) - VARHDRSZ;
   int32 arg2_size = VARSIZE(arg2) - VARHDRSZ;
   int32 new_text_size = arg1_size + arg2_size + VARHDRSZ + 1;
   text *new_text = (text *)palloc(new_text_size);

   SET_VARSIZE(new_text, new_text_size);
   memcpy(VARDATA(new_text), VARDATA(arg1), arg1_size);
   VARDATA(new_text)
   [arg1_size] = '\0';
   memcpy(VARDATA(new_text) + arg1_size + 1, VARDATA(arg2), arg2_size);
   return new_text;
}
ore_en *
concat_text1(ore_en *arg1, text *arg2)
{
   int32 arg1_size = VARSIZE(arg1) - VARHDRSZ;
   int32 arg2_size = VARSIZE(arg2) - VARHDRSZ;
   int32 new_text_size = arg1_size + arg2_size + VARHDRSZ + 1;
   ore_en *new_text = (text *)palloc(new_text_size);

   SET_VARSIZE(new_text, new_text_size);
   memcpy(VARDATA(new_text), VARDATA(arg1), arg1_size);
   VARDATA(new_text)[arg1_size] = '\0';
   memcpy(VARDATA(new_text) + arg1_size + 1, VARDATA(arg2), arg2_size);
   return new_text;
}

void split_to_2_text(text *src, text **ore, text **aes)
{
   int32 arg1_size = VARSIZE(src) - VARHDRSZ;
   int32 ore_size = 0;
   if (arg1_size != 0)
      ore_size = strlen(VARDATA(src)); // 初始时src不一定有\0
   int32 aes_size = Max(arg1_size - ore_size - 1, 0);

   text *pore = (text *)palloc(ore_size + VARHDRSZ);
   SET_VARSIZE(pore, ore_size + VARHDRSZ);

   text *paes = (text *)palloc(aes_size + VARHDRSZ);
   SET_VARSIZE(paes, aes_size + VARHDRSZ);

   memcpy(VARDATA(paes), VARDATA(src) + ore_size + 1, aes_size);
   memcpy(VARDATA(pore), VARDATA(src), ore_size);

   *ore = pore;
   *aes = paes;
}
void split_to_2_text1(ore_en* src, ore_en** ore, text** aes) {
   int32 arg1_size = VARSIZE(src) - VARHDRSZ;
   int32 ore_size = 0;
   if(arg1_size != 0)
      ore_size = strlen(VARDATA(src)); // 初始时src不一定有\0
   int32 aes_size = Max(arg1_size - ore_size - 1, 0);

   ore_en *pore = (text *)palloc(ore_size + VARHDRSZ);
   SET_VARSIZE(pore, ore_size + VARHDRSZ);

   text *paes = (text *)palloc(aes_size + VARHDRSZ);
   SET_VARSIZE(paes, aes_size + VARHDRSZ);

   memcpy(VARDATA(paes), VARDATA(src) + ore_size + 1, aes_size);
   memcpy(VARDATA(pore), VARDATA(src), ore_size);

   *ore = pore;
   *aes = paes;
}

PG_FUNCTION_INFO_V1(sahe_add);
Datum sahe_add(PG_FUNCTION_ARGS)
{
   void* timer = startTimer();
   text *arg1 = PG_GETARG_TEXT_P(0);
   text *arg2 = PG_GETARG_TEXT_P(1);
   text *arg3 = PG_GETARG_TEXT_P(2);
   text *arg4 = PG_GETARG_TEXT_P(3);

   //! BUG arg1->vl_dat可能不为 \0 也就没有c风格字符串
   // TODO：此为低效解决方案
   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   size_t s2 = VARSIZE(arg2) - VARHDRSZ;
   size_t s3 = VARSIZE(arg3) - VARHDRSZ;
   size_t s4 = VARSIZE(arg4) - VARHDRSZ;

   char *dat1 = palloc0(s1 + 1);
   char *dat2 = palloc0(s2 + 1);
   char *dat3 = palloc0(s3 + 1);
   char *dat4 = palloc0(s4 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   memcpy(dat2, arg2->vl_dat, s2);
   memcpy(dat3, arg3->vl_dat, s3);
   memcpy(dat4, arg4->vl_dat, s4);

   bool isLeftFloat = dat1[s1 - 1] == '2';
   bool isRightFloat = dat2[s2 - 1] == '2';
   // 去除标志位
   dat1[s1 - 1] = 0;
   dat2[s2 - 1] = 0;
   // if (isLeftFloat || isRightFloat)
   // {
   //    if (!(isLeftFloat && isRightFloat))
   //    {
   //       if (!isLeftFloat)
   //       {
   //          //TODO: 怎么乘倍数？
   //       }
   //    }
   // }
   char *buffer = saheAdd(dat1, dat2, dat3, dat4, isLeftFloat, isRightFloat);// ！！！将标志位传入函数中

   size_t buffSize = strlen(buffer);
   text *destination = (text *)palloc0(VARHDRSZ + buffSize + 1);
   SET_VARSIZE(destination, VARHDRSZ + buffSize + 1);

   char *pbuf = VARDATA(destination);
   memcpy(pbuf, buffer, buffSize);
   free(buffer);
   // int+int也放缩了，结果按浮点数处理
   destination->vl_dat[buffSize] = '2';
   // if(isLeftFloat || isRightFloat) {
   //    destination->vl_dat[buffSize] = '2';
   // } else {
   //    destination->vl_dat[buffSize] = '1';
   // }
c_count("interface_c: ahe", getPassedTime(timer, true));
   PG_RETURN_TEXT_P(destination);
}

PG_FUNCTION_INFO_V1(sahe_addplain);

Datum
    sahe_addplain(PG_FUNCTION_ARGS)
{
   text *arg1 = PG_GETARG_TEXT_P(0);
   int32 m1 = PG_GETARG_INT32(1);

   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   // size_t s2 = VARSIZE(arg2) - VARHDRSZ;

   char *dat1 = palloc(s1 + 1);
   // char *dat2 = palloc(s2 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   // memcpy(dat2, arg2->vl_dat, s2);
   dat1[s1] = '\0';
   // 去除标志位
   dat1[s1 - 1] = 0;

   char *buffer = saheAddp(dat1, m1); /* our source data */

   size_t buffSize = strlen(buffer);

   text *destination = (text *)palloc0(VARHDRSZ + buffSize + 1);
   SET_VARSIZE(destination, VARHDRSZ + buffSize + 1);
   memcpy(destination->vl_dat, buffer, buffSize);
// 没有解决加法下放缩的问题，只能先设置为1了
destination->vl_dat[buffSize ] = '1';
   free(buffer);

   free(dat1);
   PG_RETURN_TEXT_P(destination);
}

PG_FUNCTION_INFO_V1(sahe_substract);

Datum
    sahe_substract(PG_FUNCTION_ARGS)
{
   text *arg1 = PG_GETARG_TEXT_P(0);
   text *arg2 = PG_GETARG_TEXT_P(1);
   text *arg3 = PG_GETARG_TEXT_P(2);
   text *arg4 = PG_GETARG_TEXT_P(3);

   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   size_t s2 = VARSIZE(arg2) - VARHDRSZ;
   size_t s3 = VARSIZE(arg3) - VARHDRSZ;
   size_t s4 = VARSIZE(arg4) - VARHDRSZ;

   char *dat1 = palloc0(s1 + 1);
   char *dat2 = palloc0(s2 + 1);
   char *dat3 = palloc0(s3 + 1);
   char *dat4 = palloc0(s4 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   memcpy(dat2, arg2->vl_dat, s2);
   memcpy(dat3, arg3->vl_dat, s3);
   memcpy(dat4, arg4->vl_dat, s4);

   bool isLeftFloat = dat1[s1 - 1] == '2';
   bool isRightFloat = dat2[s2 - 1] == '2';
   // 去除标志位
   dat1[s1 - 1] = 0;
   dat2[s2 - 1] = 0;

   char *buffer = saheSub(dat1, dat2, dat3, dat4, isLeftFloat, isRightFloat); /* our source data */
   size_t buffSize = strlen(buffer);

   text *destination = (text *)palloc(VARHDRSZ + buffSize + 1);
   SET_VARSIZE(destination, VARHDRSZ + buffSize + 1);
   mymemcpy(destination->vl_dat, buffer, buffSize);

   destination->vl_dat[buffSize ] = '2';
   free(buffer);
// 没有解决加法下放缩的问题，只能先设置为1了

   PG_RETURN_TEXT_P(destination);
}

PG_FUNCTION_INFO_V1(sahe_multiply);

Datum
    sahe_multiply(PG_FUNCTION_ARGS)
{
   text *arg1 = PG_GETARG_TEXT_P(0);
   int32 m1 = PG_GETARG_INT32(1);
   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   // size_t s2 = VARSIZE(arg2) - VARHDRSZ;

   char *dat1 = palloc(s1 + 1);
   // char *dat2 = palloc(s2 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   // memcpy(dat2, arg2->vl_dat, s2);
   dat1[s1] = '\0';
   // dat2[s2] = '\0';
   char *buffer = saheMul(dat1, m1); /* our source data */

   size_t buffSize = strlen(buffer);
   text *destination = (text *)palloc(VARHDRSZ + buffSize + 1);
   SET_VARSIZE(destination, VARHDRSZ + buffSize + 1);
   mymemcpy(destination->vl_dat, buffer, buffSize);

   free(buffer);
   free(dat1);
   PG_RETURN_TEXT_P(destination);
}

PG_FUNCTION_INFO_V1(sahe_negate);

Datum
    sahe_negate(PG_FUNCTION_ARGS)
{
   text *arg1 = PG_GETARG_TEXT_P(0);

   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   // size_t s2 = VARSIZE(arg2) - VARHDRSZ;

   char *dat1 = palloc(s1 + 1);
   // char *dat2 = palloc(s2 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   // memcpy(dat2, arg2->vl_dat, s2);
   // 去除标志位
   dat1[s1 - 1] = 0;

   char *buffer = saheNeg(dat1); /* our source data */
   size_t buffSize = strlen(buffer);
   text *destination = (text *)palloc(VARHDRSZ + buffSize + 1);
   SET_VARSIZE(destination, VARHDRSZ + buffSize + 1);
   mymemcpy(destination->vl_dat, buffer, buffSize);

   free(buffer);
   free(dat1);
// 没有解决加法下放缩的问题，只能先设置为1了
destination->vl_dat[buffSize ] = '1';
   PG_RETURN_TEXT_P(destination);
}

PG_FUNCTION_INFO_V1(smhe_multiply);

Datum
    smhe_multiply(PG_FUNCTION_ARGS)
{
   text *arg1 = PG_GETARG_TEXT_P(0);
   text *arg2 = PG_GETARG_TEXT_P(1);
   text *arg3 = PG_GETARG_TEXT_P(2);
   text *arg4 = PG_GETARG_TEXT_P(3);

   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   size_t s2 = VARSIZE(arg2) - VARHDRSZ;
   size_t s3 = VARSIZE(arg3) - VARHDRSZ;
   size_t s4 = VARSIZE(arg4) - VARHDRSZ;

   char *dat1 = palloc0(s1 + 1);
   char *dat2 = palloc0(s2 + 1);
   char *dat3 = palloc0(s3 + 1);
   char *dat4 = palloc0(s4 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   memcpy(dat2, arg2->vl_dat, s2);
   memcpy(dat3, arg3->vl_dat, s3);
   memcpy(dat4, arg4->vl_dat, s4);

   bool leftOpIsFloat = dat1[s1 - 1] == '2';
   bool rightOpIsFloat = dat2[s2 - 1] == '2';
   // 去掉标识位
   dat1[s1 - 1] = 0;
   dat2[s2 - 1] = 0;
   char *buffer = smheMul(dat1, dat2, dat3, dat4, leftOpIsFloat, rightOpIsFloat); /* our source data */
   size_t buffSize = strlen(buffer);
   char *buffer2 = NULL;
   // 浮点数的同台乘法是放缩处理的，两个处理后的浮点数相乘会导致缩放失真，需要除掉一个缩放倍数
   // if (leftOpIsFloat && rightOpIsFloat)
   // {
   //    char *scaleSMHECiphertext = getFloatScaleCiphertext();
   //    buffer2 = SMHE_DIVIDE_udf(buffer, scaleSMHECiphertext, buffSize, strlen(scaleSMHECiphertext));
   // }
   // else
   // {
      // 两个操作数并非都是浮点数，不需要操作。
      buffer2 = buffer;
   // }

   // buffer= 46(char) + 1(flag) + 1(\0)
   text *destination = (text *)palloc0(VARHDRSZ + strlen(buffer2) + 1);

   SET_VARSIZE(destination, VARHDRSZ + strlen(buffer2) + 1);
   mymemcpy(destination->vl_dat, buffer2, strlen(buffer2));
   // 添加标识位
   // if (leftOpIsFloat || rightOpIsFloat)
   // {
   //    destination->vl_dat[strlen(buffer2)] = '2';
   // }
   // else {
   //    destination->vl_dat[strlen(buffer2)] = '1';
   // }
   if (leftOpIsFloat || rightOpIsFloat)
   {
      destination->vl_dat[strlen(buffer2)] = '4';
   }
   else if (leftOpIsFloat && rightOpIsFloat)
   {
      destination->vl_dat[strlen(buffer2)] = '4';
   }
   else {
      destination->vl_dat[strlen(buffer2)] = '1';
   }

   free(buffer);
   if (buffer2 != buffer)
   {
      free(buffer2);
   }
   PG_RETURN_TEXT_P(destination);
}

PG_FUNCTION_INFO_V1(smhe_multiplyplain);

Datum
    smhe_multiplyplain(PG_FUNCTION_ARGS)
{
   text *arg1 = PG_GETARG_TEXT_P(0);
   int32 m1 = PG_GETARG_INT32(1);

   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   // size_t s2 = VARSIZE(arg2) - VARHDRSZ;

   char *dat1 = palloc(s1 + 1);
   // char *dat2 = palloc(s2 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   // memcpy(dat2, arg2->vl_dat, s2);
   dat1[s1 - 1] = '\0';
   // dat2[s2] = '\0';

   char *buffer = smheMulp(dat1, m1); /* our source data */
   size_t buffSize = strlen(buffer);
   text *destination = (text *)palloc(VARHDRSZ + buffSize + 1);
   SET_VARSIZE(destination, VARHDRSZ + buffSize + 1);
   mymemcpy(destination->vl_dat, buffer, buffSize);

   free(buffer);
   free(dat1);
// 没有解决加法下放缩的问题，只能先设置为1了
destination->vl_dat[buffSize ] = '1';
   PG_RETURN_TEXT_P(destination);
}

PG_FUNCTION_INFO_V1(smhe_divide);

Datum
    smhe_divide(PG_FUNCTION_ARGS)
{
   text *arg1 = PG_GETARG_TEXT_P(0);
   text *arg2 = PG_GETARG_TEXT_P(1);
   text *arg3 = PG_GETARG_TEXT_P(2);
   text *arg4 = PG_GETARG_TEXT_P(3);

   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   size_t s2 = VARSIZE(arg2) - VARHDRSZ;
   size_t s3 = VARSIZE(arg3) - VARHDRSZ;
   size_t s4 = VARSIZE(arg4) - VARHDRSZ;

   char *dat1 = palloc0(s1 + 1);
   char *dat2 = palloc0(s2 + 1);
   char *dat3 = palloc0(s3 + 1);
   char *dat4 = palloc0(s4 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   memcpy(dat2, arg2->vl_dat, s2);
   memcpy(dat3, arg3->vl_dat, s3);
   memcpy(dat4, arg4->vl_dat, s4);

   bool leftOpIsFloat = dat1[s1 - 1] == '2';
   bool rightOpIsFloat = dat2[s2 - 1] == '2';
   // 去掉标识位
   dat1[s1 - 1] = 0;
   dat2[s1 - 1] = 0;

   // char *buffer = smheDiv(dat1, dat2, dat3, dat4); /* our source data */
   // size_t buffSize = strlen(buffer);
   // char *buffer2 = NULL;
   // // 浮点数的同台乘法是放缩处理的，两个处理后的浮点数相乘会导致缩放失真，需要除掉一个缩放倍数
   // if (leftOpIsFloat && rightOpIsFloat)
   // {
   //    char *scaleSMHECiphertext = getFloatScaleCiphertext();
   //    buffer2 = SMHE_MULTIPLY_udf(buffer, scaleSMHECiphertext, buffSize, strlen(scaleSMHECiphertext));
   // }
   // else
   // {
   //    // 两个操作数并非都是浮点数，不需要操作。
   //    buffer2 = buffer;
   // }

   char *buffer = smheDiv(dat1, dat2, dat3, dat4, leftOpIsFloat, rightOpIsFloat); /* our source data */
   printf("buffer: %s\n", buffer);
   size_t buffSize = strlen(buffer);
   char *buffer2 = NULL;
   /*
   // 浮点数的同台乘法是放缩处理的，两个处理后的浮点数相除最后再除以一个放缩倍数会导致缩放失真，需要乘以一个缩放倍数
   if (leftOpIsFloat && rightOpIsFloat)
   {
      char *scaleSMHECiphertext = getFloatScaleCiphertext();
      buffer2 = SMHE_MULTIPLY_udf(buffer, scaleSMHECiphertext, buffSize, strlen(scaleSMHECiphertext));
   }
   else
   {
      // 两个操作数并非都是浮点数，不需要操作。*/
      buffer2 = buffer;
   //}

   text *destination = (text *)palloc0(VARHDRSZ + strlen(buffer2) + 1);

   SET_VARSIZE(destination, VARHDRSZ + strlen(buffer2) + 1);
   mymemcpy(destination->vl_dat, buffer2, strlen(buffer2));
   // 添加标识位
   // if (leftOpIsFloat || rightOpIsFloat)
   // {
   //    destination->vl_dat[strlen(buffer2)] = '2';
   // }
   // else {
   //    destination->vl_dat[strlen(buffer2)] = '2';      
   // }
   destination->vl_dat[strlen(buffer2)] = '3';

   free(buffer);
   if (buffer2 != buffer)
   {
      free(buffer2);
   }

   PG_RETURN_TEXT_P(destination);
}

PG_FUNCTION_INFO_V1(smhe_pow);

Datum
    smhe_pow(PG_FUNCTION_ARGS)
{
   text *arg1 = PG_GETARG_TEXT_P(0);
   text *arg2 = PG_GETARG_TEXT_P(1);
   int32 m1 = PG_GETARG_INT32(2);

   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   size_t s2 = VARSIZE(arg2) - VARHDRSZ;

   char *dat1 = palloc(s1 + 1);
   char *dat2 = palloc(s2 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   memcpy(dat2, arg2->vl_dat, s2);
   dat1[s1] = '\0';
   dat2[s2] = '\0';

   char *buffer = smhePow(dat1, dat2, m1); /* our source data */
   size_t buffSize = strlen(buffer);
   text *destination = (text *)palloc(VARHDRSZ + buffSize + 1);
   SET_VARSIZE(destination, VARHDRSZ + buffSize + 1);
   mymemcpy(destination->vl_dat, buffer, buffSize);

   free(buffer);
   PG_RETURN_TEXT_P(destination);
}

PG_FUNCTION_INFO_V1(smhe_inverse);

Datum
    smhe_inverse(PG_FUNCTION_ARGS)
{
   text *arg1 = PG_GETARG_TEXT_P(0);

   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   // size_t s2 = VARSIZE(arg2) - VARHDRSZ;

   char *dat1 = palloc(s1 + 1);
   // char *dat2 = palloc(s2 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   // memcpy(dat2, arg2->vl_dat, s2);
   dat1[s1 - 1] = '\0';
   // dat2[s2] = '\0';

   char *buffer = smheInv(dat1); /* our source data */
   size_t buffSize = strlen(buffer);
   text *destination = (text *)palloc(VARHDRSZ + buffSize + 1);
   SET_VARSIZE(destination, VARHDRSZ + buffSize + 1);
   mymemcpy(destination->vl_dat, buffer, buffSize);

   free(buffer);
   free(dat1);
// 没有解决加法下放缩的问题，只能先设置为1了
destination->vl_dat[buffSize ] = '1';
   PG_RETURN_TEXT_P(destination);
}

PG_FUNCTION_INFO_V1(ore_comp);

Datum ore_comp(PG_FUNCTION_ARGS)
{
   text *arg1 = PG_GETARG_TEXT_P(0);
   text *arg2 = PG_GETARG_TEXT_P(1);
   text *arg3 = PG_GETARG_TEXT_P(2);
   text *arg4 = PG_GETARG_TEXT_P(3);

   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   size_t s2 = VARSIZE(arg2) - VARHDRSZ;
   size_t s3 = VARSIZE(arg3) - VARHDRSZ;
   size_t s4 = VARSIZE(arg4) - VARHDRSZ;

   char *dat1 = palloc0(s1 + 1);
   char *dat2 = palloc0(s2 + 1);
   char *dat3 = palloc0(s3 + 1);
   char *dat4 = palloc0(s4 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   memcpy(dat2, arg2->vl_dat, s2);
   memcpy(dat3, arg3->vl_dat, s3);
   memcpy(dat4, arg4->vl_dat, s4);

   int32 res = oreCompare(dat1, dat2, dat3, dat4, -1); /* our source data */

   PG_RETURN_INT32(res);
}

PG_FUNCTION_INFO_V1(udf_ore_lt);

Datum udf_ore_lt(PG_FUNCTION_ARGS)
{
   void* timer = startTimer();
   text *arg1 = PG_GETARG_TEXT_P(0);
   text *arg2 = PG_GETARG_TEXT_P(1);
   text *arg3 = PG_GETARG_TEXT_P(2);
   text *arg4 = PG_GETARG_TEXT_P(3);

   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   size_t s2 = VARSIZE(arg2) - VARHDRSZ;
   size_t s3 = VARSIZE(arg3) - VARHDRSZ;
   size_t s4 = VARSIZE(arg4) - VARHDRSZ;

   char *dat1 = palloc0(s1 + 1);
   char *dat2 = palloc0(s2 + 1);
   char *dat3 = palloc0(s3 + 1);
   char *dat4 = palloc0(s4 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   memcpy(dat2, arg2->vl_dat, s2);
   memcpy(dat3, arg3->vl_dat, s3);
   memcpy(dat4, arg4->vl_dat, s4);

   int32 res = oreCompare(dat1, dat2, dat3, dat4, 1); /* our source data */

   bool judge = (res == -1) ? true : false;
c_count("interface_c: ore_lt", getPassedTime(timer, true));
   PG_RETURN_BOOL(judge);
}

PG_FUNCTION_INFO_V1(udf_ore_le);

Datum udf_ore_le(PG_FUNCTION_ARGS)
{
   void* timer = startTimer();
   text *arg1 = PG_GETARG_TEXT_P(0);
   text *arg2 = PG_GETARG_TEXT_P(1);
   text *arg3 = PG_GETARG_TEXT_P(2);
   text *arg4 = PG_GETARG_TEXT_P(3);

   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   size_t s2 = VARSIZE(arg2) - VARHDRSZ;
   size_t s3 = VARSIZE(arg3) - VARHDRSZ;
   size_t s4 = VARSIZE(arg4) - VARHDRSZ;

   char *dat1 = palloc0(s1 + 1);
   char *dat2 = palloc0(s2 + 1);
   char *dat3 = palloc0(s3 + 1);
   char *dat4 = palloc0(s4 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   memcpy(dat2, arg2->vl_dat, s2);
   memcpy(dat3, arg3->vl_dat, s3);
   memcpy(dat4, arg4->vl_dat, s4);

   int32 res = oreCompare(dat1, dat2, dat3, dat4, 2); /* our source data */

   bool judge = (res == 1) ? false : true;
c_count("interface_c: ore_le", getPassedTime(timer, true));
   PG_RETURN_BOOL(judge);
}

PG_FUNCTION_INFO_V1(udf_ore_gt);

Datum udf_ore_gt(PG_FUNCTION_ARGS)
{
   void* timer = startTimer();

   text *arg1 = PG_GETARG_TEXT_P(0);
   text *arg2 = PG_GETARG_TEXT_P(1);
   text *arg3 = PG_GETARG_TEXT_P(2);
   text *arg4 = PG_GETARG_TEXT_P(3);

   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   size_t s2 = VARSIZE(arg2) - VARHDRSZ;
   size_t s3 = VARSIZE(arg3) - VARHDRSZ;
   size_t s4 = VARSIZE(arg4) - VARHDRSZ;

   char *dat1 = palloc0(s1 + 1);
   char *dat2 = palloc0(s2 + 1);
   char *dat3 = palloc0(s3 + 1);
   char *dat4 = palloc0(s4 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   memcpy(dat2, arg2->vl_dat, s2);
   memcpy(dat3, arg3->vl_dat, s3);
   memcpy(dat4, arg4->vl_dat, s4);

   int32 res = oreCompare(dat1, dat2, dat3, dat4, 3); /* our source data */

   bool judge = (res == 1) ? true : false;
   c_count("interface_c: ore_gt", getPassedTime(timer, true));
   PG_RETURN_BOOL(judge);
}

PG_FUNCTION_INFO_V1(udf_ore_ge);

Datum udf_ore_ge(PG_FUNCTION_ARGS)
{
   void* timer = startTimer();

   text *arg1 = PG_GETARG_TEXT_P(0);
   text *arg2 = PG_GETARG_TEXT_P(1);
   text *arg3 = PG_GETARG_TEXT_P(2);
   text *arg4 = PG_GETARG_TEXT_P(3);

   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   size_t s2 = VARSIZE(arg2) - VARHDRSZ;
   size_t s3 = VARSIZE(arg3) - VARHDRSZ;
   size_t s4 = VARSIZE(arg4) - VARHDRSZ;

   char *dat1 = palloc0(s1 + 1);
   char *dat2 = palloc0(s2 + 1);
   char *dat3 = palloc0(s3 + 1);
   char *dat4 = palloc0(s4 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   memcpy(dat2, arg2->vl_dat, s2);
   memcpy(dat3, arg3->vl_dat, s3);
   memcpy(dat4, arg4->vl_dat, s4);

   int32 res = oreCompare(dat1, dat2, dat3, dat4, 4); /* our source data */

   bool judge = (res == -1) ? false : true;

   c_count("interface_c: ore_ge", getPassedTime(timer, true));

   PG_RETURN_BOOL(judge);
}

PG_FUNCTION_INFO_V1(udf_ore_ee);

Datum udf_ore_ee(PG_FUNCTION_ARGS)
{
   text *arg1 = PG_GETARG_TEXT_P(0);
   text *arg2 = PG_GETARG_TEXT_P(1);
   text *arg3 = PG_GETARG_TEXT_P(2);
   text *arg4 = PG_GETARG_TEXT_P(3);

   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   size_t s2 = VARSIZE(arg2) - VARHDRSZ;
   size_t s3 = VARSIZE(arg3) - VARHDRSZ;
   size_t s4 = VARSIZE(arg4) - VARHDRSZ;

   char *dat1 = palloc0(s1 + 1);
   char *dat2 = palloc0(s2 + 1);
   char *dat3 = palloc0(s3 + 1);
   char *dat4 = palloc0(s4 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   memcpy(dat2, arg2->vl_dat, s2);
   memcpy(dat3, arg3->vl_dat, s3);
   memcpy(dat4, arg4->vl_dat, s4);

   int32 res = oreCompare(dat1, dat2, dat3, dat4, 5); /* our source data */

   bool judge = (res == 0) ? true : false;

   PG_RETURN_BOOL(judge);
}

//没加ore_en索引之间的udf函数
PG_FUNCTION_INFO_V1(udf_ore_ne);

Datum udf_ore_ne(PG_FUNCTION_ARGS)
{
   text *arg1 = PG_GETARG_TEXT_P(0);
   text *arg2 = PG_GETARG_TEXT_P(1);
   text *arg3 = PG_GETARG_TEXT_P(2);
   text *arg4 = PG_GETARG_TEXT_P(3);

   size_t s1 = VARSIZE(arg1) - VARHDRSZ;
   size_t s2 = VARSIZE(arg2) - VARHDRSZ;
   size_t s3 = VARSIZE(arg3) - VARHDRSZ;
   size_t s4 = VARSIZE(arg4) - VARHDRSZ;

   char *dat1 = palloc0(s1 + 1);
   char *dat2 = palloc0(s2 + 1);
   char *dat3 = palloc0(s3 + 1);
   char *dat4 = palloc0(s4 + 1);
   memcpy(dat1, arg1->vl_dat, s1);
   memcpy(dat2, arg2->vl_dat, s2);
   memcpy(dat3, arg3->vl_dat, s3);
   memcpy(dat4, arg4->vl_dat, s4);

   int32 res = oreCompare(dat1, dat2, dat3, dat4, 5); /* our source data */

   bool judge = (res != 0) ? true : false;

   PG_RETURN_BOOL(judge);
}

// PG_FUNCTION_INFO_V1(ore_max_sfunc);
// Datum ore_max_sfunc(PG_FUNCTION_ARGS) // sfunc
// {
//    text *interval = PG_GETARG_TEXT_P(0);
//    text *interval_ore = NULL;
//    text *interval_aes = NULL;
//    split_to_2_text(interval, &interval_ore, &interval_aes);

//    text *newVal_ore = PG_GETARG_TEXT_P(1);
//    text *newVal_aes = PG_GETARG_TEXT_P(2);

//    size_t s1 = VARSIZE(interval_ore) - VARHDRSZ;
//    size_t s2 = VARSIZE(interval_aes) - VARHDRSZ;
//    size_t s3 = VARSIZE(newVal_ore) - VARHDRSZ;
//    size_t s4 = VARSIZE(newVal_aes) - VARHDRSZ;
//    if (s2 == 0)
//    {
//       interval_ore = (text *)palloc(VARHDRSZ + s3);
//       SET_VARSIZE(interval_ore, VARHDRSZ + s3);

//       interval_aes = (text *)palloc(VARHDRSZ + s4);
//       SET_VARSIZE(interval_aes, VARHDRSZ + s4);

//       memcpy(interval_ore->vl_dat, newVal_ore->vl_dat, s3);
//       memcpy(interval_aes->vl_dat, newVal_aes->vl_dat, s4);

//       interval = concat_text(interval_ore, interval_aes);
//       PG_RETURN_TEXT_P(interval);
//    }

//    char *dat1 = palloc0(s1 + 1);
//    char *dat2 = palloc0(s2 + 1);
//    char *dat3 = palloc0(s3 + 1);
//    char *dat4 = palloc0(s4 + 1);

//    memcpy(dat1, interval_ore->vl_dat, s1);
//    memcpy(dat2, interval_aes->vl_dat, s2);
//    memcpy(dat3, newVal_ore->vl_dat, s3);
//    memcpy(dat4, newVal_aes->vl_dat, s4);

//    assert(s2 == s4 && s1 == s3);
//    int32 res = oreCompare(dat1, dat3, dat2, dat4, 6);
//    if (res == -1)
//    {
//       interval_ore = (text *)palloc(VARHDRSZ + s3);
//       SET_VARSIZE(interval_ore, VARHDRSZ + s3);

//       interval_aes = (text *)palloc(VARHDRSZ + s4);
//       SET_VARSIZE(interval_aes, VARHDRSZ + s4);

//       memcpy(interval_ore->vl_dat, newVal_ore->vl_dat, s3);
//       memcpy(interval_aes->vl_dat, newVal_aes->vl_dat, s4);
//       interval = concat_text(interval_ore, interval_aes);
//    }

//    PG_RETURN_TEXT_P(interval);
// }

// PG_FUNCTION_INFO_V1(ore_max_final);
// Datum ore_max_final(PG_FUNCTION_ARGS)
// {
//    text *data = PG_GETARG_TEXT_P(0);
//    text *interval_ore = NULL;
//    text *interval_aes = NULL;
//    split_to_2_text(data, &interval_ore, &interval_aes);
//    PG_RETURN_TEXT_P(interval_aes);
// }

// PG_FUNCTION_INFO_V1(ore_min_sfunc);

// Datum ore_min_sfunc(PG_FUNCTION_ARGS) // sfunc
// {
//    text *interval = PG_GETARG_TEXT_P(0);
//    text *interval_ore = NULL;
//    text *interval_aes = NULL;
//    split_to_2_text(interval, &interval_ore, &interval_aes);

//    text *newVal_ore = PG_GETARG_TEXT_P(1);
//    text *newVal_aes = PG_GETARG_TEXT_P(2);

//    size_t s1 = VARSIZE(interval_ore) - VARHDRSZ;
//    size_t s2 = VARSIZE(interval_aes) - VARHDRSZ;
//    size_t s3 = VARSIZE(newVal_ore) - VARHDRSZ;
//    size_t s4 = VARSIZE(newVal_aes) - VARHDRSZ;

//    if (s2 == 0)
//    {
//       interval_ore = (text *)palloc(VARHDRSZ + s3);
//       SET_VARSIZE(interval_ore, VARHDRSZ + s3);

//       interval_aes = (text *)palloc(VARHDRSZ + s4);
//       SET_VARSIZE(interval_aes, VARHDRSZ + s4);

//       memcpy(interval_ore->vl_dat, newVal_ore->vl_dat, s3);
//       memcpy(interval_aes->vl_dat, newVal_aes->vl_dat, s4);

//       interval = concat_text(interval_ore, interval_aes);
//       PG_RETURN_TEXT_P(interval);
//    }
//    assert(s2 == s4 && s1 == s3);
//    char *dat1 = palloc0(s1 + 1);
//    char *dat2 = palloc0(s2 + 1);
//    char *dat3 = palloc0(s3 + 1);
//    char *dat4 = palloc0(s4 + 1);

//    memcpy(dat1, interval_ore->vl_dat, s1);
//    memcpy(dat2, interval_aes->vl_dat, s2);
//    memcpy(dat3, newVal_ore->vl_dat, s3);
//    memcpy(dat4, newVal_aes->vl_dat, s4);

//    int32 res = oreCompare(dat1, dat3, dat2, dat4, 7);
//    if (res == 1)
//    {
//       interval_ore = (text *)palloc(VARHDRSZ + s3);
//       SET_VARSIZE(interval_ore, VARHDRSZ + s3);

//       interval_aes = (text *)palloc(VARHDRSZ + s4);
//       SET_VARSIZE(interval_aes, VARHDRSZ + s4);

//       memcpy(interval_ore->vl_dat, newVal_ore->vl_dat, s3);
//       memcpy(interval_aes->vl_dat, newVal_aes->vl_dat, s4);
//       interval = concat_text(interval_ore, interval_aes);
//    }

//    PG_RETURN_TEXT_P(interval);
// }

// PG_FUNCTION_INFO_V1(ore_min_final);
// Datum ore_min_final(PG_FUNCTION_ARGS)
// {
//    text *data = PG_GETARG_TEXT_P(0);
//    text *interval_ore = NULL;
//    text *interval_aes = NULL;
//    split_to_2_text(data, &interval_ore, &interval_aes);
//    PG_RETURN_TEXT_P(interval_aes);
// }

PG_FUNCTION_INFO_V1(sum_sahe_sfunc);

Datum sum_sahe_sfunc(PG_FUNCTION_ARGS)
{
   text *sum = PG_GETARG_TEXT_P(0);
   text *plus_val = PG_GETARG_TEXT_P(1);

   size_t s1 = VARSIZE(sum);
   size_t s2 = VARSIZE(plus_val);

   //printf("C:::::%s\n%s", sum->vl_dat, plus_val->vl_dat);
   // 当检测到null时自动将下一个值传给sum, 省去调用函数
   if (s1 < 10)
   {
      sum = (text *)palloc(VARHDRSZ + s2);
      SET_VARSIZE(sum, VARHDRSZ + s2);
      mymemcpy(sum->vl_dat, plus_val->vl_dat, s2);

      PG_RETURN_TEXT_P(sum);
   }

   char *dat1 = palloc(s1 + 1);
   char *dat2 = palloc(s2 + 1);
   memcpy(dat1, sum->vl_dat, s1);
   memcpy(dat2, plus_val->vl_dat, s2);
   dat1[s1] = '\0';
   dat2[s2] = '\0';

   char *interval_sum = SAHE_add_udf(dat1, dat2, s1 + 1, s2 + 1); //TODO: sum 未采用SGX

   sum = (text *)palloc(VARHDRSZ + s1 + 1);
   SET_VARSIZE(sum, VARHDRSZ + s1);

   // #ifdef ENCALVE
   // #else
   // #endif
   strcpy(sum->vl_dat, interval_sum);

   free(interval_sum);

   PG_RETURN_TEXT_P(sum);
}

Datum		ore_en_in(PG_FUNCTION_ARGS);

Datum		ore_en_out(PG_FUNCTION_ARGS);
Datum		ore_en_recv(PG_FUNCTION_ARGS);
Datum		ore_en_send(PG_FUNCTION_ARGS);
// Datum		ore_en_add(PG_FUNCTION_ARGS);
Datum		ore_en_abs_lt(PG_FUNCTION_ARGS);
Datum		ore_en_abs_le(PG_FUNCTION_ARGS);
Datum		ore_en_abs_eq(PG_FUNCTION_ARGS);
Datum    ore_en_abs_ne(PG_FUNCTION_ARGS);
Datum		ore_en_abs_ge(PG_FUNCTION_ARGS);
Datum		ore_en_abs_gt(PG_FUNCTION_ARGS);
Datum		ore_en_abs_cmp(PG_FUNCTION_ARGS);


ore_en *
cstring_to_ore_text_with_len(const char *s, int len)
{
	ore_en	   *result = (ore_en *) palloc(len + VARHDRSZ);

	SET_VARSIZE(result, len + VARHDRSZ);
	memcpy(VARDATA(result), s, len);

	return result;
}

ore_en *
cstring_to_ore_text(const char *s)
{
	return cstring_to_ore_text_with_len(s, strlen(s));
}

PG_FUNCTION_INFO_V1(ore_en_in);
Datum
ore_en_in(PG_FUNCTION_ARGS)
{
	char	   *inputText = PG_GETARG_CSTRING(0);

	PG_RETURN_TEXT_P(cstring_to_ore_text(inputText));
}



char *
ore_text_to_cstring(const ore_en *t)
{
	/* must cast away the const, unfortunately */
	ore_en	   *tunpacked = pg_detoast_datum_packed((struct varlena *) t);
	int			len = VARSIZE_ANY_EXHDR(tunpacked);
	char	   *result;

	result = (char *) palloc(len + 1);
	memcpy(result, VARDATA_ANY(tunpacked), len);
	result[len] = '\0';

	if (tunpacked != t)
		pfree(tunpacked);

	return result;
}

PG_FUNCTION_INFO_V1(ore_en_out);
Datum
ore_en_out(PG_FUNCTION_ARGS)
{
	Datum		txt = PG_GETARG_DATUM(0);

	PG_RETURN_CSTRING(TextDatumGetCString(txt));
}

// Datum
// ore_en_recv(PG_FUNCTION_ARGS)
// {
// 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
// 	ore_en	   *result;
// 	char	   *str;
// 	int			nbytes;

// 	str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);

// 	result = cstring_to_ore_text_with_len(str, nbytes);
// 	pfree(str);
// 	PG_RETURN_TEXT_P(result);
// }




// PG_FUNCTION_INFO_V1(ore_en_send);
// /*
//  *		textsend			- converts text to binary format
//  */
// Datum
// ore_en_send(PG_FUNCTION_ARGS)
// {
// 	ore_en	   *t = PG_GETARG_TEXT_PP(0);
// 	StringInfoData buf;

// 	pq_begintypsend(&buf);
// 	pq_sendtext(&buf, VARDATA_ANY(t), VARSIZE_ANY_EXHDR(t));
// 	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
// }


static int
ore_en_abs_cmp_internal(ore_en * a, ore_en * b)
{  
   size_t s1 = VARSIZE(a) - VARHDRSZ;
   size_t s2 = VARSIZE(b) - VARHDRSZ;
   char *dat1 = palloc(s1 + 1);
   char *dat2 = palloc(s2 + 1);
   memcpy(dat1, a->vl_dat, s1);
   memcpy(dat2, b->vl_dat, s2);

   int32 res = -3;
   res = ore_compare(dat1, dat2);
	// int32 res = ore_com(dat1, dat2);

	return res;
}
PG_FUNCTION_INFO_V1(ore_en_abs_lt);

Datum
ore_en_abs_lt(PG_FUNCTION_ARGS)
{  
	ore_en    *a = (ore_en *) PG_GETARG_TEXT_P(0);
	ore_en    *b = (ore_en *) PG_GETARG_TEXT_P(1);
	PG_RETURN_BOOL(ore_en_abs_cmp_internal(a, b) < 0);
}

PG_FUNCTION_INFO_V1(ore_en_abs_le);

Datum
ore_en_abs_le(PG_FUNCTION_ARGS)
{
	ore_en    *a = (ore_en *) PG_GETARG_TEXT_P(0);
	ore_en    *b = (ore_en *) PG_GETARG_TEXT_P(1);

	PG_RETURN_BOOL(ore_en_abs_cmp_internal(a, b) <= 0);
}

PG_FUNCTION_INFO_V1(ore_en_abs_eq);

Datum
ore_en_abs_eq(PG_FUNCTION_ARGS)
{
	ore_en    *a = (ore_en *) PG_GETARG_TEXT_P(0);
	ore_en    *b = (ore_en *) PG_GETARG_TEXT_P(1);

	PG_RETURN_BOOL(ore_en_abs_cmp_internal(a, b) == 0);
}

PG_FUNCTION_INFO_V1(ore_en_abs_ne);

Datum
ore_en_abs_ne(PG_FUNCTION_ARGS)
{
	ore_en    *a = (ore_en *) PG_GETARG_TEXT_P(0);
	ore_en    *b = (ore_en *) PG_GETARG_TEXT_P(1);

	PG_RETURN_BOOL(ore_en_abs_cmp_internal(a, b) != 0);
}

PG_FUNCTION_INFO_V1(ore_en_abs_ge);

Datum
ore_en_abs_ge(PG_FUNCTION_ARGS)
{
	ore_en    *a = (ore_en *) PG_GETARG_TEXT_P(0);
	ore_en    *b = (ore_en *) PG_GETARG_TEXT_P(1);

	PG_RETURN_BOOL(ore_en_abs_cmp_internal(a, b) >= 0);
}

PG_FUNCTION_INFO_V1(ore_en_abs_gt);

Datum
ore_en_abs_gt(PG_FUNCTION_ARGS)
{
	ore_en    *a = (ore_en *) PG_GETARG_TEXT_P(0);
	ore_en    *b = (ore_en *) PG_GETARG_TEXT_P(1);

	PG_RETURN_BOOL(ore_en_abs_cmp_internal(a, b) > 0);
}

PG_FUNCTION_INFO_V1(ore_en_abs_cmp);

Datum
ore_en_abs_cmp(PG_FUNCTION_ARGS)
{
	ore_en    *a = (ore_en *) PG_GETARG_TEXT_P(0);
	ore_en    *b = (ore_en *) PG_GETARG_TEXT_P(1);

	PG_RETURN_INT32(ore_en_abs_cmp_internal(a, b));
}
PG_FUNCTION_INFO_V1(ore_en_max_sfunc);
Datum ore_en_max_sfunc(PG_FUNCTION_ARGS) // sfunc
{
   ore_en *interval = PG_GETARG_TEXT_P(0);
   ore_en *interval_ore = NULL;
   text *interval_aes = NULL;
   split_to_2_text1(interval, &interval_ore, &interval_aes);

   ore_en *newVal_ore = PG_GETARG_TEXT_P(1);
   ore_en *newVal_aes = PG_GETARG_TEXT_P(2);

   size_t s1 = VARSIZE(interval_ore) - VARHDRSZ;
   size_t s2 = VARSIZE(interval_aes) - VARHDRSZ;
   size_t s3 = VARSIZE(newVal_ore) - VARHDRSZ;
   size_t s4 = VARSIZE(newVal_aes) - VARHDRSZ;
   if (s2 == 0)
   {
      interval_ore = (ore_en *)palloc(VARHDRSZ + s3);
      SET_VARSIZE(interval_ore, VARHDRSZ + s3);

      interval_aes = (text *)palloc(VARHDRSZ + s4);
      SET_VARSIZE(interval_aes, VARHDRSZ + s4);

      memcpy(interval_ore->vl_dat, newVal_ore->vl_dat, s3);
      memcpy(interval_aes->vl_dat, newVal_aes->vl_dat, s4);

      interval = concat_text1(interval_ore, interval_aes);
      PG_RETURN_ORE_EN_P(interval);
   }

   char *dat1 = palloc(s1 + 1);
   char *dat2 = palloc(s2 + 1);
   char *dat3 = palloc(s3 + 1);
   char *dat4 = palloc(s4 + 1);

   memcpy(dat1, interval_ore->vl_dat, s1);
   memcpy(dat2, interval_aes->vl_dat, s2);
   memcpy(dat3, newVal_ore->vl_dat, s3);
   memcpy(dat4, newVal_aes->vl_dat, s4);
   dat1[s1] = '\0';
   dat2[s2] = '\0';
   dat3[s3] = '\0';
   dat4[s4] = '\0';
   assert(s2 == s4 && s1 == s3);   
   int32 res = oreCompare(dat1, dat3, dat2, dat4,6);
   if (res == -1)
   {
      interval_ore = (ore_en *)palloc(VARHDRSZ + s3);
      SET_VARSIZE(interval_ore, VARHDRSZ + s3);

      interval_aes = (text *)palloc(VARHDRSZ + s4);
      SET_VARSIZE(interval_aes, VARHDRSZ + s4);

      memcpy(interval_ore->vl_dat, newVal_ore->vl_dat, s3);
      memcpy(interval_aes->vl_dat, newVal_aes->vl_dat, s4);
      interval = concat_text1(interval_ore, interval_aes);
   }


   PG_RETURN_ORE_EN_P(interval);
}

PG_FUNCTION_INFO_V1(ore_en_max_final);
Datum ore_en_max_final(PG_FUNCTION_ARGS)
{
   ore_en *data = PG_GETARG_TEXT_P(0);
   ore_en *interval_ore = NULL;
   text *interval_aes = NULL;
   split_to_2_text1(data, &interval_ore, &interval_aes);
   PG_RETURN_TEXT_P(interval_aes);
}

PG_FUNCTION_INFO_V1(ore_en_min_sfunc);

Datum ore_en_min_sfunc(PG_FUNCTION_ARGS) // sfunc
{
   ore_en *interval = PG_GETARG_TEXT_P(0);
   ore_en *interval_ore = NULL;
   text *interval_aes = NULL;
   split_to_2_text1(interval, &interval_ore, &interval_aes);

   ore_en *newVal_ore = PG_GETARG_TEXT_P(1);
   ore_en *newVal_aes = PG_GETARG_TEXT_P(2);

   size_t s1 = VARSIZE(interval_ore) - VARHDRSZ;
   size_t s2 = VARSIZE(interval_aes) - VARHDRSZ;
   size_t s3 = VARSIZE(newVal_ore) - VARHDRSZ;
   size_t s4 = VARSIZE(newVal_aes) - VARHDRSZ;

   if (s2 == 0)
   {
      interval_ore = (ore_en *)palloc(VARHDRSZ + s3);
      SET_VARSIZE(interval_ore, VARHDRSZ + s3);

      interval_aes = (text *)palloc(VARHDRSZ + s4);
      SET_VARSIZE(interval_aes, VARHDRSZ + s4);

      memcpy(interval_ore->vl_dat, newVal_ore->vl_dat, s3);
      memcpy(interval_aes->vl_dat, newVal_aes->vl_dat, s4);

      interval = concat_text1(interval_ore, interval_aes);
      PG_RETURN_ORE_EN_P(interval);
      
   }
   assert(s2 == s4 && s1 == s3);
   char *dat1 = palloc(s1 + 1);
   char *dat2 = palloc(s2 + 1);
   char *dat3 = palloc(s3 + 1);
   char *dat4 = palloc(s4 + 1);

   memcpy(dat1, interval_ore->vl_dat, s1);
   memcpy(dat2, interval_aes->vl_dat, s2);
   memcpy(dat3, newVal_ore->vl_dat, s3);
   memcpy(dat4, newVal_aes->vl_dat, s4);
   dat1[s1] = '\0';
   dat2[s2] = '\0';
   dat3[s3] = '\0';
   dat4[s4] = '\0';

   int32 res = oreCompare(dat1, dat3, dat2, dat4,7);
   if (res == 1)
   {
      interval_ore = (ore_en *)palloc(VARHDRSZ + s3);
      SET_VARSIZE(interval_ore, VARHDRSZ + s3);

      interval_aes = (text *)palloc(VARHDRSZ + s4);
      SET_VARSIZE(interval_aes, VARHDRSZ + s4);

      memcpy(interval_ore->vl_dat, newVal_ore->vl_dat, s3);
      memcpy(interval_aes->vl_dat, newVal_aes->vl_dat, s4);
      interval = concat_text1(interval_ore, interval_aes);
   }

   
   PG_RETURN_ORE_EN_P(interval);
}

PG_FUNCTION_INFO_V1(ore_en_min_final);
Datum ore_en_min_final(PG_FUNCTION_ARGS)
{
   ore_en *data = PG_GETARG_TEXT_P(0);
   ore_en *interval_ore = NULL;
   text *interval_aes = NULL;
   split_to_2_text1(data, &interval_ore, &interval_aes);
   PG_RETURN_TEXT_P(interval_aes);
}
PG_FUNCTION_INFO_V1(ore_en_smaller);

Datum
ore_en_smaller(PG_FUNCTION_ARGS)
{
	ore_en	*left = PG_GETARG_TEXT_PP(0);
	ore_en	   *right = PG_GETARG_TEXT_PP(1);
	ore_en	   *result;

   int ret = -3;
   ret = ore_compare(left, right);
   result = ret < 0 ? left : right;
	// result = ore_com(left, right) < 0 ? left : right;
	PG_RETURN_ORE_EN_P(result);
}

PG_FUNCTION_INFO_V1(ore_en_larger);

Datum
ore_en_larger(PG_FUNCTION_ARGS)
{
	ore_en	*left = PG_GETARG_TEXT_PP(0);
	ore_en	   *right = PG_GETARG_TEXT_PP(1);
	ore_en	   *result;

   int ret = -3;
   ret = ore_compare(left, right);
   result = ret > 0 ? left : right;
	// result = ore_com(left, right) > 0 ? left : right;
	PG_RETURN_ORE_EN_P(result);
}


PG_FUNCTION_INFO_V1(ore_max_sfunc);
Datum ore_max_sfunc(PG_FUNCTION_ARGS) // sfunc
{
   ore_en *interval = PG_GETARG_TEXT_P(0);
   ore_en *interval_ore = NULL;
   text *interval_aes = NULL;
   split_to_2_text1(interval, &interval_ore, &interval_aes);

   ore_en *newVal_ore = PG_GETARG_TEXT_P(1);
   ore_en *newVal_aes = PG_GETARG_TEXT_P(2);

   size_t s1 = VARSIZE(interval_ore) - VARHDRSZ;
   size_t s2 = VARSIZE(interval_aes) - VARHDRSZ;
   size_t s3 = VARSIZE(newVal_ore) - VARHDRSZ;
   size_t s4 = VARSIZE(newVal_aes) - VARHDRSZ;
   if (s2 == 0)
   {
      interval_ore = (ore_en *)palloc(VARHDRSZ + s3);
      SET_VARSIZE(interval_ore, VARHDRSZ + s3);

      interval_aes = (text *)palloc(VARHDRSZ + s4);
      SET_VARSIZE(interval_aes, VARHDRSZ + s4);

      memcpy(interval_ore->vl_dat, newVal_ore->vl_dat, s3);
      memcpy(interval_aes->vl_dat, newVal_aes->vl_dat, s4);

      interval = concat_text1(interval_ore, interval_aes);
      PG_RETURN_ORE_EN_P(interval);
   }

   char *dat1 = palloc(s1 + 1);
   char *dat2 = palloc(s2 + 1);
   char *dat3 = palloc(s3 + 1);
   char *dat4 = palloc(s4 + 1);

   memcpy(dat1, interval_ore->vl_dat, s1);
   memcpy(dat2, interval_aes->vl_dat, s2);
   memcpy(dat3, newVal_ore->vl_dat, s3);
   memcpy(dat4, newVal_aes->vl_dat, s4);
   dat1[s1] = '\0';
   dat2[s2] = '\0';
   dat3[s3] = '\0';
   dat4[s4] = '\0';
   assert(s2 == s4 && s1 == s3);
   int32 res = oreCompare(dat1, dat3, dat2, dat4,6);
   if (res == -1)
   {
      interval_ore = (ore_en *)palloc(VARHDRSZ + s3);
      SET_VARSIZE(interval_ore, VARHDRSZ + s3);

      interval_aes = (text *)palloc(VARHDRSZ + s4);
      SET_VARSIZE(interval_aes, VARHDRSZ + s4);

      memcpy(interval_ore->vl_dat, newVal_ore->vl_dat, s3);
      memcpy(interval_aes->vl_dat, newVal_aes->vl_dat, s4);
      interval = concat_text1(interval_ore, interval_aes);
   }


   PG_RETURN_ORE_EN_P(interval);
}

PG_FUNCTION_INFO_V1(ore_max_final);
Datum ore_max_final(PG_FUNCTION_ARGS)
{
   ore_en *data = PG_GETARG_TEXT_P(0);
   ore_en *interval_ore = NULL;
   text *interval_aes = NULL;
   split_to_2_text1(data, &interval_ore, &interval_aes);
   PG_RETURN_TEXT_P(interval_aes);
}

PG_FUNCTION_INFO_V1(ore_min_sfunc);

Datum ore_min_sfunc(PG_FUNCTION_ARGS) // sfunc
{
   ore_en *interval = PG_GETARG_TEXT_P(0);
   ore_en *interval_ore = NULL;
   text *interval_aes = NULL;
   split_to_2_text1(interval, &interval_ore, &interval_aes);

   ore_en *newVal_ore = PG_GETARG_TEXT_P(1);
   ore_en *newVal_aes = PG_GETARG_TEXT_P(2);

   size_t s1 = VARSIZE(interval_ore) - VARHDRSZ;
   size_t s2 = VARSIZE(interval_aes) - VARHDRSZ;
   size_t s3 = VARSIZE(newVal_ore) - VARHDRSZ;
   size_t s4 = VARSIZE(newVal_aes) - VARHDRSZ;

   if (s2 == 0)
   {
      interval_ore = (ore_en *)palloc(VARHDRSZ + s3);
      SET_VARSIZE(interval_ore, VARHDRSZ + s3);

      interval_aes = (text *)palloc(VARHDRSZ + s4);
      SET_VARSIZE(interval_aes, VARHDRSZ + s4);

      memcpy(interval_ore->vl_dat, newVal_ore->vl_dat, s3);
      memcpy(interval_aes->vl_dat, newVal_aes->vl_dat, s4);

      interval = concat_text1(interval_ore, interval_aes);
      PG_RETURN_ORE_EN_P(interval);
      
   }
   assert(s2 == s4 && s1 == s3);
   char *dat1 = palloc(s1 + 1);
   char *dat2 = palloc(s2 + 1);
   char *dat3 = palloc(s3 + 1);
   char *dat4 = palloc(s4 + 1);

   memcpy(dat1, interval_ore->vl_dat, s1);
   memcpy(dat2, interval_aes->vl_dat, s2);
   memcpy(dat3, newVal_ore->vl_dat, s3);
   memcpy(dat4, newVal_aes->vl_dat, s4);
   dat1[s1] = '\0';
   dat2[s2] = '\0';
   dat3[s3] = '\0';
   dat4[s4] = '\0';

   int32 res = oreCompare(dat1, dat3, dat2, dat4,7);
   if (res == 1)
   {
      interval_ore = (ore_en *)palloc(VARHDRSZ + s3);
      SET_VARSIZE(interval_ore, VARHDRSZ + s3);

      interval_aes = (text *)palloc(VARHDRSZ + s4);
      SET_VARSIZE(interval_aes, VARHDRSZ + s4);

      memcpy(interval_ore->vl_dat, newVal_ore->vl_dat, s3);
      memcpy(interval_aes->vl_dat, newVal_aes->vl_dat, s4);
      interval = concat_text1(interval_ore, interval_aes);
   }

   
   PG_RETURN_ORE_EN_P(interval);
}

PG_FUNCTION_INFO_V1(ore_min_final);
Datum ore_min_final(PG_FUNCTION_ARGS)
{
   ore_en *data = PG_GETARG_TEXT_P(0);
   ore_en *interval_ore = NULL;
   text *interval_aes = NULL;
   split_to_2_text1(data, &interval_ore, &interval_aes);
   PG_RETURN_TEXT_P(interval_aes);
}
