commit 6634ce4f3bf233266c8c3aa54dedf081ae7e3434
Author: Martin Szulecki <[email protected]>
Date: Tue Jul 27 16:14:17 2010 +0200
[sqlitedb] Implement iPhoneSortKey and iPhoneSortSection sqlite functions
The latest iOS 4 post process commands expect these sqlite functions to be
defined or a range of commands will fail. The implementation is ugly as it
attempts to emulate the data blob structure as closely as possible to the
one iTunes generates.
src/itdb_sqlite.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 178 insertions(+), 0 deletions(-)
---
diff --git a/src/itdb_sqlite.c b/src/itdb_sqlite.c
index b107e4e..5b8f216 100644
--- a/src/itdb_sqlite.c
+++ b/src/itdb_sqlite.c
@@ -1572,6 +1572,180 @@ leave:
return res;
}
+static void sort_key_get_buffer_boundaries(const char* sval, int *length, int
*word_offset)
+{
+ int word_count = 0;
+ int i = 0;
+ int l = 0;
+ int o = 0;
+ char *sval_uppercase = NULL;
+ if (sval && strlen(sval)) {
+ sval_uppercase = g_ascii_strup(sval, strlen(sval));
+ while (sval_uppercase[i]) {
+ if (g_ascii_isalnum(sval_uppercase[i])) {
+ l++;
+ } else {
+ switch (sval_uppercase[i]) {
+ case ' ':
+ word_count++;
+ l++;
+ break;
+ case ':':
+ case '-':
+ case ',':
+ case '.':
+ case '\'':
+ default:
+ l += 2;
+ break;
+ }
+ }
+ i++;
+ }
+ free(sval_uppercase);
+
+ word_count++;
+ /* magic + transformed string + length + word weights + null */
+ o = 1 + l + 3;
+ l = o + (word_count*2) + 1;
+ } else {
+ l = 4;
+ }
+
+ *length = l;
+ *word_offset = o;
+}
+
+static void sqlite_func_iphone_sort_key(sqlite3_context *context, int argc,
sqlite3_value **argv)
+{
+ const char *sval;
+ char *sval_uppercase = NULL;
+
+ char *buffer = NULL;
+
+ int word_count = 0;
+ int word_offset = 0;
+ int word_length = 0;
+ int i = 0;
+ int buffer_index = 0;
+ int buffer_size = 0;
+
+ if (argc != 1)
+ fprintf(stderr, "[%s] Error: Unexpected number of arguments:
%d\n", __func__, argc);
+
+ switch (sqlite3_value_type(argv[0])) {
+ case SQLITE_TEXT:
+ sval = (const char*)sqlite3_value_text(argv[0]);
+ sort_key_get_buffer_boundaries(sval, &buffer_size,
&word_offset);
+ buffer = (char*)malloc(buffer_size);
+ memset(buffer, '\0', buffer_size);
+ buffer[buffer_index] = 0x31;
+ if (sval) {
+ if (buffer_size > 4) {
+ buffer[buffer_index++] = 0x30;
+ /* transform text value */
+ /* uppercase the text */
+ sval_uppercase = g_ascii_strup(sval,
strlen(sval));
+ while (sval_uppercase[i]) {
+ word_length++;
+ if
(g_ascii_isalnum(sval_uppercase[i])) {
+ /* transform regular
character */
+ buffer[buffer_index++]
= sval_uppercase[i] - (0x55 - sval_uppercase[i]);
+ } else {
+ /* transform special
chars (punctuation,special) */
+ switch
(sval_uppercase[i]) {
+ case ' ':
+
buffer[buffer_index++] = 0x06;
+
word_length--;
+
+ /*
since we reached word end, calculate word weight */
+
buffer[word_offset + word_count*2] = 0x8f;
+
buffer[word_offset + word_count*2 + 1] = (char)(0x86 - word_length);
+
word_count++;
+
word_length = 0;
+ break;
+ case ':':
+
buffer[buffer_index++] = 0x07;
+
buffer[buffer_index++] = 0xd8;
+ break;
+ case '-':
+
buffer[buffer_index++] = 0x07;
+
buffer[buffer_index++] = 0x90;
+ break;
+ case ',':
+
buffer[buffer_index++] = 0x07;
+
buffer[buffer_index++] = 0xb2;
+ break;
+ case '.':
+
buffer[buffer_index++] = 0x08;
+
buffer[buffer_index++] = 0x51;
+ break;
+ case '\'':
+
buffer[buffer_index++] = 0x07;
+
buffer[buffer_index++] = 0x31;
+ break;
+ default:
+ /*
FIXME: We just simulate "-" for any other char, needs proper conversion */
+
buffer[buffer_index++] = 0x07;
+
buffer[buffer_index++] = 0x90;
+ break;
+ }
+ }
+ i++;
+ }
+ g_free(sval_uppercase);
+
+ /* calculate word weight for last word
*/
+ buffer[word_offset + word_count*2] =
0x8f;
+ buffer[word_offset + word_count*2 + 1]
= 3 + word_length;
+ word_count++;
+ word_length = 0;
+
+ /* write length of input string */
+ buffer[word_offset - 3] = 0x01;
+ buffer[word_offset - 2] = i + 4; /*
length of input string + 4 */
+ buffer[word_offset - 1] = 0x01;
+ } else {
+ buffer[0] = 0x31;
+ buffer[1] = 0x01;
+ buffer[2] = 0x01;
+ }
+ }
+ sqlite3_result_blob(context, buffer, buffer_size, free);
+ break;
+ case SQLITE_NULL:
+ buffer = (char*)malloc(4);
+ memcpy(buffer, "\x31\x01\x01\x00", 4);
+ sqlite3_result_blob(context, buffer, 4, free);
+ break;
+ default:
+ sqlite3_result_null(context);
+ break;
+ }
+}
+
+static void sqlite_func_iphone_sort_section(sqlite3_context *context, int
argc, sqlite3_value **argv)
+{
+ const unsigned char *sval;
+ int res = 26;
+
+ if (argc != 1)
+ fprintf(stderr, "[%s] Error: Unexpected number of arguments:
%d\n", __func__, argc);
+
+ switch (sqlite3_value_type(argv[0])) {
+ case SQLITE_BLOB:
+ case SQLITE_TEXT:
+ sval = sqlite3_value_text(argv[0]);
+ if (sval && (sval[0] == 0x30) && (sval[1] >= 0x2D) &&
(sval[1] <= 0x5F)) {
+ res = (sval[1] - 0x2D) / 2;
+ }
+ break;
+ default:
+ break;
+ }
+ sqlite3_result_int(context, res);
+}
+
static void run_post_process_commands(Itdb_iTunesDB *itdb, const char
*outpath, const char *uuid)
{
plist_t plist_node = NULL;
@@ -1743,6 +1917,10 @@ static void run_post_process_commands(Itdb_iTunesDB
*itdb, const char *outpath,
i++;
}
+ printf("[%s] binding functions\n", __func__);
+ sqlite3_create_function(db, "iPhoneSortKey", 1,
SQLITE_ANY, NULL, &sqlite_func_iphone_sort_key, NULL, NULL);
+ sqlite3_create_function(db, "iPhoneSortSection", 1,
SQLITE_ANY, NULL, &sqlite_func_iphone_sort_section, NULL, NULL);
+
cnt = plist_array_get_size(user_ver_cmds);
printf("[%s] Running %d post process commands now\n",
__func__, cnt);
------------------------------------------------------------------------------
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and,
should the need arise, upgrade to a full multi-node Oracle RAC database
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl
_______________________________________________
gtkpod-cvs2 mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gtkpod-cvs2