Fossil

Check-in [8027581c]
Login

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

Overview
Comment:Made a few more functions static. th1 ob doc additions.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | th1-query-api
Files: files | file ages | folders
SHA1: 8027581c5e9e8754d9a629bc94b3baa7980d9e61
User & Date: stephan 2012-07-15 12:52:17
Context
2012-07-15
13:14
Minor cleanups. Made Th_Ob_Man opaque. Renamed TH_USE_xxx to TH_ENABLE_xxx. check-in: 3d243a56 user: stephan tags: th1-query-api
12:52
Made a few more functions static. th1 ob doc additions. check-in: 8027581c user: stephan tags: th1-query-api
12:27
Refactored th1/sqlite bits to use Th_Data_Get/Set(), removed sqlite data from Th_Interp class. Other minor cleanups. check-in: 3167ff33 user: stephan tags: th1-query-api
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/th_main.c.

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
...
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
...
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
...
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
** pStmt is transfered to interp and it must be cleaned up by the
** client by calling Th_FinalizeStmt(), passing it the value returned
** by this function.
**
** If interp is destroyed before all statements are finalized,
** it will finalize them but may emit a warning message.
*/
int Th_AddStmt(Th_Interp *interp, sqlite3_stmt * pStmt);

/*
** Expects stmtId to be a statement identifier returned by
** Th_AddStmt(). On success, finalizes the statement and returns 0.
** On error (statement not found) non-0 is returned. After this
** call, some subsequent call to Th_AddStmt() may return the
** same statement ID.
*/
int Th_FinalizeStmt(Th_Interp *interp, int stmtId);

/*
** Fetches the statement with the given ID, as returned by
** Th_AddStmt(). Returns NULL if stmtId does not refer (or no longer
** refers) to a statement added via Th_AddStmt().
*/
sqlite3_stmt * Th_GetStmt(Th_Interp *interp, int stmtId);


struct Th_Sqlite {
  sqlite3_stmt ** aStmt;
  int nStmt;
};
#define Th_Sqlite_KEY "Th_Sqlite"
................................................................................
typedef struct Th_Sqlite Th_Sqlite;

static Th_Sqlite * Th_sqlite_manager( Th_Interp * interp ){
  void * p = Th_Data_Get( interp, Th_Sqlite_KEY );
  return p ? (Th_Sqlite*)p : NULL;
}

