xml/cxmllibrary/src/wbxmlp/src/dictionary.c
branchRCL_3
changeset 20 889504eac4fb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xml/cxmllibrary/src/wbxmlp/src/dictionary.c	Tue Aug 31 17:02:56 2010 +0300
@@ -0,0 +1,776 @@
+/*
+* Copyright (c) 2000 - 2001 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+/*****************************************************************
+**  File: dictionary.c
+**  Description:
+*****************************************************************/
+#include "cxml_internal.h"
+#include "nw_wbxml_parsei.h"
+#include <xml/cxml/nw_string_char.h>
+#include <xml/cxml/nw_wbxml_dictionary.h>
+#include "DictionaryContext.h"
+
+/* HTTP_iso_8859_1 IANA MIBenum 4 */
+#define NW_WBXML_DICTIONARY_CHARSET 4
+
+/*
+ * The dictionaries ...
+ */
+
+
+static
+NW_Bool
+NW_WBXML_Dictionary_CmpDictDocType(NW_WBXML_Dictionary_t* dictionary,
+                                   NW_String_t* string,
+                                   NW_Uint32 encoding)
+{
+  NW_Ucs2* docType;
+
+  docType = dictionary->doc_type;
+  while (*docType != 0)
+  {
+    NW_Int32 bytesRead;
+    NW_Ucs2 c;
+
+    bytesRead = NW_String_readChar(string->storage, &c, encoding);
+    if (c != *docType){
+      return NW_FALSE;
+    }
+    NW_ASSERT(bytesRead > 0);
+    string->storage = string->storage + bytesRead;
+    string->length = string->length - (NW_Uint32)bytesRead;
+    docType++;
+  }
+  return NW_TRUE;
+}
+
+static 
+NW_String_UCS2Buff_t *
+getTagByToken (NW_WBXML_Codepage_t * page, 
+               NW_Byte token)
+{
+  NW_WBXML_DictEntry_t *e;
+  NW_Int32 r;
+  NW_Int32 l = 0;
+  
+  if (page == NULL)
+    return NULL;
+  
+  r = page->count - 1;
+  e = page->tokens;
+  
+  /* Binary search (tokens must be stored in order) */
+  
+  while (r >= l)
+  {
+    NW_Int32 m = (l + r) / 2;
+    if (token == e[m].token)
+      return e[m].name;
+    if (token < e[m].token)
+      r = m - 1;
+    else
+      l = m + 1;
+  }
+  
+  return NULL;
+}
+
+/*
+ * Return -1 if tag is not found, page is 0 or tag is 0
+ */
+
+static 
+NW_Int16
+getTokenByTag (NW_WBXML_Codepage_t * page, 
+               NW_String_UCS2Buff_t * tag,
+               NW_Bool matchCase)
+{
+  NW_Byte *names;
+  NW_Int32 r;
+  NW_Int32 l = 0;
+  
+  if (page == NULL || tag == NULL)
+    return -1;
+  
+  names = page->names;
+  r = page->count - 1;
+  
+  while (r >= l)
+  {
+    NW_Int32 m = (l + r) / 2;
+    NW_Int32 c = NW_String_UCS2BuffCmp (tag, (page->tokens)[names[m]].name, matchCase);
+    if (c == 0)
+      return (page->tokens)[names[m]].token;
+    if (c < 0)
+      r = m - 1;
+    else
+      l = m + 1;
+  }
+  
+  return -1;
+}
+
+static 
+NW_Status_t
+getTokenByTag2 (NW_WBXML_Codepage_t * page,
+                NW_Uint32 encoding,
+                NW_Uint32 charCount,
+                NW_Uint8 * name,
+                NW_Uint16 * pageToken)
+{
+    NW_Byte *names;
+    NW_Int32 r;
+    NW_Int32 l = 0;
+
+    if (page == NULL || name == NULL || pageToken == NULL) {
+        return NW_STAT_FAILURE;
+    }
+
+    names = page->names;
+    r = page->count - 1;
+
+    while (r >= l)
+    {
+        NW_Int32 m = (l + r) / 2;
+        NW_Int32 c;
+        NW_Status_t s;
+        s = NW_String_CmpToNativeAlignedUCS2 (encoding, charCount, name,
+                                              (NW_Uint16*)((page->tokens)[names[m]].name),
+                                              &c);
+        if (NW_STAT_IS_FAILURE(s)) {
+            return s;
+        }
+        if (c == 0) {
+            *pageToken = (page->tokens)[names[m]].token;
+            return NW_STAT_SUCCESS;
+        }
+        if (c < 0)
+            r = m - 1;
+        else
+            l = m + 1;
+    }
+    return NW_STAT_FAILURE;
+}
+
+static 
+NW_Status_t
+getTokenByTag_HandleDuplicates (NW_WBXML_Codepage_t * page,
+																NW_Uint32 encoding,
+																NW_Uint32 charCount,
+																NW_Uint8 * name,
+																NW_Uint16 * pageToken,
+																NW_Bool isName)
+{
+    NW_Byte *names;
+		NW_Int32 i = 0;
+		NW_Uint16 tmpToken;
+
+    if (page == NULL || name == NULL || pageToken == NULL) {
+        return NW_STAT_FAILURE;
+    }
+
+    names = page->names;
+
+    while (i < page->count)
+    {
+        NW_Int32 c;
+        NW_Status_t s;
+        tmpToken = (page->tokens)[names[i]].token;
+				/* If the tag is AttributeTag, then MSB of lower order byte (token) 
+				 * should be unset. If the tag is AttributeValueTag, then MSB of 
+				 * lower order byte (token) should be set.
+				 */
+				if((isName && !(tmpToken & 0x80)) || (!isName && (tmpToken & 0x80)))
+				{
+				    s = NW_String_CmpToNativeAlignedUCS2 (encoding, charCount, name,
+							                                    (NW_Uint16*)((page->tokens)[names[i]].name),
+																									&c);
+						if (NW_STAT_IS_FAILURE(s)) {
+						    return s;
+						}
+						if (c == 0) {
+						    *pageToken = tmpToken;
+								return NW_STAT_SUCCESS;
+						}
+				}
+				i++;
+    }
+    return NW_STAT_FAILURE;
+}
+
+/* 
+ * Dictionary ids are a 1-based index into the dictionary table 
+ *
+ * Return NULL if id is < 1 or id is greater than dictionary_count
+ */
+
+static 
+NW_WBXML_Dictionary_t *
+getDictionaryById (NW_Uint32 id)
+{
+  NW_WBXML_Dictionary_t *d;
+  NW_WBXML_Dictionary_t **dictionaries = GetDictionaries();
+  
+  if (id < 1 || id > GetDictionaryCount())
+    return NULL;
+  
+//#ifdef __WINS__  
+  d = dictionaries[id - 1];
+//#endif
+  
+  return d;
+}
+
+/* 
+ * This function checks if the dictionary has already been added
+ * to the 'dictionaries' table. The comparison is based on 
+ * puclic ids, and therefore it is important that each dictionary
+ * has unique public id.
+ *
+ */
+static NW_Bool ExistingDictionary(NW_WBXML_Dictionary_t *dictionary)
+{
+//#ifdef __WINS__
+  NW_Uint32 i;
+  NW_Uint32 dictionary_count = GetDictionaryCount();
+  NW_WBXML_Dictionary_t **dictionaries = GetDictionaries();
+
+  for (i=0; i<dictionary_count; i++) {
+      if (dictionaries[i]->public_id == dictionary->public_id) {
+          return NW_TRUE;
+      }
+  }
+//#endif
+  return NW_FALSE;
+}
+
+EXPORT_C NW_Status_t
+NW_WBXML_Dictionary_initialize (NW_Int32 n, 
+                                NW_WBXML_Dictionary_t * d[])
+{
+  NW_WBXML_Dictionary_t **dictionaries = GetDictionaries();
+
+  /* Make sure that adding dictionaries is done by calling NW_WBXML_Dictionary_add(). */
+  if (dictionaries == NULL)
+  {
+    dictionaries = (NW_WBXML_Dictionary_t **)NW_Mem_Malloc(sizeof(NW_WBXML_Dictionary_t*) * MAX_DICTIONARIES);
+    if (dictionaries == NULL) {
+		DestroyDictionaries();
+        return NW_STAT_OUT_OF_MEMORY;
+    }
+    StoreDictionaries(dictionaries);
+    StoreDictionaryCount(0);
+  }
+  UpdateDictRefCnt(NW_CONTEXT_REF_DICT_CNT_INR);
+  return NW_WBXML_Dictionary_add(n, d);
+}
+
+NW_Status_t 
+NW_WBXML_Dictionary_add(NW_Int32 n, NW_WBXML_Dictionary_t* d[])
+{
+  NW_Int32 i;
+  NW_WBXML_Dictionary_t **dictionaries = GetDictionaries();
+
+  if (dictionaries == NULL)
+  {
+    return NW_STAT_FAILURE;
+  }
+  
+  NW_ASSERT(n > 0);
+  NW_ASSERT(d != NULL);
+
+  /* This loop adds only the new dictionaries received in the
+     function call (the *d[] table) into the 'dictionaries' table. */
+  for (i=0; i<n; i++) {
+      if (!ExistingDictionary(d[i])) {
+           NW_Uint32 dictionary_count = GetDictionaryCount();
+     
+          /* Return error if the table is full */
+          if ((NW_Uint32)GetDictionaryCount() >= MAX_DICTIONARIES) {
+              return NW_STAT_FAILURE;
+          }
+          dictionaries[dictionary_count++] = d[i];
+          StoreDictionaryCount(dictionary_count);
+      }
+  }
+
+  return NW_STAT_SUCCESS;
+}
+
+EXPORT_C NW_Status_t
+NW_WBXML_Dictionary_destroy ()
+{
+  UpdateDictRefCnt(NW_CONTEXT_REF_DICT_CNT_DCR);
+  DestroyDictionaries();
+  return NW_STAT_SUCCESS;
+}
+
+
+/*
+ * Return NULL if GetDictionaryById returns 0 or if GetTagByToken returns 0
+ */
+
+EXPORT_C NW_String_UCS2Buff_t *
+NW_WBXML_Dictionary_getTagByFqToken (NW_Uint32 fq_token)
+{
+  NW_WBXML_Dictionary_t *d;
+  NW_Byte cp_index = (NW_Byte) ((fq_token & NW_WBXML_MASK_CODEPAGE) >> 8);
+  NW_Byte token = (NW_Byte) (fq_token & NW_WBXML_MASK_TOKEN);
+  NW_WBXML_Codepage_t page;
+  NW_Uint16 dict_id = (NW_Uint16) ((fq_token & NW_WBXML_MASK_DICTIONARY) >> 16);
+  
+  if ((d = getDictionaryById (dict_id)) == NULL)
+    return NULL;
+  
+  if ((fq_token & NW_WBXML_MASK_CPSTATE) == NW_WBXML_CP_STATE_TAG)
+  {
+    if (cp_index > (d->tag_page_count - 1))
+      return NULL;
+    page = d->tag_pages[cp_index];
+    token &= NW_WBXML_MASK_TAG_ID;  /* Only lowest 6 bits for tags */
+  }
+  else
+  {
+    if (cp_index > (d->attr_page_count - 1))
+      return NULL;
+    page = d->attr_pages[cp_index];
+  }
+  
+  
+  return getTagByToken (&page, token);
+}
+
+NW_String_UCS2Buff_t *
+NW_WBXML_Dictionary_getElementNameByToken (NW_WBXML_Dictionary_t *dictionary, 
+                                           NW_Uint16 token)
+{
+  NW_Byte cp_index = (NW_Byte) ((token & NW_WBXML_MASK_CODEPAGE) >> 8);
+  NW_Byte tok = (NW_Byte) (token & NW_WBXML_MASK_TOKEN);
+  NW_WBXML_Codepage_t page;
+  
+  if (dictionary == NULL)
+    return NULL;
+  
+  if (cp_index > (dictionary->tag_page_count - 1))
+    return NULL;
+  page = dictionary->tag_pages[cp_index];
+  tok &= NW_WBXML_MASK_TAG_ID;  /* Only lowest 6 bits for tags */
+  return getTagByToken (&page, tok);
+}
+
+EXPORT_C NW_String_UCS2Buff_t *
+NW_WBXML_Dictionary_getAttributeNameByToken (NW_WBXML_Dictionary_t *dictionary, 
+                                             NW_Uint16 token)
+{
+  NW_Byte cp_index = (NW_Byte) ((token & NW_WBXML_MASK_CODEPAGE) >> 8);
+  NW_Byte tok = (NW_Byte) (token & NW_WBXML_MASK_TOKEN);
+  NW_WBXML_Codepage_t page;
+  
+  if (dictionary == NULL)
+    return NULL;
+  
+  if (cp_index > (dictionary->attr_page_count - 1))
+    return NULL;
+  page = dictionary->attr_pages[cp_index];
+  return getTagByToken (&page, tok);
+}
+
+/*
+ * These return the lower 16 bits of the fully qualified token 
+ * i.e., the token and code page. The rest of the token can be
+ * constructed by the caller if needed. We don't use all 32 bits
+ * in order to be able to return a signed quantity to indicate
+ * failure.
+ */
+
+/*
+ * Return -1 if the token is not found for the given attribute name or if
+ * dictionary or name is 0
+ */
+
+EXPORT_C NW_Int16
+NW_WBXML_Dictionary_getAttributeToken (NW_WBXML_Dictionary_t * dictionary,
+                                       const NW_String_t* name,
+                                       NW_Uint32 encoding,
+                                       NW_Bool matchCase)
+{
+  NW_Int16 token = -1;
+  NW_WBXML_Codepage_t *page;
+  NW_Byte i;
+  NW_Ucs2* ucs2Name;
+  NW_Status_t status;
+  
+  if (dictionary == NULL || name == NULL){
+    return -1;
+  }
+  if (encoding != HTTP_iso_10646_ucs_2){
+    status = NW_String_stringToUCS2Char(name, encoding, &ucs2Name);
+    NW_ASSERT(status == NW_STAT_SUCCESS);
+		/* To fix TI compiler warning */
+		(void) status;
+  }
+  else{
+    ucs2Name = (NW_Ucs2*)name->storage;
+  }
+  
+  for (i = 0; i < dictionary->attr_page_count; i++)
+  {
+    page = dictionary->attr_pages + i;
+    /* this is a hack - ucs2buff types should be removed */
+    if ((token = getTokenByTag (page, (NW_String_UCS2Buff_t*) ucs2Name, matchCase)) >= 0){
+      token = (NW_Int16) (token | (i << 8));
+      break;
+    }
+  }
+  if (encoding != HTTP_iso_10646_ucs_2){
+    NW_Mem_Free(ucs2Name);  
+  }
+  return token;
+}
+
+NW_Status_t
+NW_WBXML_Dictionary_getAttributeToken2 (NW_WBXML_Dictionary_t * dictionary,
+                                        NW_Uint32 encoding,
+                                        NW_Uint32 charCount,
+                                        NW_Uint8 * name,
+                                        NW_Uint16 * pageToken,
+                                        NW_Bool isName)
+{
+  NW_WBXML_Codepage_t *page;
+  NW_Byte i;
+  NW_Status_t s;
+  
+  if (dictionary == NULL || name == NULL || pageToken == NULL) {
+    return NW_STAT_FAILURE;
+  }
+  
+  for (i = 0; i < dictionary->attr_page_count; i++) {
+    page = dictionary->attr_pages + i;
+    s = getTokenByTag2 (page, encoding, charCount, name, pageToken);
+    if (NW_STAT_IS_FAILURE(s)) {
+        /* failure may mean "not found" so continue to next page */
+        continue;
+    }
+      if (isName) {
+        if (*pageToken >= 128) {
+					s = getTokenByTag_HandleDuplicates (page, encoding, charCount, name, pageToken, isName);
+					if (NW_STAT_IS_FAILURE(s)) {
+							/* failure may mean "not found" so continue to next page */
+          continue;
+        }
+        }
+      } else {
+        if (*pageToken < 128) {
+					s = getTokenByTag_HandleDuplicates (page, encoding, charCount, name, pageToken, isName);
+					if (NW_STAT_IS_FAILURE(s)) {
+							/* failure may mean "not found" so continue to next page */
+          continue;
+        }
+      }
+      }
+      *pageToken |= (i << 8);
+      return NW_STAT_SUCCESS;
+    }
+  return NW_STAT_FAILURE;
+}
+
+NW_Status_t
+NW_WBXML_Dictionary_getAttributeNameToken (NW_WBXML_Dictionary_t * dictionary,
+                                           NW_Uint32 encoding,
+                                           NW_Uint32 charCount,
+                                           NW_Uint8 * name,
+                                           NW_Uint16 * pageToken)
+{
+    return NW_WBXML_Dictionary_getAttributeToken2 (dictionary, encoding,
+                                                   charCount, name, pageToken,
+                                                   NW_TRUE);
+    
+}
+
+NW_Status_t
+NW_WBXML_Dictionary_getAttributeValueToken (NW_WBXML_Dictionary_t * dictionary,
+                                            NW_Uint32 encoding,
+                                            NW_Uint32 charCount,
+                                            NW_Uint8 * name,
+                                            NW_Uint16 * pageToken)
+{
+    return NW_WBXML_Dictionary_getAttributeToken2 (dictionary, encoding,
+                                                   charCount, name, pageToken,
+                                                   NW_FALSE);
+    
+}
+
+/*
+ * Return -1 if the token is not found for the given tag name or if
+ * dictionary or name is 0
+ */
+
+EXPORT_C NW_Int16
+NW_WBXML_Dictionary_getTagToken (NW_WBXML_Dictionary_t * dictionary,
+                                 NW_String_UCS2Buff_t * name,
+                                 NW_Bool matchCase)
+{
+  NW_Int16 token = 0;
+  NW_WBXML_Codepage_t *page;
+  NW_Byte i;
+  
+  if (dictionary == NULL || name == NULL)
+    return -1;
+  
+  for (i = 0; i < dictionary->tag_page_count; i++)
+  {
+    page = dictionary->tag_pages + i;
+    if ((token = getTokenByTag (page, name, matchCase)) >= 0)
+      return (NW_Int16)(token | (i << 8));
+  }
+  
+  return -1;
+}
+
+NW_Status_t
+NW_WBXML_Dictionary_getTagToken2(NW_WBXML_Dictionary_t * dictionary,
+                                 NW_Uint32 encoding,
+                                 NW_Uint32 charCount,
+                                 NW_Uint8* name,
+                                 NW_Uint16* pageToken)
+{
+  NW_WBXML_Codepage_t *page;
+  NW_Byte i;
+  NW_Status_t s;
+  
+  if (dictionary == NULL || name == NULL || pageToken == NULL) {
+    return NW_STAT_FAILURE;
+  }
+  
+  for (i = 0; i < dictionary->tag_page_count; i++) {
+    page = dictionary->tag_pages + i;
+    s = getTokenByTag2 (page, encoding, charCount, name, pageToken);
+    if (NW_STAT_IS_FAILURE(s)) {
+        /* failure may mean "not found" so continue to next page */
+        continue;
+    }
+      *pageToken |= (i << 8);
+      return NW_STAT_SUCCESS;
+    }
+  return NW_STAT_FAILURE;
+}
+
+/* Linear searches are ok here since we only do these once */
+
+/*
+ * Return NULL if a dictionary is not found for the given public_id
+ */
+
+EXPORT_C
+NW_WBXML_Dictionary_t *
+NW_WBXML_Dictionary_getByPublicId (NW_Uint32 public_id)
+{
+//#ifdef __WINS__
+  NW_Uint32 i;
+  NW_Uint32 dictionary_count = GetDictionaryCount();
+  NW_WBXML_Dictionary_t **dictionaries = GetDictionaries();
+  
+  for (i = 0; i < dictionary_count; i++)
+  {
+    if (dictionaries[i]->public_id == public_id)
+      return dictionaries[i];
+  }
+//#endif  
+  return NULL;
+}
+
+/*
+ * Return NULL if a dictionary is not found for the given doc_type or if
+ *   doc_type is 0
+ */
+
+NW_WBXML_Dictionary_t *
+NW_WBXML_Dictionary_getByDocType (NW_String_t * doc_type, NW_Uint32 encoding)
+{
+//#ifdef __WINS__
+  NW_Uint32 i;
+  NW_Uint32 dictionary_count = GetDictionaryCount();
+  NW_WBXML_Dictionary_t **dictionaries = GetDictionaries();
+  
+  if (doc_type == NULL)
+    return NULL;
+  
+  for (i = 0; i < dictionary_count; i++)
+  {
+    if (NW_WBXML_Dictionary_CmpDictDocType(dictionaries[i], doc_type, encoding)){
+      return dictionaries[i];
+  }
+  }
+//#endif  
+  return NULL;
+}
+
+/* Get the 1-based index into the dictionary table */
+
+/*
+ * Return 0 if the dictionary is not found
+ */
+
+NW_Uint32
+NW_WBXML_Dictionary_getIndexByPublicId (NW_Uint32 public_id)
+{
+//#ifdef __WINS__
+  NW_Uint32 i;
+  NW_Uint32 dictionary_count = GetDictionaryCount();
+  NW_WBXML_Dictionary_t **dictionaries = GetDictionaries();
+  
+  for (i = 0; i < dictionary_count; i++)
+  {
+    if (dictionaries[i]->public_id == public_id)
+      return i + 1;
+  }
+//#endif  
+  return 0;
+}
+
+/*
+ * Return 0 if the dictionary is not found or doc_type is 0
+ */
+
+NW_Uint32
+NW_WBXML_Dictionary_getIndexByDocType (NW_String_t * doc_type, NW_Uint32 encoding)
+{
+//#ifdef __WINS__
+  NW_Uint32 i;
+  NW_Uint32 dictionary_count = GetDictionaryCount();
+  NW_WBXML_Dictionary_t **dictionaries = GetDictionaries();
+  
+  if(doc_type == NULL){
+    return 0;
+  }
+  
+  for (i = 0; i < dictionary_count; i++) {
+    if (NW_WBXML_Dictionary_CmpDictDocType(dictionaries[i], doc_type, encoding)){
+      return i + 1;
+    }
+  }
+//#endif
+  return 0;
+}
+
+NW_WBXML_Dictionary_t * 
+NW_WBXML_Dictionary_getByIndex(NW_Uint32 dictIndex)
+{
+//#ifdef __WINS__
+  NW_WBXML_Dictionary_t **dictionaries = GetDictionaries();
+
+  if (dictIndex == 0){
+    return NULL;
+  }
+  return dictionaries[dictIndex -1];
+//#else
+//  return NULL;
+//#endif
+}
+
+/*
+ * Given a tag or attribute token, if the token is a literal,
+ * use the given name to lookup the tag/attribute's "real" token
+ * and return that token.
+ *
+ *
+ * Returns NW_STAT_SUCCESS
+ *         NW_STAT_FAILURE - if the token lookup fails (NOT fatal)
+ *         NW_STAT_OUT_OF_MEMORY
+ */
+
+EXPORT_C NW_Status_t
+NW_WBXML_Dictionary_resolveLiteralToken(NW_Uint32 *token,     /* In/Out */
+                                        NW_String_t *name,    /* Ask Deepika why NULL is allowed */
+                                        NW_Bool is_tag,       /* NW_TRUE == token is for tag; 
+                                                                 NW_FALSE == attribute */
+                                        NW_Uint32 encoding,   /* Used in the name conversion */
+                                        NW_Bool matchCase)
+{
+  
+  NW_Ucs2 * buff;
+  NW_Uint32 dict_id = ((*token) & NW_WBXML_MASK_DICTIONARY) >> 16;
+  NW_Int16 tmp_token;  
+  
+  if (NW_WBXML_Dictionary_getTagByFqToken(*token) != NULL){
+    /* The token is NOT a literal, no need for further processing */
+    return NW_STAT_SUCCESS;
+  }
+  
+  if(name == NULL){ /* TODO:  Ask Deepika if this can be made an assert?? */
+    return NW_STAT_FAILURE;
+  }
+
+  /* 
+   * Before looking up the name in the dictionary, must convert
+   * name to the type used in dictionary names.
+   */
+
+  if (NW_String_stringToUCS2Char(name, encoding, &buff) != NW_STAT_SUCCESS) {
+    return NW_STAT_OUT_OF_MEMORY;
+  }
+  
+  tmp_token = (NW_Int16) ((is_tag == NW_TRUE) ?
+    NW_WBXML_Dictionary_getTagToken(getDictionaryById(dict_id), (NW_String_UCS2Buff_t *) buff, matchCase) : 
+    NW_WBXML_Dictionary_getAttributeToken(getDictionaryById(dict_id), name, encoding, matchCase));
+  
+  NW_Mem_Free (buff);
+
+  if (tmp_token == -1)
+  {
+    return NW_STAT_FAILURE;
+  }
+  
+  *token = ((NW_Uint16) dict_id << 16)| (NW_Uint16) tmp_token;
+  
+  return NW_STAT_SUCCESS; 
+}
+
+
+/* 1. returns success, oom, or failure
+   2. if oom or failure, no leaks and no residual memory allocations
+   3. if oom or failure on return *ppDocType is NULL
+   4  if success on return *ppDocType is a valid string or NULL if
+   no matching dictionary or dictionary did not have a doc_type string. */
+NW_Status_t
+NW_WBXML_Dictionary_publicId_to_doctypeString(NW_Uint32 publicId,
+                                              NW_String_t** ppDocType)
+{
+  NW_WBXML_Dictionary_t *pDictionary
+    = NW_WBXML_Dictionary_getByPublicId (publicId);
+  *ppDocType = NULL;
+  if (pDictionary != NULL) {
+    if (pDictionary->doc_type != NULL) {
+      *ppDocType = NW_String_new();
+      if (*ppDocType != NULL) {
+        if (NW_String_initialize(*ppDocType, pDictionary->doc_type,
+                                 NW_WBXML_DICTIONARY_CHARSET)
+            != NW_STAT_SUCCESS) {
+          NW_String_delete(*ppDocType);
+          *ppDocType = NULL;
+          return NW_STAT_FAILURE;
+        }
+      } else {
+        return NW_STAT_OUT_OF_MEMORY;
+      }
+    }
+  }
+  return NW_STAT_SUCCESS;
+}
+