nuttx/libs/libc/net/lib_base64.c
Xiang Xiao 10adf76209 libc: Add b64_ntop and b64_pton implementation
implemented by many libc(e.g. freebsd, glibc, newlib)

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2020-12-28 13:53:20 -03:00

227 lines
5.2 KiB
C

/****************************************************************************
* libs/libc/net/lib_base64.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <ctype.h>
#include <resolv.h>
#include <string.h>
/****************************************************************************
* Private Data
****************************************************************************/
static const char g_base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char g_pad64 = '=';
/****************************************************************************
* Public Functions
****************************************************************************/
int b64_ntop(FAR const unsigned char *src, size_t srclen,
FAR char *target, size_t targsize)
{
size_t datalen = 0;
while (srclen >= 3)
{
if ((datalen += 4) >= targsize)
{
return -1;
}
*target++ = g_base64[src[0] >> 2];
*target++ = g_base64[((src[0] & 0x03) << 4) + (src[1] >> 4)];
*target++ = g_base64[((src[1] & 0x0f) << 2) + (src[2] >> 6)];
*target++ = g_base64[src[2] & 0x3f];
src += 3;
srclen -= 3;
}
if (srclen != 0)
{
if ((datalen += 4) >= targsize)
{
return -1;
}
*target++ = g_base64[src[0] >> 2];
if (srclen == 1)
{
*target++ = g_base64[(src[0] & 0x03) << 4];
*target++ = g_pad64;
}
else
{
*target++ = g_base64[((src[0] & 0x03) << 4) + (src[1] >> 4)];
*target++ = g_base64[(src[1] & 0x0f) << 2];
}
*target++ = g_pad64;
}
*target = '\0';
return datalen;
}
int b64_pton(FAR const char *src,
FAR unsigned char *target, size_t targsize)
{
FAR char *pos;
size_t datalen = 0;
int state = 0;
int ch;
while ((ch = *src++) != '\0')
{
if (isspace(ch))
{
continue;
}
if (ch == g_pad64)
{
break;
}
pos = strchr(g_base64, ch);
if (pos == NULL)
{
return -1;
}
switch (state)
{
case 0:
if (target)
{
if (datalen >= targsize)
{
return -1;
}
*target = (pos - g_base64) << 2;
}
state = 1;
break;
case 1:
if (target)
{
if ((datalen += 1) >= targsize)
{
return -1;
}
*target++ |= (pos - g_base64) >> 4;
*target = ((pos - g_base64) & 0x0f) << 4;
}
state = 2;
break;
case 2:
if (target)
{
if ((datalen += 1) >= targsize)
{
return -1;
}
*target++ |= (pos - g_base64) >> 2;
*target = ((pos - g_base64) & 0x03) << 6;
}
state = 3;
break;
case 3:
if (target)
{
*target++ |= pos - g_base64;
}
datalen++;
state = 0;
break;
default:
return -1;
}
}
if (ch == g_pad64)
{
ch = *src++;
switch (state)
{
case 0:
case 1:
return -1;
case 2:
for (; ch != '\0'; ch = *src++)
{
if (!isspace(ch))
{
break;
}
}
if (ch != g_pad64)
{
return -1;
}
ch = *src++;
/* FALLTHROUGH */
case 3:
for (; ch != '\0'; ch = *src++)
{
if (!isspace(ch))
{
return -1;
}
}
if (target && *target != 0)
{
return -1;
}
}
}
else
{
if (state != 0)
{
return -1;
}
}
return datalen;
}