UnQL

Check-in [34eea27b86]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Change to using xjd1_malloc() etc. internally instead of using malloc() directly.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 34eea27b8608a292ca8544a49e223033d5f29cc3
User & Date: dan 2011-07-25 11:59:45
Context
2011-07-25
13:51
Add SQLITE_NO_SYNC to the SQLite backing store compilation. This makes tests run much faster, at the expense of crash survivability. We do not really care about surviving crashes in this prototype - at least not yet. check-in: 6ec01596ed user: drh tags: trunk
11:59
Change to using xjd1_malloc() etc. internally instead of using malloc() directly. check-in: 34eea27b86 user: dan tags: trunk
09:46
Add support for scalar sub-queries. check-in: 9648d8798c user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/conn.c.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
** Open a new database connection
*/
int xjd1_open(xjd1_context *pContext, const char *zURI, xjd1 **ppNewConn){
  xjd1 *pConn;
  int rc;

  *ppNewConn = pConn = malloc( sizeof(*pConn) );
  if( pConn==0 ) return XJD1_NOMEM;
  memset(pConn, 0, sizeof(*pConn));
  pConn->pContext = pContext;
  rc = sqlite3_open_v2(zURI, &pConn->db, 
            SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI, 0);
  if( rc ){
    xjd1Error(pConn, XJD1_ERROR, "%s", sqlite3_errmsg(pConn->db));
................................................................................
int xjd1_close(xjd1 *pConn){
  if( pConn==0 ) return XJD1_OK;
  pConn->isDying = 1;
  if( pConn->nRef>0 ) return XJD1_OK;
  xjd1ContextUnref(pConn->pContext);
  sqlite3_close(pConn->db);
  xjd1StringClear(&pConn->errMsg);
  free(pConn);
  return XJD1_OK;
}

/*
** Report the most recent error.
*/
int xjd1_errcode(xjd1 *pConn){







|







 







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
** Open a new database connection
*/
int xjd1_open(xjd1_context *pContext, const char *zURI, xjd1 **ppNewConn){
  xjd1 *pConn;
  int rc;

  *ppNewConn = pConn = xjd1_malloc( sizeof(*pConn) );
  if( pConn==0 ) return XJD1_NOMEM;
  memset(pConn, 0, sizeof(*pConn));
  pConn->pContext = pContext;
  rc = sqlite3_open_v2(zURI, &pConn->db, 
            SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI, 0);
  if( rc ){
    xjd1Error(pConn, XJD1_ERROR, "%s", sqlite3_errmsg(pConn->db));
................................................................................
int xjd1_close(xjd1 *pConn){
  if( pConn==0 ) return XJD1_OK;
  pConn->isDying = 1;
  if( pConn->nRef>0 ) return XJD1_OK;
  xjd1ContextUnref(pConn->pContext);
  sqlite3_close(pConn->db);
  xjd1StringClear(&pConn->errMsg);
  xjd1_free(pConn);
  return XJD1_OK;
}

/*
** Report the most recent error.
*/
int xjd1_errcode(xjd1 *pConn){

Changes to src/context.c.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
..
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
*/
#include "xjd1Int.h"


int xjd1_context_new(xjd1_context **ppNew){
  xjd1_context *p;

  *ppNew = p = malloc( sizeof(*p) );
  if( p ){
    memset(p, 0, sizeof(*p));
    return XJD1_OK;
  }else{
    return XJD1_NOMEM;
  }
}
................................................................................
int xjd1_context_config(xjd1_context *p, int op, ...){
  return XJD1_UNKNOWN;
}
int xjd1_context_delete(xjd1_context *p){
  if( p==0 ) return XJD1_OK;
  p->isDying = 1;
  if( p->nRef>0 ) return XJD1_OK;
  free(p);
  return XJD1_OK;
}

PRIVATE void xjd1ContextUnref(xjd1_context *p){
  if( p==0 ) return;
  p->nRef--;
  if( p->nRef<=0 && p->isDying ) xjd1_context_delete(p);
}







|







 







|








18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
..
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
*/
#include "xjd1Int.h"


int xjd1_context_new(xjd1_context **ppNew){
  xjd1_context *p;

  *ppNew = p = xjd1_malloc( sizeof(*p) );
  if( p ){
    memset(p, 0, sizeof(*p));
    return XJD1_OK;
  }else{
    return XJD1_NOMEM;
  }
}
................................................................................
int xjd1_context_config(xjd1_context *p, int op, ...){
  return XJD1_UNKNOWN;
}
int xjd1_context_delete(xjd1_context *p){
  if( p==0 ) return XJD1_OK;
  p->isDying = 1;
  if( p->nRef>0 ) return XJD1_OK;
  xjd1_free(p);
  return XJD1_OK;
}

PRIVATE void xjd1ContextUnref(xjd1_context *p){
  if( p==0 ) return;
  p->nRef--;
  if( p->nRef<=0 && p->isDying ) xjd1_context_delete(p);
}

Changes to src/expr.c.

601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
      int i;
      JsonStructElem *pElem, **ppPrev;
      ExprList *pList = p->u.st;
      ppPrev = &pRes->u.st.pFirst;
      pRes->eJType = XJD1_STRUCT;
      for(i=0; i<pList->nEItem; i++){
        ExprItem *pItem = &pList->apEItem[i];
        pElem = malloc( sizeof(*pElem) );
        if( pElem==0 ) break;
        *ppPrev = pRes->u.st.pLast = pElem;
        ppPrev = &pElem->pNext;
        memset(pElem, 0, sizeof(*pElem));
        pElem->zLabel = xjd1PoolDup(0, pItem->zAs, -1);
        pElem->pValue = xjd1ExprEval(pItem->pExpr);
      }
      break;
    }
    case TK_ARRAY: {
      int i;
      ExprList *pList = p->u.st;
      pRes->u.ar.apElem = malloc( pList->nEItem*sizeof(JsonNode*) );
      if( pRes->u.ar.apElem ){
        pRes->u.ar.nElem = pList->nEItem;
        pRes->eJType = XJD1_ARRAY;
        for(i=0; i<pList->nEItem; i++){
          ExprItem *pItem = &pList->apEItem[i];
          pRes->u.ar.apElem[i] = xjd1ExprEval(pItem->pExpr);
        }







|












|







601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
      int i;
      JsonStructElem *pElem, **ppPrev;
      ExprList *pList = p->u.st;
      ppPrev = &pRes->u.st.pFirst;
      pRes->eJType = XJD1_STRUCT;
      for(i=0; i<pList->nEItem; i++){
        ExprItem *pItem = &pList->apEItem[i];
        pElem = xjd1_malloc( sizeof(*pElem) );
        if( pElem==0 ) break;
        *ppPrev = pRes->u.st.pLast = pElem;
        ppPrev = &pElem->pNext;
        memset(pElem, 0, sizeof(*pElem));
        pElem->zLabel = xjd1PoolDup(0, pItem->zAs, -1);
        pElem->pValue = xjd1ExprEval(pItem->pExpr);
      }
      break;
    }
    case TK_ARRAY: {
      int i;
      ExprList *pList = p->u.st;
      pRes->u.ar.apElem = xjd1_malloc( pList->nEItem*sizeof(JsonNode*) );
      if( pRes->u.ar.apElem ){
        pRes->u.ar.nElem = pList->nEItem;
        pRes->eJType = XJD1_ARRAY;
        for(i=0; i<pList->nEItem; i++){
          ExprItem *pItem = &pList->apEItem[i];
          pRes->u.ar.apElem[i] = xjd1ExprEval(pItem->pExpr);
        }

Changes to src/json.c.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
...
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
...
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
...
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
...
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
/*
** Change a JsonNode to be a NULL.  Any substructure is deleted.
*/
void xjd1JsonToNull(JsonNode *p){
  if( p==0 ) return;
  switch( p->eJType ){
    case XJD1_STRING: {
      free(p->u.z);
      break;
    }
    case XJD1_ARRAY: {
      int i;
      for(i=0; i<p->u.ar.nElem; i++){
        xjd1JsonFree(p->u.ar.apElem[i]);
      }
      free(p->u.ar.apElem);
      break;
    }
    case XJD1_STRUCT: {
      JsonStructElem *pElem, *pNext;
      for(pElem=p->u.st.pFirst; pElem; pElem=pNext){
        pNext = pElem->pNext;
        free(pElem->zLabel);
        xjd1JsonFree(pElem->pValue);
        free(pElem);
      }
      break;
    }
  }
  p->eJType = XJD1_NULL;
}

/*
** Reclaim memory used by JsonNode objects 
*/
void xjd1JsonFree(JsonNode *p){
  if( p && (--p->nRef)<=0 ){
    xjd1JsonToNull(p);
    free(p);
  }
}

/*
** Allocate a new Json node.
*/
JsonNode *xjd1JsonNew(Pool *pPool){
  JsonNode *p;
  if( pPool ){
    p = xjd1PoolMalloc(pPool, sizeof(*p));
    if( p ) p->nRef = 10000;
  }else{
    p = malloc( sizeof(*p) );
    if( p ){
      memset(p, 0, sizeof(*p));
      p->nRef = 1;
    }
  }
  return p;
}
................................................................................
  switch( pNew->eJType ){
    case XJD1_STRING: {
      pNew->u.z = xjd1PoolDup(0, p->u.z, -1);
      break;
    }
    case XJD1_ARRAY: {
      JsonNode **ap;
      pNew->u.ar.apElem = ap = malloc( sizeof(JsonNode*)*p->u.ar.nElem );
      if( ap==0 ){
        pNew->eJType = XJD1_NULL;
      }else{
        int i;
        pNew->u.ar.nElem = p->u.ar.nElem;
        for(i=0; i<p->u.ar.nElem; i++){
          ap[i] = xjd1JsonRef(p->u.ar.apElem[i]);
................................................................................
      }
      break;
    }
    case XJD1_STRUCT: {
      JsonStructElem *pSrc, *pDest, **ppPrev;
      ppPrev = &pNew->u.st.pFirst;
      for(pSrc=p->u.st.pFirst; pSrc; pSrc=pSrc->pNext){
        pNew->u.st.pLast = pDest = malloc( sizeof(*pDest) );
        if( pDest==0 ) break;
        memset(pDest, 0, sizeof(*pDest));
        *ppPrev = pDest;
        ppPrev = &pDest->pNext;
        pDest->zLabel = xjd1PoolDup(0, pSrc->zLabel, -1);
        pDest->pValue = xjd1JsonRef(pSrc->pValue);
      }
................................................................................
    }
  }
  z[j] = 0;
}

/* Convert the current token (which must be a string) into a true
** string (resolving all of the backslash escapes) and return a pointer
** to the true string.  Space is obtained form malloc().
*/
static char *tokenDequoteString(JsonStr *pIn){
  const char *zIn;
  char *zOut;
  int n;
  zIn = &pIn->zIn[pIn->iCur];
  zOut = malloc( pIn->n );
  if( zOut==0 ) return 0;
  assert( zIn[0]=='"' && zIn[pIn->n-1]=='"' );
  n = pIn->n-1;
  memcpy(zOut, zIn, pIn->n);
  xjd1DequoteString(zOut, pIn->n);
  return zOut;
}
................................................................................
      if( tokenType(pIn)==JSON_END_STRUCT ) break;
      ppTail = &pNew->u.st.pFirst;
      while( 1 ){
        JsonStructElem *pElem;
        if( tokenType(pIn)!=JSON_STRING ){
          goto json_error; 
        }
        pElem = malloc( sizeof(*pElem) );
        if( pElem==0 ) goto json_error;
        memset(pElem, 0, sizeof(*pElem));
        *ppTail = pElem;
        pNew->u.st.pLast = pElem;
        ppTail = &pElem->pNext;
        pElem->zLabel = tokenDequoteString(pIn);
        tokenNext(pIn);
................................................................................
      int nAlloc = 0;
      tokenNext(pIn);
      if( tokenType(pIn)==JSON_END_ARRAY ) break;
      while( 1 ){
        if( pNew->u.ar.nElem>=nAlloc ){
          JsonNode **pNewArray;
          nAlloc = nAlloc*2 + 5;
          pNewArray = realloc(pNew->u.ar.apElem,
                              sizeof(JsonNode*)*nAlloc);
          if( pNewArray==0 ) goto json_error;
          pNew->u.ar.apElem = pNewArray;
        }
        pNew->u.ar.apElem[pNew->u.ar.nElem++] = parseJson(pIn);
        if( tokenType(pIn)==JSON_COMMA ){
          tokenNext(pIn);
................................................................................
    case JSON_TRUE:
    case JSON_FALSE:
    case JSON_NULL: {
      tokenNext(pIn);
      break;
    }
    default: {
      free(pNew);
      pNew = 0;
      break;
    }
  }
  return pNew;

json_error:







|







|






|

|













|












|







 







|







 







|







 







|






|







 







|







 







|







 







|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
...
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
...
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
...
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
...
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
/*
** Change a JsonNode to be a NULL.  Any substructure is deleted.
*/
void xjd1JsonToNull(JsonNode *p){
  if( p==0 ) return;
  switch( p->eJType ){
    case XJD1_STRING: {
      xjd1_free(p->u.z);
      break;
    }
    case XJD1_ARRAY: {
      int i;
      for(i=0; i<p->u.ar.nElem; i++){
        xjd1JsonFree(p->u.ar.apElem[i]);
      }
      xjd1_free(p->u.ar.apElem);
      break;
    }
    case XJD1_STRUCT: {
      JsonStructElem *pElem, *pNext;
      for(pElem=p->u.st.pFirst; pElem; pElem=pNext){
        pNext = pElem->pNext;
        xjd1_free(pElem->zLabel);
        xjd1JsonFree(pElem->pValue);
        xjd1_free(pElem);
      }
      break;
    }
  }
  p->eJType = XJD1_NULL;
}

/*
** Reclaim memory used by JsonNode objects 
*/
void xjd1JsonFree(JsonNode *p){
  if( p && (--p->nRef)<=0 ){
    xjd1JsonToNull(p);
    xjd1_free(p);
  }
}

/*
** Allocate a new Json node.
*/
JsonNode *xjd1JsonNew(Pool *pPool){
  JsonNode *p;
  if( pPool ){
    p = xjd1PoolMalloc(pPool, sizeof(*p));
    if( p ) p->nRef = 10000;
  }else{
    p = xjd1_malloc( sizeof(*p) );
    if( p ){
      memset(p, 0, sizeof(*p));
      p->nRef = 1;
    }
  }
  return p;
}
................................................................................
  switch( pNew->eJType ){
    case XJD1_STRING: {
      pNew->u.z = xjd1PoolDup(0, p->u.z, -1);
      break;
    }
    case XJD1_ARRAY: {
      JsonNode **ap;
      pNew->u.ar.apElem = ap = xjd1_malloc( sizeof(JsonNode*)*p->u.ar.nElem );
      if( ap==0 ){
        pNew->eJType = XJD1_NULL;
      }else{
        int i;
        pNew->u.ar.nElem = p->u.ar.nElem;
        for(i=0; i<p->u.ar.nElem; i++){
          ap[i] = xjd1JsonRef(p->u.ar.apElem[i]);
................................................................................
      }
      break;
    }
    case XJD1_STRUCT: {
      JsonStructElem *pSrc, *pDest, **ppPrev;
      ppPrev = &pNew->u.st.pFirst;
      for(pSrc=p->u.st.pFirst; pSrc; pSrc=pSrc->pNext){
        pNew->u.st.pLast = pDest = xjd1_malloc( sizeof(*pDest) );
        if( pDest==0 ) break;
        memset(pDest, 0, sizeof(*pDest));
        *ppPrev = pDest;
        ppPrev = &pDest->pNext;
        pDest->zLabel = xjd1PoolDup(0, pSrc->zLabel, -1);
        pDest->pValue = xjd1JsonRef(pSrc->pValue);
      }
................................................................................
    }
  }
  z[j] = 0;
}

/* Convert the current token (which must be a string) into a true
** string (resolving all of the backslash escapes) and return a pointer
** to the true string.  Space is obtained from xjd1_malloc().
*/
static char *tokenDequoteString(JsonStr *pIn){
  const char *zIn;
  char *zOut;
  int n;
  zIn = &pIn->zIn[pIn->iCur];
  zOut = xjd1_malloc( pIn->n );
  if( zOut==0 ) return 0;
  assert( zIn[0]=='"' && zIn[pIn->n-1]=='"' );
  n = pIn->n-1;
  memcpy(zOut, zIn, pIn->n);
  xjd1DequoteString(zOut, pIn->n);
  return zOut;
}
................................................................................
      if( tokenType(pIn)==JSON_END_STRUCT ) break;
      ppTail = &pNew->u.st.pFirst;
      while( 1 ){
        JsonStructElem *pElem;
        if( tokenType(pIn)!=JSON_STRING ){
          goto json_error; 
        }
        pElem = xjd1_malloc( sizeof(*pElem) );
        if( pElem==0 ) goto json_error;
        memset(pElem, 0, sizeof(*pElem));
        *ppTail = pElem;
        pNew->u.st.pLast = pElem;
        ppTail = &pElem->pNext;
        pElem->zLabel = tokenDequoteString(pIn);
        tokenNext(pIn);
................................................................................
      int nAlloc = 0;
      tokenNext(pIn);
      if( tokenType(pIn)==JSON_END_ARRAY ) break;
      while( 1 ){
        if( pNew->u.ar.nElem>=nAlloc ){
          JsonNode **pNewArray;
          nAlloc = nAlloc*2 + 5;
          pNewArray = xjd1_realloc(pNew->u.ar.apElem,
                              sizeof(JsonNode*)*nAlloc);
          if( pNewArray==0 ) goto json_error;
          pNew->u.ar.apElem = pNewArray;
        }
        pNew->u.ar.apElem[pNew->u.ar.nElem++] = parseJson(pIn);
        if( tokenType(pIn)==JSON_COMMA ){
          tokenNext(pIn);
................................................................................
    case JSON_TRUE:
    case JSON_FALSE:
    case JSON_NULL: {
      tokenNext(pIn);
      break;
    }
    default: {
      xjd1_free(pNew);
      pNew = 0;
      break;
    }
  }
  return pNew;

json_error:

Changes to src/memory.c.

13
14
15
16
17
18
19



































20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
..
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Pooled memory allocation
*/
#include "xjd1Int.h"




































/*
** Create a new memory allocation pool.  Return a pointer to the
** memory pool or NULL on OOM error.
*/
Pool *xjd1PoolNew(void){
  Pool *p = malloc( sizeof(*p) );
  if( p ) memset(p, 0, sizeof(*p));
  return p;
}

/*
** Free a memory allocation pool allocated using xjd1PoolNew().
*/
void xjd1PoolDelete(Pool *p){
  if( p ){
    xjd1PoolClear(p);
    free(p);
  }
}

/*
** Clear a memory allocation pool.  That is to say, free all the
** memory allocations associated with the pool, though do not free
** the memory pool itself.
*/
void xjd1PoolClear(Pool *p){
  PoolChunk *pChunk, *pNext;
  for(pChunk = p->pChunk; pChunk; pChunk = pNext){
    pNext = pChunk->pNext;
    free(pChunk);
  }
  memset(p, 0, sizeof(*p));
}

/*
** Allocate N bytes of memory from the memory allocation pool.
*/
#define POOL_CHUNK_SIZE 3000
void *xjd1PoolMalloc(Pool *p, int N){
  N = (N+7)&~7;
  if( N>POOL_CHUNK_SIZE/4 ){
    PoolChunk *pChunk = malloc( N + 8 );
    if( pChunk==0 ) return 0;
    pChunk->pNext = p->pChunk;
    p->pChunk = pChunk;
    return &((char*)pChunk)[8];
  }else{
    void *x;
    if( p->nSpace<N ){
      PoolChunk *pChunk = malloc( POOL_CHUNK_SIZE + 8 );
      if( pChunk==0 ) return 0;
      pChunk->pNext = p->pChunk;
      p->pChunk = pChunk;
      p->pSpace = (char*)pChunk;
      p->pSpace += 8;
      p->nSpace = POOL_CHUNK_SIZE;
    }
................................................................................
  void *x = xjd1PoolMalloc(p,N);
  if( x ) memset(x, 0, (N+7)&~7);
  return x;
}

/*
** Create a duplicate of a string using a memory pool.  Or if pPool==0
** obtain the memory for the duplicate from malloc().
*/
char *xjd1PoolDup(Pool *pPool, const char *z, int n){
  char *zOut;
  if( n<0 ) n = xjd1Strlen30(z);
  if( pPool ){
    zOut = xjd1PoolMalloc(pPool, n+1);
  }else{
    zOut = malloc( n+1 );
  }
  if( zOut ){
     memcpy(zOut, z, n);
     zOut[n] = 0;
  }
  return zOut;
}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|










|




|
|






|











|







|







 







|







|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Pooled memory allocation
*/
#include "xjd1Int.h"

static void *dflt_malloc(int N){ return malloc(N); }
static void dflt_free(void *p){ free(p); }
static void *dflt_realloc(void *p, int N){ return realloc(p, N); }

static struct {
  void *(*xMalloc)(int);
  void *(*xRealloc)(void *, int);
  void (*xFree)(void *);
} global = {
  dflt_malloc,
  dflt_realloc,
  dflt_free
};

void xjd1_configure_malloc(
  void *(*xMalloc)(int),
  void *(*xRealloc)(void *, int),
  void (*xFree)(void *)
){
  global.xMalloc = xMalloc;
  global.xRealloc = xRealloc;
  global.xFree = xFree;
}

void *xjd1_malloc(int N){
  return global.xMalloc(N);
}
void xjd1_free(void *p){
  global.xFree(p);
}
void *xjd1_realloc(void *p, int N){
  return global.xRealloc(p, N);
}


/*
** Create a new memory allocation pool.  Return a pointer to the
** memory pool or NULL on OOM error.
*/
Pool *xjd1PoolNew(void){
  Pool *p = xjd1_malloc( sizeof(*p) );
  if( p ) memset(p, 0, sizeof(*p));
  return p;
}

/*
** Free a memory allocation pool allocated using xjd1PoolNew().
*/
void xjd1PoolDelete(Pool *p){
  if( p ){
    xjd1PoolClear(p);
    xjd1_free(p);
  }
}

/*
** Clear a memory allocation pool.  That is to say, xjd1_free all the
** memory allocations associated with the pool, though do not xjd1_free
** the memory pool itself.
*/
void xjd1PoolClear(Pool *p){
  PoolChunk *pChunk, *pNext;
  for(pChunk = p->pChunk; pChunk; pChunk = pNext){
    pNext = pChunk->pNext;
    xjd1_free(pChunk);
  }
  memset(p, 0, sizeof(*p));
}

/*
** Allocate N bytes of memory from the memory allocation pool.
*/
#define POOL_CHUNK_SIZE 3000
void *xjd1PoolMalloc(Pool *p, int N){
  N = (N+7)&~7;
  if( N>POOL_CHUNK_SIZE/4 ){
    PoolChunk *pChunk = xjd1_malloc( N + 8 );
    if( pChunk==0 ) return 0;
    pChunk->pNext = p->pChunk;
    p->pChunk = pChunk;
    return &((char*)pChunk)[8];
  }else{
    void *x;
    if( p->nSpace<N ){
      PoolChunk *pChunk = xjd1_malloc( POOL_CHUNK_SIZE + 8 );
      if( pChunk==0 ) return 0;
      pChunk->pNext = p->pChunk;
      p->pChunk = pChunk;
      p->pSpace = (char*)pChunk;
      p->pSpace += 8;
      p->nSpace = POOL_CHUNK_SIZE;
    }
................................................................................
  void *x = xjd1PoolMalloc(p,N);
  if( x ) memset(x, 0, (N+7)&~7);
  return x;
}

/*
** Create a duplicate of a string using a memory pool.  Or if pPool==0
** obtain the memory for the duplicate from xjd1_malloc().
*/
char *xjd1PoolDup(Pool *pPool, const char *z, int n){
  char *zOut;
  if( n<0 ) n = xjd1Strlen30(z);
  if( pPool ){
    zOut = xjd1PoolMalloc(pPool, n+1);
  }else{
    zOut = xjd1_malloc( n+1 );
  }
  if( zOut ){
     memcpy(zOut, z, n);
     zOut[n] = 0;
  }
  return zOut;
}

Changes to src/stmt.c.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
...
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
  xjd1_stmt *p;
  int dummy;
  Command *pCmd;
  int rc;

  if( pN==0 ) pN = &dummy;
  *pN = strlen(zStmt);
  *ppNew = p = malloc( sizeof(*p) );
  if( p==0 ) return XJD1_NOMEM;
  memset(p, 0, sizeof(*p));
  p->pConn = pConn;
  p->pNext = pConn->pStmt;
  pConn->pStmt = p;
  p->zCode = xjd1PoolDup(&p->sPool, zStmt, -1);
  xjd1StringInit(&p->retValue, &p->sPool, 0);
................................................................................
  }
  if( pStmt->pNext ){
    pStmt->pNext->pPrev = pStmt->pPrev;
  }
  xjd1Unref(pStmt->pConn);
  xjd1PoolClear(&pStmt->sPool);
  xjd1StringClear(&pStmt->retValue);
  free(pStmt);
  return XJD1_OK;
}

/*
** Execute a prepared statement up to its next return value or until
** it completes.
*/
................................................................................
  return XJD1_OK;
}

/*
** Construct a human-readable listing of a prepared statement showing
** its internal structure.  Used for debugging and analysis only.
**
** The return string is obtained from malloc and must be freed by
** the caller.
*/
char *xjd1_stmt_debug_listing(xjd1_stmt *p){
  String x;
  xjd1StringInit(&x, 0, 0);
  xjd1TraceCommand(&x, 0, p->pCmd);
  return x.zBuf;







|







 







|







 







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
...
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
  xjd1_stmt *p;
  int dummy;
  Command *pCmd;
  int rc;

  if( pN==0 ) pN = &dummy;
  *pN = strlen(zStmt);
  *ppNew = p = xjd1_malloc( sizeof(*p) );
  if( p==0 ) return XJD1_NOMEM;
  memset(p, 0, sizeof(*p));
  p->pConn = pConn;
  p->pNext = pConn->pStmt;
  pConn->pStmt = p;
  p->zCode = xjd1PoolDup(&p->sPool, zStmt, -1);
  xjd1StringInit(&p->retValue, &p->sPool, 0);
................................................................................
  }
  if( pStmt->pNext ){
    pStmt->pNext->pPrev = pStmt->pPrev;
  }
  xjd1Unref(pStmt->pConn);
  xjd1PoolClear(&pStmt->sPool);
  xjd1StringClear(&pStmt->retValue);
  xjd1_free(pStmt);
  return XJD1_OK;
}

/*
** Execute a prepared statement up to its next return value or until
** it completes.
*/
................................................................................
  return XJD1_OK;
}

/*
** Construct a human-readable listing of a prepared statement showing
** its internal structure.  Used for debugging and analysis only.
**
** The return string is obtained from xjd1_malloc and must be freed by
** the caller.
*/
char *xjd1_stmt_debug_listing(xjd1_stmt *p){
  String x;
  xjd1StringInit(&x, 0, 0);
  xjd1TraceCommand(&x, 0, p->pCmd);
  return x.zBuf;

Changes to src/string.c.

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
...
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
...
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
...
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
static int resizeString(String *pStr, int newSize){
  char *zNew;
  if( pStr->pPool ){
    zNew = xjd1PoolMalloc(pStr->pPool, newSize);
    if( zNew==0 ) return 1;
    memcpy(zNew, pStr->zBuf, pStr->nUsed);
  }else{
    zNew = realloc(pStr->zBuf, newSize);
    if( zNew==0 ) return 1;
  }
  pStr->nAlloc = newSize;
  pStr->zBuf = zNew;
  return 0;
}

................................................................................

/*
** Allocate a new string object.  Initialize the string buffer to
** initSize bytes.  initSize can be zero.
**
** If pPool is not NULL then all string memory allocations including
** the allocation of the String object itself, come from the identified
** memory pool.  If pPool is NULL, then malloc()/free() are used.
*/
PRIVATE String *xjd1StringNew(Pool *pPool, int initSize){
  String *pStr;
  if( pPool ){
    pStr = xjd1PoolMalloc(pPool, sizeof(*pStr));
  }else{
    pStr = malloc( sizeof(*pStr) );
  }
  if( pStr) xjd1StringInit(pStr, pPool, initSize);
  return pStr;
}

/*
** Free the content of a string but not the String object itself.
*/
PRIVATE void xjd1StringClear(String *pStr){
  if( pStr ){
    if( pStr->pPool==0 ) free(pStr->zBuf);
    memset(pStr, 0, sizeof(*pStr));
  }
}

/*
** Free a string previously allocated using xjd1StringNew().
*/
PRIVATE void xjd1StringDelete(String *pStr){
  if( pStr && pStr->pPool==0 ){
    free(pStr->zBuf);
    free(pStr);
  }
}

/*
** Consume the first N characters from the front of the string.
*/
PRIVATE void xjd1StringRemovePrefix(String *pStr, int N){
................................................................................
        if( isnull ) escarg = "(NULL)";
        if( limit<0 ) limit = strlen(escarg);
        for(i=n=0; i<limit; i++){
          if( escarg[i]=='"' || escarg[i]=='\\' )  n++;
        }
        n += i + 1;
        if( n>etBUFSIZE ){
          bufpt = zExtra = malloc( n );
        }else{
          bufpt = buf;
        }
        j = 0;
        for(i=0; i<limit; i++){
          ch = escarg[i];
          if( ch=='"' || ch=='\\' ) bufpt[j++] = '\\';
................................................................................
          xjd1StringAppend(pStr,spaces,etSPACESIZE);
          nspace -= etSPACESIZE;
        }
        if( nspace>0 ) xjd1StringAppend(pStr,spaces,nspace);
      }
    }
    if( zExtra ){
      free(zExtra);
    }
  }/* End for loop over the format string */
  return errorflag ? -1 : count;
} /* End of function */

/*
** Append formatted text to a string.  Return the number of bytes appended.







|







 







|






|










|









|
|







 







|







 







|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
...
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
...
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
...
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
static int resizeString(String *pStr, int newSize){
  char *zNew;
  if( pStr->pPool ){
    zNew = xjd1PoolMalloc(pStr->pPool, newSize);
    if( zNew==0 ) return 1;
    memcpy(zNew, pStr->zBuf, pStr->nUsed);
  }else{
    zNew = xjd1_realloc(pStr->zBuf, newSize);
    if( zNew==0 ) return 1;
  }
  pStr->nAlloc = newSize;
  pStr->zBuf = zNew;
  return 0;
}

................................................................................

/*
** Allocate a new string object.  Initialize the string buffer to
** initSize bytes.  initSize can be zero.
**
** If pPool is not NULL then all string memory allocations including
** the allocation of the String object itself, come from the identified
** memory pool.  If pPool is NULL, then xjd1_malloc()/xjd1_free() are used.
*/
PRIVATE String *xjd1StringNew(Pool *pPool, int initSize){
  String *pStr;
  if( pPool ){
    pStr = xjd1PoolMalloc(pPool, sizeof(*pStr));
  }else{
    pStr = xjd1_malloc( sizeof(*pStr) );
  }
  if( pStr) xjd1StringInit(pStr, pPool, initSize);
  return pStr;
}

/*
** Free the content of a string but not the String object itself.
*/
PRIVATE void xjd1StringClear(String *pStr){
  if( pStr ){
    if( pStr->pPool==0 ) xjd1_free(pStr->zBuf);
    memset(pStr, 0, sizeof(*pStr));
  }
}

/*
** Free a string previously allocated using xjd1StringNew().
*/
PRIVATE void xjd1StringDelete(String *pStr){
  if( pStr && pStr->pPool==0 ){
    xjd1_free(pStr->zBuf);
    xjd1_free(pStr);
  }
}

/*
** Consume the first N characters from the front of the string.
*/
PRIVATE void xjd1StringRemovePrefix(String *pStr, int N){
................................................................................
        if( isnull ) escarg = "(NULL)";
        if( limit<0 ) limit = strlen(escarg);
        for(i=n=0; i<limit; i++){
          if( escarg[i]=='"' || escarg[i]=='\\' )  n++;
        }
        n += i + 1;
        if( n>etBUFSIZE ){
          bufpt = zExtra = xjd1_malloc( n );
        }else{
          bufpt = buf;
        }
        j = 0;
        for(i=0; i<limit; i++){
          ch = escarg[i];
          if( ch=='"' || ch=='\\' ) bufpt[j++] = '\\';
................................................................................
          xjd1StringAppend(pStr,spaces,etSPACESIZE);
          nspace -= etSPACESIZE;
        }
        if( nspace>0 ) xjd1StringAppend(pStr,spaces,nspace);
      }
    }
    if( zExtra ){
      xjd1_free(zExtra);
    }
  }/* End for loop over the format string */
  return errorflag ? -1 : count;
} /* End of function */

/*
** Append formatted text to a string.  Return the number of bytes appended.

Changes to src/tokenize.c.

405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
...
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
#ifndef NDEBUG
  if( pConn->parserTrace ){
    extern void xjd1ParserTrace(FILE*, char*);
    xjd1ParserTrace(stdout, "parser> ");
  }
#endif

  pEngine = xjd1ParserAlloc(malloc);
  memset(&sParse, 0, sizeof(sParse));
  if( pEngine==0 ){
    sParse.errCode = XJD1_NOMEM;
    goto abort_parse;
  }

  sParse.pConn = pConn;
................................................................................
    if( lastTokenParsed!=TK_SEMI ){
      sParse.sTok.z = ";";
      sParse.sTok.n = 1;
      xjd1Parser(pEngine, TK_SEMI, sParse.sTok, &sParse);
    }
    xjd1Parser(pEngine, 0, sParse.sTok, &sParse);
  }
  xjd1ParserFree(pEngine, free);

  if( sParse.errCode!=XJD1_OK ){
    xjd1Error(pConn, sParse.errCode, "%s", sParse.errMsg.zBuf);
  }
  pStmt->pCmd = sParse.pCmd;
  *pN = i;








|







 







|







405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
...
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
#ifndef NDEBUG
  if( pConn->parserTrace ){
    extern void xjd1ParserTrace(FILE*, char*);
    xjd1ParserTrace(stdout, "parser> ");
  }
#endif

  pEngine = xjd1ParserAlloc(xjd1_malloc);
  memset(&sParse, 0, sizeof(sParse));
  if( pEngine==0 ){
    sParse.errCode = XJD1_NOMEM;
    goto abort_parse;
  }

  sParse.pConn = pConn;
................................................................................
    if( lastTokenParsed!=TK_SEMI ){
      sParse.sTok.z = ";";
      sParse.sTok.n = 1;
      xjd1Parser(pEngine, TK_SEMI, sParse.sTok, &sParse);
    }
    xjd1Parser(pEngine, 0, sParse.sTok, &sParse);
  }
  xjd1ParserFree(pEngine, xjd1_free);

  if( sParse.errCode!=XJD1_OK ){
    xjd1Error(pConn, sParse.errCode, "%s", sParse.errMsg.zBuf);
  }
  pStmt->pCmd = sParse.pCmd;
  *pN = i;

Changes to src/update.c.

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
..
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
    pBase->u.st.pLast = 0;
  }
  for(pElem=pBase->u.st.pFirst; pElem; pElem=pElem->pNext){
    if( strcmp(pElem->zLabel, zField)==0 ){
      return pElem->pValue;
    }
  }
  pElem = malloc( sizeof(*pElem) );
  if( pElem==0 ) return 0;
  pElem->pNext = 0;
  if( pBase->u.st.pLast==0 ){
    pBase->u.st.pFirst = pElem;
  }else{
    pBase->u.st.pLast->pNext = pElem;
  }
................................................................................
  JsonNode *pX;

  pNode = findOrCreateJsonNode(pDoc, pLvalue);
  if( pNode ){
    pX = xjd1JsonEdit(xjd1ExprEval(pValue));
    xjd1JsonToNull(pNode);
    *pNode = *pX;
    free(pX);
  }
}


/*
** Evaluate an UPDATE.
*/







|







 







|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
..
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
    pBase->u.st.pLast = 0;
  }
  for(pElem=pBase->u.st.pFirst; pElem; pElem=pElem->pNext){
    if( strcmp(pElem->zLabel, zField)==0 ){
      return pElem->pValue;
    }
  }
  pElem = xjd1_malloc( sizeof(*pElem) );
  if( pElem==0 ) return 0;
  pElem->pNext = 0;
  if( pBase->u.st.pLast==0 ){
    pBase->u.st.pFirst = pElem;
  }else{
    pBase->u.st.pLast->pNext = pElem;
  }
................................................................................
  JsonNode *pX;

  pNode = findOrCreateJsonNode(pDoc, pLvalue);
  if( pNode ){
    pX = xjd1JsonEdit(xjd1ExprEval(pValue));
    xjd1JsonToNull(pNode);
    *pNode = *pX;
    xjd1_free(pX);
  }
}


/*
** Evaluate an UPDATE.
*/

Changes to src/xjd1.h.

73
74
75
76
77
78
79












80

/* Return true if zStmt is a complete query statement */
int xjd1_complete(const char *zStmt);

/* Show the internal structure of a statement */
char *xjd1_stmt_debug_listing(xjd1_stmt*);













#endif /* _XJD1_H */







>
>
>
>
>
>
>
>
>
>
>
>

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

/* Return true if zStmt is a complete query statement */
int xjd1_complete(const char *zStmt);

/* Show the internal structure of a statement */
char *xjd1_stmt_debug_listing(xjd1_stmt*);


/* Configure or access the malloc/realloc/free used by the module. This
** will change. */
void xjd1_configure_malloc(
  void *(*xMalloc)(int),
  void *(*xRealloc)(void *, int),
  void (*xFree)(void *)
);
void *xjd1_malloc(int N);
void xjd1_free(void *p);
void *xjd1_realloc(void *p, int N);

#endif /* _XJD1_H */