Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e44d25d6 authored by Elliott Hughes's avatar Elliott Hughes Committed by Gerrit Code Review
Browse files

Merge "Add Google-style StringPrintf."

parents d4a6fc5b 6b3be290
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed 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.
 */

#ifndef UTILS_STRINGPRINTF_H_
#define UTILS_STRINGPRINTF_H_

#include <stdarg.h>
#include <string>

namespace android {

// Returns a string corresponding to printf-like formatting of the arguments.
std::string StringPrintf(const char* fmt, ...)
        __attribute__((__format__(__printf__, 1, 2)));

// Appends a printf-like formatting of the arguments to 'dst'.
void StringAppendF(std::string* dst, const char* fmt, ...)
        __attribute__((__format__(__printf__, 2, 3)));

// Appends a printf-like formatting of the arguments to 'dst'.
void StringAppendV(std::string* dst, const char* format, va_list ap);

}  // namespace android

#endif
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ commonSources:= \
	VectorImpl.cpp \
	file.cpp \
	misc.cpp \
	stringprintf.cpp \

host_commonCflags := -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS) -Werror

+77 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed 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.
 */

#include <utils/stringprintf.h>

#include <stdio.h>

void android::StringAppendV(std::string* dst, const char* format, va_list ap) {
  // First try with a small fixed size buffer
  char space[1024];

  // It's possible for methods that use a va_list to invalidate
  // the data in it upon use.  The fix is to make a copy
  // of the structure before using it and use that copy instead.
  va_list backup_ap;
  va_copy(backup_ap, ap);
  int result = vsnprintf(space, sizeof(space), format, backup_ap);
  va_end(backup_ap);

  if (result < static_cast<int>(sizeof(space))) {
    if (result >= 0) {
      // Normal case -- everything fit.
      dst->append(space, result);
      return;
    }

    if (result < 0) {
      // Just an error.
      return;
    }
  }

  // Increase the buffer size to the size requested by vsnprintf,
  // plus one for the closing \0.
  int length = result+1;
  char* buf = new char[length];

  // Restore the va_list before we use it again
  va_copy(backup_ap, ap);
  result = vsnprintf(buf, length, format, backup_ap);
  va_end(backup_ap);

  if (result >= 0 && result < length) {
    // It fit
    dst->append(buf, result);
  }
  delete[] buf;
}

std::string android::StringPrintf(const char* fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  std::string result;
  StringAppendV(&result, fmt, ap);
  va_end(ap);
  return result;
}

void android::StringAppendF(std::string* dst, const char* format, ...) {
  va_list ap;
  va_start(ap, format);
  StringAppendV(dst, format, ap);
  va_end(ap);
}
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ LOCAL_SRC_FILES := \
    Looper_test.cpp \
    LruCache_test.cpp \
    String8_test.cpp \
    stringprintf_test.cpp \
    Unicode_test.cpp \
    Vector_test.cpp \

+58 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed 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.
 */

#include <utils/stringprintf.h>

#include <gtest/gtest.h>

TEST(StringPrintfTest, HexSizeT) {
  size_t size = 0x00107e59;
  EXPECT_EQ("00107e59", android::StringPrintf("%08zx", size));
  EXPECT_EQ("0x00107e59", android::StringPrintf("0x%08zx", size));
}

TEST(StringPrintfTest, StringAppendF) {
  std::string s("a");
  android::StringAppendF(&s, "b");
  EXPECT_EQ("ab", s);
}

TEST(StringPrintfTest, Errno) {
  errno = 123;
  android::StringPrintf("hello %s", "world");
  EXPECT_EQ(123, errno);
}

void TestN(size_t n) {
  char* buf = new char[n + 1];
  memset(buf, 'x', n);
  buf[n] = '\0';
  std::string s(android::StringPrintf("%s", buf));
  EXPECT_EQ(buf, s);
  delete[] buf;
}

TEST(StringPrintfTest, At1023) {
  TestN(1023);
}

TEST(StringPrintfTest, At1024) {
  TestN(1024);
}

TEST(StringPrintfTest, At1025) {
  TestN(1025);
}