brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.7 KiB · 2d6be5c Raw
150 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++0310 11// <fstream>12 13// streamsize xsputn(const char_type*, streamsize) override;14 15// This isn't a required override by the standard, but most implementations override it, since it allows for16// significantly improved performance in some cases. All of this code is required to work, so this isn't a libc++17// extension18 19#include <algorithm>20#include <cassert>21#include <codecvt>22#include <cstring>23#include <fstream>24#include <locale>25#include <vector>26 27#include "test_macros.h"28 29typedef std::filebuf::pos_type pos_type;30typedef std::filebuf::off_type off_type;31 32void sputn_seekoff(char* buf,33                   const size_t buf_size,34                   const std::streamsize chunk_size1,35                   const off_type offset1,36                   const std::streamsize chunk_size2) {37  std::string data{"abcdefghijklmnopqrstuvwxyz"};38  const std::streamsize data_size = static_cast<std::streamsize>(data.size());39  assert(chunk_size1 <= data_size);40  assert(chunk_size2 <= data_size);41  // vector with expected data in the file to be written42  std::size_t result_size = 5 + chunk_size1 + chunk_size2 + 1;43  if (offset1 > 0) {44    result_size += offset1;45  }46  std::vector<char> result(result_size, 0);47  {48    std::filebuf f;49    f.pubsetbuf(buf, buf_size);50    assert(f.open("sputn_seekoff.dat", std::ios_base::out) != 0);51    assert(f.is_open());52 53    assert(f.pubseekoff(off_type(5), std::ios_base::beg) = off_type(5));54 55    std::vector<char> chunk(data.begin() + 5, data.begin() + 5 + chunk_size1);56    std::copy(chunk.begin(), chunk.end(), result.begin() + 5);57    const std::streamsize len1 = f.sputn(chunk.data(), chunk_size1);58    assert(len1 == chunk_size1);59    // check that nothing in the original chunk was modified by sputn()60    assert(std::strncmp(chunk.data(), data.substr(5, len1).c_str(), len1) == 0);61 62    pos_type p1 = f.pubseekoff(offset1, std::ios_base::cur);63    char c;64    if (p1 < 0) {65      p1 = f.pubseekoff(0, std::ios_base::beg);66      assert(p1 == 0);67      c = '^';68    } else {69      assert(p1 == 5 + len1 + offset1);70      if (p1 > data_size) {71        c = '_';72      } else {73        c = data[p1];74      }75    }76 77    result[p1] = c;78    assert(f.sputc(c) == c);79 80    f.pubseekpos(std::ios_base::beg);81    result[0] = 'A';82    assert(f.sputc(toupper(data[0])) == 'A');83 84    pos_type end_pos = f.pubseekoff(off_type(0), std::ios_base::end);85    assert(f.sputc(toupper(data[data_size - 1])) == 'Z');86    result[end_pos] = 'Z';87 88    assert(f.pubseekpos(p1) == p1);89    result[p1] = toupper(c);90    assert(f.sputc(toupper(c)) == toupper(c));91 92    pos_type new_pos = result_size - chunk_size2;93    pos_type p2      = f.pubseekoff(new_pos, std::ios_base::beg);94    assert(p2 == new_pos);95    chunk = std::vector<char>(data.end() - chunk_size2, data.end());96    std::copy(chunk.begin(), chunk.end(), result.begin() + p2);97    const std::streamsize len2 = f.sputn(chunk.data(), chunk_size2);98    assert(len2 == chunk_size2);99    assert(std::strncmp(chunk.data(), data.substr(data_size - chunk_size2, chunk_size2).c_str(), len2) == 0);100    f.close();101  }102  std::filebuf f;103  assert(f.open("sputn_seekoff.dat", std::ios_base::in) != 0);104  assert(f.is_open());105  std::vector<char> check(result.size(), -1);106  const std::size_t len = f.sgetn(check.data(), check.size());107  assert(len == result.size());108  for (size_t i = 0; i < len; ++i) {109    assert(check[i] == result[i]);110  }111}112 113void sputn_not_open() {114  std::vector<char> data(10, 'a');115  std::filebuf f;116  std::streamsize len = f.sputn(data.data(), data.size());117  assert(len == 0);118  assert(std::strncmp(data.data(), "aaaaaaaaaa", 10) == 0);119}120 121#ifndef TEST_HAS_NO_WIDE_CHARACTERS122void sputn_not_open_wchar() {123  std::vector<wchar_t> data(10, L'a');124  std::wfilebuf f;125  std::streamsize len = f.sputn(data.data(), data.size());126  assert(len == 0);127  assert(std::wcsncmp(data.data(), L"aaaaaaaaaa", 10) == 0);128}129#endif130 131int main(int, char**) {132  sputn_not_open();133#ifndef TEST_HAS_NO_WIDE_CHARACTERS134  sputn_not_open_wchar();135#endif136 137  sputn_seekoff(nullptr, 10, 21, -27, 1);138  sputn_seekoff(nullptr, 10, 1, -27, 1);139  sputn_seekoff(nullptr, 10, 10, 14, 12);140  sputn_seekoff(nullptr, 10, 1, -2, 1);141  sputn_seekoff(nullptr, 10, 10, -4, 12);142  sputn_seekoff(nullptr, 10, 11, -12, 3);143  sputn_seekoff(nullptr, 10, 7, 3, 8);144  sputn_seekoff(nullptr, 10, 5, -5, 12);145  sputn_seekoff(nullptr, 10, 1, 1, 1);146  sputn_seekoff(nullptr, 10, 9, 0, 1);147 148  return 0;149}150