int Th_AddStmt(Th_Interp *interp, sqlite3_stmt * pStmt){
  Th_Sqlite * sq = Th_sqlite_manager(interp);
  int i, x;
  sqlite3_stmt * s;
  sqlite3_stmt ** list = sq->aStmt;
  for( i = 0; i < sq->nStmt; ++i ){
    s = list[i];
    if(NULL==s){
................................................................................
  x = sq->nStmt;
  sq->nStmt = i;
  sq->aStmt = list;
  return x + 1;
}


int Th_FinalizeStmt(Th_Interp *interp, int stmtId){
  Th_Sqlite * sq = Th_sqlite_manager(interp);
  sqlite3_stmt * st;
  int rc = 0;
  assert( stmtId>0 && stmtId<=sq->nStmt );
  st = sq->aStmt[stmtId-1];
  if(NULL != st){
    sq->aStmt[stmtId-1] = NULL;
................................................................................
    sqlite3_finalize(st);
    return 0;
  }else{
    return 1;
  }
}

sqlite3_stmt * Th_GetStmt(Th_Interp *interp, int stmtId){
  Th_Sqlite * sq = Th_sqlite_manager(interp);
  return ((stmtId<1) || (stmtId > sq->nStmt))
    ? NULL
    : sq->aStmt[stmtId-1];
}


static void finalizerSqlite( Th_Interp * interp, void * p ){
  Th_Sqlite * sq = Th_sqlite_manager( interp );
  int i;
  sqlite3_stmt * st = NULL;
  if(!sq) {
    fossil_warning("Got a finalizer call for a NULL Th_Sqlite.");
    return;
  }
  for( i = 0; i < sq->nStmt; ++i ){
    st = sq->aStmt[i];
    if(NULL != st){
      fossil_warning("Auto-finalizing unfinalized query_prepare "
                     "statement id #%d: %s",
                     i+1, sqlite3_sql(st));
      Th_FinalizeStmt( interp, i+1 );
    }
  }
  Th_Free(interp, sq->aStmt);
  Th_Free(interp, sq);







|








|






|







 







|







 







|







 







|








|









|







849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
...
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
...
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
...
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
** pStmt is transfered to interp and it must be cleaned up by the
** client by calling Th_FinalizeStmt(), passing it the value returned
** by this function.
**
** If interp is destroyed before all statements are finalized,
** it will finalize them but may emit a warning message.
*/
static int Th_AddStmt(Th_Interp *interp, sqlite3_stmt * pStmt);

/*
** Expects stmtId to be a statement identifier returned by
** Th_AddStmt(). On success, finalizes the statement and returns 0.
** On error (statement not found) non-0 is returned. After this
** call, some subsequent call to Th_AddStmt() may return the
** same statement ID.
*/
static int Th_FinalizeStmt(Th_Interp *interp, int stmtId);

/*
** Fetches the statement with the given ID, as returned by
** Th_AddStmt(). Returns NULL if stmtId does not refer (or no longer
** refers) to a statement added via Th_AddStmt().
*/
static sqlite3_stmt * Th_GetStmt(Th_Interp *interp, int stmtId);


struct Th_Sqlite {
  sqlite3_stmt ** aStmt;
  int nStmt;
};
#define Th_Sqlite_KEY "Th_Sqlite"
................................................................................
typedef struct Th_Sqlite Th_Sqlite;

static Th_Sqlite * Th_sqlite_manager( Th_Interp * interp ){
  void * p = Th_Data_Get( interp, Th_Sqlite_KEY );
  return p ? (Th_Sqlite*)p : NULL;
}

static int Th_AddStmt(Th_Interp *interp, sqlite3_stmt * pStmt){
  Th_Sqlite * sq = Th_sqlite_manager(interp);
  int i, x;
  sqlite3_stmt * s;
  sqlite3_stmt ** list = sq->aStmt;
  for( i = 0; i < sq->nStmt; ++i ){
    s = list[i];
    if(NULL==s){
................................................................................
  x = sq->nStmt;
  sq->nStmt = i;
  sq->aStmt = list;
  return x + 1;
}


static int Th_FinalizeStmt(Th_Interp *interp, int stmtId){
  Th_Sqlite * sq = Th_sqlite_manager(interp);
  sqlite3_stmt * st;
  int rc = 0;
  assert( stmtId>0 && stmtId<=sq->nStmt );
  st = sq->aStmt[stmtId-1];
  if(NULL != st){
    sq->aStmt[stmtId-1] = NULL;
................................................................................
    sqlite3_finalize(st);
    return 0;
  }else{
    return 1;
  }
}

static sqlite3_stmt * Th_GetStmt(Th_Interp *interp, int stmtId){
  Th_Sqlite * sq = Th_sqlite_manager(interp);
  return ((stmtId<1) || (stmtId > sq->nStmt))
    ? NULL
    : sq->aStmt[stmtId-1];
}


static void finalizerSqlite( Th_Interp * interp, void * p ){
  Th_Sqlite * sq = (Th_Sqlite *)p;
  int i;
  sqlite3_stmt * st = NULL;
  if(!sq) {
    fossil_warning("Got a finalizer call for a NULL Th_Sqlite.");
    return;
  }
  for( i = 0; i < sq->nStmt; ++i ){
    st = sq->aStmt[i];
    if(NULL != st){
      fossil_warning("Auto-finalizing unfinalized "
                     "statement id #%d: %s",
                     i+1, sqlite3_sql(st));
      Th_FinalizeStmt( interp, i+1 );
    }
  }
  Th_Free(interp, sq->aStmt);
  Th_Free(interp, sq);

Changes to www/th1_ob.wiki.

9
10
11
12
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
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
..
79
80
81
82
83
84
85





   *  Supports nesting buffering arbitrarily deep, but each level which gets opened must also be closed by the scripter.

Example usage:

<nowiki><pre>
&lt;th1>
puts "this is unbuffered"
ob start
# all output until the next ob start|end gets collected
# in a buffer...
&lt;/th1>

this is buffered

&lt;th1>
puts "current buffer level = " [ob level] "\n"
puts "this part is also collected in the buffer."

# Collect the buffer's contents:
set buf [ob get end]
# That is equivalent to:
#  set buf [ob get]
#  ob  end

puts "\nThis is now unbuffered, but we buffered: $buf\n"
&lt;/th1>
</pre></nowiki>

The functions are summarized below...

<h2>ob start</h2>




<tt>ob start</tt> pushes a level of buffering onto the buffer stack, such that
future calls which generate output through the th1-internal mechanism will have it
transparently redirected to the current buffer.

It is important that every call to <tt>ob start</tt> be followed up (eventually)
by either <tt>ob end</tt> or <tt>ob get end</tt>.

<h2>ob end</h2>




This discards any current buffered contents and reverts the output state to
the one it had before the previous <tt>ob start</tt>. i.e. that might be another
buffering level or it might be the th1-normal output mechanism.

The global resources associated with buffering are cleaned up when the
last buffering level is left (and re-created as needed when a new
................................................................................

This discards the current contents of the current buffer level but
does not change the buffer stack level.

<h2>ob get</h2>

This fetches the current contents as a string. It optionally accepts
either <tt>end</tt> or <tt>clean</tt>, in which cases it behaves like
either <tt>ob end</tt> or <tt>ob clean</tt>, respectively, in addition
to returning the buffer contents. i.e. <tt>ob get clean</tt> will
fetch the contents and clean up the buffer, but does not change the
buffering level, whereas <tt>ob get end</tt> pops the buffer off the
stack after fetching its contents.

<h2>ob level</h2>

Returns the current buffering level (0 if not buffering).

<h2>ob flush</h2>
................................................................................
It is not expected that this will be useful all that often, but for
the cases where it is, here's how it works: this behaves as if we
fetched the buffer state (<tt>ob get</tt>), reverted TH1 to its
previous output mechanism, push the buffer state to TH1, revert TH1
<em>back</em> to the current buffering state, and then clear the
current buffer contents (like <tt>ob clean</tt>). This does not change
the buffering level, though it temporarily behaves as if it does.












|











|


|







|
>
>
>








|
>
>
>







 







|
|


|







 







>
>
>
>
>
9
10
11
12
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
..
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
..
85
86
87
88
89
90
91
92
93
94
95
96
   *  Supports nesting buffering arbitrarily deep, but each level which gets opened must also be closed by the scripter.

Example usage:

<nowiki><pre>
&lt;th1>
puts "this is unbuffered"
ob push # or: ob start (same thing)
# all output until the next ob start|end gets collected
# in a buffer...
&lt;/th1>

this is buffered

&lt;th1>
puts "current buffer level = " [ob level] "\n"
puts "this part is also collected in the buffer."

# Collect the buffer's contents:
set buf [ob get pop]
# That is equivalent to:
#  set buf [ob get]
#  ob pop

puts "\nThis is now unbuffered, but we buffered: $buf\n"
&lt;/th1>
</pre></nowiki>

The functions are summarized below...

<h2>ob push|start</h2>

<tt>push</tt> and <tt>start</tt> are aliases ("start" comes from the PHP API, but
"push" is probably more natural to those working with th1).

<tt>ob start</tt> pushes a level of buffering onto the buffer stack, such that
future calls which generate output through the th1-internal mechanism will have it
transparently redirected to the current buffer.

It is important that every call to <tt>ob start</tt> be followed up (eventually)
by either <tt>ob end</tt> or <tt>ob get end</tt>.

<h2>ob pop|end</h2>

<tt>pop</tt> and <tt>end</tt> are aliases ("end" comes from the PHP API, but
"pop" is probably more natural to those working with th1).

This discards any current buffered contents and reverts the output state to
the one it had before the previous <tt>ob start</tt>. i.e. that might be another
buffering level or it might be the th1-normal output mechanism.

The global resources associated with buffering are cleaned up when the
last buffering level is left (and re-created as needed when a new
................................................................................

This discards the current contents of the current buffer level but
does not change the buffer stack level.

<h2>ob get</h2>

This fetches the current contents as a string. It optionally accepts
either <tt>end</tt> (or its alias <tt>pop</tt>) or <tt>clean</tt>, in which cases it behaves like
either <tt>ob end|pop</tt> or <tt>ob clean</tt>, respectively, in addition
to returning the buffer contents. i.e. <tt>ob get clean</tt> will
fetch the contents and clean up the buffer, but does not change the
buffering level, whereas <tt>ob get end|pop</tt> pops the buffer off the
stack after fetching its contents.

<h2>ob level</h2>

Returns the current buffering level (0 if not buffering).

<h2>ob flush</h2>
................................................................................
It is not expected that this will be useful all that often, but for
the cases where it is, here's how it works: this behaves as if we
fetched the buffer state (<tt>ob get</tt>), reverted TH1 to its
previous output mechanism, push the buffer state to TH1, revert TH1
<em>back</em> to the current buffering state, and then clear the
current buffer contents (like <tt>ob clean</tt>). This does not change
the buffering level, though it temporarily behaves as if it does.

In other words, this function pushes the current buffer contents to the
next-lower output mechanism (which may be another ob buffering level,
fossil's internal CGI output buffer, or it might be be
<tt>fwrite(stdout)</tt>).